FD.io VPP  v20.01-48-g3e0dafb74
Vector Packet Processing
in2out_ed.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 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 inside to outside network translation
18  */
19 
20 #include <vlib/vlib.h>
21 #include <vnet/vnet.h>
22 #include <vnet/pg/pg.h>
23 #include <vnet/ip/ip.h>
24 #include <vnet/ethernet/ethernet.h>
25 #include <vnet/fib/ip4_fib.h>
26 #include <vnet/udp/udp.h>
27 #include <vppinfra/error.h>
28 #include <nat/nat.h>
29 #include <nat/nat_ipfix_logging.h>
30 #include <nat/nat_inlines.h>
31 #include <nat/nat44_inlines.h>
32 #include <nat/nat_syslog.h>
33 #include <nat/nat_ha.h>
34 
35 static char *nat_in2out_ed_error_strings[] = {
36 #define _(sym,string) string,
38 #undef _
39 };
40 
41 typedef struct
42 {
48 
49 static u8 *
50 format_nat_in2out_ed_trace (u8 * s, va_list * args)
51 {
52  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
53  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
54  nat_in2out_ed_trace_t *t = va_arg (*args, nat_in2out_ed_trace_t *);
55  char *tag;
56 
57  tag =
58  t->is_slow_path ? "NAT44_IN2OUT_ED_SLOW_PATH" :
59  "NAT44_IN2OUT_ED_FAST_PATH";
60 
61  s = format (s, "%s: sw_if_index %d, next index %d, session %d", tag,
63 
64  return s;
65 }
66 
67 #ifndef CLIB_MARCH_VARIANT
68 int
70 {
71  snat_main_t *sm = &snat_main;
73  snat_session_t *s;
74  u64 sess_timeout_time;
75  nat_ed_ses_key_t ed_key;
77  int i;
81  ctx->thread_index);
82 
83  s = pool_elt_at_index (tsm->sessions, kv->value);
84  sess_timeout_time = s->last_heard + (f64) nat44_session_get_timeout (sm, s);
85  if (ctx->now >= sess_timeout_time)
86  {
87  if (is_fwd_bypass_session (s))
88  goto delete;
89 
90  ed_key.l_addr = s->out2in.addr;
91  ed_key.r_addr = s->ext_host_addr;
92  ed_key.fib_index = s->out2in.fib_index;
94  {
95  ed_key.proto = s->in2out.port;
96  ed_key.r_port = 0;
97  ed_key.l_port = 0;
98  }
99  else
100  {
101  ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol);
102  ed_key.l_port = s->out2in.port;
103  ed_key.r_port = s->ext_host_port;
104  }
105  ed_kv.key[0] = ed_key.as_u64[0];
106  ed_kv.key[1] = ed_key.as_u64[1];
107  if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &ed_kv, 0))
108  nat_elog_warn ("out2in_ed key del failed");
109 
111  goto delete;
112 
114  s->in2out.addr.as_u32,
115  s->out2in.addr.as_u32,
116  s->in2out.protocol,
117  s->in2out.port,
118  s->out2in.port,
119  s->in2out.fib_index);
120 
121  nat_syslog_nat44_sdel (s->user_index, s->in2out.fib_index,
122  &s->in2out.addr, s->in2out.port,
123  &s->ext_host_nat_addr, s->ext_host_nat_port,
124  &s->out2in.addr, s->out2in.port,
125  &s->ext_host_addr, s->ext_host_port,
126  s->in2out.protocol, is_twice_nat_session (s));
127 
128  nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
129  s->ext_host_port, s->out2in.protocol, s->out2in.fib_index,
130  ctx->thread_index);
131 
132  if (is_twice_nat_session (s))
133  {
134  for (i = 0; i < vec_len (sm->twice_nat_addresses); i++)
135  {
136  key.protocol = s->in2out.protocol;
137  key.port = s->ext_host_nat_port;
138  a = sm->twice_nat_addresses + i;
139  if (a->addr.as_u32 == s->ext_host_nat_addr.as_u32)
140  {
142  ctx->thread_index,
143  &key);
144  break;
145  }
146  }
147  }
148 
149  if (snat_is_session_static (s))
150  goto delete;
151 
153  &s->out2in);
154  delete:
155  nat44_delete_session (sm, s, ctx->thread_index);
156  return 1;
157  }
158 
159  return 0;
160 }
161 #endif
162 
163 static inline u32
165  ip4_header_t * ip0, icmp46_header_t * icmp0,
166  u32 sw_if_index0, u32 rx_fib_index0,
167  vlib_node_runtime_t * node, u32 next0, f64 now,
168  u32 thread_index, snat_session_t ** p_s0)
169 {
170  next0 = icmp_in2out (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
171  next0, thread_index, p_s0, 0);
172  snat_session_t *s0 = *p_s0;
173  if (PREDICT_TRUE (next0 != NAT_NEXT_DROP && s0))
174  {
175  /* Accounting */
178  (sm->vlib_main, b0), thread_index);
179  /* Per-user LRU list maintenance */
180  nat44_session_update_lru (sm, s0, thread_index);
181  }
182  return next0;
183 }
184 
185 static u32
187  vlib_buffer_t * b,
188  u32 rx_fib_index,
190  snat_session_t ** sessionp,
191  vlib_node_runtime_t * node, u32 next, u32 thread_index, f64 now)
192 {
193  snat_session_t *s = 0;
194  snat_user_t *u;
195  snat_session_key_t key0, key1;
196  lb_nat_type_t lb = 0, is_sm = 0;
197  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
200  nat_outside_fib_t *outside_fib;
202  u8 identity_nat;
203  fib_prefix_t pfx = {
205  .fp_len = 32,
206  .fp_addr = {
207  .ip4.as_u32 = key->r_addr.as_u32,
208  },
209  };
211 
212  nat44_session_try_cleanup (&key->l_addr, rx_fib_index, thread_index, now);
213 
214  if (PREDICT_FALSE (maximum_sessions_exceeded (sm, thread_index)))
215  {
216  b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
218  nat_elog_notice ("maximum sessions exceeded");
219  return NAT_NEXT_DROP;
220  }
221 
222  key0.addr = key->l_addr;
223  key0.port = key->l_port;
224  key1.protocol = key0.protocol = proto;
225  key0.fib_index = rx_fib_index;
226  key1.fib_index = sm->outside_fib_index;
227  /* First try to match static mapping by local address and port */
229  (sm, key0, &key1, 0, 0, 0, &lb, 0, &identity_nat))
230  {
231  /* Try to create dynamic translation */
232  if (snat_alloc_outside_address_and_port (sm->addresses, rx_fib_index,
233  thread_index, &key1,
234  sm->port_per_thread,
235  tsm->snat_thread_index))
236  {
237  nat_elog_notice ("addresses exhausted");
238  b->error = node->errors[NAT_IN2OUT_ED_ERROR_OUT_OF_PORTS];
239  return NAT_NEXT_DROP;
240  }
241  }
242  else
243  {
244  if (PREDICT_FALSE (identity_nat))
245  {
246  *sessionp = s;
247  return next;
248  }
249 
250  is_sm = 1;
251  }
252 
253  if (proto == SNAT_PROTOCOL_TCP)
254  {
255  if (!tcp_flags_is_init
256  (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags))
257  {
258  b->error = node->errors[NAT_IN2OUT_ED_ERROR_NON_SYN];
259  return NAT_NEXT_DROP;
260  }
261  }
262 
263  u = nat_user_get_or_create (sm, &key->l_addr, rx_fib_index, thread_index);
264  if (!u)
265  {
266  nat_elog_warn ("create NAT user failed");
267  if (!is_sm)
269  thread_index, &key1);
270  return NAT_NEXT_DROP;
271  }
272 
273  s = nat_ed_session_alloc (sm, u, thread_index, now);
274  if (!s)
275  {
276  nat44_delete_user_with_no_session (sm, u, thread_index);
277  nat_elog_warn ("create NAT session failed");
278  if (!is_sm)
280  thread_index, &key1);
281  return NAT_NEXT_DROP;
282  }
283 
284  user_session_increment (sm, u, is_sm);
285  if (is_sm)
287  if (lb)
290  s->ext_host_addr = key->r_addr;
291  s->ext_host_port = key->r_port;
292  s->in2out = key0;
293  s->out2in = key1;
294  s->out2in.protocol = key0.protocol;
295 
296  switch (vec_len (sm->outside_fibs))
297  {
298  case 0:
299  s->out2in.fib_index = sm->outside_fib_index;
300  break;
301  case 1:
302  s->out2in.fib_index = sm->outside_fibs[0].fib_index;
303  break;
304  default:
305  /* *INDENT-OFF* */
306  vec_foreach (outside_fib, sm->outside_fibs)
307  {
308  fei = fib_table_lookup (outside_fib->fib_index, &pfx);
309  if (FIB_NODE_INDEX_INVALID != fei)
310  {
311  if (fib_entry_get_resolving_interface (fei) != ~0)
312  {
313  s->out2in.fib_index = outside_fib->fib_index;
314  break;
315  }
316  }
317  }
318  /* *INDENT-ON* */
319  break;
320  }
321 
322  /* Add to lookup tables */
323  kv->value = s - tsm->sessions;
324  ctx.now = now;
325  ctx.thread_index = thread_index;
326  if (clib_bihash_add_or_overwrite_stale_16_8 (&tsm->in2out_ed, kv,
328  &ctx))
329  nat_elog_notice ("in2out-ed key add failed");
330 
331  make_ed_kv (kv, &key1.addr, &key->r_addr, key->proto, s->out2in.fib_index,
332  key1.port, key->r_port);
333  kv->value = s - tsm->sessions;
334  if (clib_bihash_add_or_overwrite_stale_16_8 (&tsm->out2in_ed, kv,
336  &ctx))
337  nat_elog_notice ("out2in-ed key add failed");
338 
339  *sessionp = s;
340 
341  /* log NAT event */
343  s->in2out.addr.as_u32,
344  s->out2in.addr.as_u32,
345  s->in2out.protocol,
346  s->in2out.port,
347  s->out2in.port, s->in2out.fib_index);
348 
349  nat_syslog_nat44_sadd (s->user_index, s->in2out.fib_index,
350  &s->in2out.addr, s->in2out.port,
351  &s->ext_host_nat_addr, s->ext_host_nat_port,
352  &s->out2in.addr, s->out2in.port,
353  &s->ext_host_addr, s->ext_host_port,
354  s->in2out.protocol, 0);
355 
356  nat_ha_sadd (&s->in2out.addr, s->in2out.port, &s->out2in.addr,
357  s->out2in.port, &s->ext_host_addr, s->ext_host_port,
358  &s->ext_host_nat_addr, s->ext_host_nat_port,
359  s->in2out.protocol, s->in2out.fib_index, s->flags,
360  thread_index, 0);
361 
362  return next;
363 }
364 
368  u32 rx_fib_index, u32 thread_index)
369 {
370  udp_header_t *udp = ip4_next_header (ip);
371  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
373  snat_session_key_t key0, key1;
374 
375  make_ed_kv (&kv, &ip->dst_address, &ip->src_address, ip->protocol,
376  sm->outside_fib_index, udp->dst_port, udp->src_port);
377 
378  /* NAT packet aimed at external address if */
379  /* has active sessions */
380  if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
381  {
382  key0.addr = ip->dst_address;
383  key0.port = udp->dst_port;
384  key0.protocol = proto;
385  key0.fib_index = sm->outside_fib_index;
386  /* or is static mappings */
387  if (!snat_static_mapping_match (sm, key0, &key1, 1, 0, 0, 0, 0, 0))
388  return 0;
389  }
390  else
391  return 0;
392 
393  if (sm->forwarding_enabled)
394  return 1;
395 
396  return snat_not_translate_fast (sm, node, sw_if_index, ip, proto,
397  rx_fib_index);
398 }
399 
402  u32 thread_index, f64 now,
403  vlib_main_t * vm, vlib_buffer_t * b)
404 {
407  snat_session_t *s = 0;
408  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
409 
410  if (!sm->forwarding_enabled)
411  return 0;
412 
413  if (ip->protocol == IP_PROTOCOL_ICMP)
414  {
415  key.as_u64[0] = key.as_u64[1] = 0;
416  if (get_icmp_i2o_ed_key (b, ip, &key))
417  return 0;
418  key.fib_index = 0;
419  kv.key[0] = key.as_u64[0];
420  kv.key[1] = key.as_u64[1];
421  }
422  else if (ip->protocol == IP_PROTOCOL_UDP || ip->protocol == IP_PROTOCOL_TCP)
423  {
424  make_ed_kv (&kv, &ip->src_address, &ip->dst_address, ip->protocol, 0,
425  vnet_buffer (b)->ip.reass.l4_src_port,
426  vnet_buffer (b)->ip.reass.l4_dst_port);
427  }
428  else
429  {
430  make_ed_kv (&kv, &ip->src_address, &ip->dst_address, ip->protocol, 0, 0,
431  0);
432  }
433 
434  if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
435  {
436  s = pool_elt_at_index (tsm->sessions, value.value);
437  if (is_fwd_bypass_session (s))
438  {
439  if (ip->protocol == IP_PROTOCOL_TCP)
440  {
441  if (nat44_set_tcp_session_state_i2o (sm, s, b, thread_index))
442  return 1;
443  }
444  /* Accounting */
447  thread_index);
448  /* Per-user LRU list maintenance */
449  nat44_session_update_lru (sm, s, thread_index);
450  return 1;
451  }
452  else
453  return 0;
454  }
455 
456  return 0;
457 }
458 
462  u32 thread_index, u32 rx_sw_if_index,
464 {
466  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
468  snat_session_t *s;
469  u32 rx_fib_index = ip4_fib_table_get_index_for_sw_if_index (rx_sw_if_index);
470  u32 tx_fib_index = ip4_fib_table_get_index_for_sw_if_index (tx_sw_if_index);
471 
472  /* src NAT check */
473  make_ed_kv (&kv, &ip->src_address, &ip->dst_address, proto, tx_fib_index,
474  src_port, dst_port);
475  if (!clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
476  {
477  s = pool_elt_at_index (tsm->sessions, value.value);
478  if (nat44_is_ses_closed (s))
479  {
480  nat_free_session_data (sm, s, thread_index, 0);
481  nat44_delete_session (sm, s, thread_index);
482  }
483  else
485  return 1;
486  }
487 
488  /* dst NAT check */
489  make_ed_kv (&kv, &ip->dst_address, &ip->src_address, proto, rx_fib_index,
490  dst_port, src_port);
491  if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
492  {
493  s = pool_elt_at_index (tsm->sessions, value.value);
494  if (is_fwd_bypass_session (s))
495  return 0;
496 
497  /* hairpinning */
498  /* *INDENT-OFF* */
500  ({
501  if ((nat_interface_is_inside (i)) && (rx_sw_if_index == i->sw_if_index))
502  return 0;
503  }));
504  /* *INDENT-ON* */
505  return 1;
506  }
507 
508  return 0;
509 }
510 
511 #ifndef CLIB_MARCH_VARIANT
512 u32
514  u32 thread_index, vlib_buffer_t * b, ip4_header_t * ip,
515  u8 * p_proto, snat_session_key_t * p_value,
516  u8 * p_dont_translate, void *d, void *e)
517 {
519  u32 rx_fib_index;
521  snat_session_t *s = 0;
522  u8 dont_translate = 0;
524  u32 next = ~0;
525  int err;
526  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
527 
528  sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
529  rx_fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
530 
531  key.as_u64[0] = key.as_u64[1] = 0;
532  err = get_icmp_i2o_ed_key (b, ip, &key);
533  if (err != 0)
534  {
535  b->error = node->errors[err];
536  next = NAT_NEXT_DROP;
537  goto out;
538  }
539  key.fib_index = rx_fib_index;
540 
541  kv.key[0] = key.as_u64[0];
542  kv.key[1] = key.as_u64[1];
543 
544  if (clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
545  {
546  if (vnet_buffer (b)->sw_if_index[VLIB_TX] != ~0)
547  {
548  if (PREDICT_FALSE
550  (sm, ip, key.proto, key.l_port, key.r_port, thread_index,
551  sw_if_index, vnet_buffer (b)->sw_if_index[VLIB_TX])))
552  {
553  dont_translate = 1;
554  goto out;
555  }
556  }
557  else
558  {
559  if (PREDICT_FALSE (nat44_ed_not_translate (sm, node, sw_if_index,
560  ip, SNAT_PROTOCOL_ICMP,
561  rx_fib_index,
562  thread_index)))
563  {
564  dont_translate = 1;
565  goto out;
566  }
567  }
568 
569  if (PREDICT_FALSE
571  (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags)))
572  {
573  b->error = node->errors[NAT_IN2OUT_ED_ERROR_BAD_ICMP_TYPE];
574  next = NAT_NEXT_DROP;
575  goto out;
576  }
577 
578  next = slow_path_ed (sm, b, rx_fib_index, &kv, &s, node, next,
579  thread_index, vlib_time_now (sm->vlib_main));
580 
581  if (PREDICT_FALSE (next == NAT_NEXT_DROP))
582  goto out;
583 
584  if (!s)
585  {
586  dont_translate = 1;
587  goto out;
588  }
589  }
590  else
591  {
592  if (PREDICT_FALSE
593  (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags !=
594  ICMP4_echo_request
595  && vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags !=
596  ICMP4_echo_reply
598  reass.icmp_type_or_tcp_flags)))
599  {
600  b->error = node->errors[NAT_IN2OUT_ED_ERROR_BAD_ICMP_TYPE];
601  next = NAT_NEXT_DROP;
602  goto out;
603  }
604 
605  s = pool_elt_at_index (tsm->sessions, value.value);
606  }
607 
608  *p_proto = ip_proto_to_snat_proto (key.proto);
609 out:
610  if (s)
611  *p_value = s->out2in;
612  *p_dont_translate = dont_translate;
613  if (d)
614  *(snat_session_t **) d = s;
615  return next;
616 }
617 #endif
618 
619 static snat_session_t *
621  vlib_buffer_t * b,
622  ip4_header_t * ip,
623  u32 rx_fib_index,
624  u32 thread_index,
625  f64 now,
627 {
629  clib_bihash_kv_16_8_t s_kv, s_value;
631  u32 old_addr, new_addr = 0;
632  ip_csum_t sum;
633  snat_user_t *u;
634  dlist_elt_t *head, *elt;
635  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
636  u32 elt_index, head_index, ses_index;
637  snat_session_t *s;
638  u32 outside_fib_index = sm->outside_fib_index;
639  int i;
640  u8 is_sm = 0;
641  nat_outside_fib_t *outside_fib;
643  fib_prefix_t pfx = {
645  .fp_len = 32,
646  .fp_addr = {
647  .ip4.as_u32 = ip->dst_address.as_u32,
648  },
649  };
650 
651  switch (vec_len (sm->outside_fibs))
652  {
653  case 0:
654  outside_fib_index = sm->outside_fib_index;
655  break;
656  case 1:
657  outside_fib_index = sm->outside_fibs[0].fib_index;
658  break;
659  default:
660  /* *INDENT-OFF* */
661  vec_foreach (outside_fib, sm->outside_fibs)
662  {
663  fei = fib_table_lookup (outside_fib->fib_index, &pfx);
664  if (FIB_NODE_INDEX_INVALID != fei)
665  {
666  if (fib_entry_get_resolving_interface (fei) != ~0)
667  {
668  outside_fib_index = outside_fib->fib_index;
669  break;
670  }
671  }
672  }
673  /* *INDENT-ON* */
674  break;
675  }
676  old_addr = ip->src_address.as_u32;
677 
678  make_ed_kv (&s_kv, &ip->src_address, &ip->dst_address, ip->protocol,
679  rx_fib_index, 0, 0);
680 
681  if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &s_kv, &s_value))
682  {
683  s = pool_elt_at_index (tsm->sessions, s_value.value);
684  new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32;
685  }
686  else
687  {
688  if (PREDICT_FALSE (maximum_sessions_exceeded (sm, thread_index)))
689  {
690  b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
692  nat_elog_notice ("maximum sessions exceeded");
693  return 0;
694  }
695 
696  u = nat_user_get_or_create (sm, &ip->src_address, rx_fib_index,
697  thread_index);
698  if (!u)
699  {
700  nat_elog_warn ("create NAT user failed");
701  return 0;
702  }
703 
704  make_sm_kv (&kv, &ip->src_address, 0, rx_fib_index, 0);
705 
706  /* Try to find static mapping first */
707  if (!clib_bihash_search_8_8 (&sm->static_mapping_by_local, &kv, &value))
708  {
709  m = pool_elt_at_index (sm->static_mappings, value.value);
710  new_addr = ip->src_address.as_u32 = m->external_addr.as_u32;
711  is_sm = 1;
712  goto create_ses;
713  }
714  /* Fallback to 3-tuple key */
715  else
716  {
717  /* Choose same out address as for TCP/UDP session to same destination */
718  head_index = u->sessions_per_user_list_head_index;
719  head = pool_elt_at_index (tsm->list_pool, head_index);
720  elt_index = head->next;
721  if (PREDICT_FALSE (elt_index == ~0))
722  ses_index = ~0;
723  else
724  {
725  elt = pool_elt_at_index (tsm->list_pool, elt_index);
726  ses_index = elt->value;
727  }
728 
729  while (ses_index != ~0)
730  {
731  s = pool_elt_at_index (tsm->sessions, ses_index);
732  elt_index = elt->next;
733  elt = pool_elt_at_index (tsm->list_pool, elt_index);
734  ses_index = elt->value;
735 
736  if (s->ext_host_addr.as_u32 == ip->dst_address.as_u32)
737  {
738  new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32;
739 
740  make_ed_kv (&s_kv, &s->out2in.addr, &ip->dst_address,
741  ip->protocol, outside_fib_index, 0, 0);
742  if (clib_bihash_search_16_8
743  (&tsm->out2in_ed, &s_kv, &s_value))
744  goto create_ses;
745 
746  break;
747  }
748  }
749 
750  for (i = 0; i < vec_len (sm->addresses); i++)
751  {
752  make_ed_kv (&s_kv, &sm->addresses[i].addr, &ip->dst_address,
753  ip->protocol, outside_fib_index, 0, 0);
754  if (clib_bihash_search_16_8 (&tsm->out2in_ed, &s_kv, &s_value))
755  {
756  new_addr = ip->src_address.as_u32 =
757  sm->addresses[i].addr.as_u32;
758  goto create_ses;
759  }
760  }
761  return 0;
762  }
763 
764  create_ses:
765  s = nat_ed_session_alloc (sm, u, thread_index, now);
766  if (!s)
767  {
768  nat44_delete_user_with_no_session (sm, u, thread_index);
769  nat_elog_warn ("create NAT session failed");
770  return 0;
771  }
772 
773  s->ext_host_addr.as_u32 = ip->dst_address.as_u32;
776  s->out2in.addr.as_u32 = new_addr;
777  s->out2in.fib_index = outside_fib_index;
778  s->in2out.addr.as_u32 = old_addr;
779  s->in2out.fib_index = rx_fib_index;
780  s->in2out.port = s->out2in.port = ip->protocol;
781  if (is_sm)
783  user_session_increment (sm, u, is_sm);
784 
785  /* Add to lookup tables */
786  make_ed_kv (&s_kv, &s->in2out.addr, &ip->dst_address, ip->protocol,
787  rx_fib_index, 0, 0);
788  s_kv.value = s - tsm->sessions;
789  if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &s_kv, 1))
790  nat_elog_notice ("in2out key add failed");
791 
792  make_ed_kv (&s_kv, &s->out2in.addr, &ip->dst_address, ip->protocol,
793  outside_fib_index, 0, 0);
794  s_kv.value = s - tsm->sessions;
795  if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &s_kv, 1))
796  nat_elog_notice ("out2in key add failed");
797  }
798 
799  /* Update IP checksum */
800  sum = ip->checksum;
801  sum = ip_csum_update (sum, old_addr, new_addr, ip4_header_t, src_address);
802  ip->checksum = ip_csum_fold (sum);
803 
804  /* Accounting */
806  thread_index);
807  /* Per-user LRU list maintenance */
808  nat44_session_update_lru (sm, s, thread_index);
809 
810  /* Hairpinning */
811  if (vnet_buffer (b)->sw_if_index[VLIB_TX] == ~0)
813 
814  if (vnet_buffer (b)->sw_if_index[VLIB_TX] == ~0)
815  vnet_buffer (b)->sw_if_index[VLIB_TX] = outside_fib_index;
816 
817  return s;
818 }
819 
820 static inline uword
823  vlib_frame_t * frame, int is_slow_path,
824  int is_output_feature)
825 {
826  u32 n_left_from, *from, *to_next, pkts_processed = 0, stats_node_index;
827  nat_next_t next_index;
828  snat_main_t *sm = &snat_main;
829  f64 now = vlib_time_now (vm);
830  u32 thread_index = vm->thread_index;
831  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
832  u32 tcp_packets = 0, udp_packets = 0, icmp_packets = 0, other_packets =
833  0, def_slow;
834 
835  def_slow = is_output_feature ? NAT_NEXT_IN2OUT_ED_OUTPUT_SLOW_PATH :
837 
838  stats_node_index = is_slow_path ? sm->ed_in2out_slowpath_node_index :
840 
841  from = vlib_frame_vector_args (frame);
842  n_left_from = frame->n_vectors;
843  next_index = node->cached_next_index;
844 
845  while (n_left_from > 0)
846  {
847  u32 n_left_to_next;
848 
849  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
850 
851  while (n_left_from >= 4 && n_left_to_next >= 2)
852  {
853  u32 bi0, bi1;
854  vlib_buffer_t *b0, *b1;
855  u32 next0, sw_if_index0, rx_fib_index0, iph_offset0 = 0, proto0,
856  new_addr0, old_addr0;
857  u32 next1, sw_if_index1, rx_fib_index1, iph_offset1 = 0, proto1,
858  new_addr1, old_addr1;
859  u16 old_port0, new_port0, old_port1, new_port1;
860  ip4_header_t *ip0, *ip1;
861  udp_header_t *udp0, *udp1;
862  tcp_header_t *tcp0, *tcp1;
863  icmp46_header_t *icmp0, *icmp1;
864  snat_session_t *s0 = 0, *s1 = 0;
865  clib_bihash_kv_16_8_t kv0, value0, kv1, value1;
866  ip_csum_t sum0, sum1;
867 
868  /* Prefetch next iteration. */
869  {
870  vlib_buffer_t *p2, *p3;
871 
872  p2 = vlib_get_buffer (vm, from[2]);
873  p3 = vlib_get_buffer (vm, from[3]);
874 
875  vlib_prefetch_buffer_header (p2, LOAD);
876  vlib_prefetch_buffer_header (p3, LOAD);
877 
880  }
881 
882  /* speculatively enqueue b0 and b1 to the current next frame */
883  to_next[0] = bi0 = from[0];
884  to_next[1] = bi1 = from[1];
885  from += 2;
886  to_next += 2;
887  n_left_from -= 2;
888  n_left_to_next -= 2;
889 
890  b0 = vlib_get_buffer (vm, bi0);
891  b1 = vlib_get_buffer (vm, bi1);
892 
893  if (is_output_feature)
894  {
895  // output feature fast path is enabled on the arc
896  // we need new arc_next feature
897  if (PREDICT_TRUE (!is_slow_path))
898  {
899  vnet_feature_next (&nat_buffer_opaque (b0)->arc_next, b0);
900  vnet_feature_next (&nat_buffer_opaque (b1)->arc_next, b1);
901  }
902 
903  iph_offset0 = vnet_buffer (b0)->ip.reass.save_rewrite_length;
904  iph_offset1 = vnet_buffer (b1)->ip.reass.save_rewrite_length;
905  }
906 
907  next0 = nat_buffer_opaque (b0)->arc_next;
908  next1 = nat_buffer_opaque (b1)->arc_next;
909 
910  ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
911  iph_offset0);
912 
913  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
914  rx_fib_index0 =
916  sw_if_index0);
917 
918  if (PREDICT_FALSE (ip0->ttl == 1))
919  {
920  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
921  icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
922  ICMP4_time_exceeded_ttl_exceeded_in_transit,
923  0);
924  next0 = NAT_NEXT_ICMP_ERROR;
925  goto trace00;
926  }
927 
928  udp0 = ip4_next_header (ip0);
929  tcp0 = (tcp_header_t *) udp0;
930  icmp0 = (icmp46_header_t *) udp0;
931  proto0 = ip_proto_to_snat_proto (ip0->protocol);
932 
933  if (is_slow_path)
934  {
935  if (PREDICT_FALSE (proto0 == ~0))
936  {
937  s0 = nat44_ed_in2out_unknown_proto (sm, b0, ip0,
938  rx_fib_index0,
939  thread_index, now, vm,
940  node);
941  if (!s0)
942  next0 = NAT_NEXT_DROP;
943  other_packets++;
944  goto trace00;
945  }
946 
947  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
948  {
950  (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
951  next0, now, thread_index, &s0);
952  icmp_packets++;
953  goto trace00;
954  }
955  }
956  else
957  {
958  if (PREDICT_FALSE (proto0 == ~0))
959  {
960  next0 = def_slow;
961  goto trace00;
962  }
963 
964  if (is_output_feature)
965  {
966  if (PREDICT_FALSE
968  (sm, ip0, thread_index, now, vm, b0)))
969  goto trace00;
970  }
971 
972  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
973  {
974  next0 = def_slow;
975  goto trace00;
976  }
977  }
978 
979  make_ed_kv (&kv0, &ip0->src_address, &ip0->dst_address,
980  ip0->protocol, rx_fib_index0,
981  vnet_buffer (b0)->ip.reass.l4_src_port,
982  vnet_buffer (b0)->ip.reass.l4_dst_port);
983 
984  if (clib_bihash_search_16_8 (&tsm->in2out_ed, &kv0, &value0))
985  {
986  if (is_slow_path)
987  {
988  if (is_output_feature)
989  {
990  if (PREDICT_FALSE
992  (sm, ip0, ip0->protocol,
993  vnet_buffer (b0)->ip.reass.l4_src_port,
994  vnet_buffer (b0)->ip.reass.l4_dst_port,
995  thread_index, sw_if_index0,
997  goto trace00;
998 
999  /*
1000  * Send DHCP packets to the ipv4 stack, or we won't
1001  * be able to use dhcp client on the outside interface
1002  */
1003  if (PREDICT_FALSE
1004  ((b0->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED)
1005  && proto0 == SNAT_PROTOCOL_UDP
1006  && (vnet_buffer (b0)->ip.reass.l4_dst_port ==
1007  clib_host_to_net_u16
1008  (UDP_DST_PORT_dhcp_to_server))))
1009  goto trace00;
1010  }
1011  else
1012  {
1013  if (PREDICT_FALSE (nat44_ed_not_translate (sm, node,
1014  sw_if_index0,
1015  ip0, proto0,
1016  rx_fib_index0,
1017  thread_index)))
1018  goto trace00;
1019  }
1020 
1021  next0 =
1022  slow_path_ed (sm, b0, rx_fib_index0, &kv0, &s0, node,
1023  next0, thread_index, now);
1024 
1025  if (PREDICT_FALSE (next0 == NAT_NEXT_DROP))
1026  goto trace00;
1027 
1028  if (PREDICT_FALSE (!s0))
1029  goto trace00;
1030  }
1031  else
1032  {
1033  next0 = def_slow;
1034  goto trace00;
1035  }
1036  }
1037  else
1038  {
1039  s0 = pool_elt_at_index (tsm->sessions, value0.value);
1040  }
1041 
1042  b0->flags |= VNET_BUFFER_F_IS_NATED;
1043 
1044  if (!is_output_feature)
1045  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->out2in.fib_index;
1046 
1047  old_addr0 = ip0->src_address.as_u32;
1048  new_addr0 = ip0->src_address.as_u32 = s0->out2in.addr.as_u32;
1049  sum0 = ip0->checksum;
1050  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1051  src_address);
1053  sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1054  s0->ext_host_addr.as_u32, ip4_header_t,
1055  dst_address);
1056  ip0->checksum = ip_csum_fold (sum0);
1057 
1058  old_port0 = vnet_buffer (b0)->ip.reass.l4_src_port;
1059 
1060  if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP))
1061  {
1062  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1063  {
1064  new_port0 = udp0->src_port = s0->out2in.port;
1065  sum0 = tcp0->checksum;
1066  sum0 =
1067  ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1068  dst_address);
1069  sum0 =
1070  ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
1071  length);
1073  {
1074  sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1075  s0->ext_host_addr.as_u32,
1076  ip4_header_t, dst_address);
1077  sum0 =
1078  ip_csum_update (sum0,
1079  vnet_buffer (b0)->ip.
1080  reass.l4_dst_port, s0->ext_host_port,
1081  ip4_header_t, length);
1082  tcp0->dst_port = s0->ext_host_port;
1083  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1084  }
1085  mss_clamping (sm, tcp0, &sum0);
1086  tcp0->checksum = ip_csum_fold (sum0);
1087  }
1088  tcp_packets++;
1089  if (nat44_set_tcp_session_state_i2o (sm, s0, b0, thread_index))
1090  goto trace00;
1091  }
1092  else if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment
1093  && udp0->checksum)
1094  {
1095  new_port0 = udp0->src_port = s0->out2in.port;
1096  sum0 = udp0->checksum;
1097  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1098  dst_address);
1099  sum0 = ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
1100  length);
1102  {
1103  sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1104  s0->ext_host_addr.as_u32,
1105  ip4_header_t, dst_address);
1106  sum0 =
1107  ip_csum_update (sum0,
1108  vnet_buffer (b0)->ip.reass.l4_dst_port,
1109  s0->ext_host_port, ip4_header_t, length);
1110  udp0->dst_port = s0->ext_host_port;
1111  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1112  }
1113  udp0->checksum = ip_csum_fold (sum0);
1114  udp_packets++;
1115  }
1116  else
1117  {
1118  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1119  {
1120  new_port0 = udp0->src_port = s0->out2in.port;
1122  {
1123  udp0->dst_port = s0->ext_host_port;
1124  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1125  }
1126  udp_packets++;
1127  }
1128  }
1129 
1130  /* Accounting */
1133  b0),
1134  thread_index);
1135  /* Per-user LRU list maintenance */
1136  nat44_session_update_lru (sm, s0, thread_index);
1137 
1138  trace00:
1140  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1141  {
1143  vlib_add_trace (vm, node, b0, sizeof (*t));
1144  t->is_slow_path = is_slow_path;
1145  t->sw_if_index = sw_if_index0;
1146  t->next_index = next0;
1147  t->session_index = ~0;
1148  if (s0)
1149  t->session_index = s0 - tsm->sessions;
1150  }
1151 
1152  pkts_processed += next0 == nat_buffer_opaque (b0)->arc_next;
1153 
1154  ip1 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b1) +
1155  iph_offset1);
1156 
1157  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
1158  rx_fib_index1 =
1160  sw_if_index1);
1161 
1162  if (PREDICT_FALSE (ip1->ttl == 1))
1163  {
1164  vnet_buffer (b1)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1165  icmp4_error_set_vnet_buffer (b1, ICMP4_time_exceeded,
1166  ICMP4_time_exceeded_ttl_exceeded_in_transit,
1167  0);
1168  next1 = NAT_NEXT_ICMP_ERROR;
1169  goto trace01;
1170  }
1171 
1172  udp1 = ip4_next_header (ip1);
1173  tcp1 = (tcp_header_t *) udp1;
1174  icmp1 = (icmp46_header_t *) udp1;
1175  proto1 = ip_proto_to_snat_proto (ip1->protocol);
1176 
1177  if (is_slow_path)
1178  {
1179  if (PREDICT_FALSE (proto1 == ~0))
1180  {
1181  s1 = nat44_ed_in2out_unknown_proto (sm, b1, ip1,
1182  rx_fib_index1,
1183  thread_index, now,
1184  vm, node);
1185  if (!s1)
1186  next1 = NAT_NEXT_DROP;
1187  other_packets++;
1188  goto trace01;
1189  }
1190 
1191  if (PREDICT_FALSE (proto1 == SNAT_PROTOCOL_ICMP))
1192  {
1193  next1 = icmp_in2out_ed_slow_path
1194  (sm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1,
1195  node, next1, now, thread_index, &s1);
1196  icmp_packets++;
1197  goto trace01;
1198  }
1199  }
1200  else
1201  {
1202  if (PREDICT_FALSE (proto1 == ~0))
1203  {
1204  next1 = def_slow;
1205  goto trace01;
1206  }
1207 
1208  if (is_output_feature)
1209  {
1210  if (PREDICT_FALSE
1212  (sm, ip1, thread_index, now, vm, b1)))
1213  goto trace01;
1214  }
1215 
1216  if (PREDICT_FALSE (proto1 == SNAT_PROTOCOL_ICMP))
1217  {
1218  next1 = def_slow;
1219  goto trace01;
1220  }
1221  }
1222 
1223  make_ed_kv (&kv1, &ip1->src_address, &ip1->dst_address,
1224  ip1->protocol, rx_fib_index1,
1225  vnet_buffer (b1)->ip.reass.l4_src_port,
1226  vnet_buffer (b1)->ip.reass.l4_dst_port);
1227 
1228  if (clib_bihash_search_16_8 (&tsm->in2out_ed, &kv1, &value1))
1229  {
1230  if (is_slow_path)
1231  {
1232  if (is_output_feature)
1233  {
1234  if (PREDICT_FALSE
1236  (sm, ip1, ip1->protocol,
1237  vnet_buffer (b1)->ip.reass.l4_src_port,
1238  vnet_buffer (b1)->ip.reass.l4_dst_port,
1239  thread_index, sw_if_index1,
1240  vnet_buffer (b1)->sw_if_index[VLIB_TX])))
1241  goto trace01;
1242 
1243  /*
1244  * Send DHCP packets to the ipv4 stack, or we won't
1245  * be able to use dhcp client on the outside interface
1246  */
1247  if (PREDICT_FALSE
1248  ((b1->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED)
1249  && proto1 == SNAT_PROTOCOL_UDP
1250  && (vnet_buffer (b1)->ip.reass.l4_dst_port ==
1251  clib_host_to_net_u16
1252  (UDP_DST_PORT_dhcp_to_server))))
1253  goto trace01;
1254  }
1255  else
1256  {
1257  if (PREDICT_FALSE (nat44_ed_not_translate (sm, node,
1258  sw_if_index1,
1259  ip1,
1260  proto1,
1261  rx_fib_index1,
1262  thread_index)))
1263  goto trace01;
1264  }
1265 
1266  next1 =
1267  slow_path_ed (sm, b1, rx_fib_index1, &kv1, &s1, node,
1268  next1, thread_index, now);
1269 
1270  if (PREDICT_FALSE (next1 == NAT_NEXT_DROP))
1271  goto trace01;
1272 
1273  if (PREDICT_FALSE (!s1))
1274  goto trace01;
1275  }
1276  else
1277  {
1278  next1 = def_slow;
1279  goto trace01;
1280  }
1281  }
1282  else
1283  {
1284  s1 = pool_elt_at_index (tsm->sessions, value1.value);
1285  }
1286 
1287  b1->flags |= VNET_BUFFER_F_IS_NATED;
1288 
1289  if (!is_output_feature)
1290  vnet_buffer (b1)->sw_if_index[VLIB_TX] = s1->out2in.fib_index;
1291 
1292  old_addr1 = ip1->src_address.as_u32;
1293  new_addr1 = ip1->src_address.as_u32 = s1->out2in.addr.as_u32;
1294  sum1 = ip1->checksum;
1295  sum1 = ip_csum_update (sum1, old_addr1, new_addr1, ip4_header_t,
1296  src_address);
1298  sum1 = ip_csum_update (sum1, ip1->dst_address.as_u32,
1299  s1->ext_host_addr.as_u32, ip4_header_t,
1300  dst_address);
1301  ip1->checksum = ip_csum_fold (sum1);
1302 
1303  old_port1 = vnet_buffer (b1)->ip.reass.l4_src_port;
1304 
1305  if (PREDICT_TRUE (proto1 == SNAT_PROTOCOL_TCP))
1306  {
1307  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1308  {
1309  new_port1 = udp1->src_port = s1->out2in.port;
1310  sum1 = tcp1->checksum;
1311  sum1 =
1312  ip_csum_update (sum1, old_addr1, new_addr1,
1313  ip4_header_t, dst_address);
1314  sum1 =
1315  ip_csum_update (sum1, old_port1, new_port1,
1316  ip4_header_t, length);
1318  {
1319  sum1 =
1320  ip_csum_update (sum1, ip1->dst_address.as_u32,
1321  s1->ext_host_addr.as_u32,
1322  ip4_header_t, dst_address);
1323  sum1 =
1324  ip_csum_update (sum1,
1325  vnet_buffer (b1)->ip.
1326  reass.l4_dst_port, s1->ext_host_port,
1327  ip4_header_t, length);
1328  tcp1->dst_port = s1->ext_host_port;
1329  ip1->dst_address.as_u32 = s1->ext_host_addr.as_u32;
1330  }
1331  tcp1->checksum = ip_csum_fold (sum1);
1332  mss_clamping (sm, tcp1, &sum1);
1333  }
1334  tcp_packets++;
1335  if (nat44_set_tcp_session_state_i2o (sm, s1, b1, thread_index))
1336  goto trace01;
1337  }
1338  else if (!vnet_buffer (b1)->ip.reass.is_non_first_fragment
1339  && udp1->checksum)
1340  {
1341  new_port1 = udp1->src_port = s1->out2in.port;
1342  sum1 = udp1->checksum;
1343  sum1 =
1344  ip_csum_update (sum1, old_addr1, new_addr1, ip4_header_t,
1345  dst_address);
1346  sum1 =
1347  ip_csum_update (sum1, old_port1, new_port1, ip4_header_t,
1348  length);
1349 
1351  {
1352  sum1 = ip_csum_update (sum1, ip1->dst_address.as_u32,
1353  s1->ext_host_addr.as_u32,
1354  ip4_header_t, dst_address);
1355  sum1 =
1356  ip_csum_update (sum1,
1357  vnet_buffer (b1)->ip.reass.l4_dst_port,
1358  s1->ext_host_port, ip4_header_t, length);
1359  udp1->dst_port = s1->ext_host_port;
1360  ip1->dst_address.as_u32 = s1->ext_host_addr.as_u32;
1361  }
1362  udp1->checksum = ip_csum_fold (sum1);
1363  udp_packets++;
1364  }
1365  else
1366  {
1367  if (!vnet_buffer (b1)->ip.reass.is_non_first_fragment)
1368  {
1369  new_port1 = udp1->src_port = s1->out2in.port;
1371  {
1372  udp1->dst_port = s1->ext_host_port;
1373  ip1->dst_address.as_u32 = s1->ext_host_addr.as_u32;
1374  }
1375  }
1376  udp_packets++;
1377  }
1378 
1379  /* Accounting */
1382  b1),
1383  thread_index);
1384  /* Per-user LRU list maintenance */
1385  nat44_session_update_lru (sm, s1, thread_index);
1386 
1387  trace01:
1389  && (b1->flags & VLIB_BUFFER_IS_TRACED)))
1390  {
1392  vlib_add_trace (vm, node, b1, sizeof (*t));
1393  t->is_slow_path = is_slow_path;
1394  t->sw_if_index = sw_if_index1;
1395  t->next_index = next1;
1396  t->session_index = ~0;
1397  if (s1)
1398  t->session_index = s1 - tsm->sessions;
1399  }
1400 
1401  pkts_processed += next1 == nat_buffer_opaque (b1)->arc_next;
1402 
1403 
1404  /* verify speculative enqueues, maybe switch current next frame */
1405  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
1406  to_next, n_left_to_next,
1407  bi0, bi1, next0, next1);
1408  }
1409 
1410  while (n_left_from > 0 && n_left_to_next > 0)
1411  {
1412  u32 bi0;
1413  vlib_buffer_t *b0;
1414  u32 next0, sw_if_index0, rx_fib_index0, iph_offset0 = 0, proto0,
1415  new_addr0, old_addr0;
1416  u16 old_port0, new_port0;
1417  ip4_header_t *ip0;
1418  udp_header_t *udp0;
1419  tcp_header_t *tcp0;
1420  icmp46_header_t *icmp0;
1421  snat_session_t *s0 = 0;
1422  clib_bihash_kv_16_8_t kv0, value0;
1423  ip_csum_t sum0;
1424 
1425  /* speculatively enqueue b0 to the current next frame */
1426  bi0 = from[0];
1427  to_next[0] = bi0;
1428  from += 1;
1429  to_next += 1;
1430  n_left_from -= 1;
1431  n_left_to_next -= 1;
1432 
1433  b0 = vlib_get_buffer (vm, bi0);
1434 
1435  if (is_output_feature)
1436  {
1437  // output feature fast path is enabled on the arc
1438  // we need new arc_next feature
1439  if (PREDICT_TRUE (!is_slow_path))
1440  vnet_feature_next (&nat_buffer_opaque (b0)->arc_next, b0);
1441 
1442  iph_offset0 = vnet_buffer (b0)->ip.reass.save_rewrite_length;
1443  }
1444 
1445  next0 = nat_buffer_opaque (b0)->arc_next;
1446 
1447  ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
1448  iph_offset0);
1449 
1450  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1451  rx_fib_index0 =
1453  sw_if_index0);
1454 
1455  if (PREDICT_FALSE (ip0->ttl == 1))
1456  {
1457  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1458  icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
1459  ICMP4_time_exceeded_ttl_exceeded_in_transit,
1460  0);
1461  next0 = NAT_NEXT_ICMP_ERROR;
1462  goto trace0;
1463  }
1464 
1465  udp0 = ip4_next_header (ip0);
1466  tcp0 = (tcp_header_t *) udp0;
1467  icmp0 = (icmp46_header_t *) udp0;
1468  proto0 = ip_proto_to_snat_proto (ip0->protocol);
1469 
1470  if (is_slow_path)
1471  {
1472  if (PREDICT_FALSE (proto0 == ~0))
1473  {
1474  s0 = nat44_ed_in2out_unknown_proto (sm, b0, ip0,
1475  rx_fib_index0,
1476  thread_index, now,
1477  vm, node);
1478  if (!s0)
1479  next0 = NAT_NEXT_DROP;
1480  other_packets++;
1481  goto trace0;
1482  }
1483 
1484  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
1485  {
1486  next0 = icmp_in2out_ed_slow_path
1487  (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0,
1488  node, next0, now, thread_index, &s0);
1489  icmp_packets++;
1490  goto trace0;
1491  }
1492  }
1493  else
1494  {
1495  if (PREDICT_FALSE (proto0 == ~0))
1496  {
1497  next0 = def_slow;
1498  goto trace0;
1499  }
1500 
1501  if (is_output_feature)
1502  {
1503  if (PREDICT_FALSE
1505  (sm, ip0, thread_index, now, vm, b0)))
1506  goto trace0;
1507  }
1508 
1509  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
1510  {
1511  next0 = def_slow;
1512  goto trace0;
1513  }
1514  }
1515 
1516  make_ed_kv (&kv0, &ip0->src_address, &ip0->dst_address,
1517  ip0->protocol, rx_fib_index0,
1518  vnet_buffer (b0)->ip.reass.l4_src_port,
1519  vnet_buffer (b0)->ip.reass.l4_dst_port);
1520 
1521  if (clib_bihash_search_16_8 (&tsm->in2out_ed, &kv0, &value0))
1522  {
1523  if (is_slow_path)
1524  {
1525  if (is_output_feature)
1526  {
1527  if (PREDICT_FALSE
1529  (sm, ip0, ip0->protocol,
1530  vnet_buffer (b0)->ip.reass.l4_src_port,
1531  vnet_buffer (b0)->ip.reass.l4_dst_port,
1532  thread_index, sw_if_index0,
1533  vnet_buffer (b0)->sw_if_index[VLIB_TX])))
1534  goto trace0;
1535 
1536  /*
1537  * Send DHCP packets to the ipv4 stack, or we won't
1538  * be able to use dhcp client on the outside interface
1539  */
1540  if (PREDICT_FALSE
1541  ((b0->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED)
1542  && proto0 == SNAT_PROTOCOL_UDP
1543  && (vnet_buffer (b0)->ip.reass.l4_dst_port ==
1544  clib_host_to_net_u16
1545  (UDP_DST_PORT_dhcp_to_server))))
1546  goto trace0;
1547  }
1548  else
1549  {
1550  if (PREDICT_FALSE (nat44_ed_not_translate (sm, node,
1551  sw_if_index0,
1552  ip0,
1553  proto0,
1554  rx_fib_index0,
1555  thread_index)))
1556  goto trace0;
1557  }
1558 
1559  next0 =
1560  slow_path_ed (sm, b0, rx_fib_index0, &kv0, &s0, node,
1561  next0, thread_index, now);
1562 
1563  if (PREDICT_FALSE (next0 == NAT_NEXT_DROP))
1564  goto trace0;
1565 
1566  if (PREDICT_FALSE (!s0))
1567  goto trace0;
1568  }
1569  else
1570  {
1571  next0 = def_slow;
1572  goto trace0;
1573  }
1574  }
1575  else
1576  {
1577  s0 = pool_elt_at_index (tsm->sessions, value0.value);
1578  }
1579 
1580  b0->flags |= VNET_BUFFER_F_IS_NATED;
1581 
1582  if (!is_output_feature)
1583  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->out2in.fib_index;
1584 
1585  old_addr0 = ip0->src_address.as_u32;
1586  new_addr0 = ip0->src_address.as_u32 = s0->out2in.addr.as_u32;
1587  sum0 = ip0->checksum;
1588  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1589  src_address);
1591  sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1592  s0->ext_host_addr.as_u32, ip4_header_t,
1593  dst_address);
1594  ip0->checksum = ip_csum_fold (sum0);
1595 
1596  old_port0 = vnet_buffer (b0)->ip.reass.l4_src_port;
1597 
1598  if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP))
1599  {
1600  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1601  {
1602  new_port0 = udp0->src_port = s0->out2in.port;
1603  sum0 = tcp0->checksum;
1604  sum0 =
1605  ip_csum_update (sum0, old_addr0, new_addr0,
1606  ip4_header_t, dst_address);
1607  sum0 =
1608  ip_csum_update (sum0, old_port0, new_port0,
1609  ip4_header_t, length);
1611  {
1612  sum0 =
1613  ip_csum_update (sum0, ip0->dst_address.as_u32,
1614  s0->ext_host_addr.as_u32,
1615  ip4_header_t, dst_address);
1616  sum0 =
1617  ip_csum_update (sum0,
1618  vnet_buffer (b0)->ip.
1619  reass.l4_dst_port, s0->ext_host_port,
1620  ip4_header_t, length);
1621  tcp0->dst_port = s0->ext_host_port;
1622  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1623  }
1624  mss_clamping (sm, tcp0, &sum0);
1625  tcp0->checksum = ip_csum_fold (sum0);
1626  }
1627  tcp_packets++;
1628  if (nat44_set_tcp_session_state_i2o (sm, s0, b0, thread_index))
1629  goto trace0;
1630  }
1631  else if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment
1632  && udp0->checksum)
1633  {
1634  new_port0 = udp0->src_port = s0->out2in.port;
1635  sum0 = udp0->checksum;
1636  sum0 =
1637  ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1638  dst_address);
1639  sum0 =
1640  ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
1641  length);
1643  {
1644  sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1645  s0->ext_host_addr.as_u32,
1646  ip4_header_t, dst_address);
1647  sum0 =
1648  ip_csum_update (sum0,
1649  vnet_buffer (b0)->ip.reass.l4_dst_port,
1650  s0->ext_host_port, ip4_header_t, length);
1651  udp0->dst_port = s0->ext_host_port;
1652  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1653  }
1654  udp0->checksum = ip_csum_fold (sum0);
1655  udp_packets++;
1656  }
1657  else
1658  {
1659  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1660  {
1661  new_port0 = udp0->src_port = s0->out2in.port;
1663  {
1664  udp0->dst_port = s0->ext_host_port;
1665  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1666  }
1667  udp_packets++;
1668  }
1669  }
1670 
1671  /* Accounting */
1674  (vm, b0), thread_index);
1675  /* Per-user LRU list maintenance */
1676  nat44_session_update_lru (sm, s0, thread_index);
1677 
1678  trace0:
1680  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1681  {
1683  vlib_add_trace (vm, node, b0, sizeof (*t));
1684  t->is_slow_path = is_slow_path;
1685  t->sw_if_index = sw_if_index0;
1686  t->next_index = next0;
1687  t->session_index = ~0;
1688  if (s0)
1689  t->session_index = s0 - tsm->sessions;
1690  }
1691 
1692  pkts_processed += next0 == nat_buffer_opaque (b0)->arc_next;
1693 
1694  /* verify speculative enqueue, maybe switch current next frame */
1695  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1696  to_next, n_left_to_next,
1697  bi0, next0);
1698  }
1699 
1700  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1701  }
1702 
1703  vlib_node_increment_counter (vm, stats_node_index,
1704  NAT_IN2OUT_ED_ERROR_IN2OUT_PACKETS,
1705  pkts_processed);
1706  vlib_node_increment_counter (vm, stats_node_index,
1707  NAT_IN2OUT_ED_ERROR_TCP_PACKETS, tcp_packets);
1708  vlib_node_increment_counter (vm, stats_node_index,
1709  NAT_IN2OUT_ED_ERROR_UDP_PACKETS, udp_packets);
1710  vlib_node_increment_counter (vm, stats_node_index,
1711  NAT_IN2OUT_ED_ERROR_ICMP_PACKETS,
1712  icmp_packets);
1713  vlib_node_increment_counter (vm, stats_node_index,
1714  NAT_IN2OUT_ED_ERROR_OTHER_PACKETS,
1715  other_packets);
1716  return frame->n_vectors;
1717 }
1718 
1721  vlib_frame_t * frame)
1722 {
1723  return nat44_ed_in2out_node_fn_inline (vm, node, frame, 0, 0);
1724 }
1725 
1726 /* *INDENT-OFF* */
1728  .name = "nat44-ed-in2out",
1729  .vector_size = sizeof (u32),
1730  .sibling_of = "nat-default",
1731  .format_trace = format_nat_in2out_ed_trace,
1733  .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1734  .error_strings = nat_in2out_ed_error_strings,
1735  .runtime_data_bytes = sizeof (snat_runtime_t),
1736 };
1737 /* *INDENT-ON* */
1738 
1741  vlib_frame_t * frame)
1742 {
1743  return nat44_ed_in2out_node_fn_inline (vm, node, frame, 0, 1);
1744 }
1745 
1746 /* *INDENT-OFF* */
1748  .name = "nat44-ed-in2out-output",
1749  .vector_size = sizeof (u32),
1750  .sibling_of = "nat-default",
1751  .format_trace = format_nat_in2out_ed_trace,
1753  .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1754  .error_strings = nat_in2out_ed_error_strings,
1755  .runtime_data_bytes = sizeof (snat_runtime_t),
1756 };
1757 /* *INDENT-ON* */
1758 
1761  node, vlib_frame_t * frame)
1762 {
1763  return nat44_ed_in2out_node_fn_inline (vm, node, frame, 1, 0);
1764 }
1765 
1766 /* *INDENT-OFF* */
1768  .name = "nat44-ed-in2out-slowpath",
1769  .vector_size = sizeof (u32),
1770  .sibling_of = "nat-default",
1771  .format_trace = format_nat_in2out_ed_trace,
1773  .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1774  .error_strings = nat_in2out_ed_error_strings,
1775  .runtime_data_bytes = sizeof (snat_runtime_t),
1776 };
1777 /* *INDENT-ON* */
1778 
1781  * node,
1782  vlib_frame_t * frame)
1783 {
1784  return nat44_ed_in2out_node_fn_inline (vm, node, frame, 1, 1);
1785 }
1786 
1787 /* *INDENT-OFF* */
1789  .name = "nat44-ed-in2out-output-slowpath",
1790  .vector_size = sizeof (u32),
1791  .sibling_of = "nat-default",
1792  .format_trace = format_nat_in2out_ed_trace,
1794  .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1795  .error_strings = nat_in2out_ed_error_strings,
1796  .runtime_data_bytes = sizeof (snat_runtime_t),
1797 };
1798 /* *INDENT-ON* */
1799 
1800 static u8 *
1801 format_nat_pre_trace (u8 * s, va_list * args)
1802 {
1803  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1804  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1805  nat_pre_trace_t *t = va_arg (*args, nat_pre_trace_t *);
1806  return format (s, "in2out next_index %d", t->next_index);
1807 }
1808 
1812  return nat_pre_node_fn_inline (vm, node, frame,
1814 }
1815 
1816 /* *INDENT-OFF* */
1818  .name = "nat-pre-in2out",
1819  .vector_size = sizeof (u32),
1820  .sibling_of = "nat-default",
1821  .format_trace = format_nat_pre_trace,
1823  .n_errors = 0,
1824 };
1825 /* *INDENT-ON* */
1826 
1827 /*
1828  * fd.io coding-style-patch-verification: ON
1829  *
1830  * Local Variables:
1831  * eval: (c-set-style "gnu")
1832  * End:
1833  */
ip4_address_t external_addr
Definition: nat.h:443
u32 next
Definition: dlist.h:30
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:124
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:212
nat_outside_fib_t * outside_fibs
Definition: nat.h:598
#define nat_buffer_opaque(b)
Definition: nat.h:71
#define snat_is_session_static(s)
Check if SNAT session is created from static mapping.
Definition: nat.h:765
u32 sessions_per_user_list_head_index
Definition: nat.h:349
vlib_node_registration_t nat44_ed_in2out_output_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_output_node)
Definition: in2out_ed.c:1747
static uword nat44_ed_in2out_node_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_slow_path, int is_output_feature)
Definition: in2out_ed.c:821
u8 proto
Definition: acl_types.api:47
#define CLIB_UNUSED(x)
Definition: clib.h:82
a
Definition: bitmap.h:538
ip4_address_t src_address
Definition: ip4_packet.h:170
static u32 nat44_session_get_timeout(snat_main_t *sm, snat_session_t *s)
Definition: nat_inlines.h:394
#define nat_elog_notice(nat_elog_str)
Definition: nat.h:1023
#define PREDICT_TRUE(x)
Definition: clib.h:112
unsigned long u64
Definition: types.h:89
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:279
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:989
static void make_sm_kv(clib_bihash_kv_8_8_t *kv, ip4_address_t *addr, u8 proto, u32 fib_index, u16 port)
Definition: nat_inlines.h:458
u16 port_per_thread
Definition: nat.h:564
u32 thread_index
Definition: main.h:218
void nat_free_session_data(snat_main_t *sm, snat_session_t *s, u32 thread_index, u8 is_ha)
Free NAT44 session data (lookup keys, external addrres port)
Definition: nat.c:194
u8 data[0]
Packet data.
Definition: buffer.h:181
int i
#define foreach_nat_in2out_ed_error
Definition: nat.h:217
void nat_syslog_nat44_sdel(u32 ssubix, u32 sfibix, ip4_address_t *isaddr, u16 isport, ip4_address_t *idaddr, u16 idport, ip4_address_t *xsaddr, u16 xsport, ip4_address_t *xdaddr, u16 xdport, snat_protocol_t proto, u8 is_twicenat)
Definition: nat_syslog.c:211
uword ip_csum_t
Definition: ip_packet.h:244
#define nat_elog_warn(nat_elog_str)
Definition: nat.h:1025
void nat_ha_sadd(ip4_address_t *in_addr, u16 in_port, ip4_address_t *out_addr, u16 out_port, ip4_address_t *eh_addr, u16 eh_port, ip4_address_t *ehn_addr, u16 ehn_port, u8 proto, u32 fib_index, u16 flags, u32 thread_index, u8 is_resync)
Create session add HA event.
Definition: nat_ha.c:689
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
#define nat44_is_ses_closed(s)
Check if NAT44 endpoint-dependent TCP session is closed.
Definition: nat.h:819
#define VLIB_NODE_FN(node)
Definition: node.h:202
static_always_inline int nat44_ed_not_translate(snat_main_t *sm, vlib_node_runtime_t *node, u32 sw_if_index, ip4_header_t *ip, u32 proto, u32 rx_fib_index, u32 thread_index)
Definition: in2out_ed.c:366
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:470
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:366
dlist_elt_t * list_pool
Definition: nat.h:512
struct _tcp_header tcp_header_t
#define snat_is_unk_proto_session(s)
Check if SNAT session for unknown protocol.
Definition: nat.h:771
static snat_session_t * nat44_ed_in2out_unknown_proto(snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, u32 rx_fib_index, u32 thread_index, f64 now, vlib_main_t *vm, vlib_node_runtime_t *node)
Definition: in2out_ed.c:620
unsigned char u8
Definition: types.h:56
u16 l_port
Definition: nat.h:108
double f64
Definition: types.h:142
u32 next_index
Definition: nat.h:68
static int snat_not_translate_fast(snat_main_t *sm, vlib_node_runtime_t *node, u32 sw_if_index0, ip4_header_t *ip0, u32 proto0, u32 rx_fib_index0)
Check if packet should be translated.
Definition: nat_inlines.h:639
u16 src_port
Definition: udp.api:41
u32 ed_in2out_node_index
Definition: nat.h:635
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
Definition: ip4_fib.c:230
#define static_always_inline
Definition: clib.h:99
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:498
vl_api_interface_index_t sw_if_index
Definition: gre.api:59
u16 r_port
Definition: nat.h:109
ip4_address_t dst_address
Definition: ip4_packet.h:170
lb_nat_type_t
Definition: nat.h:428
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:203
#define SNAT_SESSION_FLAG_OUTPUT_FEATURE
Definition: nat.h:288
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Aggregate type for a prefix.
Definition: fib_types.h:203
u32 icmp_in2out(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: in2out.c:655
#define is_fwd_bypass_session(s)
Check if NAT session is forwarding bypass.
Definition: nat.h:789
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:241
unsigned int u32
Definition: types.h:88
void nat_ipfix_logging_max_sessions(u32 thread_index, u32 limit)
Generate maximum session entries exceeded event.
fib_node_index_t fib_table_lookup(u32 fib_index, const fib_prefix_t *prefix)
Perfom a longest prefix match in the non-forwarding table.
Definition: fib_table.c:68
u64 as_u64[2]
Definition: nat.h:111
static u8 maximum_sessions_exceeded(snat_main_t *sm, u32 thread_index)
Definition: nat_inlines.h:215
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:2604
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:2530
static void nat44_delete_session(snat_main_t *sm, snat_session_t *ses, u32 thread_index)
Definition: nat_inlines.h:289
vl_api_fib_path_type_t type
Definition: fib_types.api:123
static_always_inline int get_icmp_i2o_ed_key(vlib_buffer_t *b, ip4_header_t *ip0, nat_ed_ses_key_t *p_key0)
Definition: nat_inlines.h:473
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:136
u32 max_translations
Definition: nat.h:666
static void mss_clamping(snat_main_t *sm, tcp_header_t *tcp, ip_csum_t *sum)
Definition: nat_inlines.h:576
static int nat44_set_tcp_session_state_i2o(snat_main_t *sm, snat_session_t *ses, vlib_buffer_t *b, u32 thread_index)
Set TCP session state.
Definition: nat_inlines.h:325
int snat_alloc_outside_address_and_port(snat_address_t *addresses, u32 fib_index, u32 thread_index, snat_session_key_t *k, u16 port_per_thread, u32 snat_thread_index)
Alloc outside address and port.
Definition: nat.c:2763
u32 fib_index
Definition: nat.h:107
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:328
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:519
u32 fib_index
Definition: nat.h:370
clib_bihash_16_8_t out2in_ed
Definition: nat.h:499
static_always_inline u8 icmp_type_is_error_message(u8 icmp_type)
Definition: nat_inlines.h:174
long ctx[MAX_CONNS]
Definition: main.c:144
vlib_main_t * vlib_main
Definition: nat.h:698
vlib_node_registration_t nat44_ed_in2out_slowpath_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_slowpath_node)
Definition: in2out_ed.c:1767
unsigned short u16
Definition: types.h:57
u16 protocol
Definition: nat.h:92
snat_session_t * nat_ed_session_alloc(snat_main_t *sm, snat_user_t *u, u32 thread_index, f64 now)
Allocate NAT endpoint-dependent session.
Definition: nat.c:450
snat_static_mapping_t * static_mappings
Definition: nat.h:577
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
void nat_syslog_nat44_sadd(u32 ssubix, u32 sfibix, ip4_address_t *isaddr, u16 isport, ip4_address_t *idaddr, u16 idport, ip4_address_t *xsaddr, u16 xsport, ip4_address_t *xdaddr, u16 xdport, snat_protocol_t proto, u8 is_twicenat)
Definition: nat_syslog.c:199
nat_next_t
Definition: nat.h:52
#define PREDICT_FALSE(x)
Definition: clib.h:111
vl_api_address_union_t src_address
Definition: ip_types.api:98
#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
#define SNAT_SESSION_FLAG_UNKNOWN_PROTO
Definition: nat.h:282
#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:338
vlib_main_t * vm
Definition: in2out_ed.c:1810
static u8 * format_nat_pre_trace(u8 *s, va_list *args)
Definition: in2out_ed.c:1801
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1150
static u32 slow_path_ed(snat_main_t *sm, vlib_buffer_t *b, u32 rx_fib_index, clib_bihash_kv_16_8_t *kv, snat_session_t **sessionp, vlib_node_runtime_t *node, u32 next, u32 thread_index, f64 now)
Definition: in2out_ed.c:186
u32 fib_entry_get_resolving_interface(fib_node_index_t entry_index)
Definition: fib_entry.c:1458
static u8 * format_nat_in2out_ed_trace(u8 *s, va_list *args)
Definition: in2out_ed.c:50
snat_interface_t * output_feature_interfaces
Definition: nat.h:581
snat_main_t snat_main
Definition: nat.c:39
void snat_ipfix_logging_nat44_ses_delete(u32 thread_index, 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.
u64 value
the value
Definition: bihash_8_8.h:36
vlib_node_registration_t nat_pre_in2out_node
(constructor) VLIB_REGISTER_NODE (nat_pre_in2out_node)
Definition: in2out_ed.c:1817
static void nat44_delete_user_with_no_session(snat_main_t *sm, snat_user_t *u, u32 thread_index)
Definition: nat_inlines.h:267
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
static u8 snat_proto_to_ip_proto(snat_protocol_t snat_proto)
Definition: nat_inlines.h:162
u16 n_vectors
Definition: node.h:397
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
int nat44_o2i_ed_is_idle_session_cb(clib_bihash_kv_16_8_t *kv, void *arg)
Definition: out2in_ed.c:91
vlib_node_registration_t nat44_ed_in2out_output_slowpath_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_output_slowpath_node)
Definition: in2out_ed.c:1788
ip4_address_t l_addr
Definition: nat.h:105
static_always_inline void vnet_feature_next(u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:302
static void nat44_session_update_counters(snat_session_t *s, f64 now, uword bytes, u32 thread_index)
Definition: nat_inlines.h:417
u32 ed_in2out_slowpath_node_index
Definition: nat.h:636
u32 outside_fib_index
Definition: nat.h:671
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:30
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:33
#define ARRAY_LEN(x)
Definition: clib.h:62
ip4_address_t addr
Definition: nat.h:90
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:456
static_always_inline int nat_not_translate_output_feature_fwd(snat_main_t *sm, ip4_header_t *ip, u32 thread_index, f64 now, vlib_main_t *vm, vlib_buffer_t *b)
Definition: in2out_ed.c:401
static uword nat_pre_node_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, u32 def_next)
The NAT inline functions.
Definition: nat_inlines.h:27
static void make_ed_kv(clib_bihash_kv_16_8_t *kv, ip4_address_t *l_addr, ip4_address_t *r_addr, u8 proto, u32 fib_index, u16 l_port, u16 r_port)
Definition: nat_inlines.h:441
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1810
ip4_address_t r_addr
Definition: nat.h:106
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:515
vl_api_interface_index_t tx_sw_if_index
Definition: ip.api:415
u8 value
Definition: qos.api:54
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:431
#define SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT
Definition: nat.h:285
static u32 icmp_in2out_ed_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: in2out_ed.c:164
ip4_address_t addr
Definition: nat.h:356
vlib_node_registration_t nat44_ed_in2out_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_node)
Definition: in2out_ed.c:1727
snat_address_t * twice_nat_addresses
Definition: nat.h:601
void nat_ha_sdel(ip4_address_t *out_addr, u16 out_port, ip4_address_t *eh_addr, u16 eh_port, u8 proto, u32 fib_index, u32 thread_index)
Create session delete HA event.
Definition: nat_ha.c:715
u32 value
Definition: dlist.h:32
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:55
typedef key
Definition: ipsec_types.api:83
Definition: defs.h:47
vl_api_address_t ip
Definition: l2.api:490
static u32 ip_proto_to_snat_proto(u8 ip_proto)
Definition: nat_inlines.h:147
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:31
int nat44_i2o_ed_is_idle_session_cb(clib_bihash_kv_16_8_t *kv, void *arg)
Definition: in2out_ed.c:69
static void user_session_increment(snat_main_t *sm, snat_user_t *u, u8 is_static)
Definition: nat_inlines.h:255
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
snat_main_per_thread_data_t * per_thread_data
Definition: nat.h:568
static_always_inline void nat44_session_try_cleanup(ip4_address_t *addr, u32 fib_index, u32 thread_index, f64 now)
Definition: nat44_inlines.h:65
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:244
#define ip_csum_update(sum, old, new, type, field)
Definition: ip_packet.h:294
NAT syslog logging.
snat_address_t * addresses
Definition: nat.h:584
#define vnet_buffer(b)
Definition: buffer.h:408
#define SNAT_SESSION_FLAG_STATIC_MAPPING
Definition: nat.h:281
void nat44_ed_hairpinning_unknown_proto(snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip)
u8 forwarding_enabled
Definition: nat.h:656
#define vec_foreach(var, vec)
Vector iterator.
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1811
u32 icmp_match_in2out_ed(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b, ip4_header_t *ip, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Definition: in2out_ed.c:513
u16 flags
Copy of main node flags.
Definition: node.h:509
#define is_twice_nat_session(s)
Check if NAT session is twice NAT.
Definition: nat.h:777
clib_bihash_16_8_t in2out_ed
Definition: nat.h:500
u16 dst_port
Definition: udp.api:42
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:302
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
snat_session_t * sessions
Definition: nat.h:509
static_always_inline void icmp4_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
Definition: icmp4.h:51
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
static char * nat_in2out_ed_error_strings[]
Definition: in2out_ed.c:35
#define SNAT_SESSION_FLAG_LOAD_BALANCING
Definition: nat.h:283
clib_bihash_8_8_t static_mapping_by_local
Definition: nat.h:571
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:300
Definition: defs.h:46
NAT active-passive HA.
u16 fib_index
Definition: nat.h:92
void snat_ipfix_logging_nat44_ses_create(u32 thread_index, 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.
static bool tcp_flags_is_init(u8 f)
Check if client initiating TCP connection (received SYN from client)
Definition: nat.h:850
static_always_inline int nat44_ed_not_translate_output_feature(snat_main_t *sm, ip4_header_t *ip, u8 proto, u16 src_port, u16 dst_port, u32 thread_index, u32 rx_sw_if_index, u32 tx_sw_if_index)
Definition: in2out_ed.c:460