FD.io VPP  v20.05.1-6-gf53edbc3b
Vector Packet Processing
in2out_ed.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /**
16  * @file
17  * @brief NAT44 endpoint-dependent inside to outside network translation
18  */
19 
20 #include <vlib/vlib.h>
21 #include <vnet/vnet.h>
22 #include <vnet/pg/pg.h>
23 #include <vnet/ip/ip.h>
24 #include <vnet/ethernet/ethernet.h>
25 #include <vnet/fib/ip4_fib.h>
26 #include <vnet/udp/udp.h>
27 #include <vppinfra/error.h>
28 #include <nat/nat.h>
29 #include <nat/nat_ipfix_logging.h>
30 #include <nat/nat_inlines.h>
31 #include <nat/nat44/inlines.h>
32 #include <nat/nat_syslog.h>
33 #include <nat/nat_ha.h>
34 #include <nat/nat44/ed_inlines.h>
35 
36 static char *nat_in2out_ed_error_strings[] = {
37 #define _(sym,string) string,
39 #undef _
40 };
41 
42 typedef struct
43 {
49 
50 static u8 *
51 format_nat_in2out_ed_trace (u8 * s, va_list * args)
52 {
53  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
54  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
55  nat_in2out_ed_trace_t *t = va_arg (*args, nat_in2out_ed_trace_t *);
56  char *tag;
57 
58  tag =
59  t->is_slow_path ? "NAT44_IN2OUT_ED_SLOW_PATH" :
60  "NAT44_IN2OUT_ED_FAST_PATH";
61 
62  s = format (s, "%s: sw_if_index %d, next index %d, session %d", tag,
64 
65  return s;
66 }
67 
68 #ifndef CLIB_MARCH_VARIANT
69 int
71 {
72  snat_main_t *sm = &snat_main;
74  snat_session_t *s;
75  u64 sess_timeout_time;
76  u8 proto;
77  u16 r_port, l_port;
78  ip4_address_t *l_addr, *r_addr;
79  u32 fib_index;
81  int i;
85  ctx->thread_index);
86 
87  s = pool_elt_at_index (tsm->sessions, kv->value);
88  sess_timeout_time = s->last_heard + (f64) nat44_session_get_timeout (sm, s);
89  if (ctx->now >= sess_timeout_time)
90  {
91  if (is_fwd_bypass_session (s))
92  goto delete;
93 
94  l_addr = &s->out2in.addr;
95  r_addr = &s->ext_host_addr;
96  fib_index = s->out2in.fib_index;
98  {
99  proto = s->in2out.port;
100  r_port = 0;
101  l_port = 0;
102  }
103  else
104  {
105  proto = nat_proto_to_ip_proto (s->in2out.protocol);
106  l_port = s->out2in.port;
107  r_port = s->ext_host_port;
108  }
109  make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL,
110  &ed_kv);
111  if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &ed_kv, 0))
112  nat_elog_warn ("out2in_ed key del failed");
113 
115  goto delete;
116 
118  s->in2out.addr.as_u32,
119  s->out2in.addr.as_u32,
120  s->in2out.protocol,
121  s->in2out.port,
122  s->out2in.port,
123  s->in2out.fib_index);
124 
125  nat_syslog_nat44_sdel (s->user_index, s->in2out.fib_index,
126  &s->in2out.addr, s->in2out.port,
127  &s->ext_host_nat_addr, s->ext_host_nat_port,
128  &s->out2in.addr, s->out2in.port,
129  &s->ext_host_addr, s->ext_host_port,
130  s->in2out.protocol, is_twice_nat_session (s));
131 
132  nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
133  s->ext_host_port, s->out2in.protocol, s->out2in.fib_index,
134  ctx->thread_index);
135 
136  if (is_twice_nat_session (s))
137  {
138  for (i = 0; i < vec_len (sm->twice_nat_addresses); i++)
139  {
140  key.protocol = s->in2out.protocol;
141  key.port = s->ext_host_nat_port;
142  a = sm->twice_nat_addresses + i;
143  if (a->addr.as_u32 == s->ext_host_nat_addr.as_u32)
144  {
146  ctx->thread_index,
147  &key);
148  break;
149  }
150  }
151  }
152 
153  if (snat_is_session_static (s))
154  goto delete;
155 
157  &s->out2in);
158  delete:
159  nat_ed_session_delete (sm, s, ctx->thread_index, 1);
160  return 1;
161  }
162 
163  return 0;
164 }
165 #endif
166 
167 static inline u32
169  ip4_header_t * ip0, icmp46_header_t * icmp0,
170  u32 sw_if_index0, u32 rx_fib_index0,
171  vlib_node_runtime_t * node, u32 next0, f64 now,
172  u32 thread_index, snat_session_t ** p_s0)
173 {
174  vlib_main_t *vm = vlib_get_main ();
175 
176  next0 = icmp_in2out (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
177  next0, thread_index, p_s0, 0);
178  snat_session_t *s0 = *p_s0;
179  if (PREDICT_TRUE (next0 != NAT_NEXT_DROP && s0))
180  {
181  /* Accounting */
184  (vm, b0), thread_index);
185  /* Per-user LRU list maintenance */
186  nat44_session_update_lru (sm, s0, thread_index);
187  }
188  return next0;
189 }
190 
193 {
194  snat_main_t *sm = &snat_main;
195  return min + random_u32 (&sm->random_seed) /
196  (random_u32_max () / (max - min + 1) + 1);
197 }
198 
199 static int
201  u32 nat_proto, u32 thread_index,
202  ip4_address_t r_addr, u16 r_port, u8 proto,
203  u16 port_per_thread, u32 snat_thread_index,
204  snat_session_t * s,
205  ip4_address_t * allocated_addr,
206  u16 * allocated_port,
207  clib_bihash_kv_16_8_t * out2in_ed_kv)
208 {
209  int i;
210  snat_address_t *a, *ga = 0;
211  u32 portnum;
212  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
213 
214  const u16 port_thread_offset = (port_per_thread * snat_thread_index) + 1024;
215 
216  for (i = 0; i < vec_len (sm->addresses); i++)
217  {
218  a = sm->addresses + i;
219  switch (nat_proto)
220  {
221 #define _(N, j, n, unused) \
222  case NAT_PROTOCOL_##N: \
223  if (a->fib_index == rx_fib_index) \
224  { \
225  u16 port = snat_random_port (1, port_per_thread); \
226  u16 attempts = port_per_thread; \
227  while (attempts > 0) \
228  { \
229  --attempts; \
230  portnum = port_thread_offset + port; \
231  make_ed_kv (&a->addr, &r_addr, proto, s->out2in.fib_index, \
232  clib_host_to_net_u16 (portnum), r_port, \
233  s - tsm->sessions, out2in_ed_kv); \
234  int rv = clib_bihash_add_del_16_8 (&tsm->out2in_ed, out2in_ed_kv, \
235  2 /* is_add */); \
236  if (0 == rv) \
237  { \
238  ++a->busy_##n##_port_refcounts[portnum]; \
239  a->busy_##n##_ports_per_thread[thread_index]++; \
240  a->busy_##n##_ports++; \
241  *allocated_addr = a->addr; \
242  *allocated_port = clib_host_to_net_u16 (portnum); \
243  return 0; \
244  } \
245  port = (port + 1) % port_per_thread; \
246  } \
247  } \
248  else if (a->fib_index == ~0) \
249  { \
250  ga = a; \
251  } \
252  break;
253 
255  default:
256  nat_elog_info ("unknown protocol");
257  return 1;
258  }
259  }
260 
261  if (ga)
262  {
263  /* fake fib_index to reuse macro */
264  rx_fib_index = ~0;
265  a = ga;
266  switch (nat_proto)
267  {
269  default:
270  nat_elog_info ("unknown protocol");
271  return 1;
272  }
273  }
274 
275 #undef _
276 
277  /* Totally out of translations to use... */
278  snat_ipfix_logging_addresses_exhausted (thread_index, 0);
279  return 1;
280 }
281 
282 static u32
284  vlib_buffer_t * b,
285  ip4_address_t l_addr,
286  ip4_address_t r_addr,
287  u16 l_port,
288  u16 r_port,
289  u8 proto,
290  u32 rx_fib_index,
291  snat_session_t ** sessionp,
292  vlib_node_runtime_t * node, u32 next, u32 thread_index, f64 now)
293 {
294  snat_session_t *s = NULL;
295  snat_session_key_t key0, key1;
296  lb_nat_type_t lb = 0;
297  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
298  u32 nat_proto = ip_proto_to_nat_proto (proto);
299  nat_outside_fib_t *outside_fib;
301  clib_bihash_kv_16_8_t out2in_ed_kv;
302  ip4_address_t allocated_addr;
303  u16 allocated_port;
304  u8 identity_nat;
305  fib_prefix_t pfx = {
307  .fp_len = 32,
308  .fp_addr = {.ip4.as_u32 = r_addr.as_u32,},
309  };
311 
312  if (PREDICT_TRUE (nat_proto == NAT_PROTOCOL_TCP))
313  {
314  if (PREDICT_FALSE
316  (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags)))
317  {
318  b->error = node->errors[NAT_IN2OUT_ED_ERROR_NON_SYN];
319  return NAT_NEXT_DROP;
320  }
321  }
322 
323  // TODO: based on fib index do a lookup
324  if (PREDICT_FALSE
325  (nat44_ed_maximum_sessions_exceeded (sm, rx_fib_index, thread_index)))
326  {
327  if (!nat_lru_free_one (sm, thread_index, now))
328  {
329  b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
331  nat_elog_notice ("maximum sessions exceeded");
332  return NAT_NEXT_DROP;
333  }
334  }
335 
336  key0.addr = l_addr;
337  key0.port = l_port;
338  key1.protocol = key0.protocol = nat_proto;
339  key0.fib_index = rx_fib_index;
340  key1.fib_index = sm->outside_fib_index;
341 
342  /* First try to match static mapping by local address and port */
344  (sm, key0, &key1, 0, 0, 0, &lb, 0, &identity_nat))
345  {
346  s = nat_ed_session_alloc (sm, thread_index, now, proto);
347  if (!s)
348  {
349  nat_elog_warn ("create NAT session failed");
350  b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_USER_SESS_EXCEEDED];
351  return NAT_NEXT_DROP;
352  }
353  switch (vec_len (sm->outside_fibs))
354  {
355  case 0:
356  s->out2in.fib_index = sm->outside_fib_index;
357  break;
358  case 1:
359  s->out2in.fib_index = sm->outside_fibs[0].fib_index;
360  break;
361  default:
362  /* *INDENT-OFF* */
363  vec_foreach (outside_fib, sm->outside_fibs)
364  {
365  fei = fib_table_lookup (outside_fib->fib_index, &pfx);
366  if (FIB_NODE_INDEX_INVALID != fei)
367  {
368  if (fib_entry_get_resolving_interface (fei) != ~0)
369  {
370  s->out2in.fib_index = outside_fib->fib_index;
371  break;
372  }
373  }
374  }
375  /* *INDENT-ON* */
376  break;
377  }
378 
379  /* Try to create dynamic translation */
380  if (nat_ed_alloc_addr_and_port (sm, rx_fib_index, nat_proto,
381  thread_index, r_addr, r_port, proto,
382  sm->port_per_thread,
383  tsm->snat_thread_index, s,
384  &allocated_addr,
385  &allocated_port, &out2in_ed_kv))
386  {
387  nat_elog_notice ("addresses exhausted");
388  b->error = node->errors[NAT_IN2OUT_ED_ERROR_OUT_OF_PORTS];
389  nat_ed_session_delete (sm, s, thread_index, 1);
390  return NAT_NEXT_DROP;
391  }
392  key1.addr = allocated_addr;
393  key1.port = allocated_port;
394  }
395  else
396  {
397  if (PREDICT_FALSE (identity_nat))
398  {
399  *sessionp = s;
400  return next;
401  }
402  s = nat_ed_session_alloc (sm, thread_index, now, proto);
403  if (!s)
404  {
405  nat_elog_warn ("create NAT session failed");
406  b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_USER_SESS_EXCEEDED];
407  return NAT_NEXT_DROP;
408  }
409  switch (vec_len (sm->outside_fibs))
410  {
411  case 0:
412  s->out2in.fib_index = sm->outside_fib_index;
413  break;
414  case 1:
415  s->out2in.fib_index = sm->outside_fibs[0].fib_index;
416  break;
417  default:
418  /* *INDENT-OFF* */
419  vec_foreach (outside_fib, sm->outside_fibs)
420  {
421  fei = fib_table_lookup (outside_fib->fib_index, &pfx);
422  if (FIB_NODE_INDEX_INVALID != fei)
423  {
424  if (fib_entry_get_resolving_interface (fei) != ~0)
425  {
426  s->out2in.fib_index = outside_fib->fib_index;
427  break;
428  }
429  }
430  }
431  /* *INDENT-ON* */
432  break;
433  }
434 
436 
437 
438  make_ed_kv (&key1.addr, &r_addr, proto,
439  s->out2in.fib_index, key1.port, r_port, s - tsm->sessions,
440  &out2in_ed_kv);
441  if (clib_bihash_add_or_overwrite_stale_16_8
442  (&tsm->out2in_ed, &out2in_ed_kv, nat44_o2i_ed_is_idle_session_cb,
443  &ctx))
444  nat_elog_notice ("out2in-ed key add failed");
445  }
446 
447  if (lb)
450  s->ext_host_addr = r_addr;
451  s->ext_host_port = r_port;
452  s->in2out = key0;
453  s->out2in = key1;
454  s->out2in.protocol = key0.protocol;
455 
456  clib_bihash_kv_16_8_t in2out_ed_kv;
457  make_ed_kv (&l_addr, &r_addr, proto, rx_fib_index, l_port, r_port,
458  s - tsm->sessions, &in2out_ed_kv);
459  ctx.now = now;
460  ctx.thread_index = thread_index;
461  if (clib_bihash_add_or_overwrite_stale_16_8 (&tsm->in2out_ed, &in2out_ed_kv,
463  &ctx))
464  nat_elog_notice ("in2out-ed key add failed");
465 
466  *sessionp = s;
467 
468  /* log NAT event */
470  s->in2out.addr.as_u32,
471  s->out2in.addr.as_u32,
472  s->in2out.protocol,
473  s->in2out.port,
474  s->out2in.port, s->in2out.fib_index);
475 
476  nat_syslog_nat44_sadd (s->user_index, s->in2out.fib_index,
477  &s->in2out.addr, s->in2out.port,
478  &s->ext_host_nat_addr, s->ext_host_nat_port,
479  &s->out2in.addr, s->out2in.port,
480  &s->ext_host_addr, s->ext_host_port,
481  s->in2out.protocol, 0);
482 
483  nat_ha_sadd (&s->in2out.addr, s->in2out.port, &s->out2in.addr,
484  s->out2in.port, &s->ext_host_addr, s->ext_host_port,
485  &s->ext_host_nat_addr, s->ext_host_nat_port,
486  s->in2out.protocol, s->in2out.fib_index, s->flags,
487  thread_index, 0);
488 
489  return next;
490 }
491 
495  u32 rx_fib_index, u32 thread_index)
496 {
497  udp_header_t *udp = ip4_next_header (ip);
498  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
500  snat_session_key_t key0, key1;
501 
502  make_ed_kv (&ip->dst_address, &ip->src_address, ip->protocol,
503  sm->outside_fib_index, udp->dst_port, udp->src_port, ~0ULL,
504  &kv);
505 
506  /* NAT packet aimed at external address if has active sessions */
507  if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
508  {
509  key0.addr = ip->dst_address;
510  key0.port = udp->dst_port;
511  key0.protocol = proto;
512  key0.fib_index = sm->outside_fib_index;
513  /* or is static mappings */
514  if (!snat_static_mapping_match (sm, key0, &key1, 1, 0, 0, 0, 0, 0))
515  return 0;
516  }
517  else
518  return 0;
519 
520  if (sm->forwarding_enabled)
521  return 1;
522 
523  return snat_not_translate_fast (sm, node, sw_if_index, ip, proto,
524  rx_fib_index);
525 }
526 
529  u32 thread_index, f64 now,
530  vlib_main_t * vm, vlib_buffer_t * b)
531 {
533  snat_session_t *s = 0;
534  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
535 
536  if (!sm->forwarding_enabled)
537  return 0;
538 
539  if (ip->protocol == IP_PROTOCOL_ICMP)
540  {
541  if (get_icmp_i2o_ed_key (b, ip, 0, ~0ULL, 0, 0, 0, &kv))
542  return 0;
543  }
544  else if (ip->protocol == IP_PROTOCOL_UDP || ip->protocol == IP_PROTOCOL_TCP)
545  {
546  make_ed_kv (&ip->src_address, &ip->dst_address, ip->protocol, 0,
547  vnet_buffer (b)->ip.reass.l4_src_port,
548  vnet_buffer (b)->ip.reass.l4_dst_port, ~0ULL, &kv);
549  }
550  else
551  {
552  make_ed_kv (&ip->src_address, &ip->dst_address, ip->protocol, 0, 0,
553  0, ~0ULL, &kv);
554  }
555 
556  if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
557  {
558  s = pool_elt_at_index (tsm->sessions, value.value);
559  if (is_fwd_bypass_session (s))
560  {
561  if (ip->protocol == IP_PROTOCOL_TCP)
562  {
564  (sm, now, s, b, thread_index))
565  return 1;
566  }
567  /* Accounting */
570  thread_index);
571  /* Per-user LRU list maintenance */
572  nat44_session_update_lru (sm, s, thread_index);
573  return 1;
574  }
575  else
576  return 0;
577  }
578 
579  return 0;
580 }
581 
585  u32 thread_index, u32 rx_sw_if_index,
587 {
589  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
591  snat_session_t *s;
592  u32 rx_fib_index = ip4_fib_table_get_index_for_sw_if_index (rx_sw_if_index);
593  u32 tx_fib_index = ip4_fib_table_get_index_for_sw_if_index (tx_sw_if_index);
594 
595  /* src NAT check */
596  make_ed_kv (&ip->src_address, &ip->dst_address, ip->protocol,
597  tx_fib_index, src_port, dst_port, ~0ULL, &kv);
598  if (!clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
599  {
600  s = pool_elt_at_index (tsm->sessions, value.value);
601  if (nat44_is_ses_closed (s))
602  {
603  nat_free_session_data (sm, s, thread_index, 0);
604  nat_ed_session_delete (sm, s, thread_index, 1);
605  }
606  else
608  return 1;
609  }
610 
611  /* dst NAT check */
612  make_ed_kv (&ip->dst_address, &ip->src_address, ip->protocol,
613  rx_fib_index, dst_port, src_port, ~0ULL, &kv);
614  if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
615  {
616  s = pool_elt_at_index (tsm->sessions, value.value);
617  if (is_fwd_bypass_session (s))
618  return 0;
619 
620  /* hairpinning */
621  /* *INDENT-OFF* */
623  ({
624  if ((nat_interface_is_inside (i)) && (rx_sw_if_index == i->sw_if_index))
625  return 0;
626  }));
627  /* *INDENT-ON* */
628  return 1;
629  }
630 
631  return 0;
632 }
633 
634 #ifndef CLIB_MARCH_VARIANT
635 u32
637  u32 thread_index, vlib_buffer_t * b, ip4_header_t * ip,
638  u8 * p_proto, snat_session_key_t * p_value,
639  u8 * p_dont_translate, void *d, void *e)
640 {
642  u32 rx_fib_index;
643  snat_session_t *s = 0;
644  u8 dont_translate = 0;
646  u32 next = ~0;
647  int err;
648  u16 l_port = 0, r_port = 0; // initialize to workaround gcc warning
649  vlib_main_t *vm = vlib_get_main ();
650  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
651 
652  sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
653  rx_fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
654 
655  err =
656  get_icmp_i2o_ed_key (b, ip, rx_fib_index, ~0ULL, p_proto, &l_port,
657  &r_port, &kv);
658  if (err != 0)
659  {
660  b->error = node->errors[err];
661  next = NAT_NEXT_DROP;
662  goto out;
663  }
664 
665  if (clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
666  {
667  if (vnet_buffer (b)->sw_if_index[VLIB_TX] != ~0)
668  {
669  if (PREDICT_FALSE
671  (sm, ip, l_port, r_port, thread_index,
672  sw_if_index, vnet_buffer (b)->sw_if_index[VLIB_TX])))
673  {
674  dont_translate = 1;
675  goto out;
676  }
677  }
678  else
679  {
680  if (PREDICT_FALSE (nat44_ed_not_translate (sm, node, sw_if_index,
681  ip, NAT_PROTOCOL_ICMP,
682  rx_fib_index,
683  thread_index)))
684  {
685  dont_translate = 1;
686  goto out;
687  }
688  }
689 
690  if (PREDICT_FALSE
692  (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags)))
693  {
694  b->error = node->errors[NAT_IN2OUT_ED_ERROR_BAD_ICMP_TYPE];
695  next = NAT_NEXT_DROP;
696  goto out;
697  }
698 
699  next =
700  slow_path_ed (sm, b, ip->src_address, ip->dst_address, l_port, r_port,
701  ip->protocol, rx_fib_index, &s, node, next,
702  thread_index, vlib_time_now (vm));
703 
704  if (PREDICT_FALSE (next == NAT_NEXT_DROP))
705  goto out;
706 
707  if (!s)
708  {
709  dont_translate = 1;
710  goto out;
711  }
712  }
713  else
714  {
715  if (PREDICT_FALSE
716  (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags !=
717  ICMP4_echo_request
718  && vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags !=
719  ICMP4_echo_reply
721  reass.icmp_type_or_tcp_flags)))
722  {
723  b->error = node->errors[NAT_IN2OUT_ED_ERROR_BAD_ICMP_TYPE];
724  next = NAT_NEXT_DROP;
725  goto out;
726  }
727 
728  s = pool_elt_at_index (tsm->sessions, value.value);
729  }
730 out:
731  if (s)
732  *p_value = s->out2in;
733  *p_dont_translate = dont_translate;
734  if (d)
735  *(snat_session_t **) d = s;
736  return next;
737 }
738 #endif
739 
740 static snat_session_t *
742  vlib_buffer_t * b,
743  ip4_header_t * ip,
744  u32 rx_fib_index,
745  u32 thread_index,
746  f64 now,
748 {
750  clib_bihash_kv_16_8_t s_kv, s_value;
752  u32 old_addr, new_addr = 0;
753  ip_csum_t sum;
754  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
755  snat_session_t *s;
756  u32 outside_fib_index = sm->outside_fib_index;
757  int i;
758  u8 is_sm = 0;
759  nat_outside_fib_t *outside_fib;
761  fib_prefix_t pfx = {
763  .fp_len = 32,
764  .fp_addr = {
765  .ip4.as_u32 = ip->dst_address.as_u32,
766  },
767  };
768 
769  switch (vec_len (sm->outside_fibs))
770  {
771  case 0:
772  outside_fib_index = sm->outside_fib_index;
773  break;
774  case 1:
775  outside_fib_index = sm->outside_fibs[0].fib_index;
776  break;
777  default:
778  /* *INDENT-OFF* */
779  vec_foreach (outside_fib, sm->outside_fibs)
780  {
781  fei = fib_table_lookup (outside_fib->fib_index, &pfx);
782  if (FIB_NODE_INDEX_INVALID != fei)
783  {
784  if (fib_entry_get_resolving_interface (fei) != ~0)
785  {
786  outside_fib_index = outside_fib->fib_index;
787  break;
788  }
789  }
790  }
791  /* *INDENT-ON* */
792  break;
793  }
794  old_addr = ip->src_address.as_u32;
795 
796  make_ed_kv (&ip->src_address, &ip->dst_address, ip->protocol,
797  rx_fib_index, 0, 0, ~0ULL, &s_kv);
798 
799  if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &s_kv, &s_value))
800  {
801  s = pool_elt_at_index (tsm->sessions, s_value.value);
802  new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32;
803  }
804  else
805  {
806  if (PREDICT_FALSE
808  (sm, rx_fib_index, thread_index)))
809  {
810  b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
812  nat_elog_notice ("maximum sessions exceeded");
813  return 0;
814  }
815 
816  make_sm_kv (&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  make_ed_kv (&s->out2in.addr, &ip->dst_address, ip->protocol,
835  outside_fib_index, 0, 0, ~0ULL, &s_kv);
836  if (clib_bihash_search_16_8 (&tsm->out2in_ed, &s_kv, &s_value))
837  goto create_ses;
838 
839  break;
840  }
841  });
842  /* *INDENT-ON* */
843 
844  for (i = 0; i < vec_len (sm->addresses); i++)
845  {
846  make_ed_kv (&sm->addresses[i].addr, &ip->dst_address,
847  ip->protocol, outside_fib_index, 0, 0, ~0ULL,
848  &s_kv);
849  if (clib_bihash_search_16_8 (&tsm->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_USER_SESS_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  make_ed_kv (&s->in2out.addr, &ip->dst_address, ip->protocol,
881  rx_fib_index, 0, 0, s - tsm->sessions, &s_kv);
882  if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &s_kv, 1))
883  nat_elog_notice ("in2out key add failed");
884 
885  make_ed_kv (&s->out2in.addr, &ip->dst_address, ip->protocol,
886  outside_fib_index, 0, 0, s - tsm->sessions, &s_kv);
887  if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &s_kv, 1))
888  nat_elog_notice ("out2in key add failed");
889  }
890 
891  /* Update IP checksum */
892  sum = ip->checksum;
893  sum = ip_csum_update (sum, old_addr, new_addr, ip4_header_t, src_address);
894  ip->checksum = ip_csum_fold (sum);
895 
896  /* Accounting */
898  thread_index);
899  /* Per-user LRU list maintenance */
900  nat44_session_update_lru (sm, s, thread_index);
901 
902  /* Hairpinning */
903  if (vnet_buffer (b)->sw_if_index[VLIB_TX] == ~0)
905 
906  if (vnet_buffer (b)->sw_if_index[VLIB_TX] == ~0)
907  vnet_buffer (b)->sw_if_index[VLIB_TX] = outside_fib_index;
908 
909  return s;
910 }
911 
912 static inline uword
916  int is_output_feature)
917 {
918  u32 n_left_from, *from, *to_next, pkts_processed = 0, stats_node_index;
919  nat_next_t next_index;
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 tcp_packets = 0, udp_packets = 0, icmp_packets = 0, other_packets =
925  0, def_slow;
926 
927  def_slow = is_output_feature ? NAT_NEXT_IN2OUT_ED_OUTPUT_SLOW_PATH :
929 
930  stats_node_index = sm->ed_in2out_node_index;
931 
932  from = vlib_frame_vector_args (frame);
933  n_left_from = frame->n_vectors;
934  next_index = node->cached_next_index;
935 
936  while (n_left_from > 0)
937  {
938  u32 n_left_to_next;
939 
940  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
941 
942  while (n_left_from > 0 && n_left_to_next > 0)
943  {
944  u32 bi0;
945  vlib_buffer_t *b0;
946  u32 next0, sw_if_index0, rx_fib_index0, iph_offset0 = 0, proto0,
947  new_addr0, old_addr0;
948  u16 old_port0, new_port0;
949  ip4_header_t *ip0;
950  udp_header_t *udp0;
951  tcp_header_t *tcp0;
952  snat_session_t *s0 = 0;
953  clib_bihash_kv_16_8_t kv0, value0;
954  ip_csum_t sum0;
955 
956  /* speculatively enqueue b0 to the current next frame */
957  bi0 = from[0];
958  to_next[0] = bi0;
959  from += 1;
960  to_next += 1;
961  n_left_from -= 1;
962  n_left_to_next -= 1;
963 
964  b0 = vlib_get_buffer (vm, bi0);
965 
966  if (is_output_feature)
967  {
968  vnet_feature_next (&vnet_buffer2 (b0)->nat.arc_next, b0);
969  iph_offset0 = vnet_buffer (b0)->ip.reass.save_rewrite_length;
970  }
971 
972  next0 = vnet_buffer2 (b0)->nat.arc_next;
973 
974  ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
975  iph_offset0);
976 
977  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
978  rx_fib_index0 =
980  sw_if_index0);
981 
982  if (PREDICT_FALSE (ip0->ttl == 1))
983  {
984  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
985  icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
986  ICMP4_time_exceeded_ttl_exceeded_in_transit,
987  0);
988  next0 = NAT_NEXT_ICMP_ERROR;
989  goto trace0;
990  }
991 
992  udp0 = ip4_next_header (ip0);
993  tcp0 = (tcp_header_t *) udp0;
994  proto0 = ip_proto_to_nat_proto (ip0->protocol);
995 
996  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_OTHER))
997  {
998  next0 = def_slow;
999  goto trace0;
1000  }
1001 
1002  if (is_output_feature)
1003  {
1005  (sm, ip0, thread_index, now, vm, b0)))
1006  goto trace0;
1007  }
1008 
1009  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP))
1010  {
1011  next0 = def_slow;
1012  goto trace0;
1013  }
1014 
1015  make_ed_kv (&ip0->src_address, &ip0->dst_address,
1016  ip0->protocol, rx_fib_index0,
1017  vnet_buffer (b0)->ip.reass.l4_src_port,
1018  vnet_buffer (b0)->ip.reass.l4_dst_port, ~0ULL, &kv0);
1019 
1020  // lookup for session
1021  if (clib_bihash_search_16_8 (&tsm->in2out_ed, &kv0, &value0))
1022  {
1023  // session does not exist go slow path
1024  next0 = def_slow;
1025  goto trace0;
1026  }
1027  s0 = pool_elt_at_index (tsm->sessions, value0.value);
1028 
1029  if (s0->tcp_closed_timestamp)
1030  {
1031  if (now >= s0->tcp_closed_timestamp)
1032  {
1033  // session is closed, go slow path
1034  next0 = def_slow;
1035  }
1036  else
1037  {
1038  // session in transitory timeout, drop
1039  b0->error = node->errors[NAT_IN2OUT_ED_ERROR_TCP_CLOSED];
1040  next0 = NAT_NEXT_DROP;
1041  }
1042  goto trace0;
1043  }
1044 
1045  // drop if session expired
1046  u64 sess_timeout_time;
1047  sess_timeout_time = s0->last_heard +
1048  (f64) nat44_session_get_timeout (sm, s0);
1049  if (now >= sess_timeout_time)
1050  {
1051  nat_free_session_data (sm, s0, thread_index, 0);
1052  nat_ed_session_delete (sm, s0, thread_index, 1);
1053  // session is closed, go slow path
1054  next0 = def_slow;
1055  goto trace0;
1056  }
1057 
1058  b0->flags |= VNET_BUFFER_F_IS_NATED;
1059 
1060  if (!is_output_feature)
1061  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->out2in.fib_index;
1062 
1063  old_addr0 = ip0->src_address.as_u32;
1064  new_addr0 = ip0->src_address.as_u32 = s0->out2in.addr.as_u32;
1065  sum0 = ip0->checksum;
1066  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1067  src_address);
1069  sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1070  s0->ext_host_addr.as_u32, ip4_header_t,
1071  dst_address);
1072  ip0->checksum = ip_csum_fold (sum0);
1073 
1074  old_port0 = vnet_buffer (b0)->ip.reass.l4_src_port;
1075 
1076  if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP))
1077  {
1078  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1079  {
1080  new_port0 = udp0->src_port = s0->out2in.port;
1081  sum0 = tcp0->checksum;
1082  sum0 =
1083  ip_csum_update (sum0, old_addr0, new_addr0,
1084  ip4_header_t, dst_address);
1085  sum0 =
1086  ip_csum_update (sum0, old_port0, new_port0,
1087  ip4_header_t, length);
1089  {
1090  sum0 =
1091  ip_csum_update (sum0, ip0->dst_address.as_u32,
1092  s0->ext_host_addr.as_u32,
1093  ip4_header_t, dst_address);
1094  sum0 =
1095  ip_csum_update (sum0,
1096  vnet_buffer (b0)->ip.
1097  reass.l4_dst_port, s0->ext_host_port,
1098  ip4_header_t, length);
1099  tcp0->dst_port = s0->ext_host_port;
1100  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1101  }
1102  mss_clamping (sm, tcp0, &sum0);
1103  tcp0->checksum = ip_csum_fold (sum0);
1104  }
1105  tcp_packets++;
1107  (sm, now, s0, b0, thread_index))
1108  goto trace0;
1109  }
1110  else if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment
1111  && udp0->checksum)
1112  {
1113  new_port0 = udp0->src_port = s0->out2in.port;
1114  sum0 = udp0->checksum;
1115  sum0 =
1116  ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1117  dst_address);
1118  sum0 =
1119  ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
1120  length);
1122  {
1123  sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1124  s0->ext_host_addr.as_u32,
1125  ip4_header_t, dst_address);
1126  sum0 =
1127  ip_csum_update (sum0,
1128  vnet_buffer (b0)->ip.reass.l4_dst_port,
1129  s0->ext_host_port, ip4_header_t, length);
1130  udp0->dst_port = s0->ext_host_port;
1131  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1132  }
1133  udp0->checksum = ip_csum_fold (sum0);
1134  udp_packets++;
1135  }
1136  else
1137  {
1138  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1139  {
1140  new_port0 = udp0->src_port = s0->out2in.port;
1142  {
1143  udp0->dst_port = s0->ext_host_port;
1144  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1145  }
1146  udp_packets++;
1147  }
1148  }
1149 
1150  /* Accounting */
1153  (vm, b0), thread_index);
1154  /* Per-user LRU list maintenance */
1155  nat44_session_update_lru (sm, s0, thread_index);
1156 
1157  trace0:
1159  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1160  {
1162  vlib_add_trace (vm, node, b0, sizeof (*t));
1163  t->sw_if_index = sw_if_index0;
1164  t->next_index = next0;
1165  t->is_slow_path = 0;
1166 
1167  if (s0)
1168  t->session_index = s0 - tsm->sessions;
1169  else
1170  t->session_index = ~0;
1171  }
1172 
1173  pkts_processed += next0 == vnet_buffer2 (b0)->nat.arc_next;
1174  /* verify speculative enqueue, maybe switch current next frame */
1175  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1176  to_next, n_left_to_next,
1177  bi0, next0);
1178  }
1179 
1180  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1181  }
1182 
1183  vlib_node_increment_counter (vm, stats_node_index,
1184  NAT_IN2OUT_ED_ERROR_IN2OUT_PACKETS,
1185  pkts_processed);
1186  vlib_node_increment_counter (vm, stats_node_index,
1187  NAT_IN2OUT_ED_ERROR_TCP_PACKETS, tcp_packets);
1188  vlib_node_increment_counter (vm, stats_node_index,
1189  NAT_IN2OUT_ED_ERROR_UDP_PACKETS, udp_packets);
1190  vlib_node_increment_counter (vm, stats_node_index,
1191  NAT_IN2OUT_ED_ERROR_ICMP_PACKETS,
1192  icmp_packets);
1193  vlib_node_increment_counter (vm, stats_node_index,
1194  NAT_IN2OUT_ED_ERROR_OTHER_PACKETS,
1195  other_packets);
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, *to_next, pkts_processed = 0, stats_node_index;
1206  nat_next_t next_index;
1207  snat_main_t *sm = &snat_main;
1208  f64 now = vlib_time_now (vm);
1209  u32 thread_index = vm->thread_index;
1210  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
1211  u32 tcp_packets = 0, udp_packets = 0, icmp_packets = 0, other_packets = 0;
1212 
1213  stats_node_index = sm->ed_in2out_slowpath_node_index;
1214 
1215  from = vlib_frame_vector_args (frame);
1216  n_left_from = frame->n_vectors;
1217  next_index = node->cached_next_index;
1218 
1219  while (n_left_from > 0)
1220  {
1221  u32 n_left_to_next;
1222 
1223  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1224 
1225  while (n_left_from > 0 && n_left_to_next > 0)
1226  {
1227  u32 bi0;
1228  vlib_buffer_t *b0;
1229  u32 next0, sw_if_index0, rx_fib_index0, iph_offset0 = 0, proto0,
1230  new_addr0, old_addr0;
1231  u16 old_port0, new_port0;
1232  ip4_header_t *ip0;
1233  udp_header_t *udp0;
1234  tcp_header_t *tcp0;
1235  icmp46_header_t *icmp0;
1236  snat_session_t *s0 = 0;
1237  clib_bihash_kv_16_8_t kv0, value0;
1238  ip_csum_t sum0;
1239 
1240  /* speculatively enqueue b0 to the current next frame */
1241  bi0 = from[0];
1242  to_next[0] = bi0;
1243  from += 1;
1244  to_next += 1;
1245  n_left_from -= 1;
1246  n_left_to_next -= 1;
1247 
1248  b0 = vlib_get_buffer (vm, bi0);
1249 
1250  if (is_output_feature)
1251  iph_offset0 = vnet_buffer (b0)->ip.reass.save_rewrite_length;
1252 
1253  next0 = vnet_buffer2 (b0)->nat.arc_next;
1254 
1255  ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
1256  iph_offset0);
1257 
1258  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1259  rx_fib_index0 =
1261  sw_if_index0);
1262 
1263  if (PREDICT_FALSE (ip0->ttl == 1))
1264  {
1265  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1266  icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
1267  ICMP4_time_exceeded_ttl_exceeded_in_transit,
1268  0);
1269  next0 = NAT_NEXT_ICMP_ERROR;
1270  goto trace0;
1271  }
1272 
1273  udp0 = ip4_next_header (ip0);
1274  tcp0 = (tcp_header_t *) udp0;
1275  icmp0 = (icmp46_header_t *) udp0;
1276  proto0 = ip_proto_to_nat_proto (ip0->protocol);
1277 
1278  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_OTHER))
1279  {
1280  s0 = nat44_ed_in2out_unknown_proto (sm, b0, ip0,
1281  rx_fib_index0,
1282  thread_index, now,
1283  vm, node);
1284  if (!s0)
1285  next0 = NAT_NEXT_DROP;
1286 
1287  other_packets++;
1288  goto trace0;
1289  }
1290 
1291  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP))
1292  {
1293  next0 = icmp_in2out_ed_slow_path
1294  (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0,
1295  node, next0, now, thread_index, &s0);
1296  icmp_packets++;
1297  goto trace0;
1298  }
1299 
1300  // move down
1301  make_ed_kv (&ip0->src_address, &ip0->dst_address,
1302  ip0->protocol, rx_fib_index0,
1303  vnet_buffer (b0)->ip.reass.l4_src_port,
1304  vnet_buffer (b0)->ip.reass.l4_dst_port, ~0ULL, &kv0);
1305 
1306  if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv0, &value0))
1307  {
1308  s0 = pool_elt_at_index (tsm->sessions, value0.value);
1309 
1310  if (s0->tcp_closed_timestamp && now >= s0->tcp_closed_timestamp)
1311  {
1312  nat_free_session_data (sm, s0, thread_index, 0);
1313  nat_ed_session_delete (sm, s0, thread_index, 1);
1314  s0 = NULL;
1315  }
1316  }
1317 
1318  if (!s0)
1319  {
1320  if (is_output_feature)
1321  {
1322  if (PREDICT_FALSE
1324  (sm, ip0, vnet_buffer (b0)->ip.reass.l4_src_port,
1325  vnet_buffer (b0)->ip.reass.l4_dst_port, thread_index,
1326  sw_if_index0,
1327  vnet_buffer (b0)->sw_if_index[VLIB_TX])))
1328  goto trace0;
1329 
1330  /*
1331  * Send DHCP packets to the ipv4 stack, or we won't
1332  * be able to use dhcp client on the outside interface
1333  */
1334  if (PREDICT_FALSE
1335  (proto0 == NAT_PROTOCOL_UDP
1336  && (vnet_buffer (b0)->ip.reass.l4_dst_port ==
1337  clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_server))
1338  && ip0->dst_address.as_u32 == 0xffffffff))
1339  goto trace0;
1340  }
1341  else
1342  {
1343  if (PREDICT_FALSE
1345  (sm, node, sw_if_index0, ip0, proto0, rx_fib_index0,
1346  thread_index)))
1347  goto trace0;
1348  }
1349 
1350  next0 =
1351  slow_path_ed (sm, b0, ip0->src_address, ip0->dst_address,
1352  vnet_buffer (b0)->ip.reass.l4_src_port,
1353  vnet_buffer (b0)->ip.reass.l4_dst_port,
1354  ip0->protocol, rx_fib_index0, &s0, node, next0,
1355  thread_index, now);
1356 
1357  if (PREDICT_FALSE (next0 == NAT_NEXT_DROP))
1358  goto trace0;
1359 
1360  if (PREDICT_FALSE (!s0))
1361  goto trace0;
1362 
1363  }
1364 
1365  b0->flags |= VNET_BUFFER_F_IS_NATED;
1366 
1367  if (!is_output_feature)
1368  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->out2in.fib_index;
1369 
1370  old_addr0 = ip0->src_address.as_u32;
1371  new_addr0 = ip0->src_address.as_u32 = s0->out2in.addr.as_u32;
1372  sum0 = ip0->checksum;
1373  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1374  src_address);
1376  sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1377  s0->ext_host_addr.as_u32, ip4_header_t,
1378  dst_address);
1379  ip0->checksum = ip_csum_fold (sum0);
1380 
1381  old_port0 = vnet_buffer (b0)->ip.reass.l4_src_port;
1382 
1383  if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP))
1384  {
1385  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1386  {
1387  new_port0 = udp0->src_port = s0->out2in.port;
1388  sum0 = tcp0->checksum;
1389  sum0 =
1390  ip_csum_update (sum0, old_addr0, new_addr0,
1391  ip4_header_t, dst_address);
1392  sum0 =
1393  ip_csum_update (sum0, old_port0, new_port0,
1394  ip4_header_t, length);
1396  {
1397  sum0 =
1398  ip_csum_update (sum0, ip0->dst_address.as_u32,
1399  s0->ext_host_addr.as_u32,
1400  ip4_header_t, dst_address);
1401  sum0 =
1402  ip_csum_update (sum0,
1403  vnet_buffer (b0)->ip.
1404  reass.l4_dst_port, s0->ext_host_port,
1405  ip4_header_t, length);
1406  tcp0->dst_port = s0->ext_host_port;
1407  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1408  }
1409  mss_clamping (sm, tcp0, &sum0);
1410  tcp0->checksum = ip_csum_fold (sum0);
1411  }
1412  tcp_packets++;
1414  (sm, now, s0, b0, thread_index))
1415  goto trace0;
1416  }
1417  else if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment
1418  && udp0->checksum)
1419  {
1420  new_port0 = udp0->src_port = s0->out2in.port;
1421  sum0 = udp0->checksum;
1422  sum0 =
1423  ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1424  dst_address);
1425  sum0 =
1426  ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
1427  length);
1429  {
1430  sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1431  s0->ext_host_addr.as_u32,
1432  ip4_header_t, dst_address);
1433  sum0 =
1434  ip_csum_update (sum0,
1435  vnet_buffer (b0)->ip.reass.l4_dst_port,
1436  s0->ext_host_port, ip4_header_t, length);
1437  udp0->dst_port = s0->ext_host_port;
1438  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1439  }
1440  udp0->checksum = ip_csum_fold (sum0);
1441  udp_packets++;
1442  }
1443  else
1444  {
1445  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1446  {
1447  new_port0 = udp0->src_port = s0->out2in.port;
1449  {
1450  udp0->dst_port = s0->ext_host_port;
1451  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1452  }
1453  udp_packets++;
1454  }
1455  }
1456 
1457  /* Accounting */
1460  (vm, b0), thread_index);
1461  /* Per-user LRU list maintenance */
1462  nat44_session_update_lru (sm, s0, thread_index);
1463 
1464  trace0:
1466  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1467  {
1469  vlib_add_trace (vm, node, b0, sizeof (*t));
1470  t->sw_if_index = sw_if_index0;
1471  t->next_index = next0;
1472  t->is_slow_path = 1;
1473 
1474  if (s0)
1475  t->session_index = s0 - tsm->sessions;
1476  else
1477  t->session_index = ~0;
1478  }
1479 
1480  pkts_processed += next0 == vnet_buffer2 (b0)->nat.arc_next;
1481 
1482  /* verify speculative enqueue, maybe switch current next frame */
1483  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1484  to_next, n_left_to_next,
1485  bi0, next0);
1486  }
1487 
1488  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1489  }
1490 
1491  vlib_node_increment_counter (vm, stats_node_index,
1492  NAT_IN2OUT_ED_ERROR_IN2OUT_PACKETS,
1493  pkts_processed);
1494  vlib_node_increment_counter (vm, stats_node_index,
1495  NAT_IN2OUT_ED_ERROR_TCP_PACKETS, tcp_packets);
1496  vlib_node_increment_counter (vm, stats_node_index,
1497  NAT_IN2OUT_ED_ERROR_UDP_PACKETS, udp_packets);
1498  vlib_node_increment_counter (vm, stats_node_index,
1499  NAT_IN2OUT_ED_ERROR_ICMP_PACKETS,
1500  icmp_packets);
1501  vlib_node_increment_counter (vm, stats_node_index,
1502  NAT_IN2OUT_ED_ERROR_OTHER_PACKETS,
1503  other_packets);
1504  return frame->n_vectors;
1505 }
1506 
1509  vlib_frame_t * frame)
1510 {
1512 }
1513 
1514 /* *INDENT-OFF* */
1516  .name = "nat44-ed-in2out",
1517  .vector_size = sizeof (u32),
1518  .sibling_of = "nat-default",
1519  .format_trace = format_nat_in2out_ed_trace,
1521  .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1522  .error_strings = nat_in2out_ed_error_strings,
1523  .runtime_data_bytes = sizeof (snat_runtime_t),
1524 };
1525 /* *INDENT-ON* */
1526 
1529  vlib_frame_t * frame)
1530 {
1532 }
1533 
1534 /* *INDENT-OFF* */
1536  .name = "nat44-ed-in2out-output",
1537  .vector_size = sizeof (u32),
1538  .sibling_of = "nat-default",
1539  .format_trace = format_nat_in2out_ed_trace,
1541  .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1542  .error_strings = nat_in2out_ed_error_strings,
1543  .runtime_data_bytes = sizeof (snat_runtime_t),
1544 };
1545 /* *INDENT-ON* */
1546 
1549  node, vlib_frame_t * frame)
1550 {
1552 }
1553 
1554 /* *INDENT-OFF* */
1556  .name = "nat44-ed-in2out-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 
1569  * node,
1570  vlib_frame_t * frame)
1571 {
1573 }
1574 
1575 /* *INDENT-OFF* */
1577  .name = "nat44-ed-in2out-output-slowpath",
1578  .vector_size = sizeof (u32),
1579  .sibling_of = "nat-default",
1580  .format_trace = format_nat_in2out_ed_trace,
1582  .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1583  .error_strings = nat_in2out_ed_error_strings,
1584  .runtime_data_bytes = sizeof (snat_runtime_t),
1585 };
1586 /* *INDENT-ON* */
1587 
1588 static u8 *
1589 format_nat_pre_trace (u8 * s, va_list * args)
1590 {
1591  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1592  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1593  nat_pre_trace_t *t = va_arg (*args, nat_pre_trace_t *);
1594  return format (s, "in2out next_index %d arc_next_index %d", t->next_index,
1595  t->arc_next_index);
1596 }
1597 
1601  return nat_pre_node_fn_inline (vm, node, frame,
1603 }
1604 
1605 /* *INDENT-OFF* */
1607  .name = "nat-pre-in2out",
1608  .vector_size = sizeof (u32),
1609  .sibling_of = "nat-default",
1610  .format_trace = format_nat_pre_trace,
1612  .n_errors = 0,
1613 };
1614 /* *INDENT-ON* */
1615 
1616 /*
1617  * fd.io coding-style-patch-verification: ON
1618  *
1619  * Local Variables:
1620  * eval: (c-set-style "gnu")
1621  * End:
1622  */
ip4_address_t external_addr
Definition: nat.h:401
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:212
nat_outside_fib_t * outside_fibs
Definition: nat.h:566
#define snat_is_session_static(s)
Check if SNAT session is created from static mapping.
Definition: nat.h:728
vlib_node_registration_t nat44_ed_in2out_output_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_output_node)
Definition: in2out_ed.c:1535
#define CLIB_UNUSED(x)
Definition: clib.h:86
u32 arc_next_index
Definition: nat.h:68
a
Definition: bitmap.h:538
ip4_address_t src_address
Definition: ip4_packet.h:170
#define nat_elog_info(nat_elog_str)
Definition: nat.h:994
#define vnet_buffer2(b)
Definition: buffer.h:482
static u32 nat44_session_get_timeout(snat_main_t *sm, snat_session_t *s)
Definition: nat_inlines.h:385
#define nat_elog_notice(nat_elog_str)
Definition: nat.h:986
#define PREDICT_TRUE(x)
Definition: clib.h:119
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
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:291
u32 fib_table_get_index_for_sw_if_index(fib_protocol_t proto, u32 sw_if_index)
Get the index of the FIB bound to the interface.
Definition: fib_table.c:989
static void make_sm_kv(clib_bihash_kv_8_8_t *kv, ip4_address_t *addr, u8 proto, u32 fib_index, u16 port)
Definition: nat_inlines.h:489
u16 port_per_thread
Definition: nat.h:532
u32 thread_index
Definition: main.h:218
void nat_free_session_data(snat_main_t *sm, snat_session_t *s, u32 thread_index, u8 is_ha)
Free NAT44 session data (lookup keys, external address port)
Definition: nat.c:198
#define foreach_nat_in2out_ed_error
Definition: nat.h:166
uword ip_csum_t
Definition: ip_packet.h:244
#define nat_elog_warn(nat_elog_str)
Definition: nat.h:988
void nat_ha_sadd(ip4_address_t *in_addr, u16 in_port, ip4_address_t *out_addr, u16 out_port, ip4_address_t *eh_addr, u16 eh_port, ip4_address_t *ehn_addr, u16 ehn_port, u8 proto, u32 fib_index, u16 flags, u32 thread_index, u8 is_resync)
Create session add HA event.
Definition: nat_ha.c:689
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
#define nat44_is_ses_closed(s)
Check if NAT44 endpoint-dependent TCP session is closed.
Definition: nat.h:782
#define VLIB_NODE_FN(node)
Definition: node.h:202
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_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:493
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:472
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
void snat_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 vrf_id)
Generate NAT44 session create event.
struct _tcp_header tcp_header_t
#define snat_is_unk_proto_session(s)
Check if SNAT session for unknown protocol.
Definition: nat.h:734
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:741
static_always_inline int get_icmp_i2o_ed_key(vlib_buffer_t *b, ip4_header_t *ip0, u32 rx_fib_index, u64 value, u8 *nat_proto, u16 *l_port, u16 *r_port, clib_bihash_kv_16_8_t *kv)
Definition: nat_inlines.h:499
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:67
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:698
u16 src_port
Definition: udp.api:41
u32 ed_in2out_node_index
Definition: nat.h:603
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
Definition: ip4_fib.c:230
#define static_always_inline
Definition: clib.h:106
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:513
static nat_protocol_t ip_proto_to_nat_proto(u8 ip_proto)
Common NAT inline functions.
Definition: inlines.h:22
vl_api_interface_index_t sw_if_index
Definition: gre.api:53
static_always_inline u16 snat_random_port(u16 min, u16 max)
Definition: in2out_ed.c:192
ip4_address_t dst_address
Definition: ip4_packet.h:170
lb_nat_type_t
Definition: nat.h:386
#define SNAT_SESSION_FLAG_OUTPUT_FEATURE
Definition: nat.h:239
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Aggregate type for a prefix.
Definition: fib_types.h:203
static_always_inline u8 icmp_type_is_error_message(u8 icmp_type)
Definition: inlines.h:53
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:654
#define is_fwd_bypass_session(s)
Check if NAT session is forwarding bypass.
Definition: nat.h:752
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:241
void snat_ipfix_logging_addresses_exhausted(u32 thread_index, u32 pool_id)
Generate NAT addresses exhausted event.
unsigned int u32
Definition: types.h:88
void nat_ipfix_logging_max_sessions(u32 thread_index, u32 limit)
Generate maximum session entries exceeded event.
fib_node_index_t fib_table_lookup(u32 fib_index, const fib_prefix_t *prefix)
Perfom a longest prefix match in the non-forwarding table.
Definition: fib_table.c:68
int snat_static_mapping_match(snat_main_t *sm, snat_session_key_t match, snat_session_key_t *mapping, u8 by_external, u8 *is_addr_only, twice_nat_type_t *twice_nat, lb_nat_type_t *lb, ip4_address_t *ext_host_addr, u8 *is_identity_nat)
Match NAT44 static mapping.
Definition: nat.c:2741
void snat_free_outside_address_and_port(snat_address_t *addresses, u32 thread_index, snat_session_key_t *k)
Free outside address and port pair.
Definition: nat.c:2669
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
u32 max_translations
Definition: nat.h:635
static void mss_clamping(snat_main_t *sm, tcp_header_t *tcp, ip_csum_t *sum)
Definition: nat_inlines.h:635
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:534
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:283
u32 fib_index
Definition: nat.h:328
clib_bihash_16_8_t out2in_ed
Definition: nat.h:457
vl_api_ip_proto_t proto
Definition: acl_types.api:50
long ctx[MAX_CONNS]
Definition: main.c:144
vlib_node_registration_t nat44_ed_in2out_slowpath_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_slowpath_node)
Definition: in2out_ed.c:1555
unsigned short u16
Definition: types.h:57
u16 protocol
Definition: nat.h:80
snat_static_mapping_t * static_mappings
Definition: nat.h:545
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
nat_next_t
Definition: nat.h:51
#define PREDICT_FALSE(x)
Definition: clib.h:118
vl_api_address_union_t src_address
Definition: ip_types.api:99
#define SNAT_SESSION_FLAG_UNKNOWN_PROTO
Definition: nat.h:233
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:224
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:338
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
vlib_main_t * vm
Definition: in2out_ed.c:1599
static u8 * format_nat_pre_trace(u8 *s, va_list *args)
Definition: in2out_ed.c:1589
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1150
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:51
snat_interface_t * output_feature_interfaces
Definition: nat.h:549
snat_main_t snat_main
Definition: nat.c:41
u64 value
the value
Definition: bihash_8_8.h:42
vlib_node_registration_t nat_pre_in2out_node
(constructor) VLIB_REGISTER_NODE (nat_pre_in2out_node)
Definition: in2out_ed.c:1606
u32 random_seed
Definition: nat.h:579
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u16 n_vectors
Definition: node.h:399
static u32 random_u32_max(void)
Maximum value returned by random_u32()
Definition: random.h:80
int nat44_o2i_ed_is_idle_session_cb(clib_bihash_kv_16_8_t *kv, void *arg)
Definition: out2in_ed.c:94
vlib_node_registration_t nat44_ed_in2out_output_slowpath_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_output_slowpath_node)
Definition: in2out_ed.c:1576
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
static_always_inline void vnet_feature_next(u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:322
static void nat44_session_update_counters(snat_session_t *s, f64 now, uword bytes, u32 thread_index)
Definition: nat_inlines.h:408
u32 ed_in2out_slowpath_node_index
Definition: nat.h:604
u32 outside_fib_index
Definition: nat.h:643
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:30
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:39
#define ARRAY_LEN(x)
Definition: clib.h:66
ip4_address_t addr
Definition: nat.h:78
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:483
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:528
static uword nat_pre_node_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, u32 def_next)
The NAT inline functions.
Definition: nat_inlines.h:27
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1599
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
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:517
vl_api_interface_index_t tx_sw_if_index
Definition: ip.api:441
u8 value
Definition: qos.api:54
static int nat44_set_tcp_session_state_i2o(snat_main_t *sm, f64 now, snat_session_t *ses, vlib_buffer_t *b, u32 thread_index)
Set TCP session state.
Definition: nat_inlines.h:290
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:422
#define SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT
Definition: nat.h:236
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:168
void snat_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 vrf_id)
Generate NAT44 session delete event.
ip4_address_t addr
Definition: nat.h:314
vlib_node_registration_t nat44_ed_in2out_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_node)
Definition: in2out_ed.c:1515
snat_address_t * twice_nat_addresses
Definition: nat.h:569
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:715
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
typedef key
Definition: ipsec_types.api:85
Definition: defs.h:47
vl_api_address_t ip
Definition: l2.api:501
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:31
int nat44_i2o_ed_is_idle_session_cb(clib_bihash_kv_16_8_t *kv, void *arg)
Definition: in2out_ed.c:70
#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:35
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:536
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:244
#define ip_csum_update(sum, old, new, type, field)
Definition: ip_packet.h:294
NAT syslog logging.
snat_address_t * addresses
Definition: nat.h:552
#define vnet_buffer(b)
Definition: buffer.h:417
static u32 random_u32(u32 *seed)
32-bit random number generator
Definition: random.h:69
#define SNAT_SESSION_FLAG_STATIC_MAPPING
Definition: nat.h:232
void nat44_ed_hairpinning_unknown_proto(snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip)
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)
Definition: in2out_ed.c:583
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 *allocated_addr, u16 *allocated_port, clib_bihash_kv_16_8_t *out2in_ed_kv)
Definition: in2out_ed.c:200
u8 forwarding_enabled
Definition: nat.h:624
#define vec_foreach(var, vec)
Vector iterator.
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1600
u32 icmp_match_in2out_ed(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b, ip4_header_t *ip, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Definition: in2out_ed.c:636
u16 flags
Copy of main node flags.
Definition: node.h:511
#define is_twice_nat_session(s)
Check if NAT session is twice NAT.
Definition: nat.h:740
clib_bihash_16_8_t in2out_ed
Definition: nat.h:458
static_always_inline int nat_lru_free_one(snat_main_t *sm, int thread_index, f64 now)
Definition: ed_inlines.h:106
u16 dst_port
Definition: udp.api:42
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:304
snat_session_t * sessions
Definition: nat.h:467
static_always_inline void icmp4_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
Definition: icmp4.h:51
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
static char * nat_in2out_ed_error_strings[]
Definition: in2out_ed.c:36
#define SNAT_SESSION_FLAG_LOAD_BALANCING
Definition: nat.h:234
static void make_ed_kv(ip4_address_t *l_addr, ip4_address_t *r_addr, u8 proto, u32 fib_index, u16 l_port, u16 r_port, u64 value, clib_bihash_kv_16_8_t *kv)
Definition: nat_inlines.h:447
clib_bihash_8_8_t static_mapping_by_local
Definition: nat.h:539
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:300
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:913
Definition: defs.h:46
NAT active-passive HA.
u16 fib_index
Definition: nat.h:80
static bool tcp_flags_is_init(u8 f)
Check if client initiating TCP connection (received SYN from client)
Definition: nat.h:813