FD.io VPP  v21.06
Vector Packet Processing
nat44_ed_out2in.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 outside to inside 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 
28 #include <nat/lib/nat_syslog.h>
29 #include <nat/lib/ipfix_logging.h>
30 
31 #include <nat/nat44-ed/nat44_ed.h>
33 
34 static char *nat_out2in_ed_error_strings[] = {
35 #define _(sym,string) string,
37 #undef _
38 };
39 
40 typedef enum
41 {
48 
49 typedef struct
50 {
63 
64 static u8 *
65 format_slow_path_reason (u8 *s, va_list *args)
66 {
67  nat_slow_path_reason_e reason = va_arg (*args, nat_slow_path_reason_e);
68  switch (reason)
69  {
71  return format (s, "no reason for slow path");
73  return format (s, "slow path because lookup failed");
75  return format (s, "slow path because vrf expired");
77  return format (s, "slow path because tcp closed");
79  return format (s, "slow path because session expired");
80  }
81  return format (s, "invalid reason value");
82 }
83 
84 static u8 *
85 format_nat44_ed_out2in_trace (u8 * s, va_list * args)
86 {
87  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
88  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
89  nat44_ed_out2in_trace_t *t = va_arg (*args, nat44_ed_out2in_trace_t *);
90  char *tag;
91 
92  tag =
93  t->is_slow_path ? "NAT44_OUT2IN_ED_SLOW_PATH" :
94  "NAT44_OUT2IN_ED_FAST_PATH";
95 
96  s = format (s, "%s: sw_if_index %d, next index %d", tag, t->sw_if_index,
97  t->next_index);
98  if (~0 != t->session_index)
99  {
100  s = format (s, ", session %d, translation result '%U' via %s",
103  t->translation_via_i2of ? "i2of" : "o2if");
104  s = format (s, "\n i2of %U", format_nat_6t_flow, &t->i2of);
105  s = format (s, "\n o2if %U", format_nat_6t_flow, &t->o2if);
106  }
107  if (!t->is_slow_path)
108  {
109  if (t->lookup_skipped)
110  {
111  s = format (s, "\n lookup skipped - cached session index used");
112  }
113  else
114  {
115  s = format (s, "\n search key %U", format_ed_session_kvp,
116  &t->search_key);
117  }
118  s = format (s, "\n %U", format_slow_path_reason, t->slow_path_reason);
119  }
120 
121  return s;
122 }
123 
124 static int
126  u32 thread_index, u32 rx_fib_index)
127 {
129 
130  init_ed_k (&kv, ip->src_address, src_port, ip->dst_address, dst_port,
131  rx_fib_index, ip->protocol);
132  if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv, &value))
133  return 1;
134 
135  return 0;
136 }
137 
138 static void create_bypass_for_fwd (snat_main_t *sm, vlib_buffer_t *b,
139  snat_session_t *s, ip4_header_t *ip,
140  u32 rx_fib_index, u32 thread_index);
141 
142 static snat_session_t *create_session_for_static_mapping_ed (
143  snat_main_t *sm, vlib_buffer_t *b, ip4_address_t i2o_addr, u16 i2o_port,
144  u32 i2o_fib_index, ip4_address_t o2i_addr, u16 o2i_port, u32 o2i_fib_index,
145  nat_protocol_t nat_proto, vlib_node_runtime_t *node, u32 rx_fib_index,
147  snat_static_mapping_t *mapping);
148 
149 static inline u32
151  icmp46_header_t *icmp, u32 sw_if_index,
152  u32 rx_fib_index, vlib_node_runtime_t *node,
154  snat_session_t **s_p)
155 {
156  vlib_main_t *vm = vlib_get_main ();
157 
158  ip_csum_t sum;
159  u16 checksum;
160 
161  snat_session_t *s = 0;
162  u8 is_addr_only, identity_nat;
163  ip4_address_t sm_addr;
164  u16 sm_port;
165  u32 sm_fib_index;
167  u8 lookup_protocol;
168  ip4_address_t lookup_saddr, lookup_daddr;
169  u16 lookup_sport, lookup_dport;
170 
171  sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
172  rx_fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
173 
174  if (nat_get_icmp_session_lookup_values (b, ip, &lookup_saddr, &lookup_sport,
175  &lookup_daddr, &lookup_dport,
176  &lookup_protocol))
177  {
178  b->error = node->errors[NAT_OUT2IN_ED_ERROR_UNSUPPORTED_PROTOCOL];
179  next = NAT_NEXT_DROP;
180  goto out;
181  }
182 
184  vm, sm, ip->dst_address, lookup_sport, rx_fib_index,
185  ip_proto_to_nat_proto (ip->protocol), &sm_addr, &sm_port,
186  &sm_fib_index, 1, &is_addr_only, 0, 0, 0, &identity_nat, &m))
187  {
188  // static mapping not matched
189  if (!sm->forwarding_enabled)
190  {
191  /* Don't NAT packet aimed at the intfc address */
192  if (!is_interface_addr (sm, node, sw_if_index,
193  ip->dst_address.as_u32))
194  {
195  b->error = node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
196  next = NAT_NEXT_DROP;
197  }
198  }
199  else
200  {
201  if (next_src_nat (sm, ip, lookup_sport, lookup_dport, thread_index,
202  rx_fib_index))
203  {
205  }
206  else
207  {
208  create_bypass_for_fwd (sm, b, s, ip, rx_fib_index, thread_index);
209  }
210  }
211  goto out;
212  }
213 
214  if (PREDICT_FALSE (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags !=
215  ICMP4_echo_reply &&
216  (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags !=
217  ICMP4_echo_request ||
218  !is_addr_only)))
219  {
220  b->error = node->errors[NAT_OUT2IN_ED_ERROR_BAD_ICMP_TYPE];
221  next = NAT_NEXT_DROP;
222  goto out;
223  }
224 
225  if (PREDICT_FALSE (identity_nat))
226  {
227  goto out;
228  }
229 
230  /* Create session initiated by host from external network */
232  sm, b, sm_addr, sm_port, sm_fib_index, ip->dst_address, lookup_sport,
233  rx_fib_index, ip_proto_to_nat_proto (lookup_protocol), node, rx_fib_index,
234  thread_index, 0, 0, vlib_time_now (vm), m);
235  if (!s)
236  next = NAT_NEXT_DROP;
237 
238  if (PREDICT_TRUE (!ip4_is_fragment (ip)))
239  {
241  vm, b, (u8 *) icmp - (u8 *) vlib_buffer_get_current (b),
242  ntohs (ip->length) - ip4_header_bytes (ip), 0);
243  checksum = ~ip_csum_fold (sum);
244  if (checksum != 0 && checksum != 0xffff)
245  {
246  next = NAT_NEXT_DROP;
247  goto out;
248  }
249  }
250 
251  if (PREDICT_TRUE (next != NAT_NEXT_DROP && s))
252  {
253  /* Accounting */
255  s, now, vlib_buffer_length_in_chain (vm, b), thread_index);
256  /* Per-user LRU list maintenance */
257  nat44_session_update_lru (sm, s, thread_index);
258  }
259 out:
260  if (NAT_NEXT_DROP == next && s)
261  {
262  nat_ed_session_delete (sm, s, thread_index, 1);
263  s = 0;
264  }
265  *s_p = s;
266  return next;
267 }
268 
269 // allocate exact address based on preference
275  u16 * port,
276  u16 port_per_thread, u32 snat_thread_index)
277 {
278  snat_main_t *sm = &snat_main;
279  u32 portnum;
280 
281  switch (proto)
282  {
283 #define _(N, j, n, s) \
284  case NAT_PROTOCOL_##N: \
285  if (a->busy_##n##_ports_per_thread[thread_index] < port_per_thread) \
286  { \
287  while (1) \
288  { \
289  portnum = (port_per_thread * \
290  snat_thread_index) + \
291  snat_random_port(0, port_per_thread - 1) + 1024; \
292  if (a->busy_##n##_port_refcounts[portnum]) \
293  continue; \
294  --a->busy_##n##_port_refcounts[portnum]; \
295  a->busy_##n##_ports_per_thread[thread_index]++; \
296  a->busy_##n##_ports++; \
297  *addr = a->addr; \
298  *port = clib_host_to_net_u16(portnum); \
299  return 0; \
300  } \
301  } \
302  break;
304 #undef _
305  default : nat_elog_info (sm, "unknown protocol");
306  return 1;
307  }
308 
309  /* Totally out of translations to use... */
310  nat_ipfix_logging_addresses_exhausted (thread_index, 0);
311  return 1;
312 }
313 
318  u16 port_per_thread,
319  u32 snat_thread_index)
320 {
321  snat_main_t *sm = &snat_main;
322  snat_address_t *a, *ga = 0;
323  u32 portnum;
324  int i;
325 
326  for (i = 0; i < vec_len (addresses); i++)
327  {
328  a = addresses + i;
329  switch (proto)
330  {
331 #define _(N, j, n, s) \
332  case NAT_PROTOCOL_##N: \
333  if (a->busy_##n##_ports_per_thread[thread_index] < port_per_thread) \
334  { \
335  if (a->fib_index == fib_index) \
336  { \
337  while (1) \
338  { \
339  portnum = (port_per_thread * snat_thread_index) + \
340  snat_random_port (0, port_per_thread - 1) + 1024; \
341  if (a->busy_##n##_port_refcounts[portnum]) \
342  continue; \
343  --a->busy_##n##_port_refcounts[portnum]; \
344  a->busy_##n##_ports_per_thread[thread_index]++; \
345  a->busy_##n##_ports++; \
346  *addr = a->addr; \
347  *port = clib_host_to_net_u16 (portnum); \
348  return 0; \
349  } \
350  } \
351  else if (a->fib_index == ~0) \
352  { \
353  ga = a; \
354  } \
355  } \
356  break;
358 #undef _
359  default : nat_elog_info (sm, "unknown protocol");
360  return 1;
361  }
362  }
363 
364  if (ga)
365  {
366  a = ga;
367  switch (proto)
368  {
369 #define _(N, j, n, s) \
370  case NAT_PROTOCOL_##N: \
371  while (1) \
372  { \
373  portnum = (port_per_thread * snat_thread_index) + \
374  snat_random_port (0, port_per_thread - 1) + 1024; \
375  if (a->busy_##n##_port_refcounts[portnum]) \
376  continue; \
377  ++a->busy_##n##_port_refcounts[portnum]; \
378  a->busy_##n##_ports_per_thread[thread_index]++; \
379  a->busy_##n##_ports++; \
380  *addr = a->addr; \
381  *port = clib_host_to_net_u16 (portnum); \
382  return 0; \
383  }
384  break;
386 #undef _
387  default : nat_elog_info (sm, "unknown protocol");
388  return 1;
389  }
390  }
391 
392  /* Totally out of translations to use... */
393  nat_ipfix_logging_addresses_exhausted (thread_index, 0);
394  return 1;
395 }
396 
397 static snat_session_t *
399  snat_main_t *sm, vlib_buffer_t *b, ip4_address_t i2o_addr, u16 i2o_port,
400  u32 i2o_fib_index, ip4_address_t o2i_addr, u16 o2i_port, u32 o2i_fib_index,
401  nat_protocol_t nat_proto, vlib_node_runtime_t *node, u32 rx_fib_index,
403  snat_static_mapping_t *mapping)
404 {
405  snat_session_t *s;
406  ip4_header_t *ip;
408 
409  if (PREDICT_FALSE
410  (nat44_ed_maximum_sessions_exceeded (sm, rx_fib_index, thread_index)))
411  {
412  b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_SESSIONS_EXCEEDED];
413  nat_elog_notice (sm, "maximum sessions exceeded");
414  return 0;
415  }
416 
417  s = nat_ed_session_alloc (sm, thread_index, now, nat_proto);
418  if (!s)
419  {
420  b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_SESSIONS_EXCEEDED];
421  nat_elog_warn (sm, "create NAT session failed");
422  return 0;
423  }
424 
425  ip = vlib_buffer_get_current (b);
426 
427  s->ext_host_addr.as_u32 = ip->src_address.as_u32;
428  s->ext_host_port =
429  nat_proto == NAT_PROTOCOL_ICMP ? 0 : vnet_buffer (b)->ip.reass.l4_src_port;
431  if (lb_nat)
433  if (lb_nat == AFFINITY_LB_NAT)
434  s->flags |= SNAT_SESSION_FLAG_AFFINITY;
436  s->out2in.addr = o2i_addr;
437  s->out2in.port = o2i_port;
438  s->out2in.fib_index = o2i_fib_index;
439  s->in2out.addr = i2o_addr;
440  s->in2out.port = i2o_port;
441  s->in2out.fib_index = i2o_fib_index;
442  s->nat_proto = nat_proto;
443 
444  if (NAT_PROTOCOL_ICMP == nat_proto)
445  {
446  nat_6t_o2i_flow_init (sm, thread_index, s, s->ext_host_addr, o2i_port,
447  o2i_addr, o2i_port, o2i_fib_index, ip->protocol);
448  nat_6t_flow_icmp_id_rewrite_set (&s->o2i, i2o_port);
449  }
450  else
451  {
452  nat_6t_o2i_flow_init (sm, thread_index, s, s->ext_host_addr,
453  s->ext_host_port, o2i_addr, o2i_port,
454  o2i_fib_index, ip->protocol);
455  nat_6t_flow_dport_rewrite_set (&s->o2i, i2o_port);
456  }
457  nat_6t_flow_daddr_rewrite_set (&s->o2i, i2o_addr.as_u32);
458  nat_6t_flow_txfib_rewrite_set (&s->o2i, i2o_fib_index);
459 
460  if (nat_ed_ses_o2i_flow_hash_add_del (sm, thread_index, s, 1))
461  {
462  b->error = node->errors[NAT_OUT2IN_ED_ERROR_HASH_ADD_FAILED];
463  nat_ed_session_delete (sm, s, thread_index, 1);
464  nat_elog_warn (sm, "out2in flow hash add failed");
465  return 0;
466  }
467 
468  if (twice_nat == TWICE_NAT || (twice_nat == TWICE_NAT_SELF &&
469  ip->src_address.as_u32 == i2o_addr.as_u32))
470  {
471  int rc = 0;
472  snat_address_t *filter = 0;
473 
474  // if exact address is specified use this address
475  if (is_exact_address (mapping))
476  {
477  snat_address_t *ap;
479  {
480  if (mapping->pool_addr.as_u32 == ap->addr.as_u32)
481  {
482  filter = ap;
483  break;
484  }
485  }
486  }
487 
488  if (filter)
489  {
490  rc = nat_alloc_addr_and_port_exact (filter,
491  thread_index,
492  nat_proto,
493  &s->ext_host_nat_addr,
494  &s->ext_host_nat_port,
495  sm->port_per_thread,
496  tsm->snat_thread_index);
498  }
499  else
500  {
502  sm->twice_nat_addresses, 0, thread_index, nat_proto,
503  &s->ext_host_nat_addr, &s->ext_host_nat_port, sm->port_per_thread,
504  tsm->snat_thread_index);
505  }
506 
507  if (rc)
508  {
509  b->error = node->errors[NAT_OUT2IN_ED_ERROR_OUT_OF_PORTS];
510  if (nat_ed_ses_o2i_flow_hash_add_del (sm, thread_index, s, 0))
511  {
512  nat_elog_warn (sm, "out2in flow hash del failed");
513  }
515  sm->twice_nat_addresses, thread_index, &s->ext_host_nat_addr,
516  s->ext_host_nat_port, s->nat_proto);
517  nat_ed_session_delete (sm, s, thread_index, 1);
518  return 0;
519  }
520 
521  s->flags |= SNAT_SESSION_FLAG_TWICE_NAT;
522 
523  nat_6t_flow_saddr_rewrite_set (&s->o2i, s->ext_host_nat_addr.as_u32);
524  if (NAT_PROTOCOL_ICMP == nat_proto)
525  {
526  nat_6t_flow_icmp_id_rewrite_set (&s->o2i, s->ext_host_nat_port);
527  }
528  else
529  {
530  nat_6t_flow_sport_rewrite_set (&s->o2i, s->ext_host_nat_port);
531  }
532 
533  nat_6t_l3_l4_csum_calc (&s->o2i);
534 
535  nat_6t_i2o_flow_init (sm, thread_index, s, i2o_addr, i2o_port,
536  s->ext_host_nat_addr, s->ext_host_nat_port,
537  i2o_fib_index, ip->protocol);
538  nat_6t_flow_daddr_rewrite_set (&s->i2o, s->ext_host_addr.as_u32);
539  if (NAT_PROTOCOL_ICMP == nat_proto)
540  {
541  nat_6t_flow_icmp_id_rewrite_set (&s->i2o, s->ext_host_port);
542  }
543  else
544  {
545  nat_6t_flow_dport_rewrite_set (&s->i2o, s->ext_host_port);
546  }
547  }
548  else
549  {
550  if (NAT_PROTOCOL_ICMP == nat_proto)
551  {
552  nat_6t_i2o_flow_init (sm, thread_index, s, i2o_addr, i2o_port,
553  s->ext_host_addr, i2o_port, i2o_fib_index,
554  ip->protocol);
555  }
556  else
557  {
558  nat_6t_i2o_flow_init (sm, thread_index, s, i2o_addr, i2o_port,
559  s->ext_host_addr, s->ext_host_port,
560  i2o_fib_index, ip->protocol);
561  }
562  }
563 
564  nat_6t_flow_saddr_rewrite_set (&s->i2o, o2i_addr.as_u32);
565  if (NAT_PROTOCOL_ICMP == nat_proto)
566  {
567  nat_6t_flow_icmp_id_rewrite_set (&s->i2o, o2i_port);
568  }
569  else
570  {
571  nat_6t_flow_sport_rewrite_set (&s->i2o, o2i_port);
572  }
573 
574  if (nat_ed_ses_i2o_flow_hash_add_del (sm, thread_index, s, 1))
575  {
576  nat_elog_notice (sm, "in2out flow hash add failed");
577  if (nat_ed_ses_o2i_flow_hash_add_del (sm, thread_index, s, 0))
578  {
579  nat_elog_warn (sm, "out2in flow hash del failed");
580  }
581  nat_ed_session_delete (sm, s, thread_index, 1);
582  return 0;
583  }
584 
586  s->in2out.addr.as_u32,
587  s->out2in.addr.as_u32,
588  s->nat_proto,
589  s->in2out.port,
590  s->out2in.port, s->in2out.fib_index);
591 
592  nat_syslog_nat44_sadd (0, s->in2out.fib_index, &s->in2out.addr,
593  s->in2out.port, &s->ext_host_nat_addr,
594  s->ext_host_nat_port, &s->out2in.addr, s->out2in.port,
595  &s->ext_host_addr, s->ext_host_port, s->nat_proto,
597 
598  per_vrf_sessions_register_session (s, thread_index);
599 
600  return s;
601 }
602 
603 static void
604 create_bypass_for_fwd (snat_main_t *sm, vlib_buffer_t *b, snat_session_t *s,
605  ip4_header_t *ip, u32 rx_fib_index, u32 thread_index)
606 {
609  vlib_main_t *vm = vlib_get_main ();
610  f64 now = vlib_time_now (vm);
611  u16 lookup_sport, lookup_dport;
612  u8 lookup_protocol;
613  ip4_address_t lookup_saddr, lookup_daddr;
614 
615  if (ip->protocol == IP_PROTOCOL_ICMP)
616  {
617  if (nat_get_icmp_session_lookup_values (b, ip, &lookup_daddr,
618  &lookup_sport, &lookup_saddr,
619  &lookup_dport, &lookup_protocol))
620  return;
621  }
622  else
623  {
624  if (ip->protocol == IP_PROTOCOL_UDP || ip->protocol == IP_PROTOCOL_TCP)
625  {
626  lookup_sport = vnet_buffer (b)->ip.reass.l4_dst_port;
627  lookup_dport = vnet_buffer (b)->ip.reass.l4_src_port;
628  }
629  else
630  {
631  lookup_sport = 0;
632  lookup_dport = 0;
633  }
634  lookup_saddr.as_u32 = ip->dst_address.as_u32;
635  lookup_daddr.as_u32 = ip->src_address.as_u32;
636  lookup_protocol = ip->protocol;
637  }
638 
639  init_ed_k (&kv, lookup_saddr, lookup_sport, lookup_daddr, lookup_dport,
640  rx_fib_index, lookup_protocol);
641 
642  if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv, &value))
643  {
644  ASSERT (thread_index == ed_value_get_thread_index (&value));
645  s =
647  ed_value_get_session_index (&value));
648  }
649  else if (ip->protocol == IP_PROTOCOL_ICMP &&
651  (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags))
652  {
653  return;
654  }
655  else
656  {
657  u32 proto;
658 
659  if (PREDICT_FALSE
661  (sm, rx_fib_index, thread_index)))
662  return;
663 
664  s = nat_ed_session_alloc (sm, thread_index, now, ip->protocol);
665  if (!s)
666  {
667  nat_elog_warn (sm, "create NAT session failed");
668  return;
669  }
670 
671  proto = ip_proto_to_nat_proto (ip->protocol);
672 
673  s->ext_host_addr = ip->src_address;
674  s->ext_host_port = lookup_dport;
675  s->flags |= SNAT_SESSION_FLAG_FWD_BYPASS;
676  s->out2in.addr = ip->dst_address;
677  s->out2in.port = lookup_sport;
678  s->nat_proto = proto;
679  if (proto == NAT_PROTOCOL_OTHER)
680  {
682  s->out2in.port = ip->protocol;
683  }
684  s->out2in.fib_index = rx_fib_index;
685  s->in2out.addr = s->out2in.addr;
686  s->in2out.port = s->out2in.port;
687  s->in2out.fib_index = s->out2in.fib_index;
688 
689  nat_6t_i2o_flow_init (sm, thread_index, s, ip->dst_address, lookup_sport,
690  ip->src_address, lookup_dport, rx_fib_index,
691  ip->protocol);
692  nat_6t_flow_txfib_rewrite_set (&s->i2o, rx_fib_index);
693  if (nat_ed_ses_i2o_flow_hash_add_del (sm, thread_index, s, 1))
694  {
695  nat_elog_notice (sm, "in2out flow add failed");
696  nat_ed_session_delete (sm, s, thread_index, 1);
697  return;
698  }
699 
700  per_vrf_sessions_register_session (s, thread_index);
701  }
702 
703  if (ip->protocol == IP_PROTOCOL_TCP)
704  {
705  tcp_header_t *tcp = ip4_next_header (ip);
706  nat44_set_tcp_session_state_o2i (sm, now, s, tcp->flags,
707  tcp->ack_number, tcp->seq_number,
708  thread_index);
709  }
710 
711  /* Accounting */
712  nat44_session_update_counters (s, now, 0, thread_index);
713  /* Per-user LRU list maintenance */
714  nat44_session_update_lru (sm, s, thread_index);
715 }
716 
717 static snat_session_t *
719  ip4_header_t *ip, u32 rx_fib_index,
721  vlib_main_t *vm,
722  vlib_node_runtime_t *node)
723 {
726  snat_session_t *s;
727 
728  if (PREDICT_FALSE (
729  nat44_ed_maximum_sessions_exceeded (sm, rx_fib_index, thread_index)))
730  {
731  b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_SESSIONS_EXCEEDED];
732  nat_elog_notice (sm, "maximum sessions exceeded");
733  return 0;
734  }
735 
736  init_nat_k (&kv, ip->dst_address, 0, 0, 0);
737  if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
738  {
739  b->error = node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
740  return 0;
741  }
742 
743  m = pool_elt_at_index (sm->static_mappings, value.value);
744 
745  /* Create a new session */
746  s = nat_ed_session_alloc (sm, thread_index, now, ip->protocol);
747  if (!s)
748  {
749  b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_SESSIONS_EXCEEDED];
750  nat_elog_warn (sm, "create NAT session failed");
751  return 0;
752  }
753 
754  s->ext_host_addr.as_u32 = ip->src_address.as_u32;
758  s->out2in.addr.as_u32 = ip->dst_address.as_u32;
759  s->out2in.fib_index = rx_fib_index;
760  s->in2out.addr.as_u32 = m->local_addr.as_u32;
761  s->in2out.fib_index = m->fib_index;
762  s->in2out.port = s->out2in.port = ip->protocol;
763 
764  nat_6t_o2i_flow_init (sm, thread_index, s, ip->dst_address, 0,
765  ip->src_address, 0, m->fib_index, ip->protocol);
767  if (nat_ed_ses_i2o_flow_hash_add_del (sm, thread_index, s, 1))
768  {
769  nat_elog_notice (sm, "in2out key add failed");
770  nat_ed_session_delete (sm, s, thread_index, 1);
771  return NULL;
772  }
773 
774  nat_6t_o2i_flow_init (sm, thread_index, s, ip->src_address, 0,
775  ip->dst_address, 0, rx_fib_index, ip->protocol);
778  if (nat_ed_ses_o2i_flow_hash_add_del (sm, thread_index, s, 1))
779  {
780  nat_elog_notice (sm, "out2in flow hash add failed");
781  nat_ed_session_delete (sm, s, thread_index, 1);
782  return NULL;
783  }
784 
785  per_vrf_sessions_register_session (s, thread_index);
786 
787  /* Accounting */
789  thread_index);
790  /* Per-user LRU list maintenance */
791  nat44_session_update_lru (sm, s, thread_index);
792 
793  return s;
794 }
795 
796 static inline uword
798  vlib_node_runtime_t * node,
800  int is_multi_worker)
801 {
802  u32 n_left_from, *from;
803  snat_main_t *sm = &snat_main;
804  f64 now = vlib_time_now (vm);
807 
808  from = vlib_frame_vector_args (frame);
809  n_left_from = frame->n_vectors;
810 
813  vlib_get_buffers (vm, from, b, n_left_from);
814 
815  while (n_left_from > 0)
816  {
817  vlib_buffer_t *b0;
818  u32 sw_if_index0, rx_fib_index0;
819  nat_protocol_t proto0;
820  ip4_header_t *ip0;
821  snat_session_t *s0 = 0;
822  clib_bihash_kv_16_8_t kv0, value0;
825  nat_6t_flow_t *f = 0;
827  int lookup_skipped = 0;
828 
829  b0 = *b;
830  b++;
831 
832  /* Prefetch next iteration. */
833  if (PREDICT_TRUE (n_left_from >= 2))
834  {
835  vlib_buffer_t *p2;
836 
837  p2 = *b;
838 
839  vlib_prefetch_buffer_header (p2, LOAD);
840 
842  }
843 
844  next[0] = vnet_buffer2 (b0)->nat.arc_next;
845 
846  lookup.sport = vnet_buffer (b0)->ip.reass.l4_src_port;
847  lookup.dport = vnet_buffer (b0)->ip.reass.l4_dst_port;
848 
849  vnet_buffer (b0)->snat.flags = 0;
850  ip0 = vlib_buffer_get_current (b0);
851 
852  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
853  rx_fib_index0 =
855 
856  lookup.fib_index = rx_fib_index0;
857 
858  if (PREDICT_FALSE (ip0->ttl == 1))
859  {
860  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
861  icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
862  ICMP4_time_exceeded_ttl_exceeded_in_transit,
863  0);
864  next[0] = NAT_NEXT_ICMP_ERROR;
865  goto trace0;
866  }
867 
868  proto0 = ip_proto_to_nat_proto (ip0->protocol);
869 
870  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP))
871  {
872  if (vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags !=
873  ICMP4_echo_request &&
874  vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags !=
875  ICMP4_echo_reply &&
877  vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags))
878  {
879  b0->error = node->errors[NAT_OUT2IN_ED_ERROR_BAD_ICMP_TYPE];
880  next[0] = NAT_NEXT_DROP;
881  goto trace0;
882  }
884  b0, ip0, &lookup.saddr, &lookup.sport, &lookup.daddr,
885  &lookup.dport, &lookup.proto);
886  if (err != 0)
887  {
888  b0->error = node->errors[err];
889  next[0] = NAT_NEXT_DROP;
890  goto trace0;
891  }
892  }
893  else
894  {
895  lookup.saddr.as_u32 = ip0->src_address.as_u32;
896  lookup.daddr.as_u32 = ip0->dst_address.as_u32;
897  lookup.proto = ip0->protocol;
898  }
899 
900  /* there might be a stashed index in vnet_buffer2 from handoff or
901  * classify node, see if it can be used */
902  if (is_multi_worker &&
904  vnet_buffer2 (b0)->nat.cached_session_index))
905  {
906  s0 = pool_elt_at_index (tsm->sessions,
907  vnet_buffer2 (b0)->nat.cached_session_index);
908  if (PREDICT_TRUE (nat_6t_t_eq (&s0->o2i.match, &lookup)) ||
909  (s0->flags & SNAT_SESSION_FLAG_TWICE_NAT &&
910  nat_6t_t_eq (&s0->i2o.match, &lookup)))
911  {
912  /* yes, this is the droid we're looking for */
913  lookup_skipped = 1;
914  goto skip_lookup;
915  }
916  s0 = NULL;
917  }
918 
919  init_ed_k (&kv0, lookup.saddr, lookup.sport, lookup.daddr, lookup.dport,
920  lookup.fib_index, lookup.proto);
921 
922  // lookup flow
923  if (clib_bihash_search_16_8 (&sm->flow_hash, &kv0, &value0))
924  {
925  // flow does not exist go slow path
926  slow_path_reason = NAT_ED_SP_REASON_LOOKUP_FAILED;
928  goto trace0;
929  }
930  ASSERT (thread_index == ed_value_get_thread_index (&value0));
931  s0 =
933  ed_value_get_session_index (&value0));
934  skip_lookup:
935 
936  ASSERT (thread_index == s0->thread_index);
937 
938  if (PREDICT_FALSE (per_vrf_sessions_is_expired (s0, thread_index)))
939  {
940  // session is closed, go slow path
941  nat_free_session_data (sm, s0, thread_index, 0);
942  nat_ed_session_delete (sm, s0, thread_index, 1);
943  slow_path_reason = NAT_ED_SP_REASON_VRF_EXPIRED;
945  goto trace0;
946  }
947 
948  if (s0->tcp_closed_timestamp)
949  {
950  if (now >= s0->tcp_closed_timestamp)
951  {
952  // session is closed, go slow path, freed in slow path
953  slow_path_reason = NAT_ED_SP_TCP_CLOSED;
955  }
956  else
957  {
958  // session in transitory timeout, drop
959  b0->error = node->errors[NAT_OUT2IN_ED_ERROR_TCP_CLOSED];
960  next[0] = NAT_NEXT_DROP;
961  }
962  goto trace0;
963  }
964 
965  // drop if session expired
966  u64 sess_timeout_time;
967  sess_timeout_time =
968  s0->last_heard + (f64) nat44_session_get_timeout (sm, s0);
969  if (now >= sess_timeout_time)
970  {
971  // session is closed, go slow path
972  nat_free_session_data (sm, s0, thread_index, 0);
973  nat_ed_session_delete (sm, s0, thread_index, 1);
974  slow_path_reason = NAT_ED_SP_SESS_EXPIRED;
976  goto trace0;
977  }
978 
979  if (nat_6t_t_eq (&s0->o2i.match, &lookup))
980  {
981  f = &s0->o2i;
982  }
983  else if (s0->flags & SNAT_SESSION_FLAG_TWICE_NAT &&
984  nat_6t_t_eq (&s0->i2o.match, &lookup))
985  {
986  f = &s0->i2o;
987  }
988  else
989  {
990  /*
991  * Send DHCP packets to the ipv4 stack, or we won't
992  * be able to use dhcp client on the outside interface
993  */
994  if (PREDICT_FALSE (
995  proto0 == NAT_PROTOCOL_UDP &&
996  (vnet_buffer (b0)->ip.reass.l4_dst_port ==
997  clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_client))))
998  {
999  goto trace0;
1000  }
1001 
1002  if (!sm->forwarding_enabled)
1003  {
1004  b0->error = node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
1005  next[0] = NAT_NEXT_DROP;
1006  goto trace0;
1007  }
1008  else
1009  {
1010  if (nat_6t_t_eq (&s0->i2o.match, &lookup))
1011  {
1012  f = &s0->i2o;
1013  }
1014  else
1015  {
1016  // FIXME TODO bypass ???
1017  // create_bypass_for_fwd (sm, b0, s0, ip0, rx_fib_index0,
1018  // thread_index);
1019  translation_error = NAT_ED_TRNSL_ERR_FLOW_MISMATCH;
1020  nat_free_session_data (sm, s0, thread_index, 0);
1021  nat_ed_session_delete (sm, s0, thread_index, 1);
1022  next[0] = NAT_NEXT_DROP;
1023  goto trace0;
1024  }
1025  }
1026  }
1027 
1029  (translation_error = nat_6t_flow_buf_translate (
1030  sm, b0, ip0, f, proto0, 0 /* is_output_feature */)))
1031  {
1032  next[0] = NAT_NEXT_DROP;
1033  goto trace0;
1034  }
1035 
1036  switch (proto0)
1037  {
1038  case NAT_PROTOCOL_TCP:
1040  thread_index, sw_if_index0, 1);
1041  nat44_set_tcp_session_state_o2i (sm, now, s0,
1042  vnet_buffer (b0)->ip.
1043  reass.icmp_type_or_tcp_flags,
1044  vnet_buffer (b0)->ip.
1045  reass.tcp_ack_number,
1046  vnet_buffer (b0)->ip.
1047  reass.tcp_seq_number,
1048  thread_index);
1049  break;
1050  case NAT_PROTOCOL_UDP:
1052  thread_index, sw_if_index0, 1);
1053  break;
1054  case NAT_PROTOCOL_ICMP:
1056  thread_index, sw_if_index0, 1);
1057  break;
1058  case NAT_PROTOCOL_OTHER:
1059  vlib_increment_simple_counter (&sm->counters.fastpath.out2in.other,
1060  thread_index, sw_if_index0, 1);
1061  break;
1062  }
1063 
1064  /* Accounting */
1066  vlib_buffer_length_in_chain (vm, b0),
1067  thread_index);
1068  /* Per-user LRU list maintenance */
1069  nat44_session_update_lru (sm, s0, thread_index);
1070 
1071  trace0:
1073  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1074  {
1076  vlib_add_trace (vm, node, b0, sizeof (*t));
1077  t->sw_if_index = sw_if_index0;
1078  t->next_index = next[0];
1079  t->is_slow_path = 0;
1080  t->translation_error = translation_error;
1081  clib_memcpy (&t->search_key, &kv0, sizeof (t->search_key));
1082  t->lookup_skipped = lookup_skipped;
1083  t->slow_path_reason = slow_path_reason;
1084 
1085  if (s0)
1086  {
1087  t->session_index = s0 - tsm->sessions;
1088  clib_memcpy (&t->i2of, &s0->i2o, sizeof (t->i2of));
1089  clib_memcpy (&t->o2if, &s0->o2i, sizeof (t->o2if));
1090  t->translation_via_i2of = (&s0->i2o == f);
1091  }
1092  else
1093  {
1094  t->session_index = ~0;
1095  }
1096  }
1097 
1098  if (next[0] == NAT_NEXT_DROP)
1099  {
1100  vlib_increment_simple_counter (&sm->counters.fastpath.out2in.drops,
1101  thread_index, sw_if_index0, 1);
1102  }
1103 
1104  n_left_from--;
1105  next++;
1106  }
1107 
1108  vlib_buffer_enqueue_to_next (vm, node, from, (u16 *) nexts,
1109  frame->n_vectors);
1110  return frame->n_vectors;
1111 }
1112 
1113 static inline uword
1115  vlib_node_runtime_t * node,
1116  vlib_frame_t * frame)
1117 {
1118  u32 n_left_from, *from;
1119  snat_main_t *sm = &snat_main;
1120  f64 now = vlib_time_now (vm);
1124 
1125  from = vlib_frame_vector_args (frame);
1126  n_left_from = frame->n_vectors;
1127 
1130  vlib_get_buffers (vm, from, b, n_left_from);
1131 
1132  while (n_left_from > 0)
1133  {
1134  vlib_buffer_t *b0;
1135  u32 sw_if_index0, rx_fib_index0;
1136  nat_protocol_t proto0;
1137  ip4_header_t *ip0;
1138  udp_header_t *udp0;
1139  icmp46_header_t *icmp0;
1140  snat_session_t *s0 = 0;
1141  clib_bihash_kv_16_8_t kv0, value0;
1142  lb_nat_type_t lb_nat0;
1143  twice_nat_type_t twice_nat0;
1144  u8 identity_nat0;
1145  ip4_address_t sm_addr;
1146  u16 sm_port;
1147  u32 sm_fib_index;
1149 
1150  b0 = *b;
1151  next[0] = vnet_buffer2 (b0)->nat.arc_next;
1152 
1153  vnet_buffer (b0)->snat.flags = 0;
1154  ip0 = vlib_buffer_get_current (b0);
1155 
1156  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1157  rx_fib_index0 =
1159 
1160  if (PREDICT_FALSE (ip0->ttl == 1))
1161  {
1162  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1163  icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
1164  ICMP4_time_exceeded_ttl_exceeded_in_transit,
1165  0);
1166  next[0] = NAT_NEXT_ICMP_ERROR;
1167  goto trace0;
1168  }
1169 
1170  udp0 = ip4_next_header (ip0);
1171  icmp0 = (icmp46_header_t *) udp0;
1172  proto0 = ip_proto_to_nat_proto (ip0->protocol);
1173 
1174  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_OTHER))
1175  {
1177  sm, b0, ip0, rx_fib_index0, thread_index, now, vm, node);
1178  if (!sm->forwarding_enabled)
1179  {
1180  if (!s0)
1181  next[0] = NAT_NEXT_DROP;
1182  }
1183  if (NAT_NEXT_DROP != next[0] &&
1185  (translation_error = nat_6t_flow_buf_translate (
1186  sm, b0, ip0, &s0->o2i, proto0, 0 /* is_output_feature */)))
1187  {
1188  goto trace0;
1189  }
1190 
1191  vlib_increment_simple_counter (&sm->counters.slowpath.out2in.other,
1192  thread_index, sw_if_index0, 1);
1193  goto trace0;
1194  }
1195 
1196  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP))
1197  {
1198  next[0] = icmp_out2in_ed_slow_path
1199  (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
1200  next[0], now, thread_index, &s0);
1201 
1202  if (NAT_NEXT_DROP != next[0] && s0 &&
1204  (translation_error = nat_6t_flow_buf_translate (
1205  sm, b0, ip0, &s0->o2i, proto0, 0 /* is_output_feature */)))
1206  {
1207  goto trace0;
1208  }
1209 
1211  thread_index, sw_if_index0, 1);
1212  goto trace0;
1213  }
1214 
1215  init_ed_k (&kv0, ip0->src_address,
1216  vnet_buffer (b0)->ip.reass.l4_src_port, ip0->dst_address,
1217  vnet_buffer (b0)->ip.reass.l4_dst_port, rx_fib_index0,
1218  ip0->protocol);
1219 
1220  s0 = NULL;
1221  if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv0, &value0))
1222  {
1223  ASSERT (thread_index == ed_value_get_thread_index (&value0));
1224  s0 =
1226  ed_value_get_session_index (&value0));
1227 
1228  if (s0->tcp_closed_timestamp && now >= s0->tcp_closed_timestamp)
1229  {
1230  nat_free_session_data (sm, s0, thread_index, 0);
1231  nat_ed_session_delete (sm, s0, thread_index, 1);
1232  s0 = NULL;
1233  }
1234  }
1235 
1236  if (!s0)
1237  {
1238  /* Try to match static mapping by external address and port,
1239  destination address and port in packet */
1240 
1242  vm, sm, ip0->dst_address,
1243  vnet_buffer (b0)->ip.reass.l4_dst_port, rx_fib_index0, proto0,
1244  &sm_addr, &sm_port, &sm_fib_index, 1, 0, &twice_nat0, &lb_nat0,
1245  &ip0->src_address, &identity_nat0, &m))
1246  {
1247  /*
1248  * Send DHCP packets to the ipv4 stack, or we won't
1249  * be able to use dhcp client on the outside interface
1250  */
1251  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_UDP
1252  && (vnet_buffer (b0)->ip.reass.l4_dst_port ==
1253  clib_host_to_net_u16
1254  (UDP_DST_PORT_dhcp_to_client))))
1255  {
1256  goto trace0;
1257  }
1258 
1259  if (!sm->forwarding_enabled)
1260  {
1261  b0->error =
1262  node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
1263  next[0] = NAT_NEXT_DROP;
1264  }
1265  else
1266  {
1267  if (next_src_nat
1268  (sm, ip0, vnet_buffer (b0)->ip.reass.l4_src_port,
1269  vnet_buffer (b0)->ip.reass.l4_dst_port,
1270  thread_index, rx_fib_index0))
1271  {
1272  next[0] = NAT_NEXT_IN2OUT_ED_FAST_PATH;
1273  }
1274  else
1275  {
1276  create_bypass_for_fwd (sm, b0, s0, ip0, rx_fib_index0,
1277  thread_index);
1278  }
1279  }
1280  goto trace0;
1281  }
1282 
1283  if (PREDICT_FALSE (identity_nat0))
1284  goto trace0;
1285 
1286  if ((proto0 == NAT_PROTOCOL_TCP)
1287  && !tcp_flags_is_init (vnet_buffer (b0)->ip.
1288  reass.icmp_type_or_tcp_flags))
1289  {
1290  b0->error = node->errors[NAT_OUT2IN_ED_ERROR_NON_SYN];
1291  next[0] = NAT_NEXT_DROP;
1292  goto trace0;
1293  }
1294 
1295  /* Create session initiated by host from external network */
1297  sm_addr, sm_port,
1298  sm_fib_index,
1299  ip0->dst_address,
1300  vnet_buffer (b0)->
1301  ip.reass.l4_dst_port,
1302  rx_fib_index0, proto0,
1303  node, rx_fib_index0,
1304  thread_index, twice_nat0,
1305  lb_nat0, now, m);
1306  if (!s0)
1307  {
1308  next[0] = NAT_NEXT_DROP;
1309  goto trace0;
1310  }
1311  }
1312 
1314  (translation_error = nat_6t_flow_buf_translate (
1315  sm, b0, ip0, &s0->o2i, proto0, 0 /* is_output_feature */)))
1316  {
1317  next[0] = NAT_NEXT_DROP;
1318  goto trace0;
1319  }
1320 
1321  if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP))
1322  {
1324  thread_index, sw_if_index0, 1);
1325  nat44_set_tcp_session_state_o2i (sm, now, s0,
1326  vnet_buffer (b0)->ip.
1327  reass.icmp_type_or_tcp_flags,
1328  vnet_buffer (b0)->ip.
1329  reass.tcp_ack_number,
1330  vnet_buffer (b0)->ip.
1331  reass.tcp_seq_number,
1332  thread_index);
1333  }
1334  else
1335  {
1337  thread_index, sw_if_index0, 1);
1338  }
1339 
1340  /* Accounting */
1342  vlib_buffer_length_in_chain (vm, b0),
1343  thread_index);
1344  /* Per-user LRU list maintenance */
1345  nat44_session_update_lru (sm, s0, thread_index);
1346 
1347  trace0:
1349  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1350  {
1352  vlib_add_trace (vm, node, b0, sizeof (*t));
1353  t->sw_if_index = sw_if_index0;
1354  t->next_index = next[0];
1355  t->is_slow_path = 1;
1356  t->translation_error = translation_error;
1357  clib_memcpy (&t->search_key, &kv0, sizeof (t->search_key));
1358 
1359  if (s0)
1360  {
1361  t->session_index = s0 - tsm->sessions;
1362  clib_memcpy (&t->i2of, &s0->i2o, sizeof (t->i2of));
1363  clib_memcpy (&t->o2if, &s0->o2i, sizeof (t->o2if));
1364  }
1365  else
1366  {
1367  t->session_index = ~0;
1368  }
1369  }
1370 
1371  if (next[0] == NAT_NEXT_DROP)
1372  {
1373  vlib_increment_simple_counter (&sm->counters.slowpath.out2in.drops,
1374  thread_index, sw_if_index0, 1);
1375  }
1376 
1377  n_left_from--;
1378  next++;
1379  b++;
1380  }
1381 
1382  vlib_buffer_enqueue_to_next (vm, node, from, (u16 *) nexts,
1383  frame->n_vectors);
1384 
1385  return frame->n_vectors;
1386 }
1387 
1390  vlib_frame_t * frame)
1391 {
1392  if (snat_main.num_workers > 1)
1393  {
1394  return nat44_ed_out2in_fast_path_node_fn_inline (vm, node, frame, 1);
1395  }
1396  else
1397  {
1398  return nat44_ed_out2in_fast_path_node_fn_inline (vm, node, frame, 0);
1399  }
1400 }
1401 
1402 /* *INDENT-OFF* */
1404  .name = "nat44-ed-out2in",
1405  .vector_size = sizeof (u32),
1406  .sibling_of = "nat-default",
1407  .format_trace = format_nat44_ed_out2in_trace,
1410  .error_strings = nat_out2in_ed_error_strings,
1411  .runtime_data_bytes = sizeof (snat_runtime_t),
1412 };
1413 /* *INDENT-ON* */
1414 
1417  vlib_frame_t * frame)
1418 {
1420 }
1421 
1422 /* *INDENT-OFF* */
1424  .name = "nat44-ed-out2in-slowpath",
1425  .vector_size = sizeof (u32),
1426  .sibling_of = "nat-default",
1427  .format_trace = format_nat44_ed_out2in_trace,
1430  .error_strings = nat_out2in_ed_error_strings,
1431  .runtime_data_bytes = sizeof (snat_runtime_t),
1432 };
1433 /* *INDENT-ON* */
1434 
1435 static u8 *
1436 format_nat_pre_trace (u8 * s, va_list * args)
1437 {
1438  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1439  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1440  nat_pre_trace_t *t = va_arg (*args, nat_pre_trace_t *);
1441  return format (s, "out2in next_index %d arc_next_index %d", t->next_index,
1442  t->arc_next_index);
1443 }
1444 
1447  vlib_frame_t * frame)
1448 {
1449  return nat_pre_node_fn_inline (vm, node, frame,
1451 }
1452 
1453 /* *INDENT-OFF* */
1455  .name = "nat-pre-out2in",
1456  .vector_size = sizeof (u32),
1457  .sibling_of = "nat-default",
1458  .format_trace = format_nat_pre_trace,
1460  .n_errors = 0,
1461  };
1462 /* *INDENT-ON* */
1463 
1464 /*
1465  * fd.io coding-style-patch-verification: ON
1466  *
1467  * Local Variables:
1468  * eval: (c-set-style "gnu")
1469  * End:
1470  */
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:133
#define SNAT_SESSION_FLAG_STATIC_MAPPING
Definition: nat44_ed.h:172
static ip_csum_t ip_incremental_checksum_buffer(vlib_main_t *vm, vlib_buffer_t *first_buffer, u32 first_buffer_offset, u32 n_bytes_to_checksum, ip_csum_t sum)
Definition: ip.h:152
static_always_inline void nat_6t_o2i_flow_init(snat_main_t *sm, u32 thread_idx, snat_session_t *s, ip4_address_t saddr, u16 sport, ip4_address_t daddr, u16 dport, u32 fib_index, u8 proto)
static u32 nat44_session_get_timeout(snat_main_t *sm, snat_session_t *s)
static void nat44_session_update_lru(snat_main_t *sm, snat_session_t *s, u32 thread_index)
Per-user LRU list maintenance.
#define CLIB_UNUSED(x)
Definition: clib.h:90
#define nat_elog_info(_pm, nat_elog_str)
Definition: log.h:183
nat_translation_error_e
Definition: nat44_ed.h:1147
vlib_node_registration_t nat44_ed_out2in_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_out2in_node)
u32 arc_next_index
Definition: nat44_ed.h:91
a
Definition: bitmap.h:544
static_always_inline int nat_6t_t_eq(nat_6t_t *t1, nat_6t_t *t2)
static u8 * format_nat_pre_trace(u8 *s, va_list *args)
#define ntohs(x)
Definition: af_xdp.bpf.c:29
ip4_address_t src_address
Definition: ip4_packet.h:125
static uword nat44_ed_out2in_slow_path_node_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
void nat_ipfix_logging_addresses_exhausted(u32 thread_index, u32 pool_id)
Generate NAT addresses exhausted event.
#define vnet_buffer2(b)
Definition: buffer.h:499
u32 thread_index
static_always_inline void nat_6t_i2o_flow_init(snat_main_t *sm, u32 thread_idx, snat_session_t *s, ip4_address_t saddr, u16 sport, ip4_address_t daddr, u16 dport, u32 fib_index, u8 proto)
#define PREDICT_TRUE(x)
Definition: clib.h:125
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
u16 nexts[VLIB_FRAME_SIZE]
static u8 * format_slow_path_reason(u8 *s, va_list *args)
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:325
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
lb_nat_type_t
Definition: nat44_ed.h:398
u16 port_per_thread
Definition: nat44_ed.h:516
#define is_twice_nat_session(s)
Check if NAT session is twice NAT.
Definition: nat44_ed.h:736
static u8 is_interface_addr(snat_main_t *sm, vlib_node_runtime_t *node, u32 sw_if_index0, u32 ip4_addr)
u32 thread_index
Definition: main.h:213
#define SNAT_SESSION_FLAG_TWICE_NAT
Definition: nat44_ed.h:175
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
static snat_session_t * create_session_for_static_mapping_ed(snat_main_t *sm, vlib_buffer_t *b, ip4_address_t i2o_addr, u16 i2o_port, u32 i2o_fib_index, ip4_address_t o2i_addr, u16 o2i_port, u32 o2i_fib_index, nat_protocol_t nat_proto, vlib_node_runtime_t *node, u32 rx_fib_index, u32 thread_index, twice_nat_type_t twice_nat, lb_nat_type_t lb_nat, f64 now, snat_static_mapping_t *mapping)
twice_nat_type_t
Definition: nat44_ed.h:388
static uword nat44_ed_out2in_fast_path_node_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_multi_worker)
#define foreach_nat_out2in_ed_error
Definition: nat44_ed.h:143
uword ip_csum_t
Definition: ip_packet.h:245
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:74
nat_protocol_t
Definition: lib.h:63
#define VLIB_NODE_FN(node)
Definition: node.h:202
static void nat44_session_update_counters(snat_session_t *s, f64 now, uword bytes, u32 thread_index)
static void nat_6t_flow_saddr_rewrite_set(nat_6t_flow_t *f, u32 saddr)
Definition: nat44_ed.h:247
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:461
vlib_node_registration_t nat44_ed_out2in_slowpath_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_out2in_slowpath_node)
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:433
struct _tcp_header tcp_header_t
vhost_vring_addr_t addr
Definition: vhost_user.h:130
unsigned char u8
Definition: types.h:56
vlib_buffer_t ** b
static_always_inline u8 icmp_type_is_error_message(u8 icmp_type)
Definition: cnat_node.h:109
double f64
Definition: types.h:142
static int ip4_is_fragment(const ip4_header_t *i)
Definition: ip4_packet.h:168
unsigned int u32
Definition: types.h:88
#define clib_memcpy(d, s, n)
Definition: string.h:197
static void nat_6t_flow_daddr_rewrite_set(nat_6t_flow_t *f, u32 daddr)
Definition: nat44_ed.h:254
static_always_inline void per_vrf_sessions_register_session(snat_session_t *s, u32 thread_index)
vlib_frame_t * f
static snat_session_t * nat44_ed_out2in_slowpath_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)
#define static_always_inline
Definition: clib.h:112
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: nat44_ed.c:2280
static nat_protocol_t ip_proto_to_nat_proto(u8 ip_proto)
Common NAT inline functions.
Definition: inlines.h:24
vlib_get_buffers(vm, from, b, n_left_from)
ip4_address_t dst_address
Definition: ip4_packet.h:125
description fragment has unexpected format
Definition: map.api:433
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:231
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
#define nat_elog_warn(_pm, nat_elog_str)
Definition: log.h:177
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:196
static void nat_6t_flow_icmp_id_rewrite_set(nat_6t_flow_t *f, u16 id)
Definition: nat44_ed.h:282
#define SNAT_SESSION_FLAG_UNKNOWN_PROTO
Definition: nat44_ed.h:173
vlib_buffer_enqueue_to_next(vm, node, from,(u16 *) nexts, frame->n_vectors)
static_always_inline int nat_alloc_addr_and_port_exact(snat_address_t *a, u32 thread_index, nat_protocol_t proto, ip4_address_t *addr, u16 *port, u16 port_per_thread, u32 snat_thread_index)
ip4_address_t local_addr
Definition: nat44_ed.h:413
#define VLIB_FRAME_SIZE
Definition: node.h:369
u32 fib_index
Definition: nat44_ed.h:212
u8 proto
Definition: nat44_ed.h:213
struct snat_main_s::@736::@737 fastpath
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:145
nat_translation_error_e translation_error
static void create_bypass_for_fwd(snat_main_t *sm, vlib_buffer_t *b, snat_session_t *s, ip4_header_t *ip, u32 rx_fib_index, u32 thread_index)
u16 * next
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:553
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
snat_main_t snat_main
Definition: nat44_ed.c:41
vl_api_ip_proto_t proto
Definition: acl_types.api:51
icmp
Definition: map.api:387
unsigned short u16
Definition: types.h:57
snat_static_mapping_t * static_mappings
Definition: nat44_ed.h:528
#define SNAT_SESSION_FLAG_EXACT_ADDRESS
Definition: nat44_ed.h:179
format_function_t format_nat_ed_translation_error
Definition: nat44_ed.h:1161
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:257
format_function_t format_ed_session_kvp
Definition: nat44_ed.h:1163
static void nat_6t_flow_sport_rewrite_set(nat_6t_flow_t *f, u32 sport)
Definition: nat44_ed.h:261
#define PREDICT_FALSE(x)
Definition: clib.h:124
clib_bihash_8_8_t static_mapping_by_external
Definition: nat44_ed.h:525
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
static_always_inline int nat_get_icmp_session_lookup_values(vlib_buffer_t *b, ip4_header_t *ip0, ip4_address_t *lookup_saddr, u16 *lookup_sport, ip4_address_t *lookup_daddr, u16 *lookup_dport, u8 *lookup_protocol)
static void nat44_set_tcp_session_state_o2i(snat_main_t *sm, f64 now, snat_session_t *ses, u8 tcp_flags, u32 tcp_ack_number, u32 tcp_seq_number, u32 thread_index)
static u8 * format_nat44_ed_out2in_trace(u8 *s, va_list *args)
vl_api_ip_port_and_mask_t src_port
Definition: flow_types.api:91
u64 value
the value
Definition: bihash_8_8.h:44
static hash_pair_t * lookup(void *v, uword key, enum lookup_opcode op, void *new_value, void *old_value)
Definition: hash.c:545
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u16 n_vectors
Definition: node.h:388
format_function_t format_nat_6t_flow
Definition: nat44_ed.h:1162
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
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)
u8 data[]
Packet data.
Definition: buffer.h:204
struct snat_main_s::@736 counters
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.
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:302
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:41
#define ARRAY_LEN(x)
Definition: clib.h:70
static char * nat_out2in_ed_error_strings[]
#define SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT
Definition: nat44_ed.h:176
static void nat_6t_flow_txfib_rewrite_set(nat_6t_flow_t *f, u32 tx_fib_index)
Definition: nat44_ed.h:275
#define is_exact_address(s)
Check if exact pool address should be used.
Definition: nat44_ed.h:814
static_always_inline snat_session_t * nat_ed_session_alloc(snat_main_t *sm, u32 thread_index, f64 now, u8 proto)
u8 value
Definition: qos.api:54
#define ASSERT(truth)
struct snat_main_s::@736::@738 slowpath
u32 num_workers
Definition: nat44_ed.h:513
#define SNAT_SESSION_FLAG_FWD_BYPASS
Definition: nat44_ed.h:177
clib_bihash_kv_16_8_t search_key
nat_translation_error_e nat_6t_flow_buf_translate(snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, nat_6t_flow_t *f, nat_protocol_t proto, int is_output_feature)
Definition: nat44_ed.c:3424
ip4_address_t addr
Definition: nat44_ed.h:352
snat_address_t * twice_nat_addresses
Definition: nat44_ed.h:562
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:38
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: nat44_ed.c:231
static int next_src_nat(snat_main_t *sm, ip4_header_t *ip, u16 src_port, u16 dst_port, u32 thread_index, u32 rx_fib_index)
static u32 ed_value_get_session_index(clib_bihash_kv_16_8_t *value)
static u32 ed_value_get_thread_index(clib_bihash_kv_16_8_t *value)
static_always_inline u8 per_vrf_sessions_is_expired(snat_session_t *s, u32 thread_index)
static_always_inline int nat_ed_ses_o2i_flow_hash_add_del(snat_main_t *sm, u32 thread_idx, snat_session_t *s, int is_add)
static void nat_ed_session_delete(snat_main_t *sm, snat_session_t *ses, u32 thread_index, int lru_delete)
Definition: defs.h:47
u16 dport
Definition: nat44_ed.h:211
vl_api_address_t ip
Definition: l2.api:558
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
nat_slow_path_reason_e
VLIB buffer representation.
Definition: buffer.h:111
u64 uword
Definition: types.h:112
u16 sport
Definition: nat44_ed.h:210
snat_main_per_thread_data_t * per_thread_data
Definition: nat44_ed.h:519
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:301
#define SNAT_SESSION_FLAG_AFFINITY
Definition: nat44_ed.h:178
NAT syslog logging.
ip4_address_t pool_addr
Definition: nat44_ed.h:411
#define SNAT_SESSION_FLAG_LOAD_BALANCING
Definition: nat44_ed.h:174
u16 port
Definition: lb_types.api:73
static u32 icmp_out2in_ed_slow_path(snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, icmp46_header_t *icmp, u32 sw_if_index, u32 rx_fib_index, vlib_node_runtime_t *node, u32 next, f64 now, u32 thread_index, snat_session_t **s_p)
nat_slow_path_reason_e slow_path_reason
static void nat_6t_flow_dport_rewrite_set(nat_6t_flow_t *f, u32 dport)
Definition: nat44_ed.h:268
int snat_static_mapping_match(vlib_main_t *vm, 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: nat44_ed.c:2354
#define vnet_buffer(b)
Definition: buffer.h:437
void nat_6t_l3_l4_csum_calc(nat_6t_flow_t *f)
Definition: nat44_ed.c:3205
f64 now
static_always_inline u8 nat44_ed_maximum_sessions_exceeded(snat_main_t *sm, u32 fib_index, u32 thread_index)
u8 forwarding_enabled
Definition: nat44_ed.h:587
#define vec_foreach(var, vec)
Vector iterator.
#define nat_elog_notice(_pm, nat_elog_str)
Definition: log.h:175
u16 flags
Copy of main node flags.
Definition: node.h:492
static_always_inline int nat_ed_ses_i2o_flow_hash_add_del(snat_main_t *sm, u32 thread_idx, snat_session_t *s, int is_add)
clib_bihash_16_8_t flow_hash
Definition: nat44_ed.h:535
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:628
static int ip4_header_bytes(const ip4_header_t *i)
Definition: ip4_packet.h:190
vlib_node_registration_t nat_pre_out2in_node
(constructor) VLIB_REGISTER_NODE (nat_pre_out2in_node)
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:292
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
static uword nat_pre_node_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, u32 def_next)
vlib_buffer_t * bufs[VLIB_FRAME_SIZE]
snat_session_t * sessions
Definition: nat44_ed.h:468
static bool tcp_flags_is_init(u8 f)
Check if client initiating TCP connection (received SYN from client)
Definition: nat44_ed.h:821
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)
static_always_inline void icmp4_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
Definition: icmp4.h:51
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:301
static_always_inline int nat44_ed_alloc_outside_addr_and_port(snat_address_t *addresses, u32 fib_index, u32 thread_index, nat_protocol_t proto, ip4_address_t *addr, u16 *port, u16 port_per_thread, u32 snat_thread_index)
Definition: defs.h:46
ip4_address_t daddr
Definition: nat44_ed.h:209
ip4_address_t saddr
Definition: nat44_ed.h:209