FD.io VPP  v21.01.1
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/ip/ip.h>
23 #include <vnet/ethernet/ethernet.h>
24 #include <vnet/fib/ip4_fib.h>
25 #include <vnet/udp/udp_local.h>
26 #include <vppinfra/error.h>
27 #include <nat/nat.h>
28 #include <nat/lib/ipfix_logging.h>
29 #include <nat/nat_inlines.h>
30 #include <nat/nat44/inlines.h>
31 #include <nat/lib/nat_syslog.h>
32 #include <nat/nat_ha.h>
33 #include <nat/nat44/ed_inlines.h>
34 #include <nat/lib/nat_inlines.h>
35 
36 /* number of attempts to get a port for ED overloading algorithm, if rolling
37  * a dice this many times doesn't produce a free port, it's treated
38  * as if there were no free ports available to conserve resources */
39 #define ED_PORT_ALLOC_ATTEMPTS (10)
40 
41 static char *nat_in2out_ed_error_strings[] = {
42 #define _(sym,string) string,
44 #undef _
45 };
46 
47 typedef struct
48 {
54 
55 static u8 *
56 format_nat_in2out_ed_trace (u8 * s, va_list * args)
57 {
58  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
59  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
60  nat_in2out_ed_trace_t *t = va_arg (*args, nat_in2out_ed_trace_t *);
61  char *tag;
62 
63  tag =
64  t->is_slow_path ? "NAT44_IN2OUT_ED_SLOW_PATH" :
65  "NAT44_IN2OUT_ED_FAST_PATH";
66 
67  s = format (s, "%s: sw_if_index %d, next index %d, session %d", tag,
69 
70  return s;
71 }
72 
73 #ifndef CLIB_MARCH_VARIANT
74 int
76 {
77  snat_main_t *sm = &snat_main;
79  snat_session_t *s;
80  u64 sess_timeout_time;
81  u8 proto;
82  u16 r_port, l_port;
83  ip4_address_t *l_addr, *r_addr;
84  u32 fib_index;
86  int i;
89  ctx->thread_index);
90 
93  sess_timeout_time = s->last_heard + (f64) nat44_session_get_timeout (sm, s);
94  if (ctx->now >= sess_timeout_time)
95  {
96  if (is_fwd_bypass_session (s))
97  goto delete;
98 
99  l_addr = &s->out2in.addr;
100  r_addr = &s->ext_host_addr;
101  fib_index = s->out2in.fib_index;
103  {
104  proto = s->in2out.port;
105  r_port = 0;
106  l_port = 0;
107  }
108  else
109  {
110  proto = nat_proto_to_ip_proto (s->nat_proto);
111  l_port = s->out2in.port;
112  r_port = s->ext_host_port;
113  }
114  init_ed_k (&ed_kv, *l_addr, l_port, *r_addr, r_port, fib_index, proto);
115  if (clib_bihash_add_del_16_8 (&sm->out2in_ed, &ed_kv, 0))
116  nat_elog_warn ("out2in_ed key del failed");
117 
119  goto delete;
120 
122  s->in2out.addr.as_u32,
123  s->out2in.addr.as_u32,
124  s->nat_proto,
125  s->in2out.port,
126  s->out2in.port,
127  s->in2out.fib_index);
128 
129  nat_syslog_nat44_sdel (s->user_index, s->in2out.fib_index,
130  &s->in2out.addr, s->in2out.port,
131  &s->ext_host_nat_addr, s->ext_host_nat_port,
132  &s->out2in.addr, s->out2in.port,
133  &s->ext_host_addr, s->ext_host_port,
134  s->nat_proto, is_twice_nat_session (s));
135 
136  nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
137  s->ext_host_port, s->nat_proto, s->out2in.fib_index,
138  ctx->thread_index);
139 
140  if (is_twice_nat_session (s))
141  {
142  for (i = 0; i < vec_len (sm->twice_nat_addresses); i++)
143  {
144  // TODO FIXME this is obviously broken - which address should be
145  // freed here?!
146  a = sm->twice_nat_addresses + i;
147  if (a->addr.as_u32 == s->ext_host_nat_addr.as_u32)
148  {
150  ctx->thread_index,
151  &s->ext_host_nat_addr,
152  s->ext_host_nat_port,
153  s->nat_proto);
154  break;
155  }
156  }
157  }
158 
159  if (snat_is_session_static (s))
160  goto delete;
161 
163  &s->out2in.addr, s->out2in.port,
164  s->nat_proto);
165  delete:
166  nat_ed_session_delete (sm, s, ctx->thread_index, 1);
167  return 1;
168  }
169 
170  return 0;
171 }
172 #endif
173 
174 static inline u32
176  ip4_header_t * ip0, icmp46_header_t * icmp0,
177  u32 sw_if_index0, u32 rx_fib_index0,
178  vlib_node_runtime_t * node, u32 next0, f64 now,
179  u32 thread_index, snat_session_t ** p_s0)
180 {
181  vlib_main_t *vm = vlib_get_main ();
182 
183  next0 = icmp_in2out (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
184  next0, thread_index, p_s0, 0);
185  snat_session_t *s0 = *p_s0;
186  if (PREDICT_TRUE (next0 != NAT_NEXT_DROP && s0))
187  {
188  /* Accounting */
191  (vm, b0), thread_index);
192  /* Per-user LRU list maintenance */
193  nat44_session_update_lru (sm, s0, thread_index);
194  }
195  return next0;
196 }
197 
198 static int
200  u32 nat_proto, u32 thread_index,
201  ip4_address_t r_addr, u16 r_port, u8 proto,
202  u16 port_per_thread, u32 snat_thread_index,
203  snat_session_t * s,
204  ip4_address_t * outside_addr,
205  u16 * outside_port,
206  clib_bihash_kv_16_8_t * out2in_ed_kv)
207 {
208  int i;
209  snat_address_t *a, *ga = 0;
210  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
211 
212  const u16 port_thread_offset = (port_per_thread * snat_thread_index) + 1024;
213 
214  for (i = 0; i < vec_len (sm->addresses); i++)
215  {
216  a = sm->addresses + i;
217  switch (nat_proto)
218  {
219 #define _(N, j, n, unused) \
220  case NAT_PROTOCOL_##N: \
221  if (a->fib_index == rx_fib_index) \
222  { \
223  /* first try port suggested by caller */ \
224  u16 port = clib_net_to_host_u16 (*outside_port); \
225  u16 port_offset = port - port_thread_offset; \
226  if (port <= port_thread_offset || \
227  port > port_thread_offset + port_per_thread) \
228  { \
229  /* need to pick a different port, suggested port doesn't fit in \
230  * this thread's port range */ \
231  port_offset = snat_random_port (0, port_per_thread - 1); \
232  port = port_thread_offset + port_offset; \
233  } \
234  u16 attempts = ED_PORT_ALLOC_ATTEMPTS; \
235  do \
236  { \
237  init_ed_kv (out2in_ed_kv, a->addr, clib_host_to_net_u16 (port), \
238  r_addr, r_port, s->out2in.fib_index, proto, \
239  thread_index, s - tsm->sessions); \
240  int rv = clib_bihash_add_del_16_8 (&sm->out2in_ed, out2in_ed_kv, \
241  2 /* is_add */); \
242  if (0 == rv) \
243  { \
244  ++a->busy_##n##_port_refcounts[port]; \
245  a->busy_##n##_ports_per_thread[thread_index]++; \
246  a->busy_##n##_ports++; \
247  *outside_addr = a->addr; \
248  *outside_port = clib_host_to_net_u16 (port); \
249  return 0; \
250  } \
251  port_offset = snat_random_port (0, port_per_thread - 1); \
252  port = port_thread_offset + port_offset; \
253  --attempts; \
254  } \
255  while (attempts > 0); \
256  } \
257  else if (a->fib_index == ~0) \
258  { \
259  ga = a; \
260  } \
261  break;
262 
264  default:
265  nat_elog_info ("unknown protocol");
266  return 1;
267  }
268  }
269 
270  if (ga)
271  {
272  /* fake fib_index to reuse macro */
273  rx_fib_index = ~0;
274  a = ga;
275  switch (nat_proto)
276  {
278  default:
279  nat_elog_info ("unknown protocol");
280  return 1;
281  }
282  }
283 
284 #undef _
285 
286  /* Totally out of translations to use... */
287  nat_ipfix_logging_addresses_exhausted (thread_index, 0);
288  return 1;
289 }
290 
293 {
295  nat_outside_fib_t *outside_fib;
296  fib_prefix_t pfx = {
298  .fp_len = 32,
299  .fp_addr = {.ip4.as_u32 = addr.as_u32,}
300  ,
301  };
302  // TODO: multiple vrfs none can resolve addr
303  /* *INDENT-OFF* */
304  vec_foreach (outside_fib, sm->outside_fibs)
305  {
306  fei = fib_table_lookup (outside_fib->fib_index, &pfx);
307  if (FIB_NODE_INDEX_INVALID != fei)
308  {
309  if (fib_entry_get_resolving_interface (fei) != ~0)
310  {
311  return outside_fib->fib_index;
312  }
313  }
314  }
315  /* *INDENT-ON* */
316  return ~0;
317 }
318 
319 static u32
321  vlib_buffer_t * b,
322  ip4_address_t l_addr,
323  ip4_address_t r_addr,
324  u16 l_port,
325  u16 r_port,
326  u8 proto,
327  u32 rx_fib_index,
328  snat_session_t ** sessionp,
329  vlib_node_runtime_t * node, u32 next, u32 thread_index, f64 now)
330 {
331  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
332  clib_bihash_kv_16_8_t out2in_ed_kv;
334  ip4_address_t outside_addr;
335  u16 outside_port;
336  u8 identity_nat;
337 
338  u32 nat_proto = ip_proto_to_nat_proto (proto);
339  snat_session_t *s = NULL;
340  lb_nat_type_t lb = 0;
341 
342  if (PREDICT_TRUE (nat_proto == NAT_PROTOCOL_TCP))
343  {
344  if (PREDICT_FALSE
346  (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags)))
347  {
348  b->error = node->errors[NAT_IN2OUT_ED_ERROR_NON_SYN];
349  return NAT_NEXT_DROP;
350  }
351  }
352 
353  if (PREDICT_FALSE
354  (nat44_ed_maximum_sessions_exceeded (sm, rx_fib_index, thread_index)))
355  {
356  if (!nat_lru_free_one (sm, thread_index, now))
357  {
358  b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
359  nat_ipfix_logging_max_sessions (thread_index,
361  nat_elog_notice ("maximum sessions exceeded");
362  return NAT_NEXT_DROP;
363  }
364  }
365 
366  ip4_address_t sm_addr;
367  u16 sm_port;
368  u32 sm_fib_index;
369 
370  ctx.now = now;
371  ctx.thread_index = thread_index;
372 
373  /* First try to match static mapping by local address and port */
375  (sm, l_addr, l_port, rx_fib_index, nat_proto, &sm_addr, &sm_port,
376  &sm_fib_index, 0, 0, 0, &lb, 0, &identity_nat, 0))
377  {
378  s = nat_ed_session_alloc (sm, thread_index, now, proto);
379  ASSERT (s);
380  s->in2out.addr = l_addr;
381  s->in2out.port = l_port;
382  s->nat_proto = nat_proto;
383  s->in2out.fib_index = rx_fib_index;
384  s->out2in.fib_index = sm->outside_fib_index;
385 
386  switch (vec_len (sm->outside_fibs))
387  {
388  case 0:
389  s->out2in.fib_index = sm->outside_fib_index;
390  break;
391  case 1:
392  s->out2in.fib_index = sm->outside_fibs[0].fib_index;
393  break;
394  default:
395  s->out2in.fib_index = nat_outside_fib_index_lookup (sm, r_addr);
396  break;
397  }
398 
399  /* Try to create dynamic translation */
400  outside_port = l_port; // suggest using local port to allocation function
401  if (nat_ed_alloc_addr_and_port (sm, rx_fib_index, nat_proto,
402  thread_index, r_addr, r_port, proto,
403  sm->port_per_thread,
404  tsm->snat_thread_index, s,
405  &outside_addr,
406  &outside_port, &out2in_ed_kv))
407  {
408  nat_elog_notice ("addresses exhausted");
409  b->error = node->errors[NAT_IN2OUT_ED_ERROR_OUT_OF_PORTS];
410  nat_ed_session_delete (sm, s, thread_index, 1);
411  return NAT_NEXT_DROP;
412  }
413  s->out2in.addr = outside_addr;
414  s->out2in.port = outside_port;
415  }
416  else
417  {
418  if (PREDICT_FALSE (identity_nat))
419  {
420  *sessionp = NULL;
421  return next;
422  }
423  s = nat_ed_session_alloc (sm, thread_index, now, proto);
424  ASSERT (s);
425  s->out2in.addr = sm_addr;
426  s->out2in.port = sm_port;
427  s->in2out.addr = l_addr;
428  s->in2out.port = l_port;
429  s->nat_proto = nat_proto;
430  s->in2out.fib_index = rx_fib_index;
431  s->out2in.fib_index = sm->outside_fib_index;
432  switch (vec_len (sm->outside_fibs))
433  {
434  case 0:
435  s->out2in.fib_index = sm->outside_fib_index;
436  break;
437  case 1:
438  s->out2in.fib_index = sm->outside_fibs[0].fib_index;
439  break;
440  default:
441  s->out2in.fib_index = nat_outside_fib_index_lookup (sm, r_addr);
442  break;
443  }
444 
446 
447  init_ed_kv (&out2in_ed_kv, sm_addr, sm_port, r_addr, r_port,
448  s->out2in.fib_index, proto, thread_index,
449  s - tsm->sessions);
450  if (clib_bihash_add_or_overwrite_stale_16_8
451  (&sm->out2in_ed, &out2in_ed_kv, nat44_o2i_ed_is_idle_session_cb,
452  &ctx))
453  nat_elog_notice ("out2in-ed key add failed");
454  }
455 
456  if (lb)
459  s->ext_host_addr = r_addr;
460  s->ext_host_port = r_port;
461 
462  clib_bihash_kv_16_8_t in2out_ed_kv;
463  init_ed_kv (&in2out_ed_kv, l_addr, l_port, r_addr, r_port, rx_fib_index,
464  proto, thread_index, s - tsm->sessions);
465  if (clib_bihash_add_or_overwrite_stale_16_8 (&tsm->in2out_ed, &in2out_ed_kv,
467  &ctx))
468  nat_elog_notice ("in2out-ed key add failed");
469 
470  *sessionp = s;
471 
472  /* log NAT event */
474  s->in2out.addr.as_u32,
475  s->out2in.addr.as_u32,
476  s->nat_proto,
477  s->in2out.port,
478  s->out2in.port, s->in2out.fib_index);
479 
480  nat_syslog_nat44_sadd (s->user_index, s->in2out.fib_index,
481  &s->in2out.addr, s->in2out.port,
482  &s->ext_host_nat_addr, s->ext_host_nat_port,
483  &s->out2in.addr, s->out2in.port,
484  &s->ext_host_addr, s->ext_host_port, s->nat_proto,
485  0);
486 
487  nat_ha_sadd (&s->in2out.addr, s->in2out.port, &s->out2in.addr,
488  s->out2in.port, &s->ext_host_addr, s->ext_host_port,
489  &s->ext_host_nat_addr, s->ext_host_nat_port,
490  s->nat_proto, s->in2out.fib_index, s->flags, thread_index, 0);
491 
492  per_vrf_sessions_register_session (s, thread_index);
493 
494  return next;
495 }
496 
500  u32 rx_fib_index, u32 thread_index)
501 {
502  udp_header_t *udp = ip4_next_header (ip);
504 
505  init_ed_k (&kv, ip->dst_address, udp->dst_port, ip->src_address,
506  udp->src_port, sm->outside_fib_index, ip->protocol);
507 
508  /* NAT packet aimed at external address if has active sessions */
509  if (clib_bihash_search_16_8 (&sm->out2in_ed, &kv, &value))
510  {
511  /* or is static mappings */
512  ip4_address_t placeholder_addr;
513  u16 placeholder_port;
514  u32 placeholder_fib_index;
516  (sm, ip->dst_address, udp->dst_port, sm->outside_fib_index, proto,
517  &placeholder_addr, &placeholder_port, &placeholder_fib_index, 1, 0,
518  0, 0, 0, 0, 0))
519  return 0;
520  }
521  else
522  return 0;
523 
524  if (sm->forwarding_enabled)
525  return 1;
526 
527  return snat_not_translate_fast (sm, node, sw_if_index, ip, proto,
528  rx_fib_index);
529 }
530 
533  u32 thread_index, f64 now,
534  vlib_main_t * vm, vlib_buffer_t * b)
535 {
537  snat_session_t *s = 0;
538  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
539 
540  if (!sm->forwarding_enabled)
541  return 0;
542 
543  if (ip->protocol == IP_PROTOCOL_ICMP)
544  {
545  if (get_icmp_i2o_ed_key (b, ip, 0, ~0, ~0, 0, 0, 0, &kv))
546  return 0;
547  }
548  else if (ip->protocol == IP_PROTOCOL_UDP || ip->protocol == IP_PROTOCOL_TCP)
549  {
550  init_ed_k (&kv, ip->src_address, vnet_buffer (b)->ip.reass.l4_src_port,
551  ip->dst_address, vnet_buffer (b)->ip.reass.l4_dst_port, 0,
552  ip->protocol);
553  }
554  else
555  {
556  init_ed_k (&kv, ip->src_address, 0, ip->dst_address, 0, 0,
557  ip->protocol);
558  }
559 
560  if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
561  {
562  ASSERT (thread_index == ed_value_get_thread_index (&value));
563  s =
565  ed_value_get_session_index (&value));
566  if (is_fwd_bypass_session (s))
567  {
568  if (ip->protocol == IP_PROTOCOL_TCP)
569  {
570  nat44_set_tcp_session_state_i2o (sm, now, s, b, thread_index);
571  }
572  /* Accounting */
575  thread_index);
576  /* Per-user LRU list maintenance */
577  nat44_session_update_lru (sm, s, thread_index);
578  return 1;
579  }
580  else
581  return 0;
582  }
583 
584  return 0;
585 }
586 
590  u32 thread_index, u32 rx_sw_if_index,
591  u32 tx_sw_if_index, f64 now)
592 {
594  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
596  snat_session_t *s;
597  u32 rx_fib_index = ip4_fib_table_get_index_for_sw_if_index (rx_sw_if_index);
598  u32 tx_fib_index = ip4_fib_table_get_index_for_sw_if_index (tx_sw_if_index);
599 
600  /* src NAT check */
601  init_ed_k (&kv, ip->src_address, src_port, ip->dst_address, dst_port,
602  tx_fib_index, ip->protocol);
603  if (!clib_bihash_search_16_8 (&sm->out2in_ed, &kv, &value))
604  {
605  ASSERT (thread_index == ed_value_get_thread_index (&value));
606  s =
608  ed_value_get_session_index (&value));
609  if (nat44_is_ses_closed (s)
610  && (!s->tcp_closed_timestamp || now >= s->tcp_closed_timestamp))
611  {
612  nat_free_session_data (sm, s, thread_index, 0);
613  nat_ed_session_delete (sm, s, thread_index, 1);
614  }
615  return 1;
616  }
617 
618  /* dst NAT check */
619  init_ed_k (&kv, ip->dst_address, dst_port, ip->src_address, src_port,
620  rx_fib_index, ip->protocol);
621  if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
622  {
623  ASSERT (thread_index == ed_value_get_thread_index (&value));
624  s =
626  ed_value_get_session_index (&value));
627  if (is_fwd_bypass_session (s))
628  return 0;
629 
630  /* hairpinning */
631  /* *INDENT-OFF* */
633  {
634  if ((nat_interface_is_inside (i)) && (rx_sw_if_index == i->sw_if_index))
635  return 0;
636  }
637  /* *INDENT-ON* */
638  return 1;
639  }
640 
641  return 0;
642 }
643 
644 #ifndef CLIB_MARCH_VARIANT
645 u32
647  u32 thread_index, vlib_buffer_t * b,
649  u16 * port, u32 * fib_index, nat_protocol_t * proto,
650  void *d, void *e, u8 * dont_translate)
651 {
653  u32 rx_fib_index;
655  u32 next = ~0;
656  int err;
657  snat_session_t *s = NULL;
658  u16 l_port = 0, r_port = 0; // initialize to workaround gcc warning
659  vlib_main_t *vm = vlib_get_main ();
660  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
661  *dont_translate = 0;
662  f64 now = vlib_time_now (vm);
663 
664  sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
665  rx_fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
666 
667  err =
668  get_icmp_i2o_ed_key (b, ip, rx_fib_index, ~0, ~0, proto, &l_port,
669  &r_port, &kv);
670  if (err != 0)
671  {
672  b->error = node->errors[err];
673  next = NAT_NEXT_DROP;
674  goto out;
675  }
676 
677  if (clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
678  {
679  if (vnet_buffer (b)->sw_if_index[VLIB_TX] != ~0)
680  {
681  if (PREDICT_FALSE
683  (sm, ip, l_port, r_port, thread_index,
684  sw_if_index, vnet_buffer (b)->sw_if_index[VLIB_TX], now)))
685  {
686  *dont_translate = 1;
687  goto out;
688  }
689  }
690  else
691  {
692  if (PREDICT_FALSE (nat44_ed_not_translate (sm, node, sw_if_index,
693  ip, NAT_PROTOCOL_ICMP,
694  rx_fib_index,
695  thread_index)))
696  {
697  *dont_translate = 1;
698  goto out;
699  }
700  }
701 
702  if (PREDICT_FALSE
704  (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags)))
705  {
706  b->error = node->errors[NAT_IN2OUT_ED_ERROR_BAD_ICMP_TYPE];
707  next = NAT_NEXT_DROP;
708  goto out;
709  }
710 
711  next =
712  slow_path_ed (sm, b, ip->src_address, ip->dst_address, l_port, r_port,
713  ip->protocol, rx_fib_index, &s, node, next,
714  thread_index, vlib_time_now (vm));
715 
716  if (PREDICT_FALSE (next == NAT_NEXT_DROP))
717  goto out;
718 
719  if (!s)
720  {
721  *dont_translate = 1;
722  goto out;
723  }
724  }
725  else
726  {
727  if (PREDICT_FALSE
728  (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags !=
729  ICMP4_echo_request
730  && vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags !=
731  ICMP4_echo_reply
733  reass.icmp_type_or_tcp_flags)))
734  {
735  b->error = node->errors[NAT_IN2OUT_ED_ERROR_BAD_ICMP_TYPE];
736  next = NAT_NEXT_DROP;
737  goto out;
738  }
739 
740  ASSERT (thread_index == ed_value_get_thread_index (&value));
741  s =
743  ed_value_get_session_index (&value));
744  }
745 out:
746  if (s)
747  {
748  *addr = s->out2in.addr;
749  *port = s->out2in.port;
750  *fib_index = s->out2in.fib_index;
751  }
752  if (d)
753  {
754  *(snat_session_t **) d = s;
755  }
756  return next;
757 }
758 #endif
759 
760 static snat_session_t *
762  vlib_buffer_t * b,
763  ip4_header_t * ip,
764  u32 rx_fib_index,
765  u32 thread_index,
766  f64 now,
768 {
770  clib_bihash_kv_16_8_t s_kv, s_value;
772  u32 old_addr, new_addr = 0;
773  ip_csum_t sum;
774  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
775  snat_session_t *s;
776  u32 outside_fib_index = sm->outside_fib_index;
777  int i;
778  u8 is_sm = 0;
779 
780  switch (vec_len (sm->outside_fibs))
781  {
782  case 0:
783  outside_fib_index = sm->outside_fib_index;
784  break;
785  case 1:
786  outside_fib_index = sm->outside_fibs[0].fib_index;
787  break;
788  default:
789  outside_fib_index = nat_outside_fib_index_lookup (sm, ip->dst_address);
790  break;
791  }
792  old_addr = ip->src_address.as_u32;
793 
794  init_ed_k (&s_kv, ip->src_address, 0, ip->dst_address, 0, rx_fib_index,
795  ip->protocol);
796 
797  if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &s_kv, &s_value))
798  {
799  ASSERT (thread_index == ed_value_get_thread_index (&s_value));
800  s =
802  ed_value_get_session_index (&s_value));
803  new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32;
804  }
805  else
806  {
807  if (PREDICT_FALSE
809  (sm, rx_fib_index, thread_index)))
810  {
811  b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
812  nat_ipfix_logging_max_sessions (thread_index,
814  nat_elog_notice ("maximum sessions exceeded");
815  return 0;
816  }
817 
818  init_nat_k (&kv, ip->src_address, 0, rx_fib_index, 0);
819 
820  /* Try to find static mapping first */
821  if (!clib_bihash_search_8_8 (&sm->static_mapping_by_local, &kv, &value))
822  {
823  m = pool_elt_at_index (sm->static_mappings, value.value);
824  new_addr = ip->src_address.as_u32 = m->external_addr.as_u32;
825  is_sm = 1;
826  goto create_ses;
827  }
828  else
829  {
830  /* *INDENT-OFF* */
831  pool_foreach (s, tsm->sessions) {
832  if (s->ext_host_addr.as_u32 == ip->dst_address.as_u32)
833  {
834  new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32;
835 
836  init_ed_k(&s_kv, s->out2in.addr, 0, ip->dst_address, 0, outside_fib_index, ip->protocol);
837  if (clib_bihash_search_16_8 (&sm->out2in_ed, &s_kv, &s_value))
838  goto create_ses;
839 
840  break;
841  }
842  }
843  /* *INDENT-ON* */
844 
845  for (i = 0; i < vec_len (sm->addresses); i++)
846  {
847  init_ed_k (&s_kv, sm->addresses[i].addr, 0, ip->dst_address, 0,
848  outside_fib_index, ip->protocol);
849  if (clib_bihash_search_16_8 (&sm->out2in_ed, &s_kv, &s_value))
850  {
851  new_addr = ip->src_address.as_u32 =
852  sm->addresses[i].addr.as_u32;
853  goto create_ses;
854  }
855  }
856  return 0;
857  }
858 
859  create_ses:
860  s = nat_ed_session_alloc (sm, thread_index, now, ip->protocol);
861  if (!s)
862  {
863  b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
864  nat_elog_warn ("create NAT session failed");
865  return 0;
866  }
867 
868  s->ext_host_addr.as_u32 = ip->dst_address.as_u32;
871  s->out2in.addr.as_u32 = new_addr;
872  s->out2in.fib_index = outside_fib_index;
873  s->in2out.addr.as_u32 = old_addr;
874  s->in2out.fib_index = rx_fib_index;
875  s->in2out.port = s->out2in.port = ip->protocol;
876  if (is_sm)
878 
879  /* Add to lookup tables */
880  init_ed_kv (&s_kv, s->in2out.addr, 0, ip->dst_address, 0, rx_fib_index,
881  ip->protocol, thread_index, s - tsm->sessions);
882  if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &s_kv, 1))
883  nat_elog_notice ("in2out key add failed");
884 
885  init_ed_kv (&s_kv, s->out2in.addr, 0, ip->dst_address, 0,
886  outside_fib_index, ip->protocol, thread_index,
887  s - tsm->sessions);
888  if (clib_bihash_add_del_16_8 (&sm->out2in_ed, &s_kv, 1))
889  nat_elog_notice ("out2in key add failed");
890 
891  per_vrf_sessions_register_session (s, thread_index);
892  }
893 
894  /* Update IP checksum */
895  sum = ip->checksum;
896  sum = ip_csum_update (sum, old_addr, new_addr, ip4_header_t, src_address);
897  ip->checksum = ip_csum_fold (sum);
898 
899  /* Accounting */
901  thread_index);
902  /* Per-user LRU list maintenance */
903  nat44_session_update_lru (sm, s, thread_index);
904 
905  /* Hairpinning */
906  if (vnet_buffer (b)->sw_if_index[VLIB_TX] == ~0)
908 
909  if (vnet_buffer (b)->sw_if_index[VLIB_TX] == ~0)
910  vnet_buffer (b)->sw_if_index[VLIB_TX] = outside_fib_index;
911 
912  return s;
913 }
914 
915 static inline uword
919  int is_output_feature)
920 {
921  u32 n_left_from, *from;
922  snat_main_t *sm = &snat_main;
923  f64 now = vlib_time_now (vm);
924  u32 thread_index = vm->thread_index;
925  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
926  u32 def_slow = is_output_feature ? NAT_NEXT_IN2OUT_ED_OUTPUT_SLOW_PATH
928 
929  from = vlib_frame_vector_args (frame);
930  n_left_from = frame->n_vectors;
931 
932  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
933  u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
934  vlib_get_buffers (vm, from, b, n_left_from);
935 
936  while (n_left_from > 0)
937  {
938  vlib_buffer_t *b0;
939  u32 sw_if_index0, rx_fib_index0, proto0, new_addr0, old_addr0,
940  iph_offset0 = 0;
941  u16 old_port0, new_port0;
942  ip4_header_t *ip0;
943  udp_header_t *udp0;
944  tcp_header_t *tcp0;
945  snat_session_t *s0 = 0;
946  clib_bihash_kv_16_8_t kv0, value0;
947  ip_csum_t sum0;
948 
949  b0 = *b;
950  b++;
951 
952  /* Prefetch next iteration. */
953  if (PREDICT_TRUE (n_left_from >= 2))
954  {
955  vlib_buffer_t *p2;
956 
957  p2 = *b;
958 
959  vlib_prefetch_buffer_header (p2, LOAD);
960 
962  }
963 
964  if (is_output_feature)
965  {
966  iph_offset0 = vnet_buffer (b0)->ip.reass.save_rewrite_length;
967  }
968 
969  next[0] = vnet_buffer2 (b0)->nat.arc_next;
970 
971  ip0 =
972  (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) + iph_offset0);
973 
974  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
975  rx_fib_index0 =
977 
978  if (PREDICT_FALSE (ip0->ttl == 1))
979  {
980  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
981  icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
982  ICMP4_time_exceeded_ttl_exceeded_in_transit,
983  0);
984  next[0] = NAT_NEXT_ICMP_ERROR;
985  goto trace0;
986  }
987 
988  udp0 = ip4_next_header (ip0);
989  tcp0 = (tcp_header_t *) udp0;
990  proto0 = ip_proto_to_nat_proto (ip0->protocol);
991 
992  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_OTHER))
993  {
994  next[0] = def_slow;
995  goto trace0;
996  }
997 
998  if (is_output_feature)
999  {
1000  if (PREDICT_FALSE
1002  (sm, ip0, thread_index, now, vm, b0)))
1003  goto trace0;
1004  }
1005 
1006  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP))
1007  {
1008  next[0] = def_slow;
1009  goto trace0;
1010  }
1011 
1012  init_ed_k (&kv0, ip0->src_address,
1013  vnet_buffer (b0)->ip.reass.l4_src_port, ip0->dst_address,
1014  vnet_buffer (b0)->ip.reass.l4_dst_port, rx_fib_index0,
1015  ip0->protocol);
1016 
1017  // lookup for session
1018  if (clib_bihash_search_16_8 (&tsm->in2out_ed, &kv0, &value0))
1019  {
1020  // session does not exist go slow path
1021  next[0] = def_slow;
1022  goto trace0;
1023  }
1024  ASSERT (thread_index == ed_value_get_thread_index (&value0));
1025  s0 =
1027  ed_value_get_session_index (&value0));
1028 
1029  if (PREDICT_FALSE (per_vrf_sessions_is_expired (s0, thread_index)))
1030  {
1031  // session is closed, go slow path
1032  nat_free_session_data (sm, s0, thread_index, 0);
1033  nat_ed_session_delete (sm, s0, thread_index, 1);
1034  next[0] = NAT_NEXT_OUT2IN_ED_SLOW_PATH;
1035  goto trace0;
1036  }
1037 
1038  if (s0->tcp_closed_timestamp)
1039  {
1040  if (now >= s0->tcp_closed_timestamp)
1041  {
1042  // session is closed, go slow path, freed in slow path
1043  next[0] = def_slow;
1044  }
1045  else
1046  {
1047  // session in transitory timeout, drop
1048  b0->error = node->errors[NAT_IN2OUT_ED_ERROR_TCP_CLOSED];
1049  next[0] = NAT_NEXT_DROP;
1050  }
1051  goto trace0;
1052  }
1053 
1054  // drop if session expired
1055  u64 sess_timeout_time;
1056  sess_timeout_time =
1057  s0->last_heard + (f64) nat44_session_get_timeout (sm, s0);
1058  if (now >= sess_timeout_time)
1059  {
1060  nat_free_session_data (sm, s0, thread_index, 0);
1061  nat_ed_session_delete (sm, s0, thread_index, 1);
1062  // session is closed, go slow path
1063  next[0] = def_slow;
1064  goto trace0;
1065  }
1066 
1067  b0->flags |= VNET_BUFFER_F_IS_NATED;
1068 
1069  if (!is_output_feature)
1070  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->out2in.fib_index;
1071 
1072  old_addr0 = ip0->src_address.as_u32;
1073  new_addr0 = ip0->src_address.as_u32 = s0->out2in.addr.as_u32;
1074  sum0 = ip0->checksum;
1075  sum0 =
1076  ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1077  src_address);
1079  sum0 =
1080  ip_csum_update (sum0, ip0->dst_address.as_u32,
1081  s0->ext_host_addr.as_u32, ip4_header_t,
1082  dst_address);
1083  ip0->checksum = ip_csum_fold (sum0);
1084 
1085  old_port0 = vnet_buffer (b0)->ip.reass.l4_src_port;
1086 
1087  if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP))
1088  {
1089  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1090  {
1091  new_port0 = udp0->src_port = s0->out2in.port;
1092  sum0 = tcp0->checksum;
1093  sum0 =
1094  ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1095  dst_address);
1096  sum0 =
1097  ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
1098  length);
1100  {
1101  sum0 =
1102  ip_csum_update (sum0, ip0->dst_address.as_u32,
1103  s0->ext_host_addr.as_u32, ip4_header_t,
1104  dst_address);
1105  sum0 =
1106  ip_csum_update (sum0,
1107  vnet_buffer (b0)->ip.reass.l4_dst_port,
1108  s0->ext_host_port, ip4_header_t, length);
1109  tcp0->dst_port = s0->ext_host_port;
1110  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1111  }
1112  mss_clamping (sm->mss_clamping, tcp0, &sum0);
1113  tcp0->checksum = ip_csum_fold (sum0);
1114  }
1115  vlib_increment_simple_counter (&sm->counters.fastpath.in2out_ed.tcp,
1116  thread_index, sw_if_index0, 1);
1117  nat44_set_tcp_session_state_i2o (sm, now, s0, b0, thread_index);
1118  }
1119  else if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment
1120  && udp0->checksum)
1121  {
1122  new_port0 = udp0->src_port = s0->out2in.port;
1123  sum0 = udp0->checksum;
1124  sum0 =
1125  ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1126  dst_address);
1127  sum0 =
1128  ip_csum_update (sum0, old_port0, new_port0, ip4_header_t, length);
1130  {
1131  sum0 =
1132  ip_csum_update (sum0, ip0->dst_address.as_u32,
1133  s0->ext_host_addr.as_u32, ip4_header_t,
1134  dst_address);
1135  sum0 =
1136  ip_csum_update (sum0, vnet_buffer (b0)->ip.reass.l4_dst_port,
1137  s0->ext_host_port, ip4_header_t, length);
1138  udp0->dst_port = s0->ext_host_port;
1139  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1140  }
1141  udp0->checksum = ip_csum_fold (sum0);
1142  vlib_increment_simple_counter (&sm->counters.fastpath.in2out_ed.udp,
1143  thread_index, sw_if_index0, 1);
1144  }
1145  else
1146  {
1147  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1148  {
1149  new_port0 = udp0->src_port = s0->out2in.port;
1151  {
1152  udp0->dst_port = s0->ext_host_port;
1153  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1154  }
1156  in2out_ed.udp, thread_index,
1157  sw_if_index0, 1);
1158  }
1159  }
1160 
1161  /* Accounting */
1163  vlib_buffer_length_in_chain (vm, b0),
1164  thread_index);
1165  /* Per-user LRU list maintenance */
1166  nat44_session_update_lru (sm, s0, thread_index);
1167 
1168  trace0:
1169  if (PREDICT_FALSE
1170  ((node->flags & VLIB_NODE_FLAG_TRACE)
1171  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1172  {
1174  vlib_add_trace (vm, node, b0, sizeof (*t));
1175  t->sw_if_index = sw_if_index0;
1176  t->next_index = next[0];
1177  t->is_slow_path = 0;
1178 
1179  if (s0)
1180  t->session_index = s0 - tsm->sessions;
1181  else
1182  t->session_index = ~0;
1183  }
1184 
1185  if (next[0] == NAT_NEXT_DROP)
1186  {
1188  in2out_ed.drops, thread_index,
1189  sw_if_index0, 1);
1190  }
1191 
1192  n_left_from--;
1193  next++;
1194  }
1195 
1196  vlib_buffer_enqueue_to_next (vm, node, from, (u16 *) nexts,
1197  frame->n_vectors);
1198  return frame->n_vectors;
1199 }
1200 
1201 static inline uword
1204  vlib_frame_t * frame,
1205  int is_output_feature)
1206 {
1207  u32 n_left_from, *from;
1208  snat_main_t *sm = &snat_main;
1209  f64 now = vlib_time_now (vm);
1210  u32 thread_index = vm->thread_index;
1211  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
1212 
1213  from = vlib_frame_vector_args (frame);
1214  n_left_from = frame->n_vectors;
1215 
1216  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
1217  u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
1218  vlib_get_buffers (vm, from, b, n_left_from);
1219 
1220  while (n_left_from > 0)
1221  {
1222  vlib_buffer_t *b0;
1223  u32 sw_if_index0, rx_fib_index0, proto0, new_addr0, old_addr0,
1224  iph_offset0 = 0;
1225  u16 old_port0, new_port0;
1226  ip4_header_t *ip0;
1227  udp_header_t *udp0;
1228  tcp_header_t *tcp0;
1229  icmp46_header_t *icmp0;
1230  snat_session_t *s0 = 0;
1231  clib_bihash_kv_16_8_t kv0, value0;
1232  ip_csum_t sum0;
1233 
1234  b0 = *b;
1235 
1236  if (is_output_feature)
1237  iph_offset0 = vnet_buffer (b0)->ip.reass.save_rewrite_length;
1238 
1239  next[0] = vnet_buffer2 (b0)->nat.arc_next;
1240 
1241  ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
1242  iph_offset0);
1243 
1244  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1245  rx_fib_index0 =
1247 
1248  if (PREDICT_FALSE (ip0->ttl == 1))
1249  {
1250  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1251  icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
1252  ICMP4_time_exceeded_ttl_exceeded_in_transit,
1253  0);
1254  next[0] = NAT_NEXT_ICMP_ERROR;
1255  goto trace0;
1256  }
1257 
1258  udp0 = ip4_next_header (ip0);
1259  tcp0 = (tcp_header_t *) udp0;
1260  icmp0 = (icmp46_header_t *) udp0;
1261  proto0 = ip_proto_to_nat_proto (ip0->protocol);
1262 
1263  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_OTHER))
1264  {
1265  s0 = nat44_ed_in2out_unknown_proto (sm, b0, ip0,
1266  rx_fib_index0,
1267  thread_index, now, vm, node);
1268  if (!s0)
1269  next[0] = NAT_NEXT_DROP;
1270 
1272  in2out_ed.other, thread_index,
1273  sw_if_index0, 1);
1274  goto trace0;
1275  }
1276 
1277  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP))
1278  {
1279  next[0] =
1280  icmp_in2out_ed_slow_path (sm, b0, ip0, icmp0, sw_if_index0,
1281  rx_fib_index0, node, next[0], now,
1282  thread_index, &s0);
1284  in2out_ed.icmp, thread_index,
1285  sw_if_index0, 1);
1286  goto trace0;
1287  }
1288 
1289  init_ed_k (&kv0, ip0->src_address,
1290  vnet_buffer (b0)->ip.reass.l4_src_port, ip0->dst_address,
1291  vnet_buffer (b0)->ip.reass.l4_dst_port, rx_fib_index0,
1292  ip0->protocol);
1293  if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv0, &value0))
1294  {
1295  ASSERT (thread_index == ed_value_get_thread_index (&value0));
1296  s0 =
1298  ed_value_get_session_index (&value0));
1299 
1300  if (s0->tcp_closed_timestamp && now >= s0->tcp_closed_timestamp)
1301  {
1302  nat_free_session_data (sm, s0, thread_index, 0);
1303  nat_ed_session_delete (sm, s0, thread_index, 1);
1304  s0 = NULL;
1305  }
1306  }
1307 
1308  if (!s0)
1309  {
1310  if (is_output_feature)
1311  {
1312  if (PREDICT_FALSE
1314  (sm, ip0, vnet_buffer (b0)->ip.reass.l4_src_port,
1315  vnet_buffer (b0)->ip.reass.l4_dst_port, thread_index,
1316  sw_if_index0, vnet_buffer (b0)->sw_if_index[VLIB_TX],
1317  now)))
1318  goto trace0;
1319 
1320  /*
1321  * Send DHCP packets to the ipv4 stack, or we won't
1322  * be able to use dhcp client on the outside interface
1323  */
1324  if (PREDICT_FALSE
1325  (proto0 == NAT_PROTOCOL_UDP
1326  && (vnet_buffer (b0)->ip.reass.l4_dst_port ==
1327  clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_server))
1328  && ip0->dst_address.as_u32 == 0xffffffff))
1329  goto trace0;
1330  }
1331  else
1332  {
1333  if (PREDICT_FALSE
1335  (sm, node, sw_if_index0, ip0, proto0, rx_fib_index0,
1336  thread_index)))
1337  goto trace0;
1338  }
1339 
1340  next[0] =
1341  slow_path_ed (sm, b0, ip0->src_address, ip0->dst_address,
1342  vnet_buffer (b0)->ip.reass.l4_src_port,
1343  vnet_buffer (b0)->ip.reass.l4_dst_port,
1344  ip0->protocol, rx_fib_index0, &s0, node, next[0],
1345  thread_index, now);
1346 
1347  if (PREDICT_FALSE (next[0] == NAT_NEXT_DROP))
1348  goto trace0;
1349 
1350  if (PREDICT_FALSE (!s0))
1351  goto trace0;
1352 
1353  }
1354 
1355  b0->flags |= VNET_BUFFER_F_IS_NATED;
1356 
1357  if (!is_output_feature)
1358  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->out2in.fib_index;
1359 
1360  old_addr0 = ip0->src_address.as_u32;
1361  new_addr0 = ip0->src_address.as_u32 = s0->out2in.addr.as_u32;
1362  sum0 = ip0->checksum;
1363  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1364  src_address);
1366  sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1367  s0->ext_host_addr.as_u32, ip4_header_t,
1368  dst_address);
1369  ip0->checksum = ip_csum_fold (sum0);
1370 
1371  old_port0 = vnet_buffer (b0)->ip.reass.l4_src_port;
1372 
1373  if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP))
1374  {
1375  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1376  {
1377  new_port0 = udp0->src_port = s0->out2in.port;
1378  sum0 = tcp0->checksum;
1379  sum0 =
1380  ip_csum_update (sum0, old_addr0, new_addr0,
1381  ip4_header_t, dst_address);
1382  sum0 =
1383  ip_csum_update (sum0, old_port0, new_port0,
1384  ip4_header_t, length);
1386  {
1387  sum0 =
1388  ip_csum_update (sum0, ip0->dst_address.as_u32,
1389  s0->ext_host_addr.as_u32,
1390  ip4_header_t, dst_address);
1391  sum0 =
1392  ip_csum_update (sum0,
1393  vnet_buffer (b0)->ip.reass.l4_dst_port,
1394  s0->ext_host_port, ip4_header_t, length);
1395  tcp0->dst_port = s0->ext_host_port;
1396  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1397  }
1398  mss_clamping (sm->mss_clamping, tcp0, &sum0);
1399  tcp0->checksum = ip_csum_fold (sum0);
1400  }
1401  vlib_increment_simple_counter (&sm->counters.slowpath.in2out_ed.tcp,
1402  thread_index, sw_if_index0, 1);
1403  nat44_set_tcp_session_state_i2o (sm, now, s0, b0, thread_index);
1404  }
1405  else if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment
1406  && udp0->checksum)
1407  {
1408  new_port0 = udp0->src_port = s0->out2in.port;
1409  sum0 = udp0->checksum;
1410  sum0 =
1411  ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1412  dst_address);
1413  sum0 =
1414  ip_csum_update (sum0, old_port0, new_port0, ip4_header_t, length);
1416  {
1417  sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1418  s0->ext_host_addr.as_u32,
1419  ip4_header_t, dst_address);
1420  sum0 =
1421  ip_csum_update (sum0,
1422  vnet_buffer (b0)->ip.reass.l4_dst_port,
1423  s0->ext_host_port, ip4_header_t, length);
1424  udp0->dst_port = s0->ext_host_port;
1425  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1426  }
1427  udp0->checksum = ip_csum_fold (sum0);
1428  vlib_increment_simple_counter (&sm->counters.slowpath.in2out_ed.udp,
1429  thread_index, sw_if_index0, 1);
1430  }
1431  else
1432  {
1433  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1434  {
1435  new_port0 = udp0->src_port = s0->out2in.port;
1437  {
1438  udp0->dst_port = s0->ext_host_port;
1439  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1440  }
1442  in2out_ed.udp, thread_index,
1443  sw_if_index0, 1);
1444  }
1445  }
1446 
1447  /* Accounting */
1450  (vm, b0), thread_index);
1451  /* Per-user LRU list maintenance */
1452  nat44_session_update_lru (sm, s0, thread_index);
1453 
1454  trace0:
1456  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1457  {
1459  vlib_add_trace (vm, node, b0, sizeof (*t));
1460  t->sw_if_index = sw_if_index0;
1461  t->next_index = next[0];
1462  t->is_slow_path = 1;
1463 
1464  if (s0)
1465  t->session_index = s0 - tsm->sessions;
1466  else
1467  t->session_index = ~0;
1468  }
1469 
1470  if (next[0] == NAT_NEXT_DROP)
1471  {
1473  in2out_ed.drops, thread_index,
1474  sw_if_index0, 1);
1475  }
1476 
1477  n_left_from--;
1478  next++;
1479  b++;
1480  }
1481 
1482  vlib_buffer_enqueue_to_next (vm, node, from, (u16 *) nexts,
1483  frame->n_vectors);
1484 
1485  return frame->n_vectors;
1486 }
1487 
1490  vlib_frame_t * frame)
1491 {
1493 }
1494 
1495 /* *INDENT-OFF* */
1497  .name = "nat44-ed-in2out",
1498  .vector_size = sizeof (u32),
1499  .sibling_of = "nat-default",
1500  .format_trace = format_nat_in2out_ed_trace,
1502  .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1503  .error_strings = nat_in2out_ed_error_strings,
1504  .runtime_data_bytes = sizeof (snat_runtime_t),
1505 };
1506 /* *INDENT-ON* */
1507 
1510  vlib_frame_t * frame)
1511 {
1513 }
1514 
1515 /* *INDENT-OFF* */
1517  .name = "nat44-ed-in2out-output",
1518  .vector_size = sizeof (u32),
1519  .sibling_of = "nat-default",
1520  .format_trace = format_nat_in2out_ed_trace,
1522  .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1523  .error_strings = nat_in2out_ed_error_strings,
1524  .runtime_data_bytes = sizeof (snat_runtime_t),
1525 };
1526 /* *INDENT-ON* */
1527 
1530  node, vlib_frame_t * frame)
1531 {
1533 }
1534 
1535 /* *INDENT-OFF* */
1537  .name = "nat44-ed-in2out-slowpath",
1538  .vector_size = sizeof (u32),
1539  .sibling_of = "nat-default",
1540  .format_trace = format_nat_in2out_ed_trace,
1542  .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1543  .error_strings = nat_in2out_ed_error_strings,
1544  .runtime_data_bytes = sizeof (snat_runtime_t),
1545 };
1546 /* *INDENT-ON* */
1547 
1550  * node,
1551  vlib_frame_t * frame)
1552 {
1554 }
1555 
1556 /* *INDENT-OFF* */
1558  .name = "nat44-ed-in2out-output-slowpath",
1559  .vector_size = sizeof (u32),
1560  .sibling_of = "nat-default",
1561  .format_trace = format_nat_in2out_ed_trace,
1563  .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1564  .error_strings = nat_in2out_ed_error_strings,
1565  .runtime_data_bytes = sizeof (snat_runtime_t),
1566 };
1567 /* *INDENT-ON* */
1568 
1569 static u8 *
1570 format_nat_pre_trace (u8 * s, va_list * args)
1571 {
1572  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1573  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1574  nat_pre_trace_t *t = va_arg (*args, nat_pre_trace_t *);
1575  return format (s, "in2out next_index %d arc_next_index %d", t->next_index,
1576  t->arc_next_index);
1577 }
1578 
1582  return nat_pre_node_fn_inline (vm, node, frame,
1584 }
1585 
1588 {
1589  return nat_pre_node_fn_inline (vm, node, frame,
1591 }
1592 
1593 /* *INDENT-OFF* */
1595  .name = "nat-pre-in2out",
1596  .vector_size = sizeof (u32),
1597  .sibling_of = "nat-default",
1598  .format_trace = format_nat_pre_trace,
1600  .n_errors = 0,
1601 };
1602 
1604  .name = "nat-pre-in2out-output",
1605  .vector_size = sizeof (u32),
1606  .sibling_of = "nat-default",
1607  .format_trace = format_nat_pre_trace,
1609  .n_errors = 0,
1610 };
1611 /* *INDENT-ON* */
1612 
1613 /*
1614  * fd.io coding-style-patch-verification: ON
1615  *
1616  * Local Variables:
1617  * eval: (c-set-style "gnu")
1618  * End:
1619  */
ip4_address_t external_addr
Definition: nat.h:386
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:211
nat_outside_fib_t * outside_fibs
Definition: nat.h:565
#define snat_is_session_static(s)
Check if SNAT session is created from static mapping.
Definition: nat.h:786
vlib_node_registration_t nat44_ed_in2out_output_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_output_node)
Definition: in2out_ed.c:1516
clib_bihash_16_8_t out2in_ed
Definition: nat.h:541
#define CLIB_UNUSED(x)
Definition: clib.h:87
u32 arc_next_index
Definition: nat.h:100
a
Definition: bitmap.h:544
ip4_address_t src_address
Definition: ip4_packet.h:125
#define nat_elog_info(nat_elog_str)
Definition: nat.h:1064
void nat_ipfix_logging_addresses_exhausted(u32 thread_index, u32 pool_id)
Generate NAT addresses exhausted event.
#define vnet_buffer2(b)
Definition: buffer.h:481
static u32 nat44_session_get_timeout(snat_main_t *sm, snat_session_t *s)
Definition: nat_inlines.h:396
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:527
#define nat_elog_notice(nat_elog_str)
Definition: nat.h:1056
vlib_node_registration_t nat_pre_in2out_output_node
(constructor) VLIB_REGISTER_NODE (nat_pre_in2out_output_node)
Definition: in2out_ed.c:1603
#define PREDICT_TRUE(x)
Definition: clib.h:122
unsigned long u64
Definition: types.h:89
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, nat_protocol_t proto, u8 is_twicenat)
Definition: nat_syslog.c:197
vl_api_ip_port_and_mask_t dst_port
Definition: flow_types.api:92
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:334
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:998
u16 port_per_thread
Definition: nat.h:526
u32 thread_index
Definition: main.h:250
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 address port)
Definition: nat.c:376
static_always_inline void per_vrf_sessions_register_session(snat_session_t *s, u32 thread_index)
Definition: ed_inlines.h:178
#define foreach_nat_in2out_ed_error
Definition: nat.h:150
uword ip_csum_t
Definition: ip_packet.h:246
#define nat_elog_warn(nat_elog_str)
Definition: nat.h:1058
vlib_main_t * vm
Definition: in2out_ed.c:1580
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:692
static void vlib_increment_simple_counter(vlib_simple_counter_main_t *cm, u32 thread_index, u32 index, u64 increment)
Increment a simple counter.
Definition: counter.h:78
#define nat44_is_ses_closed(s)
Check if NAT44 endpoint-dependent TCP session is closed.
Definition: nat.h:846
nat_protocol_t
Definition: lib.h:63
#define VLIB_NODE_FN(node)
Definition: node.h:203
static void nat_ed_session_delete(snat_main_t *sm, snat_session_t *ses, u32 thread_index, int lru_delete)
Definition: ed_inlines.h:55
static void init_ed_kv(clib_bihash_kv_16_8_t *kv, ip4_address_t l_addr, u16 l_port, ip4_address_t r_addr, u16 r_port, u32 fib_index, u8 proto, u32 thread_index, u32 session_index)
Definition: nat_inlines.h:467
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:498
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:402
struct _tcp_header tcp_header_t
#define snat_is_unk_proto_session(s)
Check if SNAT session for unknown protocol.
Definition: nat.h:792
u32 max_translations_per_thread
Definition: nat.h:642
vhost_vring_addr_t addr
Definition: vhost_user.h:111
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:761
unsigned char u8
Definition: types.h:56
double f64
Definition: types.h:142
static uword nat44_ed_in2out_slow_path_node_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_output_feature)
Definition: in2out_ed.c:1202
u32 next_index
Definition: nat.h:99
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:671
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
Definition: ip4_fib.c:227
#define static_always_inline
Definition: clib.h:109
static nat_protocol_t ip_proto_to_nat_proto(u8 ip_proto)
Common NAT inline functions.
Definition: inlines.h:24
int snat_static_mapping_match(snat_main_t *sm, ip4_address_t match_addr, u16 match_port, u32 match_fib_index, nat_protocol_t match_protocol, ip4_address_t *mapping_addr, u16 *mapping_port, u32 *mapping_fib_index, 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, snat_static_mapping_t **out)
Match NAT44 static mapping.
Definition: nat.c:3183
ip4_address_t dst_address
Definition: ip4_packet.h:125
static void nat44_set_tcp_session_state_i2o(snat_main_t *sm, f64 now, snat_session_t *ses, vlib_buffer_t *b, u32 thread_index)
Definition: nat_inlines.h:303
description fragment has unexpected format
Definition: map.api:433
static_always_inline u8 per_vrf_sessions_is_expired(snat_session_t *s, u32 thread_index)
Definition: ed_inlines.h:241
lb_nat_type_t
Definition: nat.h:369
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:207
#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:202
static_always_inline u8 icmp_type_is_error_message(u8 icmp_type)
Definition: inlines.h:55
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:642
#define is_fwd_bypass_session(s)
Check if NAT session is forwarding bypass.
Definition: nat.h:810
const cJSON *const b
Definition: cJSON.h:255
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:196
unsigned int u32
Definition: types.h:88
static_always_inline int get_icmp_i2o_ed_key(vlib_buffer_t *b, ip4_header_t *ip0, u32 rx_fib_index, u32 thread_index, u32 session_index, nat_protocol_t *nat_proto, u16 *l_port, u16 *r_port, clib_bihash_kv_16_8_t *kv)
Definition: nat_inlines.h:519
static_always_inline u32 nat_outside_fib_index_lookup(snat_main_t *sm, ip4_address_t addr)
Definition: in2out_ed.c:292
#define VLIB_FRAME_SIZE
Definition: node.h:378
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
vl_api_fib_path_type_t type
Definition: fib_types.api:123
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:136
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:546
static u32 slow_path_ed(snat_main_t *sm, vlib_buffer_t *b, ip4_address_t l_addr, ip4_address_t r_addr, u16 l_port, u16 r_port, u8 proto, u32 rx_fib_index, snat_session_t **sessionp, vlib_node_runtime_t *node, u32 next, u32 thread_index, f64 now)
Definition: in2out_ed.c:320
u32 fib_index
Definition: nat.h:341
vl_api_ip_proto_t proto
Definition: acl_types.api:51
long ctx[MAX_CONNS]
Definition: main.c:144
u16 mss_clamping
Definition: nat.h:656
vlib_node_registration_t nat44_ed_in2out_slowpath_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_slowpath_node)
Definition: in2out_ed.c:1536
unsigned short u16
Definition: types.h:57
static u32 ed_value_get_session_index(clib_bihash_kv_16_8_t *value)
Definition: nat_inlines.h:482
snat_static_mapping_t * static_mappings
Definition: nat.h:538
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:233
struct snat_main_s::@91 counters
static void mss_clamping(u16 mss_clamping, tcp_header_t *tcp, ip_csum_t *sum)
Definition: nat_inlines.h:32
static int nat_ed_alloc_addr_and_port(snat_main_t *sm, u32 rx_fib_index, u32 nat_proto, u32 thread_index, ip4_address_t r_addr, u16 r_port, u8 proto, u16 port_per_thread, u32 snat_thread_index, snat_session_t *s, ip4_address_t *outside_addr, u16 *outside_port, clib_bihash_kv_16_8_t *out2in_ed_kv)
Definition: in2out_ed.c:199
#define PREDICT_FALSE(x)
Definition: clib.h:121
#define nat_interface_is_inside(i)
Check if NAT interface is inside.
Definition: nat.h:834
vl_api_address_union_t src_address
Definition: ip_types.api:122
struct snat_main_s::@91::@93 slowpath
#define SNAT_SESSION_FLAG_UNKNOWN_PROTO
Definition: nat.h:210
static void init_nat_k(clib_bihash_kv_8_8_t *kv, ip4_address_t addr, u16 port, u32 fib_index, nat_protocol_t proto)
Definition: nat_inlines.h:58
static_always_inline snat_session_t * nat_ed_session_alloc(snat_main_t *sm, u32 thread_index, f64 now, u8 proto)
Definition: ed_inlines.h:126
static u8 * format_nat_pre_trace(u8 *s, va_list *args)
Definition: in2out_ed.c:1570
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:56
snat_interface_t * output_feature_interfaces
Definition: nat.h:545
snat_main_t snat_main
Definition: nat.c:39
vl_api_ip_port_and_mask_t src_port
Definition: flow_types.api:91
u64 value
the value
Definition: bihash_8_8.h:44
vlib_node_registration_t nat_pre_in2out_node
(constructor) VLIB_REGISTER_NODE (nat_pre_in2out_node)
Definition: in2out_ed.c:1594
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:170
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:98
vlib_node_registration_t nat44_ed_in2out_output_slowpath_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_output_slowpath_node)
Definition: in2out_ed.c:1557
static_always_inline void vlib_buffer_enqueue_to_next(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, u16 *nexts, uword count)
Definition: buffer_node.h:339
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
static void nat44_session_update_counters(snat_session_t *s, f64 now, uword bytes, u32 thread_index)
Definition: nat_inlines.h:419
u8 data[]
Packet data.
Definition: buffer.h:181
u32 outside_fib_index
Definition: nat.h:649
void nat_ipfix_logging_nat44_ses_create(u32 thread_index, u32 src_ip, u32 nat_src_ip, nat_protocol_t nat_proto, u16 src_port, u16 nat_src_port, u32 fib_index)
Generate NAT44 session create event.
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:29
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:41
#define ARRAY_LEN(x)
Definition: clib.h:67
u32 sw_if_index
Definition: nat.h:414
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:532
static uword nat_pre_node_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, u32 def_next)
Definition: nat_inlines.h:104
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1580
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, nat_protocol_t proto, u8 is_twicenat)
Definition: nat_syslog.c:209
vl_api_interface_index_t tx_sw_if_index
Definition: ip.api:441
u8 value
Definition: qos.api:54
#define ASSERT(truth)
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:433
#define SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT
Definition: nat.h:213
char const int length
Definition: cJSON.h:163
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:175
ip4_address_t addr
Definition: nat.h:321
vlib_node_registration_t nat44_ed_in2out_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_node)
Definition: in2out_ed.c:1496
snat_address_t * twice_nat_addresses
Definition: nat.h:568
static_always_inline u8 nat44_ed_maximum_sessions_exceeded(snat_main_t *sm, u32 fib_index, u32 thread_index)
Definition: inlines.h:35
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
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:718
void nat_ipfix_logging_max_sessions(u32 thread_index, u32 limit)
Generate maximum session entries exceeded event.
Definition: defs.h:47
struct snat_main_s::@91::@92 fastpath
vl_api_address_t ip
Definition: l2.api:501
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:30
int nat44_i2o_ed_is_idle_session_cb(clib_bihash_kv_16_8_t *kv, void *arg)
Definition: in2out_ed.c:75
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static_always_inline u8 nat_proto_to_ip_proto(nat_protocol_t nat_proto)
Definition: inlines.h:37
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1581
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:529
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:297
#define ip_csum_update(sum, old, new, type, field)
Definition: ip_packet.h:296
NAT syslog logging.
snat_address_t * addresses
Definition: nat.h:548
u16 port
Definition: lb_types.api:73
static void init_ed_k(clib_bihash_kv_16_8_t *kv, ip4_address_t l_addr, u16 l_port, ip4_address_t r_addr, u16 r_port, u32 fib_index, u8 proto)
Definition: nat_inlines.h:458
#define vnet_buffer(b)
Definition: buffer.h:417
#define SNAT_SESSION_FLAG_STATIC_MAPPING
Definition: nat.h:209
void nat44_ed_hairpinning_unknown_proto(snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip)
u8 forwarding_enabled
Definition: nat.h:628
#define vec_foreach(var, vec)
Vector iterator.
u16 flags
Copy of main node flags.
Definition: node.h:501
#define is_twice_nat_session(s)
Check if NAT session is twice NAT.
Definition: nat.h:798
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:634
clib_bihash_16_8_t in2out_ed
Definition: nat.h:444
static_always_inline int nat_lru_free_one(snat_main_t *sm, int thread_index, f64 now)
Definition: ed_inlines.h:106
static_always_inline void vlib_get_buffers(vlib_main_t *vm, u32 *bi, vlib_buffer_t **b, int count)
Translate array of buffer indices into buffer pointers.
Definition: buffer_funcs.h:280
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:302
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
void snat_free_outside_address_and_port(snat_address_t *addresses, u32 thread_index, ip4_address_t *addr, u16 port, nat_protocol_t protocol)
Free outside address and port pair.
Definition: nat.c:3108
static_always_inline int nat44_ed_not_translate_output_feature(snat_main_t *sm, ip4_header_t *ip, u16 src_port, u16 dst_port, u32 thread_index, u32 rx_sw_if_index, u32 tx_sw_if_index, f64 now)
Definition: in2out_ed.c:588
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, ip4_address_t *addr, u16 *port, u32 *fib_index, nat_protocol_t *proto, void *d, void *e, u8 *dont_translate)
Definition: in2out_ed.c:646
snat_session_t * sessions
Definition: nat.h:453
static_always_inline void icmp4_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
Definition: icmp4.h:51
static char * nat_in2out_ed_error_strings[]
Definition: in2out_ed.c:41
#define SNAT_SESSION_FLAG_LOAD_BALANCING
Definition: nat.h:211
clib_bihash_8_8_t static_mapping_by_local
Definition: nat.h:532
static u32 ed_value_get_thread_index(clib_bihash_kv_16_8_t *value)
Definition: nat_inlines.h:476
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:302
static uword nat44_ed_in2out_fast_path_node_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_output_feature)
Definition: in2out_ed.c:916
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
Definition: defs.h:46
NAT active-passive HA.
void nat_ipfix_logging_nat44_ses_delete(u32 thread_index, u32 src_ip, u32 nat_src_ip, nat_protocol_t nat_proto, u16 src_port, u16 nat_src_port, u32 fib_index)
Generate NAT44 session delete event.
static bool tcp_flags_is_init(u8 f)
Check if client initiating TCP connection (received SYN from client)
Definition: nat.h:883