FD.io VPP  v18.10-32-g1161dda
Vector Packet Processing
out2in.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /**
16  * @file
17  * @brief NAT44 endpoint-dependent outside to inside network translation
18  */
19 
20 #include <vlib/vlib.h>
21 #include <vnet/vnet.h>
22 #include <vnet/pg/pg.h>
23 
24 #include <vnet/ip/ip.h>
25 #include <vnet/udp/udp.h>
26 #include <vnet/ethernet/ethernet.h>
27 #include <vnet/fib/ip4_fib.h>
28 #include <nat/nat.h>
29 #include <nat/nat_ipfix_logging.h>
30 #include <nat/nat_reass.h>
31 #include <nat/nat_inlines.h>
32 
33 #include <vppinfra/hash.h>
34 #include <vppinfra/error.h>
35 #include <vppinfra/elog.h>
36 
37 typedef struct
38 {
43 
44 /* packet trace format function */
45 static u8 *
46 format_snat_out2in_trace (u8 * s, va_list * args)
47 {
48  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
49  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
50  snat_out2in_trace_t *t = va_arg (*args, snat_out2in_trace_t *);
51 
52  s =
53  format (s,
54  "NAT44_OUT2IN: sw_if_index %d, next index %d, session index %d",
56  return s;
57 }
58 
59 static u8 *
60 format_snat_out2in_fast_trace (u8 * s, va_list * args)
61 {
62  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
63  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
64  snat_out2in_trace_t *t = va_arg (*args, snat_out2in_trace_t *);
65 
66  s = format (s, "NAT44_OUT2IN_FAST: sw_if_index %d, next index %d",
67  t->sw_if_index, t->next_index);
68  return s;
69 }
70 
74 
75 #define foreach_snat_out2in_error \
76 _(UNSUPPORTED_PROTOCOL, "Unsupported protocol") \
77 _(OUT2IN_PACKETS, "Good out2in packets processed") \
78 _(OUT_OF_PORTS, "Out of ports") \
79 _(BAD_ICMP_TYPE, "unsupported ICMP type") \
80 _(NO_TRANSLATION, "No translation") \
81 _(MAX_SESSIONS_EXCEEDED, "Maximum sessions exceeded") \
82 _(DROP_FRAGMENT, "Drop fragment") \
83 _(MAX_REASS, "Maximum reassemblies exceeded") \
84 _(MAX_FRAG, "Maximum fragments per reassembly exceeded")
85 
86 typedef enum
87 {
88 #define _(sym,str) SNAT_OUT2IN_ERROR_##sym,
90 #undef _
93 
94 static char *snat_out2in_error_strings[] = {
95 #define _(sym,string) string,
97 #undef _
98 };
99 
100 typedef enum
101 {
108 
109 int
111 {
112  snat_main_t *sm = &snat_main;
114  snat_session_t *s;
115  u64 sess_timeout_time;
117  ctx->thread_index);
119 
120  s = pool_elt_at_index (tsm->sessions, kv->value);
121  sess_timeout_time = s->last_heard + (f64) nat44_session_get_timeout (sm, s);
122  if (ctx->now >= sess_timeout_time)
123  {
124  s_kv.key = s->in2out.as_u64;
125  if (clib_bihash_add_del_8_8 (&tsm->in2out, &s_kv, 0))
126  nat_log_warn ("out2in key del failed");
127 
128  snat_ipfix_logging_nat44_ses_delete (s->in2out.addr.as_u32,
129  s->out2in.addr.as_u32,
130  s->in2out.protocol,
131  s->in2out.port,
132  s->out2in.port,
133  s->in2out.fib_index);
134 
135  if (!snat_is_session_static (s))
137  &s->out2in);
138 
139  nat44_delete_session (sm, s, ctx->thread_index);
140  return 1;
141  }
142 
143  return 0;
144 }
145 
146 /**
147  * @brief Create session for static mapping.
148  *
149  * Create NAT session initiated by host from external network with static
150  * mapping.
151  *
152  * @param sm NAT main.
153  * @param b0 Vlib buffer.
154  * @param in2out In2out NAT44 session key.
155  * @param out2in Out2in NAT44 session key.
156  * @param node Vlib node.
157  *
158  * @returns SNAT session if successfully created otherwise 0.
159  */
160 static inline snat_session_t *
162  vlib_buffer_t * b0,
163  snat_session_key_t in2out,
164  snat_session_key_t out2in,
165  vlib_node_runtime_t * node,
166  u32 thread_index, f64 now)
167 {
168  snat_user_t *u;
169  snat_session_t *s;
171  ip4_header_t *ip0;
172  udp_header_t *udp0;
174 
175  if (PREDICT_FALSE (maximum_sessions_exceeded (sm, thread_index)))
176  {
177  b0->error = node->errors[SNAT_OUT2IN_ERROR_MAX_SESSIONS_EXCEEDED];
178  nat_log_notice ("maximum sessions exceeded");
179  return 0;
180  }
181 
182  ip0 = vlib_buffer_get_current (b0);
183  udp0 = ip4_next_header (ip0);
184 
185  u =
186  nat_user_get_or_create (sm, &in2out.addr, in2out.fib_index, thread_index);
187  if (!u)
188  {
189  nat_log_warn ("create NAT user failed");
190  return 0;
191  }
192 
193  s = nat_session_alloc_or_recycle (sm, u, thread_index);
194  if (!s)
195  {
196  nat44_delete_user_with_no_session (sm, u, thread_index);
197  nat_log_warn ("create NAT session failed");
198  return 0;
199  }
200 
202  s->ext_host_addr.as_u32 = ip0->src_address.as_u32;
203  s->ext_host_port = udp0->src_port;
204  user_session_increment (sm, u, 1 /* static */ );
205  s->in2out = in2out;
206  s->out2in = out2in;
207  s->in2out.protocol = out2in.protocol;
208 
209  /* Add to translation hashes */
210  ctx0.now = now;
211  ctx0.thread_index = thread_index;
212  kv0.key = s->in2out.as_u64;
213  kv0.value = s - sm->per_thread_data[thread_index].sessions;
214  if (clib_bihash_add_or_overwrite_stale_8_8
215  (&sm->per_thread_data[thread_index].in2out, &kv0,
217  nat_log_notice ("in2out key add failed");
218 
219  kv0.key = s->out2in.as_u64;
220 
221  if (clib_bihash_add_or_overwrite_stale_8_8
222  (&sm->per_thread_data[thread_index].out2in, &kv0,
224  nat_log_notice ("out2in key add failed");
225 
226  /* log NAT event */
227  snat_ipfix_logging_nat44_ses_create (s->in2out.addr.as_u32,
228  s->out2in.addr.as_u32,
229  s->in2out.protocol,
230  s->in2out.port,
231  s->out2in.port, s->in2out.fib_index);
232  return s;
233 }
234 
237  snat_session_key_t * p_key0)
238 {
239  icmp46_header_t *icmp0;
240  snat_session_key_t key0;
241  icmp_echo_header_t *echo0, *inner_echo0 = 0;
242  ip4_header_t *inner_ip0;
243  void *l4_header = 0;
244  icmp46_header_t *inner_icmp0;
245 
246  icmp0 = (icmp46_header_t *) ip4_next_header (ip0);
247  echo0 = (icmp_echo_header_t *) (icmp0 + 1);
248 
249  if (!icmp_is_error_message (icmp0))
250  {
251  key0.protocol = SNAT_PROTOCOL_ICMP;
252  key0.addr = ip0->dst_address;
253  key0.port = echo0->identifier;
254  }
255  else
256  {
257  inner_ip0 = (ip4_header_t *) (echo0 + 1);
258  l4_header = ip4_next_header (inner_ip0);
259  key0.protocol = ip_proto_to_snat_proto (inner_ip0->protocol);
260  key0.addr = inner_ip0->src_address;
261  switch (key0.protocol)
262  {
263  case SNAT_PROTOCOL_ICMP:
264  inner_icmp0 = (icmp46_header_t *) l4_header;
265  inner_echo0 = (icmp_echo_header_t *) (inner_icmp0 + 1);
266  key0.port = inner_echo0->identifier;
267  break;
268  case SNAT_PROTOCOL_UDP:
269  case SNAT_PROTOCOL_TCP:
270  key0.port = ((tcp_udp_header_t *) l4_header)->src_port;
271  break;
272  default:
273  return SNAT_OUT2IN_ERROR_UNSUPPORTED_PROTOCOL;
274  }
275  }
276  *p_key0 = key0;
277  return -1; /* success */
278 }
279 
280 /**
281  * Get address and port values to be used for ICMP packet translation
282  * and create session if needed
283  *
284  * @param[in,out] sm NAT main
285  * @param[in,out] node NAT node runtime
286  * @param[in] thread_index thread index
287  * @param[in,out] b0 buffer containing packet to be translated
288  * @param[out] p_proto protocol used for matching
289  * @param[out] p_value address and port after NAT translation
290  * @param[out] p_dont_translate if packet should not be translated
291  * @param d optional parameter
292  * @param e optional parameter
293  */
294 u32
296  u32 thread_index, vlib_buffer_t * b0,
297  ip4_header_t * ip0, u8 * p_proto,
298  snat_session_key_t * p_value,
299  u8 * p_dont_translate, void *d, void *e)
300 {
301  icmp46_header_t *icmp0;
302  u32 sw_if_index0;
303  u32 rx_fib_index0;
304  snat_session_key_t key0;
305  snat_session_key_t sm0;
306  snat_session_t *s0 = 0;
307  u8 dont_translate = 0;
308  clib_bihash_kv_8_8_t kv0, value0;
309  u8 is_addr_only;
310  u32 next0 = ~0;
311  int err;
312  u8 identity_nat;
313 
314  icmp0 = (icmp46_header_t *) ip4_next_header (ip0);
315  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
316  rx_fib_index0 = ip4_fib_table_get_index_for_sw_if_index (sw_if_index0);
317 
318  key0.protocol = 0;
319 
320  err = icmp_get_key (ip0, &key0);
321  if (err != -1)
322  {
323  b0->error = node->errors[SNAT_OUT2IN_ERROR_UNSUPPORTED_PROTOCOL];
324  next0 = SNAT_OUT2IN_NEXT_DROP;
325  goto out;
326  }
327  key0.fib_index = rx_fib_index0;
328 
329  kv0.key = key0.as_u64;
330 
331  if (clib_bihash_search_8_8 (&sm->per_thread_data[thread_index].out2in, &kv0,
332  &value0))
333  {
334  /* Try to match static mapping by external address and port,
335  destination address and port in packet */
337  (sm, key0, &sm0, 1, &is_addr_only, 0, 0, 0, &identity_nat))
338  {
339  if (!sm->forwarding_enabled)
340  {
341  /* Don't NAT packet aimed at the intfc address */
342  if (PREDICT_FALSE (is_interface_addr (sm, node, sw_if_index0,
343  ip0->dst_address.as_u32)))
344  {
345  dont_translate = 1;
346  goto out;
347  }
348  b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
349  next0 = SNAT_OUT2IN_NEXT_DROP;
350  goto out;
351  }
352  else
353  {
354  dont_translate = 1;
355  goto out;
356  }
357  }
358 
359  if (PREDICT_FALSE (icmp0->type != ICMP4_echo_reply &&
360  (icmp0->type != ICMP4_echo_request
361  || !is_addr_only)))
362  {
363  b0->error = node->errors[SNAT_OUT2IN_ERROR_BAD_ICMP_TYPE];
364  next0 = SNAT_OUT2IN_NEXT_DROP;
365  goto out;
366  }
367 
368  if (PREDICT_FALSE (identity_nat))
369  {
370  dont_translate = 1;
371  goto out;
372  }
373  /* Create session initiated by host from external network */
374  s0 = create_session_for_static_mapping (sm, b0, sm0, key0,
375  node, thread_index,
376  vlib_time_now (sm->vlib_main));
377 
378  if (!s0)
379  {
380  next0 = SNAT_OUT2IN_NEXT_DROP;
381  goto out;
382  }
383  }
384  else
385  {
386  if (PREDICT_FALSE (icmp0->type != ICMP4_echo_reply &&
387  icmp0->type != ICMP4_echo_request &&
388  !icmp_is_error_message (icmp0)))
389  {
390  b0->error = node->errors[SNAT_OUT2IN_ERROR_BAD_ICMP_TYPE];
391  next0 = SNAT_OUT2IN_NEXT_DROP;
392  goto out;
393  }
394 
395  s0 = pool_elt_at_index (sm->per_thread_data[thread_index].sessions,
396  value0.value);
397  }
398 
399 out:
400  *p_proto = key0.protocol;
401  if (s0)
402  *p_value = s0->in2out;
403  *p_dont_translate = dont_translate;
404  if (d)
405  *(snat_session_t **) d = s0;
406  return next0;
407 }
408 
409 /**
410  * Get address and port values to be used for ICMP packet translation
411  *
412  * @param[in] sm NAT main
413  * @param[in,out] node NAT node runtime
414  * @param[in] thread_index thread index
415  * @param[in,out] b0 buffer containing packet to be translated
416  * @param[out] p_proto protocol used for matching
417  * @param[out] p_value address and port after NAT translation
418  * @param[out] p_dont_translate if packet should not be translated
419  * @param d optional parameter
420  * @param e optional parameter
421  */
422 u32
424  u32 thread_index, vlib_buffer_t * b0,
425  ip4_header_t * ip0, u8 * p_proto,
426  snat_session_key_t * p_value,
427  u8 * p_dont_translate, void *d, void *e)
428 {
429  icmp46_header_t *icmp0;
430  u32 sw_if_index0;
431  u32 rx_fib_index0;
432  snat_session_key_t key0;
433  snat_session_key_t sm0;
434  u8 dont_translate = 0;
435  u8 is_addr_only;
436  u32 next0 = ~0;
437  int err;
438 
439  icmp0 = (icmp46_header_t *) ip4_next_header (ip0);
440  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
441  rx_fib_index0 = ip4_fib_table_get_index_for_sw_if_index (sw_if_index0);
442 
443  err = icmp_get_key (ip0, &key0);
444  if (err != -1)
445  {
446  b0->error = node->errors[err];
447  next0 = SNAT_OUT2IN_NEXT_DROP;
448  goto out2;
449  }
450  key0.fib_index = rx_fib_index0;
451 
453  (sm, key0, &sm0, 1, &is_addr_only, 0, 0, 0, 0))
454  {
455  /* Don't NAT packet aimed at the intfc address */
456  if (is_interface_addr (sm, node, sw_if_index0, ip0->dst_address.as_u32))
457  {
458  dont_translate = 1;
459  goto out;
460  }
461  b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
462  next0 = SNAT_OUT2IN_NEXT_DROP;
463  goto out;
464  }
465 
466  if (PREDICT_FALSE (icmp0->type != ICMP4_echo_reply &&
467  (icmp0->type != ICMP4_echo_request || !is_addr_only) &&
468  !icmp_is_error_message (icmp0)))
469  {
470  b0->error = node->errors[SNAT_OUT2IN_ERROR_BAD_ICMP_TYPE];
471  next0 = SNAT_OUT2IN_NEXT_DROP;
472  goto out;
473  }
474 
475 out:
476  *p_value = sm0;
477 out2:
478  *p_proto = key0.protocol;
479  *p_dont_translate = dont_translate;
480  return next0;
481 }
482 
483 u32
485  vlib_buffer_t * b0,
486  ip4_header_t * ip0,
487  icmp46_header_t * icmp0,
488  u32 sw_if_index0,
489  u32 rx_fib_index0,
490  vlib_node_runtime_t * node,
491  u32 next0, u32 thread_index, void *d, void *e)
492 {
493  snat_session_key_t sm0;
494  u8 protocol;
495  icmp_echo_header_t *echo0, *inner_echo0 = 0;
496  ip4_header_t *inner_ip0 = 0;
497  void *l4_header = 0;
498  icmp46_header_t *inner_icmp0;
499  u8 dont_translate;
500  u32 new_addr0, old_addr0;
501  u16 old_id0, new_id0;
502  ip_csum_t sum0;
503  u16 checksum0;
504  u32 next0_tmp;
505 
506  echo0 = (icmp_echo_header_t *) (icmp0 + 1);
507 
508  next0_tmp = sm->icmp_match_out2in_cb (sm, node, thread_index, b0, ip0,
509  &protocol, &sm0, &dont_translate, d,
510  e);
511  if (next0_tmp != ~0)
512  next0 = next0_tmp;
513  if (next0 == SNAT_OUT2IN_NEXT_DROP || dont_translate)
514  goto out;
515 
516  if (PREDICT_TRUE (!ip4_is_fragment (ip0)))
517  {
518  sum0 = ip_incremental_checksum_buffer (sm->vlib_main, b0, (u8 *) icmp0 -
519  (u8 *)
521  ntohs (ip0->length) -
522  ip4_header_bytes (ip0), 0);
523  checksum0 = ~ip_csum_fold (sum0);
524  if (checksum0 != 0 && checksum0 != 0xffff)
525  {
526  next0 = SNAT_OUT2IN_NEXT_DROP;
527  goto out;
528  }
529  }
530 
531  old_addr0 = ip0->dst_address.as_u32;
532  new_addr0 = ip0->dst_address.as_u32 = sm0.addr.as_u32;
533  vnet_buffer (b0)->sw_if_index[VLIB_TX] = sm0.fib_index;
534 
535  sum0 = ip0->checksum;
536  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
537  dst_address /* changed member */ );
538  ip0->checksum = ip_csum_fold (sum0);
539 
540  if (icmp0->checksum == 0)
541  icmp0->checksum = 0xffff;
542 
543  if (!icmp_is_error_message (icmp0))
544  {
545  new_id0 = sm0.port;
546  if (PREDICT_FALSE (new_id0 != echo0->identifier))
547  {
548  old_id0 = echo0->identifier;
549  new_id0 = sm0.port;
550  echo0->identifier = new_id0;
551 
552  sum0 = icmp0->checksum;
553  sum0 = ip_csum_update (sum0, old_id0, new_id0, icmp_echo_header_t,
554  identifier /* changed member */ );
555  icmp0->checksum = ip_csum_fold (sum0);
556  }
557  }
558  else
559  {
560  inner_ip0 = (ip4_header_t *) (echo0 + 1);
561  l4_header = ip4_next_header (inner_ip0);
562 
563  if (!ip4_header_checksum_is_valid (inner_ip0))
564  {
565  next0 = SNAT_OUT2IN_NEXT_DROP;
566  goto out;
567  }
568 
569  old_addr0 = inner_ip0->src_address.as_u32;
570  inner_ip0->src_address = sm0.addr;
571  new_addr0 = inner_ip0->src_address.as_u32;
572 
573  sum0 = icmp0->checksum;
574  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
575  src_address /* changed member */ );
576  icmp0->checksum = ip_csum_fold (sum0);
577 
578  switch (protocol)
579  {
580  case SNAT_PROTOCOL_ICMP:
581  inner_icmp0 = (icmp46_header_t *) l4_header;
582  inner_echo0 = (icmp_echo_header_t *) (inner_icmp0 + 1);
583 
584  old_id0 = inner_echo0->identifier;
585  new_id0 = sm0.port;
586  inner_echo0->identifier = new_id0;
587 
588  sum0 = icmp0->checksum;
589  sum0 = ip_csum_update (sum0, old_id0, new_id0, icmp_echo_header_t,
590  identifier);
591  icmp0->checksum = ip_csum_fold (sum0);
592  break;
593  case SNAT_PROTOCOL_UDP:
594  case SNAT_PROTOCOL_TCP:
595  old_id0 = ((tcp_udp_header_t *) l4_header)->src_port;
596  new_id0 = sm0.port;
597  ((tcp_udp_header_t *) l4_header)->src_port = new_id0;
598 
599  sum0 = icmp0->checksum;
600  sum0 = ip_csum_update (sum0, old_id0, new_id0, tcp_udp_header_t,
601  src_port);
602  icmp0->checksum = ip_csum_fold (sum0);
603  break;
604  default:
605  ASSERT (0);
606  }
607  }
608 
609 out:
610  return next0;
611 }
612 
613 
614 static inline u32
616  vlib_buffer_t * b0,
617  ip4_header_t * ip0,
618  icmp46_header_t * icmp0,
619  u32 sw_if_index0,
620  u32 rx_fib_index0,
621  vlib_node_runtime_t * node,
622  u32 next0, f64 now,
623  u32 thread_index, snat_session_t ** p_s0)
624 {
625  next0 = icmp_out2in (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
626  next0, thread_index, p_s0, 0);
627  snat_session_t *s0 = *p_s0;
628  if (PREDICT_TRUE (next0 != SNAT_OUT2IN_NEXT_DROP && s0))
629  {
630  /* Accounting */
633  (sm->vlib_main, b0));
634  /* Per-user LRU list maintenance */
635  nat44_session_update_lru (sm, s0, thread_index);
636  }
637  return next0;
638 }
639 
640 static int
642  vlib_buffer_t * b,
643  ip4_header_t * ip, u32 rx_fib_index)
644 {
645  clib_bihash_kv_8_8_t kv, value;
647  snat_session_key_t m_key;
648  u32 old_addr, new_addr;
649  ip_csum_t sum;
650 
651  m_key.addr = ip->dst_address;
652  m_key.port = 0;
653  m_key.protocol = 0;
654  m_key.fib_index = 0;
655  kv.key = m_key.as_u64;
656  if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
657  return 1;
658 
659  m = pool_elt_at_index (sm->static_mappings, value.value);
660 
661  old_addr = ip->dst_address.as_u32;
662  new_addr = ip->dst_address.as_u32 = m->local_addr.as_u32;
663  sum = ip->checksum;
664  sum = ip_csum_update (sum, old_addr, new_addr, ip4_header_t, dst_address);
665  ip->checksum = ip_csum_fold (sum);
666 
667  vnet_buffer (b)->sw_if_index[VLIB_TX] = m->fib_index;
668  return 0;
669 }
670 
671 static uword
673  vlib_node_runtime_t * node, vlib_frame_t * frame)
674 {
675  u32 n_left_from, *from, *to_next;
676  snat_out2in_next_t next_index;
677  u32 pkts_processed = 0;
678  snat_main_t *sm = &snat_main;
679  f64 now = vlib_time_now (vm);
680  u32 thread_index = vm->thread_index;
681 
682  from = vlib_frame_vector_args (frame);
683  n_left_from = frame->n_vectors;
684  next_index = node->cached_next_index;
685 
686  while (n_left_from > 0)
687  {
688  u32 n_left_to_next;
689 
690  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
691 
692  while (n_left_from >= 4 && n_left_to_next >= 2)
693  {
694  u32 bi0, bi1;
695  vlib_buffer_t *b0, *b1;
698  u32 sw_if_index0, sw_if_index1;
699  ip4_header_t *ip0, *ip1;
700  ip_csum_t sum0, sum1;
701  u32 new_addr0, old_addr0;
702  u16 new_port0, old_port0;
703  u32 new_addr1, old_addr1;
704  u16 new_port1, old_port1;
705  udp_header_t *udp0, *udp1;
706  tcp_header_t *tcp0, *tcp1;
707  icmp46_header_t *icmp0, *icmp1;
708  snat_session_key_t key0, key1, sm0, sm1;
709  u32 rx_fib_index0, rx_fib_index1;
710  u32 proto0, proto1;
711  snat_session_t *s0 = 0, *s1 = 0;
712  clib_bihash_kv_8_8_t kv0, kv1, value0, value1;
713  u8 identity_nat0, identity_nat1;
714 
715  /* Prefetch next iteration. */
716  {
717  vlib_buffer_t *p2, *p3;
718 
719  p2 = vlib_get_buffer (vm, from[2]);
720  p3 = vlib_get_buffer (vm, from[3]);
721 
722  vlib_prefetch_buffer_header (p2, LOAD);
723  vlib_prefetch_buffer_header (p3, LOAD);
724 
727  }
728 
729  /* speculatively enqueue b0 and b1 to the current next frame */
730  to_next[0] = bi0 = from[0];
731  to_next[1] = bi1 = from[1];
732  from += 2;
733  to_next += 2;
734  n_left_from -= 2;
735  n_left_to_next -= 2;
736 
737  b0 = vlib_get_buffer (vm, bi0);
738  b1 = vlib_get_buffer (vm, bi1);
739 
740  vnet_buffer (b0)->snat.flags = 0;
741  vnet_buffer (b1)->snat.flags = 0;
742 
743  ip0 = vlib_buffer_get_current (b0);
744  udp0 = ip4_next_header (ip0);
745  tcp0 = (tcp_header_t *) udp0;
746  icmp0 = (icmp46_header_t *) udp0;
747 
748  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
749  rx_fib_index0 = vec_elt (sm->ip4_main->fib_index_by_sw_if_index,
750  sw_if_index0);
751 
752  if (PREDICT_FALSE (ip0->ttl == 1))
753  {
754  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
755  icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
756  ICMP4_time_exceeded_ttl_exceeded_in_transit,
757  0);
759  goto trace0;
760  }
761 
762  proto0 = ip_proto_to_snat_proto (ip0->protocol);
763 
764  if (PREDICT_FALSE (proto0 == ~0))
765  {
766  if (nat_out2in_sm_unknown_proto (sm, b0, ip0, rx_fib_index0))
767  {
768  if (!sm->forwarding_enabled)
769  {
770  b0->error =
771  node->errors[SNAT_OUT2IN_ERROR_UNSUPPORTED_PROTOCOL];
772  next0 = SNAT_OUT2IN_NEXT_DROP;
773  }
774  }
775  goto trace0;
776  }
777 
778  if (PREDICT_FALSE (ip4_is_fragment (ip0)))
779  {
780  next0 = SNAT_OUT2IN_NEXT_REASS;
781  goto trace0;
782  }
783 
784  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
785  {
786  next0 = icmp_out2in_slow_path
787  (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
788  next0, now, thread_index, &s0);
789  goto trace0;
790  }
791 
792  key0.addr = ip0->dst_address;
793  key0.port = udp0->dst_port;
794  key0.protocol = proto0;
795  key0.fib_index = rx_fib_index0;
796 
797  kv0.key = key0.as_u64;
798 
799  if (clib_bihash_search_8_8
800  (&sm->per_thread_data[thread_index].out2in, &kv0, &value0))
801  {
802  /* Try to match static mapping by external address and port,
803  destination address and port in packet */
805  (sm, key0, &sm0, 1, 0, 0, 0, 0, &identity_nat0))
806  {
807  /*
808  * Send DHCP packets to the ipv4 stack, or we won't
809  * be able to use dhcp client on the outside interface
810  */
811  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_UDP
812  && (udp0->dst_port ==
813  clib_host_to_net_u16
814  (UDP_DST_PORT_dhcp_to_client))))
815  {
816  vnet_feature_next (&next0, b0);
817  goto trace0;
818  }
819 
820  if (!sm->forwarding_enabled)
821  {
822  b0->error =
823  node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
824  next0 = SNAT_OUT2IN_NEXT_DROP;
825  }
826  goto trace0;
827  }
828 
829  if (PREDICT_FALSE (identity_nat0))
830  goto trace0;
831 
832  /* Create session initiated by host from external network */
833  s0 = create_session_for_static_mapping (sm, b0, sm0, key0, node,
834  thread_index, now);
835  if (!s0)
836  {
837  next0 = SNAT_OUT2IN_NEXT_DROP;
838  goto trace0;
839  }
840  }
841  else
842  s0 =
843  pool_elt_at_index (sm->per_thread_data[thread_index].sessions,
844  value0.value);
845 
846  old_addr0 = ip0->dst_address.as_u32;
847  ip0->dst_address = s0->in2out.addr;
848  new_addr0 = ip0->dst_address.as_u32;
849  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
850 
851  sum0 = ip0->checksum;
852  sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
853  ip4_header_t,
854  dst_address /* changed member */ );
855  ip0->checksum = ip_csum_fold (sum0);
856 
857  if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP))
858  {
859  old_port0 = tcp0->dst_port;
860  tcp0->dst_port = s0->in2out.port;
861  new_port0 = tcp0->dst_port;
862 
863  sum0 = tcp0->checksum;
864  sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
865  ip4_header_t,
866  dst_address /* changed member */ );
867 
868  sum0 = ip_csum_update (sum0, old_port0, new_port0,
869  ip4_header_t /* cheat */ ,
870  length /* changed member */ );
871  tcp0->checksum = ip_csum_fold (sum0);
872  }
873  else
874  {
875  old_port0 = udp0->dst_port;
876  udp0->dst_port = s0->in2out.port;
877  udp0->checksum = 0;
878  }
879 
880  /* Accounting */
883  b0));
884  /* Per-user LRU list maintenance */
885  nat44_session_update_lru (sm, s0, thread_index);
886  trace0:
887 
889  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
890  {
892  vlib_add_trace (vm, node, b0, sizeof (*t));
893  t->sw_if_index = sw_if_index0;
894  t->next_index = next0;
895  t->session_index = ~0;
896  if (s0)
897  t->session_index =
898  s0 - sm->per_thread_data[thread_index].sessions;
899  }
900 
901  pkts_processed += next0 != SNAT_OUT2IN_NEXT_DROP;
902 
903 
904  ip1 = vlib_buffer_get_current (b1);
905  udp1 = ip4_next_header (ip1);
906  tcp1 = (tcp_header_t *) udp1;
907  icmp1 = (icmp46_header_t *) udp1;
908 
909  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
910  rx_fib_index1 = vec_elt (sm->ip4_main->fib_index_by_sw_if_index,
911  sw_if_index1);
912 
913  if (PREDICT_FALSE (ip1->ttl == 1))
914  {
915  vnet_buffer (b1)->sw_if_index[VLIB_TX] = (u32) ~ 0;
916  icmp4_error_set_vnet_buffer (b1, ICMP4_time_exceeded,
917  ICMP4_time_exceeded_ttl_exceeded_in_transit,
918  0);
920  goto trace1;
921  }
922 
923  proto1 = ip_proto_to_snat_proto (ip1->protocol);
924 
925  if (PREDICT_FALSE (proto1 == ~0))
926  {
927  if (nat_out2in_sm_unknown_proto (sm, b1, ip1, rx_fib_index1))
928  {
929  if (!sm->forwarding_enabled)
930  {
931  b1->error =
932  node->errors[SNAT_OUT2IN_ERROR_UNSUPPORTED_PROTOCOL];
933  next1 = SNAT_OUT2IN_NEXT_DROP;
934  }
935  }
936  goto trace1;
937  }
938 
939  if (PREDICT_FALSE (ip4_is_fragment (ip1)))
940  {
941  next1 = SNAT_OUT2IN_NEXT_REASS;
942  goto trace1;
943  }
944 
945  if (PREDICT_FALSE (proto1 == SNAT_PROTOCOL_ICMP))
946  {
947  next1 = icmp_out2in_slow_path
948  (sm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1, node,
949  next1, now, thread_index, &s1);
950  goto trace1;
951  }
952 
953  key1.addr = ip1->dst_address;
954  key1.port = udp1->dst_port;
955  key1.protocol = proto1;
956  key1.fib_index = rx_fib_index1;
957 
958  kv1.key = key1.as_u64;
959 
960  if (clib_bihash_search_8_8
961  (&sm->per_thread_data[thread_index].out2in, &kv1, &value1))
962  {
963  /* Try to match static mapping by external address and port,
964  destination address and port in packet */
966  (sm, key1, &sm1, 1, 0, 0, 0, 0, &identity_nat1))
967  {
968  /*
969  * Send DHCP packets to the ipv4 stack, or we won't
970  * be able to use dhcp client on the outside interface
971  */
972  if (PREDICT_FALSE (proto1 == SNAT_PROTOCOL_UDP
973  && (udp1->dst_port ==
974  clib_host_to_net_u16
975  (UDP_DST_PORT_dhcp_to_client))))
976  {
977  vnet_feature_next (&next1, b1);
978  goto trace1;
979  }
980 
981  if (!sm->forwarding_enabled)
982  {
983  b1->error =
984  node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
985  next1 = SNAT_OUT2IN_NEXT_DROP;
986  }
987  goto trace1;
988  }
989 
990  if (PREDICT_FALSE (identity_nat1))
991  goto trace1;
992 
993  /* Create session initiated by host from external network */
994  s1 = create_session_for_static_mapping (sm, b1, sm1, key1, node,
995  thread_index, now);
996  if (!s1)
997  {
998  next1 = SNAT_OUT2IN_NEXT_DROP;
999  goto trace1;
1000  }
1001  }
1002  else
1003  s1 =
1004  pool_elt_at_index (sm->per_thread_data[thread_index].sessions,
1005  value1.value);
1006 
1007  old_addr1 = ip1->dst_address.as_u32;
1008  ip1->dst_address = s1->in2out.addr;
1009  new_addr1 = ip1->dst_address.as_u32;
1010  vnet_buffer (b1)->sw_if_index[VLIB_TX] = s1->in2out.fib_index;
1011 
1012  sum1 = ip1->checksum;
1013  sum1 = ip_csum_update (sum1, old_addr1, new_addr1,
1014  ip4_header_t,
1015  dst_address /* changed member */ );
1016  ip1->checksum = ip_csum_fold (sum1);
1017 
1018  if (PREDICT_TRUE (proto1 == SNAT_PROTOCOL_TCP))
1019  {
1020  old_port1 = tcp1->dst_port;
1021  tcp1->dst_port = s1->in2out.port;
1022  new_port1 = tcp1->dst_port;
1023 
1024  sum1 = tcp1->checksum;
1025  sum1 = ip_csum_update (sum1, old_addr1, new_addr1,
1026  ip4_header_t,
1027  dst_address /* changed member */ );
1028 
1029  sum1 = ip_csum_update (sum1, old_port1, new_port1,
1030  ip4_header_t /* cheat */ ,
1031  length /* changed member */ );
1032  tcp1->checksum = ip_csum_fold (sum1);
1033  }
1034  else
1035  {
1036  old_port1 = udp1->dst_port;
1037  udp1->dst_port = s1->in2out.port;
1038  udp1->checksum = 0;
1039  }
1040 
1041  /* Accounting */
1044  b1));
1045  /* Per-user LRU list maintenance */
1046  nat44_session_update_lru (sm, s1, thread_index);
1047  trace1:
1048 
1050  && (b1->flags & VLIB_BUFFER_IS_TRACED)))
1051  {
1052  snat_out2in_trace_t *t =
1053  vlib_add_trace (vm, node, b1, sizeof (*t));
1054  t->sw_if_index = sw_if_index1;
1055  t->next_index = next1;
1056  t->session_index = ~0;
1057  if (s1)
1058  t->session_index =
1059  s1 - sm->per_thread_data[thread_index].sessions;
1060  }
1061 
1062  pkts_processed += next1 != SNAT_OUT2IN_NEXT_DROP;
1063 
1064  /* verify speculative enqueues, maybe switch current next frame */
1065  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
1066  to_next, n_left_to_next,
1067  bi0, bi1, next0, next1);
1068  }
1069 
1070  while (n_left_from > 0 && n_left_to_next > 0)
1071  {
1072  u32 bi0;
1073  vlib_buffer_t *b0;
1074  u32 next0 = SNAT_OUT2IN_NEXT_LOOKUP;
1075  u32 sw_if_index0;
1076  ip4_header_t *ip0;
1077  ip_csum_t sum0;
1078  u32 new_addr0, old_addr0;
1079  u16 new_port0, old_port0;
1080  udp_header_t *udp0;
1081  tcp_header_t *tcp0;
1082  icmp46_header_t *icmp0;
1083  snat_session_key_t key0, sm0;
1084  u32 rx_fib_index0;
1085  u32 proto0;
1086  snat_session_t *s0 = 0;
1087  clib_bihash_kv_8_8_t kv0, value0;
1088  u8 identity_nat0;
1089 
1090  /* speculatively enqueue b0 to the current next frame */
1091  bi0 = from[0];
1092  to_next[0] = bi0;
1093  from += 1;
1094  to_next += 1;
1095  n_left_from -= 1;
1096  n_left_to_next -= 1;
1097 
1098  b0 = vlib_get_buffer (vm, bi0);
1099 
1100  vnet_buffer (b0)->snat.flags = 0;
1101 
1102  ip0 = vlib_buffer_get_current (b0);
1103  udp0 = ip4_next_header (ip0);
1104  tcp0 = (tcp_header_t *) udp0;
1105  icmp0 = (icmp46_header_t *) udp0;
1106 
1107  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1108  rx_fib_index0 = vec_elt (sm->ip4_main->fib_index_by_sw_if_index,
1109  sw_if_index0);
1110 
1111  proto0 = ip_proto_to_snat_proto (ip0->protocol);
1112 
1113  if (PREDICT_FALSE (proto0 == ~0))
1114  {
1115  if (nat_out2in_sm_unknown_proto (sm, b0, ip0, rx_fib_index0))
1116  {
1117  if (!sm->forwarding_enabled)
1118  {
1119  b0->error =
1120  node->errors[SNAT_OUT2IN_ERROR_UNSUPPORTED_PROTOCOL];
1121  next0 = SNAT_OUT2IN_NEXT_DROP;
1122  }
1123  }
1124  goto trace00;
1125  }
1126 
1127  if (PREDICT_FALSE (ip0->ttl == 1))
1128  {
1129  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1130  icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
1131  ICMP4_time_exceeded_ttl_exceeded_in_transit,
1132  0);
1134  goto trace00;
1135  }
1136 
1137  if (PREDICT_FALSE (ip4_is_fragment (ip0)))
1138  {
1139  next0 = SNAT_OUT2IN_NEXT_REASS;
1140  goto trace00;
1141  }
1142 
1143  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
1144  {
1145  next0 = icmp_out2in_slow_path
1146  (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
1147  next0, now, thread_index, &s0);
1148  goto trace00;
1149  }
1150 
1151  key0.addr = ip0->dst_address;
1152  key0.port = udp0->dst_port;
1153  key0.protocol = proto0;
1154  key0.fib_index = rx_fib_index0;
1155 
1156  kv0.key = key0.as_u64;
1157 
1158  if (clib_bihash_search_8_8
1159  (&sm->per_thread_data[thread_index].out2in, &kv0, &value0))
1160  {
1161  /* Try to match static mapping by external address and port,
1162  destination address and port in packet */
1164  (sm, key0, &sm0, 1, 0, 0, 0, 0, &identity_nat0))
1165  {
1166  /*
1167  * Send DHCP packets to the ipv4 stack, or we won't
1168  * be able to use dhcp client on the outside interface
1169  */
1170  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_UDP
1171  && (udp0->dst_port ==
1172  clib_host_to_net_u16
1173  (UDP_DST_PORT_dhcp_to_client))))
1174  {
1175  vnet_feature_next (&next0, b0);
1176  goto trace00;
1177  }
1178 
1179  if (!sm->forwarding_enabled)
1180  {
1181  b0->error =
1182  node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
1183  next0 = SNAT_OUT2IN_NEXT_DROP;
1184  }
1185  goto trace00;
1186  }
1187 
1188  if (PREDICT_FALSE (identity_nat0))
1189  goto trace00;
1190 
1191  /* Create session initiated by host from external network */
1192  s0 = create_session_for_static_mapping (sm, b0, sm0, key0, node,
1193  thread_index, now);
1194  if (!s0)
1195  {
1196  next0 = SNAT_OUT2IN_NEXT_DROP;
1197  goto trace00;
1198  }
1199  }
1200  else
1201  s0 =
1202  pool_elt_at_index (sm->per_thread_data[thread_index].sessions,
1203  value0.value);
1204 
1205  old_addr0 = ip0->dst_address.as_u32;
1206  ip0->dst_address = s0->in2out.addr;
1207  new_addr0 = ip0->dst_address.as_u32;
1208  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
1209 
1210  sum0 = ip0->checksum;
1211  sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1212  ip4_header_t,
1213  dst_address /* changed member */ );
1214  ip0->checksum = ip_csum_fold (sum0);
1215 
1216  if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP))
1217  {
1218  old_port0 = tcp0->dst_port;
1219  tcp0->dst_port = s0->in2out.port;
1220  new_port0 = tcp0->dst_port;
1221 
1222  sum0 = tcp0->checksum;
1223  sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1224  ip4_header_t,
1225  dst_address /* changed member */ );
1226 
1227  sum0 = ip_csum_update (sum0, old_port0, new_port0,
1228  ip4_header_t /* cheat */ ,
1229  length /* changed member */ );
1230  tcp0->checksum = ip_csum_fold (sum0);
1231  }
1232  else
1233  {
1234  old_port0 = udp0->dst_port;
1235  udp0->dst_port = s0->in2out.port;
1236  udp0->checksum = 0;
1237  }
1238 
1239  /* Accounting */
1242  b0));
1243  /* Per-user LRU list maintenance */
1244  nat44_session_update_lru (sm, s0, thread_index);
1245  trace00:
1246 
1248  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1249  {
1250  snat_out2in_trace_t *t =
1251  vlib_add_trace (vm, node, b0, sizeof (*t));
1252  t->sw_if_index = sw_if_index0;
1253  t->next_index = next0;
1254  t->session_index = ~0;
1255  if (s0)
1256  t->session_index =
1257  s0 - sm->per_thread_data[thread_index].sessions;
1258  }
1259 
1260  pkts_processed += next0 != SNAT_OUT2IN_NEXT_DROP;
1261 
1262  /* verify speculative enqueue, maybe switch current next frame */
1263  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1264  to_next, n_left_to_next,
1265  bi0, next0);
1266  }
1267 
1268  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1269  }
1270 
1272  SNAT_OUT2IN_ERROR_OUT2IN_PACKETS,
1273  pkts_processed);
1274  return frame->n_vectors;
1275 }
1276 
1277 /* *INDENT-OFF* */
1279  .function = snat_out2in_node_fn,
1280  .name = "nat44-out2in",
1281  .vector_size = sizeof (u32),
1282  .format_trace = format_snat_out2in_trace,
1283  .type = VLIB_NODE_TYPE_INTERNAL,
1284 
1285  .n_errors = ARRAY_LEN(snat_out2in_error_strings),
1286  .error_strings = snat_out2in_error_strings,
1287 
1288  .runtime_data_bytes = sizeof (snat_runtime_t),
1289 
1290  .n_next_nodes = SNAT_OUT2IN_N_NEXT,
1291 
1292  /* edit / add dispositions here */
1293  .next_nodes = {
1294  [SNAT_OUT2IN_NEXT_DROP] = "error-drop",
1295  [SNAT_OUT2IN_NEXT_LOOKUP] = "ip4-lookup",
1296  [SNAT_OUT2IN_NEXT_ICMP_ERROR] = "ip4-icmp-error",
1297  [SNAT_OUT2IN_NEXT_REASS] = "nat44-out2in-reass",
1298  },
1299 };
1300 /* *INDENT-ON* */
1301 
1303 
1304 static uword
1306  vlib_node_runtime_t * node, vlib_frame_t * frame)
1307 {
1308  u32 n_left_from, *from, *to_next;
1309  snat_out2in_next_t next_index;
1310  u32 pkts_processed = 0;
1311  snat_main_t *sm = &snat_main;
1312  f64 now = vlib_time_now (vm);
1313  u32 thread_index = vm->thread_index;
1314  snat_main_per_thread_data_t *per_thread_data =
1315  &sm->per_thread_data[thread_index];
1316  u32 *fragments_to_drop = 0;
1317  u32 *fragments_to_loopback = 0;
1318 
1319  from = vlib_frame_vector_args (frame);
1320  n_left_from = frame->n_vectors;
1321  next_index = node->cached_next_index;
1322 
1323  while (n_left_from > 0)
1324  {
1325  u32 n_left_to_next;
1326 
1327  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1328 
1329  while (n_left_from > 0 && n_left_to_next > 0)
1330  {
1331  u32 bi0, sw_if_index0, proto0, rx_fib_index0, new_addr0, old_addr0;
1332  vlib_buffer_t *b0;
1333  u32 next0;
1334  u8 cached0 = 0;
1335  ip4_header_t *ip0;
1336  nat_reass_ip4_t *reass0;
1337  udp_header_t *udp0;
1338  tcp_header_t *tcp0;
1339  icmp46_header_t *icmp0;
1340  snat_session_key_t key0, sm0;
1341  clib_bihash_kv_8_8_t kv0, value0;
1342  snat_session_t *s0 = 0;
1343  u16 old_port0, new_port0;
1344  ip_csum_t sum0;
1345  u8 identity_nat0;
1346 
1347  /* speculatively enqueue b0 to the current next frame */
1348  bi0 = from[0];
1349  to_next[0] = bi0;
1350  from += 1;
1351  to_next += 1;
1352  n_left_from -= 1;
1353  n_left_to_next -= 1;
1354 
1355  b0 = vlib_get_buffer (vm, bi0);
1356  next0 = SNAT_OUT2IN_NEXT_LOOKUP;
1357 
1358  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1359  rx_fib_index0 =
1361  sw_if_index0);
1362 
1364  {
1365  next0 = SNAT_OUT2IN_NEXT_DROP;
1366  b0->error = node->errors[SNAT_OUT2IN_ERROR_DROP_FRAGMENT];
1367  goto trace0;
1368  }
1369 
1370  ip0 = (ip4_header_t *) vlib_buffer_get_current (b0);
1371  udp0 = ip4_next_header (ip0);
1372  tcp0 = (tcp_header_t *) udp0;
1373  icmp0 = (icmp46_header_t *) udp0;
1374  proto0 = ip_proto_to_snat_proto (ip0->protocol);
1375 
1377  ip0->dst_address,
1378  ip0->fragment_id,
1379  ip0->protocol,
1380  1, &fragments_to_drop);
1381 
1382  if (PREDICT_FALSE (!reass0))
1383  {
1384  next0 = SNAT_OUT2IN_NEXT_DROP;
1385  b0->error = node->errors[SNAT_OUT2IN_ERROR_MAX_REASS];
1386  nat_log_notice ("maximum reassemblies exceeded");
1387  goto trace0;
1388  }
1389 
1391  {
1392  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
1393  {
1394  next0 = icmp_out2in_slow_path
1395  (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
1396  next0, now, thread_index, &s0);
1397 
1398  if (PREDICT_TRUE (next0 != SNAT_OUT2IN_NEXT_DROP))
1399  {
1400  if (s0)
1401  reass0->sess_index = s0 - per_thread_data->sessions;
1402  else
1403  reass0->flags |= NAT_REASS_FLAG_ED_DONT_TRANSLATE;
1404  reass0->thread_index = thread_index;
1405  nat_ip4_reass_get_frags (reass0,
1406  &fragments_to_loopback);
1407  }
1408 
1409  goto trace0;
1410  }
1411 
1412  key0.addr = ip0->dst_address;
1413  key0.port = udp0->dst_port;
1414  key0.protocol = proto0;
1415  key0.fib_index = rx_fib_index0;
1416  kv0.key = key0.as_u64;
1417 
1418  if (clib_bihash_search_8_8
1419  (&per_thread_data->out2in, &kv0, &value0))
1420  {
1421  /* Try to match static mapping by external address and port,
1422  destination address and port in packet */
1424  (sm, key0, &sm0, 1, 0, 0, 0, 0, &identity_nat0))
1425  {
1426  /*
1427  * Send DHCP packets to the ipv4 stack, or we won't
1428  * be able to use dhcp client on the outside interface
1429  */
1430  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_UDP
1431  && (udp0->dst_port
1432  ==
1433  clib_host_to_net_u16
1434  (UDP_DST_PORT_dhcp_to_client))))
1435  {
1436  vnet_feature_next (&next0, b0);
1437  goto trace0;
1438  }
1439 
1440  if (!sm->forwarding_enabled)
1441  {
1442  b0->error =
1443  node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
1444  next0 = SNAT_OUT2IN_NEXT_DROP;
1445  }
1446  else
1447  {
1448  reass0->flags |= NAT_REASS_FLAG_ED_DONT_TRANSLATE;
1449  nat_ip4_reass_get_frags (reass0,
1450  &fragments_to_loopback);
1451  }
1452  goto trace0;
1453  }
1454 
1455  if (PREDICT_FALSE (identity_nat0))
1456  goto trace0;
1457 
1458  /* Create session initiated by host from external network */
1459  s0 =
1460  create_session_for_static_mapping (sm, b0, sm0, key0,
1461  node, thread_index,
1462  now);
1463  if (!s0)
1464  {
1465  b0->error =
1466  node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
1467  next0 = SNAT_OUT2IN_NEXT_DROP;
1468  goto trace0;
1469  }
1470  reass0->sess_index = s0 - per_thread_data->sessions;
1471  reass0->thread_index = thread_index;
1472  }
1473  else
1474  {
1475  s0 = pool_elt_at_index (per_thread_data->sessions,
1476  value0.value);
1477  reass0->sess_index = value0.value;
1478  }
1479  nat_ip4_reass_get_frags (reass0, &fragments_to_loopback);
1480  }
1481  else
1482  {
1483  if (reass0->flags & NAT_REASS_FLAG_ED_DONT_TRANSLATE)
1484  goto trace0;
1485  if (PREDICT_FALSE (reass0->sess_index == (u32) ~ 0))
1486  {
1488  (reass0, bi0, &fragments_to_drop))
1489  {
1490  b0->error = node->errors[SNAT_OUT2IN_ERROR_MAX_FRAG];
1492  ("maximum fragments per reassembly exceeded");
1493  next0 = SNAT_OUT2IN_NEXT_DROP;
1494  goto trace0;
1495  }
1496  cached0 = 1;
1497  goto trace0;
1498  }
1499  s0 = pool_elt_at_index (per_thread_data->sessions,
1500  reass0->sess_index);
1501  }
1502 
1503  old_addr0 = ip0->dst_address.as_u32;
1504  ip0->dst_address = s0->in2out.addr;
1505  new_addr0 = ip0->dst_address.as_u32;
1506  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
1507 
1508  sum0 = ip0->checksum;
1509  sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1510  ip4_header_t,
1511  dst_address /* changed member */ );
1512  ip0->checksum = ip_csum_fold (sum0);
1513 
1515  {
1516  if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP))
1517  {
1518  old_port0 = tcp0->dst_port;
1519  tcp0->dst_port = s0->in2out.port;
1520  new_port0 = tcp0->dst_port;
1521 
1522  sum0 = tcp0->checksum;
1523  sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1524  ip4_header_t,
1525  dst_address /* changed member */ );
1526 
1527  sum0 = ip_csum_update (sum0, old_port0, new_port0,
1528  ip4_header_t /* cheat */ ,
1529  length /* changed member */ );
1530  tcp0->checksum = ip_csum_fold (sum0);
1531  }
1532  else
1533  {
1534  old_port0 = udp0->dst_port;
1535  udp0->dst_port = s0->in2out.port;
1536  udp0->checksum = 0;
1537  }
1538  }
1539 
1540  /* Accounting */
1543  b0));
1544  /* Per-user LRU list maintenance */
1545  nat44_session_update_lru (sm, s0, thread_index);
1546 
1547  trace0:
1549  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1550  {
1551  nat44_reass_trace_t *t =
1552  vlib_add_trace (vm, node, b0, sizeof (*t));
1553  t->cached = cached0;
1554  t->sw_if_index = sw_if_index0;
1555  t->next_index = next0;
1556  }
1557 
1558  if (cached0)
1559  {
1560  n_left_to_next++;
1561  to_next--;
1562  }
1563  else
1564  {
1565  pkts_processed += next0 != SNAT_OUT2IN_NEXT_DROP;
1566 
1567  /* verify speculative enqueue, maybe switch current next frame */
1568  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1569  to_next, n_left_to_next,
1570  bi0, next0);
1571  }
1572 
1573  if (n_left_from == 0 && vec_len (fragments_to_loopback))
1574  {
1575  from = vlib_frame_vector_args (frame);
1576  u32 len = vec_len (fragments_to_loopback);
1577  if (len <= VLIB_FRAME_SIZE)
1578  {
1579  clib_memcpy (from, fragments_to_loopback,
1580  sizeof (u32) * len);
1581  n_left_from = len;
1582  vec_reset_length (fragments_to_loopback);
1583  }
1584  else
1585  {
1586  clib_memcpy (from,
1587  fragments_to_loopback + (len -
1588  VLIB_FRAME_SIZE),
1589  sizeof (u32) * VLIB_FRAME_SIZE);
1590  n_left_from = VLIB_FRAME_SIZE;
1591  _vec_len (fragments_to_loopback) = len - VLIB_FRAME_SIZE;
1592  }
1593  }
1594  }
1595 
1596  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1597  }
1598 
1600  SNAT_OUT2IN_ERROR_OUT2IN_PACKETS,
1601  pkts_processed);
1602 
1603  nat_send_all_to_node (vm, fragments_to_drop, node,
1604  &node->errors[SNAT_OUT2IN_ERROR_DROP_FRAGMENT],
1606 
1607  vec_free (fragments_to_drop);
1608  vec_free (fragments_to_loopback);
1609  return frame->n_vectors;
1610 }
1611 
1612 /* *INDENT-OFF* */
1614  .function = nat44_out2in_reass_node_fn,
1615  .name = "nat44-out2in-reass",
1616  .vector_size = sizeof (u32),
1617  .format_trace = format_nat44_reass_trace,
1618  .type = VLIB_NODE_TYPE_INTERNAL,
1619 
1620  .n_errors = ARRAY_LEN(snat_out2in_error_strings),
1621  .error_strings = snat_out2in_error_strings,
1622 
1623  .n_next_nodes = SNAT_OUT2IN_N_NEXT,
1624 
1625  /* edit / add dispositions here */
1626  .next_nodes = {
1627  [SNAT_OUT2IN_NEXT_DROP] = "error-drop",
1628  [SNAT_OUT2IN_NEXT_LOOKUP] = "ip4-lookup",
1629  [SNAT_OUT2IN_NEXT_ICMP_ERROR] = "ip4-icmp-error",
1630  [SNAT_OUT2IN_NEXT_REASS] = "nat44-out2in-reass",
1631  },
1632 };
1633 /* *INDENT-ON* */
1634 
1637 
1638 static uword
1640  vlib_node_runtime_t * node, vlib_frame_t * frame)
1641 {
1642  u32 n_left_from, *from, *to_next;
1643  snat_out2in_next_t next_index;
1644  u32 pkts_processed = 0;
1645  snat_main_t *sm = &snat_main;
1646 
1647  from = vlib_frame_vector_args (frame);
1648  n_left_from = frame->n_vectors;
1649  next_index = node->cached_next_index;
1650 
1651  while (n_left_from > 0)
1652  {
1653  u32 n_left_to_next;
1654 
1655  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1656 
1657  while (n_left_from > 0 && n_left_to_next > 0)
1658  {
1659  u32 bi0;
1660  vlib_buffer_t *b0;
1661  u32 next0 = SNAT_OUT2IN_NEXT_DROP;
1662  u32 sw_if_index0;
1663  ip4_header_t *ip0;
1664  ip_csum_t sum0;
1665  u32 new_addr0, old_addr0;
1666  u16 new_port0, old_port0;
1667  udp_header_t *udp0;
1668  tcp_header_t *tcp0;
1669  icmp46_header_t *icmp0;
1670  snat_session_key_t key0, sm0;
1671  u32 proto0;
1672  u32 rx_fib_index0;
1673 
1674  /* speculatively enqueue b0 to the current next frame */
1675  bi0 = from[0];
1676  to_next[0] = bi0;
1677  from += 1;
1678  to_next += 1;
1679  n_left_from -= 1;
1680  n_left_to_next -= 1;
1681 
1682  b0 = vlib_get_buffer (vm, bi0);
1683 
1684  ip0 = vlib_buffer_get_current (b0);
1685  udp0 = ip4_next_header (ip0);
1686  tcp0 = (tcp_header_t *) udp0;
1687  icmp0 = (icmp46_header_t *) udp0;
1688 
1689  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1690  rx_fib_index0 =
1692 
1693  vnet_feature_next (&next0, b0);
1694 
1695  if (PREDICT_FALSE (ip0->ttl == 1))
1696  {
1697  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1698  icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
1699  ICMP4_time_exceeded_ttl_exceeded_in_transit,
1700  0);
1702  goto trace00;
1703  }
1704 
1705  proto0 = ip_proto_to_snat_proto (ip0->protocol);
1706 
1707  if (PREDICT_FALSE (proto0 == ~0))
1708  goto trace00;
1709 
1710  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
1711  {
1712  next0 = icmp_out2in (sm, b0, ip0, icmp0, sw_if_index0,
1713  rx_fib_index0, node, next0, ~0, 0, 0);
1714  goto trace00;
1715  }
1716 
1717  key0.addr = ip0->dst_address;
1718  key0.port = udp0->dst_port;
1719  key0.fib_index = rx_fib_index0;
1720 
1721  if (snat_static_mapping_match (sm, key0, &sm0, 1, 0, 0, 0, 0, 0))
1722  {
1723  b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
1724  goto trace00;
1725  }
1726 
1727  new_addr0 = sm0.addr.as_u32;
1728  new_port0 = sm0.port;
1729  vnet_buffer (b0)->sw_if_index[VLIB_TX] = sm0.fib_index;
1730  old_addr0 = ip0->dst_address.as_u32;
1731  ip0->dst_address.as_u32 = new_addr0;
1732 
1733  sum0 = ip0->checksum;
1734  sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1735  ip4_header_t,
1736  dst_address /* changed member */ );
1737  ip0->checksum = ip_csum_fold (sum0);
1738 
1739  if (PREDICT_FALSE (new_port0 != udp0->dst_port))
1740  {
1741  if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP))
1742  {
1743  old_port0 = tcp0->dst_port;
1744  tcp0->dst_port = new_port0;
1745 
1746  sum0 = tcp0->checksum;
1747  sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1748  ip4_header_t,
1749  dst_address /* changed member */ );
1750 
1751  sum0 = ip_csum_update (sum0, old_port0, new_port0,
1752  ip4_header_t /* cheat */ ,
1753  length /* changed member */ );
1754  tcp0->checksum = ip_csum_fold (sum0);
1755  }
1756  else
1757  {
1758  old_port0 = udp0->dst_port;
1759  udp0->dst_port = new_port0;
1760  udp0->checksum = 0;
1761  }
1762  }
1763  else
1764  {
1765  if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP))
1766  {
1767  sum0 = tcp0->checksum;
1768  sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1769  ip4_header_t,
1770  dst_address /* changed member */ );
1771 
1772  tcp0->checksum = ip_csum_fold (sum0);
1773  }
1774  }
1775 
1776  trace00:
1777 
1779  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1780  {
1781  snat_out2in_trace_t *t =
1782  vlib_add_trace (vm, node, b0, sizeof (*t));
1783  t->sw_if_index = sw_if_index0;
1784  t->next_index = next0;
1785  }
1786 
1787  pkts_processed += next0 != SNAT_OUT2IN_NEXT_DROP;
1788 
1789  /* verify speculative enqueue, maybe switch current next frame */
1790  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1791  to_next, n_left_to_next,
1792  bi0, next0);
1793  }
1794 
1795  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1796  }
1797 
1799  SNAT_OUT2IN_ERROR_OUT2IN_PACKETS,
1800  pkts_processed);
1801  return frame->n_vectors;
1802 }
1803 
1804 /* *INDENT-OFF* */
1806  .function = snat_out2in_fast_node_fn,
1807  .name = "nat44-out2in-fast",
1808  .vector_size = sizeof (u32),
1809  .format_trace = format_snat_out2in_fast_trace,
1810  .type = VLIB_NODE_TYPE_INTERNAL,
1811 
1812  .n_errors = ARRAY_LEN(snat_out2in_error_strings),
1813  .error_strings = snat_out2in_error_strings,
1814 
1815  .runtime_data_bytes = sizeof (snat_runtime_t),
1816 
1817  .n_next_nodes = SNAT_OUT2IN_N_NEXT,
1818 
1819  /* edit / add dispositions here */
1820  .next_nodes = {
1821  [SNAT_OUT2IN_NEXT_LOOKUP] = "ip4-lookup",
1822  [SNAT_OUT2IN_NEXT_DROP] = "error-drop",
1823  [SNAT_OUT2IN_NEXT_ICMP_ERROR] = "ip4-icmp-error",
1824  [SNAT_OUT2IN_NEXT_REASS] = "nat44-out2in-reass",
1825  },
1826 };
1827 /* *INDENT-ON* */
1828 
1831 
1832 /*
1833  * fd.io coding-style-patch-verification: ON
1834  *
1835  * Local Variables:
1836  * eval: (c-set-style "gnu")
1837  * End:
1838  */
vlib_node_registration_t snat_out2in_fast_node
(constructor) VLIB_REGISTER_NODE (snat_out2in_fast_node)
Definition: out2in.c:72
static ip_csum_t ip_incremental_checksum_buffer(vlib_main_t *vm, vlib_buffer_t *first_buffer, u32 first_buffer_offset, u32 n_bytes_to_checksum, ip_csum_t sum)
Definition: ip.h:154
VLIB_NODE_FUNCTION_MULTIARCH(snat_out2in_node, snat_out2in_node_fn)
#define snat_is_session_static(s)
Check if SNAT session is created from static mapping.
Definition: nat.h:598
#define CLIB_UNUSED(x)
Definition: clib.h:81
u32 icmp_match_out2in_slow(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation and create session if needed...
Definition: out2in.c:295
ip4_address_t src_address
Definition: ip4_packet.h:169
static u8 * format_snat_out2in_fast_trace(u8 *s, va_list *args)
Definition: out2in.c:60
static u32 nat44_session_get_timeout(snat_main_t *sm, snat_session_t *s)
Definition: nat_inlines.h:269
static u32 icmp_out2in_slow_path(snat_main_t *sm, vlib_buffer_t *b0, ip4_header_t *ip0, icmp46_header_t *icmp0, u32 sw_if_index0, u32 rx_fib_index0, vlib_node_runtime_t *node, u32 next0, f64 now, u32 thread_index, snat_session_t **p_s0)
Definition: out2in.c:615
#define PREDICT_TRUE(x)
Definition: clib.h:108
static_always_inline u8 icmp_is_error_message(icmp46_header_t *icmp)
Definition: nat_inlines.h:53
unsigned long u64
Definition: types.h:89
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:227
u32 fib_table_get_index_for_sw_if_index(fib_protocol_t proto, u32 sw_if_index)
Get the index of the FIB bound to the interface.
Definition: fib_table.c:956
u32 thread_index
Definition: main.h:179
#define nat_log_warn(...)
Definition: nat.h:687
uword ip_csum_t
Definition: ip_packet.h:181
u32 * fib_index_by_sw_if_index
Table index indexed by software interface.
Definition: ip4.h:112
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:472
int nat44_o2i_is_idle_session_cb(clib_bihash_kv_8_8_t *kv, void *arg)
Definition: out2in.c:110
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:263
struct _tcp_header tcp_header_t
unsigned char u8
Definition: types.h:56
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
double f64
Definition: types.h:142
static int ip4_is_fragment(const ip4_header_t *i)
Definition: ip4_packet.h:212
u16 src_port
Definition: udp.api:41
clib_bihash_8_8_t in2out
Definition: nat.h:380
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
Definition: ip4_fib.c:224
#define static_always_inline
Definition: clib.h:95
static uword ip4_header_checksum_is_valid(ip4_header_t *i)
Definition: ip4_packet.h:267
ip4_address_t dst_address
Definition: ip4_packet.h:169
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:187
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
ip4_main_t * ip4_main
Definition: nat.h:541
#define NAT_REASS_FLAG_ED_DONT_TRANSLATE
Definition: nat_reass.h:35
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:240
unsigned int u32
Definition: types.h:88
#define foreach_snat_out2in_error
Definition: out2in.c:75
ip4_address_t local_addr
Definition: nat.h:325
#define VLIB_FRAME_SIZE
Definition: node.h:382
static uword nat44_out2in_reass_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: out2in.c:1305
static u8 maximum_sessions_exceeded(snat_main_t *sm, u32 thread_index)
Definition: nat_inlines.h:94
int snat_static_mapping_match(snat_main_t *sm, snat_session_key_t match, snat_session_key_t *mapping, u8 by_external, u8 *is_addr_only, twice_nat_type_t *twice_nat, lb_nat_type_t *lb, ip4_address_t *ext_host_addr, u8 *is_identity_nat)
Match NAT44 static mapping.
Definition: nat.c:2070
void snat_free_outside_address_and_port(snat_address_t *addresses, u32 thread_index, snat_session_key_t *k)
Free outside address and port pair.
Definition: nat.c:2032
static void nat44_delete_session(snat_main_t *sm, snat_session_t *ses, u32 thread_index)
Definition: nat_inlines.h:166
snat_out2in_next_t
Definition: out2in.c:100
snat_user_t * nat_user_get_or_create(snat_main_t *sm, ip4_address_t *addr, u32 fib_index, u32 thread_index)
Find or create NAT user.
Definition: nat.c:278
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:464
u64 key
the key
Definition: bihash_8_8.h:33
long ctx[MAX_CONNS]
Definition: main.c:144
vlib_main_t * vlib_main
Definition: nat.h:539
unsigned short u16
Definition: types.h:57
u16 protocol
Definition: nat.h:54
snat_static_mapping_t * static_mappings
Definition: nat.h:452
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:205
void snat_ipfix_logging_nat44_ses_delete(u32 src_ip, u32 nat_src_ip, snat_protocol_t snat_proto, u16 src_port, u16 nat_src_port, u32 vrf_id)
Generate NAT44 session delete event.
#define PREDICT_FALSE(x)
Definition: clib.h:107
void snat_ipfix_logging_nat44_ses_create(u32 src_ip, u32 nat_src_ip, snat_protocol_t snat_proto, u16 src_port, u16 nat_src_port, u32 vrf_id)
Generate NAT44 session create event.
clib_bihash_8_8_t static_mapping_by_external
Definition: nat.h:449
vl_api_address_union_t src_address
Definition: ip_types.api:49
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Finish enqueueing two buffers forward in the graph.
Definition: buffer_node.h:70
vlib_node_registration_t snat_out2in_node
(constructor) VLIB_REGISTER_NODE (snat_out2in_node)
Definition: out2in.c:71
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:218
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:364
#define nat_log_notice(...)
Definition: nat.h:689
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:138
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1176
snat_main_t snat_main
Definition: nat.c:37
The fine-grained event logger allows lightweight, thread-safe event logging at minimum cost...
u64 value
the value
Definition: bihash_8_8.h:34
static void nat44_delete_user_with_no_session(snat_main_t *sm, snat_user_t *u, u32 thread_index)
Definition: nat_inlines.h:146
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:155
u16 n_vectors
Definition: node.h:401
clib_bihash_8_8_t out2in
Definition: nat.h:379
u8 nat_reass_is_drop_frag(u8 is_ip6)
Get status of virtual fragmentation reassembly.
Definition: nat_reass.c:168
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:79
vlib_main_t * vm
Definition: buffer.c:294
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:339
static_always_inline void vnet_feature_next(u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:246
void icmp4_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
Definition: icmp4.c:431
#define clib_memcpy(a, b, c)
Definition: string.h:75
static void nat44_session_update_counters(snat_session_t *s, f64 now, uword bytes)
Definition: nat_inlines.h:292
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:31
#define ARRAY_LEN(x)
Definition: clib.h:61
ip4_address_t addr
Definition: nat.h:52
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:455
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:513
#define ASSERT(truth)
snat_icmp_match_function_t * icmp_match_out2in_cb
Definition: nat.h:431
static void nat44_session_update_lru(snat_main_t *sm, snat_session_t *s, u32 thread_index)
Per-user LRU list maintenance.
Definition: nat_inlines.h:301
vlib_node_registration_t nat44_out2in_reass_node
(constructor) VLIB_REGISTER_NODE (nat44_out2in_reass_node)
Definition: out2in.c:73
snat_session_t * nat_session_alloc_or_recycle(snat_main_t *sm, snat_user_t *u, u32 thread_index)
Allocate new NAT session or recycle last used.
Definition: nat.c:322
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:57
#define vec_elt(v, i)
Get vector value at index i.
struct _vlib_node_registration vlib_node_registration_t
Definition: defs.h:47
format_function_t format_nat44_reass_trace
Definition: nat.h:590
static int ip4_is_first_fragment(const ip4_header_t *i)
Definition: ip4_packet.h:219
snat_out2in_error_t
Definition: out2in.c:86
static u32 ip_proto_to_snat_proto(u8 ip_proto)
The NAT inline functions.
Definition: nat_inlines.h:26
static void user_session_increment(snat_main_t *sm, snat_user_t *u, u8 is_static)
Definition: nat_inlines.h:134
static snat_session_t * create_session_for_static_mapping(snat_main_t *sm, vlib_buffer_t *b0, snat_session_key_t in2out, snat_session_key_t out2in, vlib_node_runtime_t *node, u32 thread_index, f64 now)
Create session for static mapping.
Definition: out2in.c:161
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static char * snat_out2in_error_strings[]
Definition: out2in.c:94
static int nat_out2in_sm_unknown_proto(snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, u32 rx_fib_index)
Definition: out2in.c:641
u64 uword
Definition: types.h:112
snat_main_per_thread_data_t * per_thread_data
Definition: nat.h:443
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:267
#define ip_csum_update(sum, old, new, type, field)
Definition: ip_packet.h:231
static u8 is_interface_addr(snat_main_t *sm, vlib_node_runtime_t *node, u32 sw_if_index0, u32 ip4_addr)
Definition: nat_inlines.h:69
static_always_inline snat_out2in_error_t icmp_get_key(ip4_header_t *ip0, snat_session_key_t *p_key0)
Definition: out2in.c:236
static u8 * format_snat_out2in_trace(u8 *s, va_list *args)
Definition: out2in.c:46
nat_reass_ip4_t * nat_ip4_reass_find_or_create(ip4_address_t src, ip4_address_t dst, u16 frag_id, u8 proto, u8 reset_timeout, u32 **bi_to_drop)
Find or create reassembly.
Definition: nat_reass.c:220
snat_address_t * addresses
Definition: nat.h:459
static uword snat_out2in_fast_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: out2in.c:1639
#define vnet_buffer(b)
Definition: buffer.h:344
#define SNAT_SESSION_FLAG_STATIC_MAPPING
Definition: nat.h:171
static uword snat_out2in_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: out2in.c:672
int nat_ip4_reass_add_fragment(nat_reass_ip4_t *reass, u32 bi, u32 **bi_to_drop)
Cache fragment.
Definition: nat_reass.c:338
u8 data[0]
Packet data.
Definition: buffer.h:175
u8 forwarding_enabled
Definition: nat.h:503
u16 flags
Copy of main node flags.
Definition: node.h:507
static void nat_send_all_to_node(vlib_main_t *vm, u32 *bi_vector, vlib_node_runtime_t *node, vlib_error_t *error, u32 next)
Definition: nat_inlines.h:104
static int ip4_header_bytes(const ip4_header_t *i)
Definition: ip4_packet.h:234
void nat_ip4_reass_get_frags(nat_reass_ip4_t *reass, u32 **bi)
Get cached fragments.
Definition: nat_reass.c:370
NAT plugin virtual fragmentation reassembly.
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:310
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:116
u32 icmp_out2in(snat_main_t *sm, vlib_buffer_t *b0, ip4_header_t *ip0, icmp46_header_t *icmp0, u32 sw_if_index0, u32 rx_fib_index0, vlib_node_runtime_t *node, u32 next0, u32 thread_index, void *d, void *e)
Definition: out2in.c:484
int nat44_i2o_is_idle_session_cb(clib_bihash_kv_8_8_t *kv, void *arg)
Definition: in2out.c:194
snat_session_t * sessions
Definition: nat.h:393
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:58
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:237
u32 icmp_match_out2in_fast(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation.
Definition: out2in.c:423
Definition: defs.h:46
u16 fib_index
Definition: nat.h:54