FD.io VPP  v21.01
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  /* First try to match static mapping by local address and port */
371  (sm, l_addr, l_port, rx_fib_index, nat_proto, &sm_addr, &sm_port,
372  &sm_fib_index, 0, 0, 0, &lb, 0, &identity_nat, 0))
373  {
374  s = nat_ed_session_alloc (sm, thread_index, now, proto);
375  ASSERT (s);
376  s->in2out.addr = l_addr;
377  s->in2out.port = l_port;
378  s->nat_proto = nat_proto;
379  s->in2out.fib_index = rx_fib_index;
380  s->out2in.fib_index = sm->outside_fib_index;
381 
382  switch (vec_len (sm->outside_fibs))
383  {
384  case 0:
385  s->out2in.fib_index = sm->outside_fib_index;
386  break;
387  case 1:
388  s->out2in.fib_index = sm->outside_fibs[0].fib_index;
389  break;
390  default:
391  s->out2in.fib_index = nat_outside_fib_index_lookup (sm, r_addr);
392  break;
393  }
394 
395  /* Try to create dynamic translation */
396  outside_port = l_port; // suggest using local port to allocation function
397  if (nat_ed_alloc_addr_and_port (sm, rx_fib_index, nat_proto,
398  thread_index, r_addr, r_port, proto,
399  sm->port_per_thread,
400  tsm->snat_thread_index, s,
401  &outside_addr,
402  &outside_port, &out2in_ed_kv))
403  {
404  nat_elog_notice ("addresses exhausted");
405  b->error = node->errors[NAT_IN2OUT_ED_ERROR_OUT_OF_PORTS];
406  nat_ed_session_delete (sm, s, thread_index, 1);
407  return NAT_NEXT_DROP;
408  }
409  s->out2in.addr = outside_addr;
410  s->out2in.port = outside_port;
411  }
412  else
413  {
414  if (PREDICT_FALSE (identity_nat))
415  {
416  *sessionp = NULL;
417  return next;
418  }
419  s = nat_ed_session_alloc (sm, thread_index, now, proto);
420  ASSERT (s);
421  s->out2in.addr = sm_addr;
422  s->out2in.port = sm_port;
423  s->in2out.addr = l_addr;
424  s->in2out.port = l_port;
425  s->nat_proto = nat_proto;
426  s->in2out.fib_index = rx_fib_index;
427  s->out2in.fib_index = sm->outside_fib_index;
428  switch (vec_len (sm->outside_fibs))
429  {
430  case 0:
431  s->out2in.fib_index = sm->outside_fib_index;
432  break;
433  case 1:
434  s->out2in.fib_index = sm->outside_fibs[0].fib_index;
435  break;
436  default:
437  s->out2in.fib_index = nat_outside_fib_index_lookup (sm, r_addr);
438  break;
439  }
440 
442 
443  init_ed_kv (&out2in_ed_kv, sm_addr, sm_port, r_addr, r_port,
444  s->out2in.fib_index, proto, thread_index,
445  s - tsm->sessions);
446  if (clib_bihash_add_or_overwrite_stale_16_8
447  (&sm->out2in_ed, &out2in_ed_kv, nat44_o2i_ed_is_idle_session_cb,
448  &ctx))
449  nat_elog_notice ("out2in-ed key add failed");
450  }
451 
452  if (lb)
455  s->ext_host_addr = r_addr;
456  s->ext_host_port = r_port;
457 
458  clib_bihash_kv_16_8_t in2out_ed_kv;
459  init_ed_kv (&in2out_ed_kv, l_addr, l_port, r_addr, r_port, rx_fib_index,
460  proto, thread_index, s - tsm->sessions);
461  ctx.now = now;
462  ctx.thread_index = thread_index;
463  if (clib_bihash_add_or_overwrite_stale_16_8 (&tsm->in2out_ed, &in2out_ed_kv,
465  &ctx))
466  nat_elog_notice ("in2out-ed key add failed");
467 
468  *sessionp = s;
469 
470  /* log NAT event */
472  s->in2out.addr.as_u32,
473  s->out2in.addr.as_u32,
474  s->nat_proto,
475  s->in2out.port,
476  s->out2in.port, s->in2out.fib_index);
477 
478  nat_syslog_nat44_sadd (s->user_index, s->in2out.fib_index,
479  &s->in2out.addr, s->in2out.port,
480  &s->ext_host_nat_addr, s->ext_host_nat_port,
481  &s->out2in.addr, s->out2in.port,
482  &s->ext_host_addr, s->ext_host_port, s->nat_proto,
483  0);
484 
485  nat_ha_sadd (&s->in2out.addr, s->in2out.port, &s->out2in.addr,
486  s->out2in.port, &s->ext_host_addr, s->ext_host_port,
487  &s->ext_host_nat_addr, s->ext_host_nat_port,
488  s->nat_proto, s->in2out.fib_index, s->flags, thread_index, 0);
489 
490  per_vrf_sessions_register_session (s, thread_index);
491 
492  return next;
493 }
494 
498  u32 rx_fib_index, u32 thread_index)
499 {
500  udp_header_t *udp = ip4_next_header (ip);
502 
503  init_ed_k (&kv, ip->dst_address, udp->dst_port, ip->src_address,
504  udp->src_port, sm->outside_fib_index, ip->protocol);
505 
506  /* NAT packet aimed at external address if has active sessions */
507  if (clib_bihash_search_16_8 (&sm->out2in_ed, &kv, &value))
508  {
509  /* or is static mappings */
510  ip4_address_t placeholder_addr;
511  u16 placeholder_port;
512  u32 placeholder_fib_index;
514  (sm, ip->dst_address, udp->dst_port, sm->outside_fib_index, proto,
515  &placeholder_addr, &placeholder_port, &placeholder_fib_index, 1, 0,
516  0, 0, 0, 0, 0))
517  return 0;
518  }
519  else
520  return 0;
521 
522  if (sm->forwarding_enabled)
523  return 1;
524 
525  return snat_not_translate_fast (sm, node, sw_if_index, ip, proto,
526  rx_fib_index);
527 }
528 
531  u32 thread_index, f64 now,
532  vlib_main_t * vm, vlib_buffer_t * b)
533 {
535  snat_session_t *s = 0;
536  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
537 
538  if (!sm->forwarding_enabled)
539  return 0;
540 
541  if (ip->protocol == IP_PROTOCOL_ICMP)
542  {
543  if (get_icmp_i2o_ed_key (b, ip, 0, ~0, ~0, 0, 0, 0, &kv))
544  return 0;
545  }
546  else if (ip->protocol == IP_PROTOCOL_UDP || ip->protocol == IP_PROTOCOL_TCP)
547  {
548  init_ed_k (&kv, ip->src_address, vnet_buffer (b)->ip.reass.l4_src_port,
549  ip->dst_address, vnet_buffer (b)->ip.reass.l4_dst_port, 0,
550  ip->protocol);
551  }
552  else
553  {
554  init_ed_k (&kv, ip->src_address, 0, ip->dst_address, 0, 0,
555  ip->protocol);
556  }
557 
558  if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
559  {
560  ASSERT (thread_index == ed_value_get_thread_index (&value));
561  s =
563  ed_value_get_session_index (&value));
564  if (is_fwd_bypass_session (s))
565  {
566  if (ip->protocol == IP_PROTOCOL_TCP)
567  {
568  nat44_set_tcp_session_state_i2o (sm, now, s, b, thread_index);
569  }
570  /* Accounting */
573  thread_index);
574  /* Per-user LRU list maintenance */
575  nat44_session_update_lru (sm, s, thread_index);
576  return 1;
577  }
578  else
579  return 0;
580  }
581 
582  return 0;
583 }
584 
588  u32 thread_index, u32 rx_sw_if_index,
589  u32 tx_sw_if_index, f64 now)
590 {
592  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
594  snat_session_t *s;
595  u32 rx_fib_index = ip4_fib_table_get_index_for_sw_if_index (rx_sw_if_index);
596  u32 tx_fib_index = ip4_fib_table_get_index_for_sw_if_index (tx_sw_if_index);
597 
598  /* src NAT check */
599  init_ed_k (&kv, ip->src_address, src_port, ip->dst_address, dst_port,
600  tx_fib_index, ip->protocol);
601  if (!clib_bihash_search_16_8 (&sm->out2in_ed, &kv, &value))
602  {
603  ASSERT (thread_index == ed_value_get_thread_index (&value));
604  s =
606  ed_value_get_session_index (&value));
607  if (nat44_is_ses_closed (s)
608  && (!s->tcp_closed_timestamp || now >= s->tcp_closed_timestamp))
609  {
610  nat_free_session_data (sm, s, thread_index, 0);
611  nat_ed_session_delete (sm, s, thread_index, 1);
612  }
613  return 1;
614  }
615 
616  /* dst NAT check */
617  init_ed_k (&kv, ip->dst_address, dst_port, ip->src_address, src_port,
618  rx_fib_index, ip->protocol);
619  if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
620  {
621  ASSERT (thread_index == ed_value_get_thread_index (&value));
622  s =
624  ed_value_get_session_index (&value));
625  if (is_fwd_bypass_session (s))
626  return 0;
627 
628  /* hairpinning */
629  /* *INDENT-OFF* */
631  {
632  if ((nat_interface_is_inside (i)) && (rx_sw_if_index == i->sw_if_index))
633  return 0;
634  }
635  /* *INDENT-ON* */
636  return 1;
637  }
638 
639  return 0;
640 }
641 
642 #ifndef CLIB_MARCH_VARIANT
643 u32
645  u32 thread_index, vlib_buffer_t * b,
647  u16 * port, u32 * fib_index, nat_protocol_t * proto,
648  void *d, void *e, u8 * dont_translate)
649 {
651  u32 rx_fib_index;
653  u32 next = ~0;
654  int err;
655  snat_session_t *s = NULL;
656  u16 l_port = 0, r_port = 0; // initialize to workaround gcc warning
657  vlib_main_t *vm = vlib_get_main ();
658  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
659  *dont_translate = 0;
660  f64 now = vlib_time_now (vm);
661 
662  sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
663  rx_fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
664 
665  err =
666  get_icmp_i2o_ed_key (b, ip, rx_fib_index, ~0, ~0, proto, &l_port,
667  &r_port, &kv);
668  if (err != 0)
669  {
670  b->error = node->errors[err];
671  next = NAT_NEXT_DROP;
672  goto out;
673  }
674 
675  if (clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
676  {
677  if (vnet_buffer (b)->sw_if_index[VLIB_TX] != ~0)
678  {
679  if (PREDICT_FALSE
681  (sm, ip, l_port, r_port, thread_index,
682  sw_if_index, vnet_buffer (b)->sw_if_index[VLIB_TX], now)))
683  {
684  *dont_translate = 1;
685  goto out;
686  }
687  }
688  else
689  {
690  if (PREDICT_FALSE (nat44_ed_not_translate (sm, node, sw_if_index,
691  ip, NAT_PROTOCOL_ICMP,
692  rx_fib_index,
693  thread_index)))
694  {
695  *dont_translate = 1;
696  goto out;
697  }
698  }
699 
700  if (PREDICT_FALSE
702  (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags)))
703  {
704  b->error = node->errors[NAT_IN2OUT_ED_ERROR_BAD_ICMP_TYPE];
705  next = NAT_NEXT_DROP;
706  goto out;
707  }
708 
709  next =
710  slow_path_ed (sm, b, ip->src_address, ip->dst_address, l_port, r_port,
711  ip->protocol, rx_fib_index, &s, node, next,
712  thread_index, vlib_time_now (vm));
713 
714  if (PREDICT_FALSE (next == NAT_NEXT_DROP))
715  goto out;
716 
717  if (!s)
718  {
719  *dont_translate = 1;
720  goto out;
721  }
722  }
723  else
724  {
725  if (PREDICT_FALSE
726  (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags !=
727  ICMP4_echo_request
728  && vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags !=
729  ICMP4_echo_reply
731  reass.icmp_type_or_tcp_flags)))
732  {
733  b->error = node->errors[NAT_IN2OUT_ED_ERROR_BAD_ICMP_TYPE];
734  next = NAT_NEXT_DROP;
735  goto out;
736  }
737 
738  ASSERT (thread_index == ed_value_get_thread_index (&value));
739  s =
741  ed_value_get_session_index (&value));
742  }
743 out:
744  if (s)
745  {
746  *addr = s->out2in.addr;
747  *port = s->out2in.port;
748  *fib_index = s->out2in.fib_index;
749  }
750  if (d)
751  {
752  *(snat_session_t **) d = s;
753  }
754  return next;
755 }
756 #endif
757 
758 static snat_session_t *
760  vlib_buffer_t * b,
761  ip4_header_t * ip,
762  u32 rx_fib_index,
763  u32 thread_index,
764  f64 now,
766 {
768  clib_bihash_kv_16_8_t s_kv, s_value;
770  u32 old_addr, new_addr = 0;
771  ip_csum_t sum;
772  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
773  snat_session_t *s;
774  u32 outside_fib_index = sm->outside_fib_index;
775  int i;
776  u8 is_sm = 0;
777 
778  switch (vec_len (sm->outside_fibs))
779  {
780  case 0:
781  outside_fib_index = sm->outside_fib_index;
782  break;
783  case 1:
784  outside_fib_index = sm->outside_fibs[0].fib_index;
785  break;
786  default:
787  outside_fib_index = nat_outside_fib_index_lookup (sm, ip->dst_address);
788  break;
789  }
790  old_addr = ip->src_address.as_u32;
791 
792  init_ed_k (&s_kv, ip->src_address, 0, ip->dst_address, 0, rx_fib_index,
793  ip->protocol);
794 
795  if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &s_kv, &s_value))
796  {
797  ASSERT (thread_index == ed_value_get_thread_index (&s_value));
798  s =
800  ed_value_get_session_index (&s_value));
801  new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32;
802  }
803  else
804  {
805  if (PREDICT_FALSE
807  (sm, rx_fib_index, thread_index)))
808  {
809  b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
810  nat_ipfix_logging_max_sessions (thread_index,
812  nat_elog_notice ("maximum sessions exceeded");
813  return 0;
814  }
815 
816  init_nat_k (&kv, ip->src_address, 0, rx_fib_index, 0);
817 
818  /* Try to find static mapping first */
819  if (!clib_bihash_search_8_8 (&sm->static_mapping_by_local, &kv, &value))
820  {
821  m = pool_elt_at_index (sm->static_mappings, value.value);
822  new_addr = ip->src_address.as_u32 = m->external_addr.as_u32;
823  is_sm = 1;
824  goto create_ses;
825  }
826  else
827  {
828  /* *INDENT-OFF* */
829  pool_foreach (s, tsm->sessions) {
830  if (s->ext_host_addr.as_u32 == ip->dst_address.as_u32)
831  {
832  new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32;
833 
834  init_ed_k(&s_kv, s->out2in.addr, 0, ip->dst_address, 0, outside_fib_index, ip->protocol);
835  if (clib_bihash_search_16_8 (&sm->out2in_ed, &s_kv, &s_value))
836  goto create_ses;
837 
838  break;
839  }
840  }
841  /* *INDENT-ON* */
842 
843  for (i = 0; i < vec_len (sm->addresses); i++)
844  {
845  init_ed_k (&s_kv, sm->addresses[i].addr, 0, ip->dst_address, 0,
846  outside_fib_index, ip->protocol);
847  if (clib_bihash_search_16_8 (&sm->out2in_ed, &s_kv, &s_value))
848  {
849  new_addr = ip->src_address.as_u32 =
850  sm->addresses[i].addr.as_u32;
851  goto create_ses;
852  }
853  }
854  return 0;
855  }
856 
857  create_ses:
858  s = nat_ed_session_alloc (sm, thread_index, now, ip->protocol);
859  if (!s)
860  {
861  b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
862  nat_elog_warn ("create NAT session failed");
863  return 0;
864  }
865 
866  s->ext_host_addr.as_u32 = ip->dst_address.as_u32;
869  s->out2in.addr.as_u32 = new_addr;
870  s->out2in.fib_index = outside_fib_index;
871  s->in2out.addr.as_u32 = old_addr;
872  s->in2out.fib_index = rx_fib_index;
873  s->in2out.port = s->out2in.port = ip->protocol;
874  if (is_sm)
876 
877  /* Add to lookup tables */
878  init_ed_kv (&s_kv, s->in2out.addr, 0, ip->dst_address, 0, rx_fib_index,
879  ip->protocol, thread_index, s - tsm->sessions);
880  if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &s_kv, 1))
881  nat_elog_notice ("in2out key add failed");
882 
883  init_ed_kv (&s_kv, s->out2in.addr, 0, ip->dst_address, 0,
884  outside_fib_index, ip->protocol, thread_index,
885  s - tsm->sessions);
886  if (clib_bihash_add_del_16_8 (&sm->out2in_ed, &s_kv, 1))
887  nat_elog_notice ("out2in key add failed");
888 
889  per_vrf_sessions_register_session (s, thread_index);
890  }
891 
892  /* Update IP checksum */
893  sum = ip->checksum;
894  sum = ip_csum_update (sum, old_addr, new_addr, ip4_header_t, src_address);
895  ip->checksum = ip_csum_fold (sum);
896 
897  /* Accounting */
899  thread_index);
900  /* Per-user LRU list maintenance */
901  nat44_session_update_lru (sm, s, thread_index);
902 
903  /* Hairpinning */
904  if (vnet_buffer (b)->sw_if_index[VLIB_TX] == ~0)
906 
907  if (vnet_buffer (b)->sw_if_index[VLIB_TX] == ~0)
908  vnet_buffer (b)->sw_if_index[VLIB_TX] = outside_fib_index;
909 
910  return s;
911 }
912 
913 static inline uword
917  int is_output_feature)
918 {
919  u32 n_left_from, *from;
920  snat_main_t *sm = &snat_main;
921  f64 now = vlib_time_now (vm);
922  u32 thread_index = vm->thread_index;
923  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
924  u32 def_slow = is_output_feature ? NAT_NEXT_IN2OUT_ED_OUTPUT_SLOW_PATH
926 
927  from = vlib_frame_vector_args (frame);
928  n_left_from = frame->n_vectors;
929 
930  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
931  u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
932  vlib_get_buffers (vm, from, b, n_left_from);
933 
934  while (n_left_from > 0)
935  {
936  vlib_buffer_t *b0;
937  u32 sw_if_index0, rx_fib_index0, proto0, new_addr0, old_addr0,
938  iph_offset0 = 0;
939  u16 old_port0, new_port0;
940  ip4_header_t *ip0;
941  udp_header_t *udp0;
942  tcp_header_t *tcp0;
943  snat_session_t *s0 = 0;
944  clib_bihash_kv_16_8_t kv0, value0;
945  ip_csum_t sum0;
946 
947  b0 = *b;
948  b++;
949 
950  /* Prefetch next iteration. */
951  if (PREDICT_TRUE (n_left_from >= 2))
952  {
953  vlib_buffer_t *p2;
954 
955  p2 = *b;
956 
957  vlib_prefetch_buffer_header (p2, LOAD);
958 
960  }
961 
962  if (is_output_feature)
963  {
964  iph_offset0 = vnet_buffer (b0)->ip.reass.save_rewrite_length;
965  }
966 
967  next[0] = vnet_buffer2 (b0)->nat.arc_next;
968 
969  ip0 =
970  (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) + iph_offset0);
971 
972  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
973  rx_fib_index0 =
975 
976  if (PREDICT_FALSE (ip0->ttl == 1))
977  {
978  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
979  icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
980  ICMP4_time_exceeded_ttl_exceeded_in_transit,
981  0);
982  next[0] = NAT_NEXT_ICMP_ERROR;
983  goto trace0;
984  }
985 
986  udp0 = ip4_next_header (ip0);
987  tcp0 = (tcp_header_t *) udp0;
988  proto0 = ip_proto_to_nat_proto (ip0->protocol);
989 
990  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_OTHER))
991  {
992  next[0] = def_slow;
993  goto trace0;
994  }
995 
996  if (is_output_feature)
997  {
998  if (PREDICT_FALSE
1000  (sm, ip0, thread_index, now, vm, b0)))
1001  goto trace0;
1002  }
1003 
1004  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP))
1005  {
1006  next[0] = def_slow;
1007  goto trace0;
1008  }
1009 
1010  init_ed_k (&kv0, ip0->src_address,
1011  vnet_buffer (b0)->ip.reass.l4_src_port, ip0->dst_address,
1012  vnet_buffer (b0)->ip.reass.l4_dst_port, rx_fib_index0,
1013  ip0->protocol);
1014 
1015  // lookup for session
1016  if (clib_bihash_search_16_8 (&tsm->in2out_ed, &kv0, &value0))
1017  {
1018  // session does not exist go slow path
1019  next[0] = def_slow;
1020  goto trace0;
1021  }
1022  ASSERT (thread_index == ed_value_get_thread_index (&value0));
1023  s0 =
1025  ed_value_get_session_index (&value0));
1026 
1027  if (PREDICT_FALSE (per_vrf_sessions_is_expired (s0, thread_index)))
1028  {
1029  // session is closed, go slow path
1030  nat_free_session_data (sm, s0, thread_index, 0);
1031  nat_ed_session_delete (sm, s0, thread_index, 1);
1032  next[0] = NAT_NEXT_OUT2IN_ED_SLOW_PATH;
1033  goto trace0;
1034  }
1035 
1036  if (s0->tcp_closed_timestamp)
1037  {
1038  if (now >= s0->tcp_closed_timestamp)
1039  {
1040  // session is closed, go slow path, freed in slow path
1041  next[0] = def_slow;
1042  }
1043  else
1044  {
1045  // session in transitory timeout, drop
1046  b0->error = node->errors[NAT_IN2OUT_ED_ERROR_TCP_CLOSED];
1047  next[0] = NAT_NEXT_DROP;
1048  }
1049  goto trace0;
1050  }
1051 
1052  // drop if session expired
1053  u64 sess_timeout_time;
1054  sess_timeout_time =
1055  s0->last_heard + (f64) nat44_session_get_timeout (sm, s0);
1056  if (now >= sess_timeout_time)
1057  {
1058  nat_free_session_data (sm, s0, thread_index, 0);
1059  nat_ed_session_delete (sm, s0, thread_index, 1);
1060  // session is closed, go slow path
1061  next[0] = def_slow;
1062  goto trace0;
1063  }
1064 
1065  b0->flags |= VNET_BUFFER_F_IS_NATED;
1066 
1067  if (!is_output_feature)
1068  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->out2in.fib_index;
1069 
1070  old_addr0 = ip0->src_address.as_u32;
1071  new_addr0 = ip0->src_address.as_u32 = s0->out2in.addr.as_u32;
1072  sum0 = ip0->checksum;
1073  sum0 =
1074  ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1075  src_address);
1077  sum0 =
1078  ip_csum_update (sum0, ip0->dst_address.as_u32,
1079  s0->ext_host_addr.as_u32, ip4_header_t,
1080  dst_address);
1081  ip0->checksum = ip_csum_fold (sum0);
1082 
1083  old_port0 = vnet_buffer (b0)->ip.reass.l4_src_port;
1084 
1085  if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP))
1086  {
1087  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1088  {
1089  new_port0 = udp0->src_port = s0->out2in.port;
1090  sum0 = tcp0->checksum;
1091  sum0 =
1092  ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1093  dst_address);
1094  sum0 =
1095  ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
1096  length);
1098  {
1099  sum0 =
1100  ip_csum_update (sum0, ip0->dst_address.as_u32,
1101  s0->ext_host_addr.as_u32, ip4_header_t,
1102  dst_address);
1103  sum0 =
1104  ip_csum_update (sum0,
1105  vnet_buffer (b0)->ip.reass.l4_dst_port,
1106  s0->ext_host_port, ip4_header_t, length);
1107  tcp0->dst_port = s0->ext_host_port;
1108  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1109  }
1110  mss_clamping (sm->mss_clamping, tcp0, &sum0);
1111  tcp0->checksum = ip_csum_fold (sum0);
1112  }
1113  vlib_increment_simple_counter (&sm->counters.fastpath.in2out_ed.tcp,
1114  thread_index, sw_if_index0, 1);
1115  nat44_set_tcp_session_state_i2o (sm, now, s0, b0, thread_index);
1116  }
1117  else if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment
1118  && udp0->checksum)
1119  {
1120  new_port0 = udp0->src_port = s0->out2in.port;
1121  sum0 = udp0->checksum;
1122  sum0 =
1123  ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1124  dst_address);
1125  sum0 =
1126  ip_csum_update (sum0, old_port0, new_port0, ip4_header_t, length);
1128  {
1129  sum0 =
1130  ip_csum_update (sum0, ip0->dst_address.as_u32,
1131  s0->ext_host_addr.as_u32, ip4_header_t,
1132  dst_address);
1133  sum0 =
1134  ip_csum_update (sum0, vnet_buffer (b0)->ip.reass.l4_dst_port,
1135  s0->ext_host_port, ip4_header_t, length);
1136  udp0->dst_port = s0->ext_host_port;
1137  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1138  }
1139  udp0->checksum = ip_csum_fold (sum0);
1140  vlib_increment_simple_counter (&sm->counters.fastpath.in2out_ed.udp,
1141  thread_index, sw_if_index0, 1);
1142  }
1143  else
1144  {
1145  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1146  {
1147  new_port0 = udp0->src_port = s0->out2in.port;
1149  {
1150  udp0->dst_port = s0->ext_host_port;
1151  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1152  }
1154  in2out_ed.udp, thread_index,
1155  sw_if_index0, 1);
1156  }
1157  }
1158 
1159  /* Accounting */
1161  vlib_buffer_length_in_chain (vm, b0),
1162  thread_index);
1163  /* Per-user LRU list maintenance */
1164  nat44_session_update_lru (sm, s0, thread_index);
1165 
1166  trace0:
1167  if (PREDICT_FALSE
1168  ((node->flags & VLIB_NODE_FLAG_TRACE)
1169  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1170  {
1172  vlib_add_trace (vm, node, b0, sizeof (*t));
1173  t->sw_if_index = sw_if_index0;
1174  t->next_index = next[0];
1175  t->is_slow_path = 0;
1176 
1177  if (s0)
1178  t->session_index = s0 - tsm->sessions;
1179  else
1180  t->session_index = ~0;
1181  }
1182 
1183  if (next[0] == NAT_NEXT_DROP)
1184  {
1186  in2out_ed.drops, thread_index,
1187  sw_if_index0, 1);
1188  }
1189 
1190  n_left_from--;
1191  next++;
1192  }
1193 
1194  vlib_buffer_enqueue_to_next (vm, node, from, (u16 *) nexts,
1195  frame->n_vectors);
1196  return frame->n_vectors;
1197 }
1198 
1199 static inline uword
1202  vlib_frame_t * frame,
1203  int is_output_feature)
1204 {
1205  u32 n_left_from, *from;
1206  snat_main_t *sm = &snat_main;
1207  f64 now = vlib_time_now (vm);
1208  u32 thread_index = vm->thread_index;
1209  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
1210 
1211  from = vlib_frame_vector_args (frame);
1212  n_left_from = frame->n_vectors;
1213 
1214  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
1215  u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
1216  vlib_get_buffers (vm, from, b, n_left_from);
1217 
1218  while (n_left_from > 0)
1219  {
1220  vlib_buffer_t *b0;
1221  u32 sw_if_index0, rx_fib_index0, proto0, new_addr0, old_addr0,
1222  iph_offset0 = 0;
1223  u16 old_port0, new_port0;
1224  ip4_header_t *ip0;
1225  udp_header_t *udp0;
1226  tcp_header_t *tcp0;
1227  icmp46_header_t *icmp0;
1228  snat_session_t *s0 = 0;
1229  clib_bihash_kv_16_8_t kv0, value0;
1230  ip_csum_t sum0;
1231 
1232  b0 = *b;
1233 
1234  if (is_output_feature)
1235  iph_offset0 = vnet_buffer (b0)->ip.reass.save_rewrite_length;
1236 
1237  next[0] = vnet_buffer2 (b0)->nat.arc_next;
1238 
1239  ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
1240  iph_offset0);
1241 
1242  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1243  rx_fib_index0 =
1245 
1246  if (PREDICT_FALSE (ip0->ttl == 1))
1247  {
1248  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1249  icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
1250  ICMP4_time_exceeded_ttl_exceeded_in_transit,
1251  0);
1252  next[0] = NAT_NEXT_ICMP_ERROR;
1253  goto trace0;
1254  }
1255 
1256  udp0 = ip4_next_header (ip0);
1257  tcp0 = (tcp_header_t *) udp0;
1258  icmp0 = (icmp46_header_t *) udp0;
1259  proto0 = ip_proto_to_nat_proto (ip0->protocol);
1260 
1261  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_OTHER))
1262  {
1263  s0 = nat44_ed_in2out_unknown_proto (sm, b0, ip0,
1264  rx_fib_index0,
1265  thread_index, now, vm, node);
1266  if (!s0)
1267  next[0] = NAT_NEXT_DROP;
1268 
1270  in2out_ed.other, thread_index,
1271  sw_if_index0, 1);
1272  goto trace0;
1273  }
1274 
1275  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP))
1276  {
1277  next[0] =
1278  icmp_in2out_ed_slow_path (sm, b0, ip0, icmp0, sw_if_index0,
1279  rx_fib_index0, node, next[0], now,
1280  thread_index, &s0);
1282  in2out_ed.icmp, thread_index,
1283  sw_if_index0, 1);
1284  goto trace0;
1285  }
1286 
1287  init_ed_k (&kv0, ip0->src_address,
1288  vnet_buffer (b0)->ip.reass.l4_src_port, ip0->dst_address,
1289  vnet_buffer (b0)->ip.reass.l4_dst_port, rx_fib_index0,
1290  ip0->protocol);
1291  if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv0, &value0))
1292  {
1293  ASSERT (thread_index == ed_value_get_thread_index (&value0));
1294  s0 =
1296  ed_value_get_session_index (&value0));
1297 
1298  if (s0->tcp_closed_timestamp && now >= s0->tcp_closed_timestamp)
1299  {
1300  nat_free_session_data (sm, s0, thread_index, 0);
1301  nat_ed_session_delete (sm, s0, thread_index, 1);
1302  s0 = NULL;
1303  }
1304  }
1305 
1306  if (!s0)
1307  {
1308  if (is_output_feature)
1309  {
1310  if (PREDICT_FALSE
1312  (sm, ip0, vnet_buffer (b0)->ip.reass.l4_src_port,
1313  vnet_buffer (b0)->ip.reass.l4_dst_port, thread_index,
1314  sw_if_index0, vnet_buffer (b0)->sw_if_index[VLIB_TX],
1315  now)))
1316  goto trace0;
1317 
1318  /*
1319  * Send DHCP packets to the ipv4 stack, or we won't
1320  * be able to use dhcp client on the outside interface
1321  */
1322  if (PREDICT_FALSE
1323  (proto0 == NAT_PROTOCOL_UDP
1324  && (vnet_buffer (b0)->ip.reass.l4_dst_port ==
1325  clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_server))
1326  && ip0->dst_address.as_u32 == 0xffffffff))
1327  goto trace0;
1328  }
1329  else
1330  {
1331  if (PREDICT_FALSE
1333  (sm, node, sw_if_index0, ip0, proto0, rx_fib_index0,
1334  thread_index)))
1335  goto trace0;
1336  }
1337 
1338  next[0] =
1339  slow_path_ed (sm, b0, ip0->src_address, ip0->dst_address,
1340  vnet_buffer (b0)->ip.reass.l4_src_port,
1341  vnet_buffer (b0)->ip.reass.l4_dst_port,
1342  ip0->protocol, rx_fib_index0, &s0, node, next[0],
1343  thread_index, now);
1344 
1345  if (PREDICT_FALSE (next[0] == NAT_NEXT_DROP))
1346  goto trace0;
1347 
1348  if (PREDICT_FALSE (!s0))
1349  goto trace0;
1350 
1351  }
1352 
1353  b0->flags |= VNET_BUFFER_F_IS_NATED;
1354 
1355  if (!is_output_feature)
1356  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->out2in.fib_index;
1357 
1358  old_addr0 = ip0->src_address.as_u32;
1359  new_addr0 = ip0->src_address.as_u32 = s0->out2in.addr.as_u32;
1360  sum0 = ip0->checksum;
1361  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1362  src_address);
1364  sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1365  s0->ext_host_addr.as_u32, ip4_header_t,
1366  dst_address);
1367  ip0->checksum = ip_csum_fold (sum0);
1368 
1369  old_port0 = vnet_buffer (b0)->ip.reass.l4_src_port;
1370 
1371  if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP))
1372  {
1373  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1374  {
1375  new_port0 = udp0->src_port = s0->out2in.port;
1376  sum0 = tcp0->checksum;
1377  sum0 =
1378  ip_csum_update (sum0, old_addr0, new_addr0,
1379  ip4_header_t, dst_address);
1380  sum0 =
1381  ip_csum_update (sum0, old_port0, new_port0,
1382  ip4_header_t, length);
1384  {
1385  sum0 =
1386  ip_csum_update (sum0, ip0->dst_address.as_u32,
1387  s0->ext_host_addr.as_u32,
1388  ip4_header_t, dst_address);
1389  sum0 =
1390  ip_csum_update (sum0,
1391  vnet_buffer (b0)->ip.reass.l4_dst_port,
1392  s0->ext_host_port, ip4_header_t, length);
1393  tcp0->dst_port = s0->ext_host_port;
1394  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1395  }
1396  mss_clamping (sm->mss_clamping, tcp0, &sum0);
1397  tcp0->checksum = ip_csum_fold (sum0);
1398  }
1399  vlib_increment_simple_counter (&sm->counters.slowpath.in2out_ed.tcp,
1400  thread_index, sw_if_index0, 1);
1401  nat44_set_tcp_session_state_i2o (sm, now, s0, b0, thread_index);
1402  }
1403  else if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment
1404  && udp0->checksum)
1405  {
1406  new_port0 = udp0->src_port = s0->out2in.port;
1407  sum0 = udp0->checksum;
1408  sum0 =
1409  ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1410  dst_address);
1411  sum0 =
1412  ip_csum_update (sum0, old_port0, new_port0, ip4_header_t, length);
1414  {
1415  sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1416  s0->ext_host_addr.as_u32,
1417  ip4_header_t, dst_address);
1418  sum0 =
1419  ip_csum_update (sum0,
1420  vnet_buffer (b0)->ip.reass.l4_dst_port,
1421  s0->ext_host_port, ip4_header_t, length);
1422  udp0->dst_port = s0->ext_host_port;
1423  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1424  }
1425  udp0->checksum = ip_csum_fold (sum0);
1426  vlib_increment_simple_counter (&sm->counters.slowpath.in2out_ed.udp,
1427  thread_index, sw_if_index0, 1);
1428  }
1429  else
1430  {
1431  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1432  {
1433  new_port0 = udp0->src_port = s0->out2in.port;
1435  {
1436  udp0->dst_port = s0->ext_host_port;
1437  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1438  }
1440  in2out_ed.udp, thread_index,
1441  sw_if_index0, 1);
1442  }
1443  }
1444 
1445  /* Accounting */
1448  (vm, b0), thread_index);
1449  /* Per-user LRU list maintenance */
1450  nat44_session_update_lru (sm, s0, thread_index);
1451 
1452  trace0:
1454  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1455  {
1457  vlib_add_trace (vm, node, b0, sizeof (*t));
1458  t->sw_if_index = sw_if_index0;
1459  t->next_index = next[0];
1460  t->is_slow_path = 1;
1461 
1462  if (s0)
1463  t->session_index = s0 - tsm->sessions;
1464  else
1465  t->session_index = ~0;
1466  }
1467 
1468  if (next[0] == NAT_NEXT_DROP)
1469  {
1471  in2out_ed.drops, thread_index,
1472  sw_if_index0, 1);
1473  }
1474 
1475  n_left_from--;
1476  next++;
1477  b++;
1478  }
1479 
1480  vlib_buffer_enqueue_to_next (vm, node, from, (u16 *) nexts,
1481  frame->n_vectors);
1482 
1483  return frame->n_vectors;
1484 }
1485 
1488  vlib_frame_t * frame)
1489 {
1491 }
1492 
1493 /* *INDENT-OFF* */
1495  .name = "nat44-ed-in2out",
1496  .vector_size = sizeof (u32),
1497  .sibling_of = "nat-default",
1498  .format_trace = format_nat_in2out_ed_trace,
1500  .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1501  .error_strings = nat_in2out_ed_error_strings,
1502  .runtime_data_bytes = sizeof (snat_runtime_t),
1503 };
1504 /* *INDENT-ON* */
1505 
1508  vlib_frame_t * frame)
1509 {
1511 }
1512 
1513 /* *INDENT-OFF* */
1515  .name = "nat44-ed-in2out-output",
1516  .vector_size = sizeof (u32),
1517  .sibling_of = "nat-default",
1518  .format_trace = format_nat_in2out_ed_trace,
1520  .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1521  .error_strings = nat_in2out_ed_error_strings,
1522  .runtime_data_bytes = sizeof (snat_runtime_t),
1523 };
1524 /* *INDENT-ON* */
1525 
1528  node, vlib_frame_t * frame)
1529 {
1531 }
1532 
1533 /* *INDENT-OFF* */
1535  .name = "nat44-ed-in2out-slowpath",
1536  .vector_size = sizeof (u32),
1537  .sibling_of = "nat-default",
1538  .format_trace = format_nat_in2out_ed_trace,
1540  .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1541  .error_strings = nat_in2out_ed_error_strings,
1542  .runtime_data_bytes = sizeof (snat_runtime_t),
1543 };
1544 /* *INDENT-ON* */
1545 
1548  * node,
1549  vlib_frame_t * frame)
1550 {
1552 }
1553 
1554 /* *INDENT-OFF* */
1556  .name = "nat44-ed-in2out-output-slowpath",
1557  .vector_size = sizeof (u32),
1558  .sibling_of = "nat-default",
1559  .format_trace = format_nat_in2out_ed_trace,
1561  .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1562  .error_strings = nat_in2out_ed_error_strings,
1563  .runtime_data_bytes = sizeof (snat_runtime_t),
1564 };
1565 /* *INDENT-ON* */
1566 
1567 static u8 *
1568 format_nat_pre_trace (u8 * s, va_list * args)
1569 {
1570  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1571  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1572  nat_pre_trace_t *t = va_arg (*args, nat_pre_trace_t *);
1573  return format (s, "in2out next_index %d arc_next_index %d", t->next_index,
1574  t->arc_next_index);
1575 }
1576 
1580  return nat_pre_node_fn_inline (vm, node, frame,
1582 }
1583 
1586 {
1587  return nat_pre_node_fn_inline (vm, node, frame,
1589 }
1590 
1591 /* *INDENT-OFF* */
1593  .name = "nat-pre-in2out",
1594  .vector_size = sizeof (u32),
1595  .sibling_of = "nat-default",
1596  .format_trace = format_nat_pre_trace,
1598  .n_errors = 0,
1599 };
1600 
1602  .name = "nat-pre-in2out-output",
1603  .vector_size = sizeof (u32),
1604  .sibling_of = "nat-default",
1605  .format_trace = format_nat_pre_trace,
1607  .n_errors = 0,
1608 };
1609 /* *INDENT-ON* */
1610 
1611 /*
1612  * fd.io coding-style-patch-verification: ON
1613  *
1614  * Local Variables:
1615  * eval: (c-set-style "gnu")
1616  * End:
1617  */
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:1514
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:1601
#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:1578
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:496
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:759
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:1200
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:1534
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:1568
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:1592
#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:1555
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:530
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:1578
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:1494
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:1579
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:586
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:644
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:914
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