FD.io VPP  v19.01.2-3-gf61a1a8
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 <vppinfra/error.h>
27 #include <nat/nat.h>
28 #include <nat/nat_ipfix_logging.h>
29 #include <nat/nat_reass.h>
30 #include <nat/nat_inlines.h>
31 #include <nat/nat_syslog.h>
32 
33 #define foreach_nat_in2out_ed_error \
34 _(UNSUPPORTED_PROTOCOL, "unsupported protocol") \
35 _(IN2OUT_PACKETS, "good in2out packets processed") \
36 _(OUT_OF_PORTS, "out of ports") \
37 _(BAD_ICMP_TYPE, "unsupported ICMP type") \
38 _(MAX_SESSIONS_EXCEEDED, "maximum sessions exceeded") \
39 _(DROP_FRAGMENT, "drop fragment") \
40 _(MAX_REASS, "maximum reassemblies exceeded") \
41 _(MAX_FRAG, "maximum fragments per reassembly exceeded")\
42 _(NON_SYN, "non-SYN packet try to create session") \
43 _(TCP_PACKETS, "TCP packets") \
44 _(UDP_PACKETS, "UDP packets") \
45 _(ICMP_PACKETS, "ICMP packets") \
46 _(OTHER_PACKETS, "other protocol packets") \
47 _(FRAGMENTS, "fragments") \
48 _(CACHED_FRAGMENTS, "cached fragments") \
49 _(PROCESSED_FRAGMENTS, "processed fragments")
50 
51 
52 typedef enum
53 {
54 #define _(sym,str) NAT_IN2OUT_ED_ERROR_##sym,
56 #undef _
59 
60 static char *nat_in2out_ed_error_strings[] = {
61 #define _(sym,string) string,
63 #undef _
64 };
65 
66 typedef enum
67 {
75 
76 typedef struct
77 {
83 
89 
90 static u8 *
91 format_nat_in2out_ed_trace (u8 * s, va_list * args)
92 {
93  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
94  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
95  nat_in2out_ed_trace_t *t = va_arg (*args, nat_in2out_ed_trace_t *);
96  char *tag;
97 
98  tag =
99  t->is_slow_path ? "NAT44_IN2OUT_ED_SLOW_PATH" :
100  "NAT44_IN2OUT_ED_FAST_PATH";
101 
102  s = format (s, "%s: sw_if_index %d, next index %d, session %d", tag,
104 
105  return s;
106 }
107 
110 {
111  icmp46_header_t *icmp0;
112  nat_ed_ses_key_t key0;
113  icmp_echo_header_t *echo0, *inner_echo0 = 0;
114  ip4_header_t *inner_ip0 = 0;
115  void *l4_header = 0;
116  icmp46_header_t *inner_icmp0;
117 
118  icmp0 = (icmp46_header_t *) ip4_next_header (ip0);
119  echo0 = (icmp_echo_header_t *) (icmp0 + 1);
120 
121  if (!icmp_is_error_message (icmp0))
122  {
123  key0.proto = IP_PROTOCOL_ICMP;
124  key0.l_addr = ip0->src_address;
125  key0.r_addr = ip0->dst_address;
126  key0.l_port = echo0->identifier;
127  key0.r_port = 0;
128  }
129  else
130  {
131  inner_ip0 = (ip4_header_t *) (echo0 + 1);
132  l4_header = ip4_next_header (inner_ip0);
133  key0.proto = inner_ip0->protocol;
134  key0.r_addr = inner_ip0->src_address;
135  key0.l_addr = inner_ip0->dst_address;
136  switch (ip_proto_to_snat_proto (inner_ip0->protocol))
137  {
138  case SNAT_PROTOCOL_ICMP:
139  inner_icmp0 = (icmp46_header_t *) l4_header;
140  inner_echo0 = (icmp_echo_header_t *) (inner_icmp0 + 1);
141  key0.r_port = 0;
142  key0.l_port = inner_echo0->identifier;
143  break;
144  case SNAT_PROTOCOL_UDP:
145  case SNAT_PROTOCOL_TCP:
146  key0.l_port = ((tcp_udp_header_t *) l4_header)->dst_port;
147  key0.r_port = ((tcp_udp_header_t *) l4_header)->src_port;
148  break;
149  default:
150  return NAT_IN2OUT_ED_ERROR_UNSUPPORTED_PROTOCOL;
151  }
152  }
153  *p_key0 = key0;
154  return 0;
155 }
156 
157 int
159 {
160  snat_main_t *sm = &snat_main;
162  snat_session_t *s;
163  u64 sess_timeout_time;
164  nat_ed_ses_key_t ed_key;
165  clib_bihash_kv_16_8_t ed_kv;
166  int i;
167  snat_address_t *a;
168  snat_session_key_t key;
170  ctx->thread_index);
171 
172  s = pool_elt_at_index (tsm->sessions, kv->value);
173  sess_timeout_time = s->last_heard + (f64) nat44_session_get_timeout (sm, s);
174  if (ctx->now >= sess_timeout_time)
175  {
176  if (is_fwd_bypass_session (s))
177  goto delete;
178 
179  ed_key.l_addr = s->out2in.addr;
180  ed_key.r_addr = s->ext_host_addr;
181  ed_key.fib_index = s->out2in.fib_index;
183  {
184  ed_key.proto = s->in2out.port;
185  ed_key.r_port = 0;
186  ed_key.l_port = 0;
187  }
188  else
189  {
190  ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol);
191  ed_key.l_port = s->out2in.port;
192  ed_key.r_port = s->ext_host_port;
193  }
194  ed_kv.key[0] = ed_key.as_u64[0];
195  ed_kv.key[1] = ed_key.as_u64[1];
196  if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &ed_kv, 0))
197  nat_log_warn ("out2in_ed key del failed");
198 
200  goto delete;
201 
202  snat_ipfix_logging_nat44_ses_delete (s->in2out.addr.as_u32,
203  s->out2in.addr.as_u32,
204  s->in2out.protocol,
205  s->in2out.port,
206  s->out2in.port,
207  s->in2out.fib_index);
208 
209  nat_syslog_nat44_sdel (s->user_index, s->in2out.fib_index,
210  &s->in2out.addr, s->in2out.port,
211  &s->ext_host_nat_addr, s->ext_host_nat_port,
212  &s->out2in.addr, s->out2in.port,
213  &s->ext_host_addr, s->ext_host_port,
214  s->in2out.protocol, is_twice_nat_session (s));
215 
216  if (is_twice_nat_session (s))
217  {
218  for (i = 0; i < vec_len (sm->twice_nat_addresses); i++)
219  {
220  key.protocol = s->in2out.protocol;
221  key.port = s->ext_host_nat_port;
222  a = sm->twice_nat_addresses + i;
223  if (a->addr.as_u32 == s->ext_host_nat_addr.as_u32)
224  {
226  ctx->thread_index,
227  &key);
228  break;
229  }
230  }
231  }
232 
233  if (snat_is_session_static (s))
234  goto delete;
235 
237  &s->out2in);
238  delete:
239  nat44_delete_session (sm, s, ctx->thread_index);
240  return 1;
241  }
242 
243  return 0;
244 }
245 
246 static inline u32
248  ip4_header_t * ip0, icmp46_header_t * icmp0,
249  u32 sw_if_index0, u32 rx_fib_index0,
250  vlib_node_runtime_t * node, u32 next0, f64 now,
251  u32 thread_index, snat_session_t ** p_s0)
252 {
253  next0 = icmp_in2out (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
254  next0, thread_index, p_s0, 0);
255  snat_session_t *s0 = *p_s0;
256  if (PREDICT_TRUE (next0 != NAT_IN2OUT_ED_NEXT_DROP && s0))
257  {
258  /* Accounting */
261  (sm->vlib_main, b0));
262  /* Per-user LRU list maintenance */
263  nat44_session_update_lru (sm, s0, thread_index);
264  }
265  return next0;
266 }
267 
268 static u32
270  vlib_buffer_t * b,
271  u32 rx_fib_index,
273  snat_session_t ** sessionp,
274  vlib_node_runtime_t * node, u32 next, u32 thread_index, f64 now,
275  tcp_header_t * tcp)
276 {
277  snat_session_t *s = 0;
278  snat_user_t *u;
279  snat_session_key_t key0, key1;
280  lb_nat_type_t lb = 0, is_sm = 0;
281  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
282  nat_ed_ses_key_t *key = (nat_ed_ses_key_t *) kv->key;
283  u32 proto = ip_proto_to_snat_proto (key->proto);
284  nat_outside_fib_t *outside_fib;
286  u8 identity_nat;
287  fib_prefix_t pfx = {
289  .fp_len = 32,
290  .fp_addr = {
291  .ip4.as_u32 = key->r_addr.as_u32,
292  },
293  };
295 
296  if (PREDICT_FALSE (maximum_sessions_exceeded (sm, thread_index)))
297  {
298  b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
300  nat_log_notice ("maximum sessions exceeded");
302  }
303 
304  key0.addr = key->l_addr;
305  key0.port = key->l_port;
306  key1.protocol = key0.protocol = proto;
307  key0.fib_index = rx_fib_index;
308  key1.fib_index = sm->outside_fib_index;
309  /* First try to match static mapping by local address and port */
311  (sm, key0, &key1, 0, 0, 0, &lb, 0, &identity_nat))
312  {
313  /* Try to create dynamic translation */
314  if (snat_alloc_outside_address_and_port (sm->addresses, rx_fib_index,
315  thread_index, &key1,
316  sm->port_per_thread,
317  tsm->snat_thread_index))
318  {
319  nat_log_notice ("addresses exhausted");
320  b->error = node->errors[NAT_IN2OUT_ED_ERROR_OUT_OF_PORTS];
322  }
323  }
324  else
325  {
326  if (PREDICT_FALSE (identity_nat))
327  {
328  *sessionp = s;
329  return next;
330  }
331 
332  is_sm = 1;
333  }
334 
335  if (proto == SNAT_PROTOCOL_TCP)
336  {
337  if (!tcp_is_init (tcp))
338  {
339  b->error = node->errors[NAT_IN2OUT_ED_ERROR_NON_SYN];
341  }
342  }
343 
344  u = nat_user_get_or_create (sm, &key->l_addr, rx_fib_index, thread_index);
345  if (!u)
346  {
347  nat_log_warn ("create NAT user failed");
348  if (!is_sm)
350  thread_index, &key1);
352  }
353 
354  s = nat_ed_session_alloc (sm, u, thread_index, now);
355  if (!s)
356  {
357  nat44_delete_user_with_no_session (sm, u, thread_index);
358  nat_log_warn ("create NAT session failed");
359  if (!is_sm)
361  thread_index, &key1);
363  }
364 
365  user_session_increment (sm, u, is_sm);
366  if (is_sm)
368  if (lb)
371  s->ext_host_addr = key->r_addr;
372  s->ext_host_port = key->r_port;
373  s->in2out = key0;
374  s->out2in = key1;
375  s->out2in.protocol = key0.protocol;
376 
377  switch (vec_len (sm->outside_fibs))
378  {
379  case 0:
380  s->out2in.fib_index = sm->outside_fib_index;
381  break;
382  case 1:
383  s->out2in.fib_index = sm->outside_fibs[0].fib_index;
384  break;
385  default:
386  /* *INDENT-OFF* */
387  vec_foreach (outside_fib, sm->outside_fibs)
388  {
389  fei = fib_table_lookup (outside_fib->fib_index, &pfx);
390  if (FIB_NODE_INDEX_INVALID != fei)
391  {
392  if (fib_entry_get_resolving_interface (fei) != ~0)
393  {
394  s->out2in.fib_index = outside_fib->fib_index;
395  break;
396  }
397  }
398  }
399  /* *INDENT-ON* */
400  break;
401  }
402 
403  /* Add to lookup tables */
404  kv->value = s - tsm->sessions;
405  ctx.now = now;
406  ctx.thread_index = thread_index;
407  if (clib_bihash_add_or_overwrite_stale_16_8 (&tsm->in2out_ed, kv,
409  &ctx))
410  nat_log_notice ("in2out-ed key add failed");
411 
412  make_ed_kv (kv, &key1.addr, &key->r_addr, key->proto, s->out2in.fib_index,
413  key1.port, key->r_port);
414  kv->value = s - tsm->sessions;
415  if (clib_bihash_add_or_overwrite_stale_16_8 (&tsm->out2in_ed, kv,
417  &ctx))
418  nat_log_notice ("out2in-ed key add failed");
419 
420  *sessionp = s;
421 
422  /* log NAT event */
423  snat_ipfix_logging_nat44_ses_create (s->in2out.addr.as_u32,
424  s->out2in.addr.as_u32,
425  s->in2out.protocol,
426  s->in2out.port,
427  s->out2in.port, s->in2out.fib_index);
428 
429  nat_syslog_nat44_sadd (s->user_index, s->in2out.fib_index,
430  &s->in2out.addr, s->in2out.port,
431  &s->ext_host_nat_addr, s->ext_host_nat_port,
432  &s->out2in.addr, s->out2in.port,
433  &s->ext_host_addr, s->ext_host_port,
434  s->in2out.protocol, 0);
435 
436  return next;
437 }
438 
441  u32 sw_if_index, ip4_header_t * ip, u32 proto,
442  u32 rx_fib_index, u32 thread_index)
443 {
444  udp_header_t *udp = ip4_next_header (ip);
445  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
446  clib_bihash_kv_16_8_t kv, value;
447  snat_session_key_t key0, key1;
448 
449  make_ed_kv (&kv, &ip->dst_address, &ip->src_address, ip->protocol,
450  sm->outside_fib_index, udp->dst_port, udp->src_port);
451 
452  /* NAT packet aimed at external address if */
453  /* has active sessions */
454  if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
455  {
456  key0.addr = ip->dst_address;
457  key0.port = udp->dst_port;
458  key0.protocol = proto;
459  key0.fib_index = sm->outside_fib_index;
460  /* or is static mappings */
461  if (!snat_static_mapping_match (sm, key0, &key1, 1, 0, 0, 0, 0, 0))
462  return 0;
463  }
464  else
465  return 0;
466 
467  if (sm->forwarding_enabled)
468  return 1;
469 
470  return snat_not_translate_fast (sm, node, sw_if_index, ip, proto,
471  rx_fib_index);
472 }
473 
476  u32 thread_index, f64 now,
478 {
479  nat_ed_ses_key_t key;
480  clib_bihash_kv_16_8_t kv, value;
481  udp_header_t *udp;
482  snat_session_t *s = 0;
483  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
484 
485  if (!sm->forwarding_enabled)
486  return 0;
487 
488  if (ip->protocol == IP_PROTOCOL_ICMP)
489  {
490  key.as_u64[0] = key.as_u64[1] = 0;
491  if (icmp_get_ed_key (ip, &key))
492  return 0;
493  key.fib_index = 0;
494  kv.key[0] = key.as_u64[0];
495  kv.key[1] = key.as_u64[1];
496  }
497  else if (ip->protocol == IP_PROTOCOL_UDP || ip->protocol == IP_PROTOCOL_TCP)
498  {
499  udp = ip4_next_header (ip);
500  make_ed_kv (&kv, &ip->src_address, &ip->dst_address, ip->protocol, 0,
501  udp->src_port, udp->dst_port);
502  }
503  else
504  {
505  make_ed_kv (&kv, &ip->src_address, &ip->dst_address, ip->protocol, 0, 0,
506  0);
507  }
508 
509  if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
510  {
511  s = pool_elt_at_index (tsm->sessions, value.value);
512  if (is_fwd_bypass_session (s))
513  {
514  if (ip->protocol == IP_PROTOCOL_TCP)
515  {
516  tcp_header_t *tcp = ip4_next_header (ip);
517  if (nat44_set_tcp_session_state_i2o (sm, s, tcp, thread_index))
518  return 1;
519  }
520  /* Accounting */
523  /* Per-user LRU list maintenance */
524  nat44_session_update_lru (sm, s, thread_index);
525  return 1;
526  }
527  else
528  return 0;
529  }
530 
531  return 0;
532 }
533 
536  u8 proto, u16 src_port, u16 dst_port,
537  u32 thread_index, u32 rx_sw_if_index,
538  u32 tx_sw_if_index)
539 {
540  clib_bihash_kv_16_8_t kv, value;
541  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
543  snat_session_t *s;
544  u32 rx_fib_index = ip4_fib_table_get_index_for_sw_if_index (rx_sw_if_index);
545  u32 tx_fib_index = ip4_fib_table_get_index_for_sw_if_index (tx_sw_if_index);
546 
547  /* src NAT check */
548  make_ed_kv (&kv, &ip->src_address, &ip->dst_address, proto, tx_fib_index,
549  src_port, dst_port);
550  if (!clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
551  {
552  s = pool_elt_at_index (tsm->sessions, value.value);
553  if (nat44_is_ses_closed (s))
554  {
555  nat_log_debug ("TCP close connection %U", format_snat_session,
556  &sm->per_thread_data[thread_index], s);
557  nat_free_session_data (sm, s, thread_index);
558  nat44_delete_session (sm, s, thread_index);
559  }
560  else
562  return 1;
563  }
564 
565  /* dst NAT check */
566  make_ed_kv (&kv, &ip->dst_address, &ip->src_address, proto, rx_fib_index,
567  dst_port, src_port);
568  if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
569  {
570  s = pool_elt_at_index (tsm->sessions, value.value);
571  if (is_fwd_bypass_session (s))
572  return 0;
573 
574  /* hairpinning */
575  /* *INDENT-OFF* */
577  ({
578  if ((nat_interface_is_inside (i)) && (rx_sw_if_index == i->sw_if_index))
579  return 0;
580  }));
581  /* *INDENT-ON* */
582  return 1;
583  }
584 
585  return 0;
586 }
587 
588 u32
590  u32 thread_index, vlib_buffer_t * b, ip4_header_t * ip,
591  u8 * p_proto, snat_session_key_t * p_value,
592  u8 * p_dont_translate, void *d, void *e)
593 {
594  icmp46_header_t *icmp;
596  u32 rx_fib_index;
597  nat_ed_ses_key_t key;
598  snat_session_t *s = 0;
599  u8 dont_translate = 0;
600  clib_bihash_kv_16_8_t kv, value;
601  u32 next = ~0;
602  int err;
603  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
604 
605  icmp = (icmp46_header_t *) ip4_next_header (ip);
606  sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
607  rx_fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
608 
609  key.as_u64[0] = key.as_u64[1] = 0;
610  err = icmp_get_ed_key (ip, &key);
611  if (err != 0)
612  {
613  b->error = node->errors[err];
615  goto out;
616  }
617  key.fib_index = rx_fib_index;
618 
619  kv.key[0] = key.as_u64[0];
620  kv.key[1] = key.as_u64[1];
621 
622  if (clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
623  {
624  if (vnet_buffer (b)->sw_if_index[VLIB_TX] != ~0)
625  {
627  key.proto,
628  key.
629  l_port,
630  key.
631  r_port,
632  thread_index,
633  sw_if_index,
635  (b)->
636  sw_if_index
637  [VLIB_TX])))
638  {
639  dont_translate = 1;
640  goto out;
641  }
642  }
643  else
644  {
645  if (PREDICT_FALSE (nat44_ed_not_translate (sm, node, sw_if_index,
646  ip, SNAT_PROTOCOL_ICMP,
647  rx_fib_index,
648  thread_index)))
649  {
650  dont_translate = 1;
651  goto out;
652  }
653  }
654 
656  {
657  b->error = node->errors[NAT_IN2OUT_ED_ERROR_BAD_ICMP_TYPE];
659  goto out;
660  }
661 
662  next = slow_path_ed (sm, b, rx_fib_index, &kv, &s, node, next,
663  thread_index, vlib_time_now (sm->vlib_main), 0);
664 
666  goto out;
667 
668  if (!s)
669  {
670  dont_translate = 1;
671  goto out;
672  }
673  }
674  else
675  {
676  if (PREDICT_FALSE (icmp->type != ICMP4_echo_request &&
677  icmp->type != ICMP4_echo_reply &&
678  !icmp_is_error_message (icmp)))
679  {
680  b->error = node->errors[NAT_IN2OUT_ED_ERROR_BAD_ICMP_TYPE];
682  goto out;
683  }
684 
685  s = pool_elt_at_index (tsm->sessions, value.value);
686  }
687 
688  *p_proto = ip_proto_to_snat_proto (key.proto);
689 out:
690  if (s)
691  *p_value = s->out2in;
692  *p_dont_translate = dont_translate;
693  if (d)
694  *(snat_session_t **) d = s;
695  return next;
696 }
697 
698 static snat_session_t *
700  vlib_buffer_t * b,
701  ip4_header_t * ip,
702  u32 rx_fib_index,
703  u32 thread_index,
704  f64 now,
706 {
707  clib_bihash_kv_8_8_t kv, value;
708  clib_bihash_kv_16_8_t s_kv, s_value;
710  u32 old_addr, new_addr = 0;
711  ip_csum_t sum;
712  snat_user_t *u;
713  dlist_elt_t *head, *elt;
714  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
715  u32 elt_index, head_index, ses_index;
716  snat_session_t *s;
717  u32 outside_fib_index = sm->outside_fib_index;
718  int i;
719  u8 is_sm = 0;
720  nat_outside_fib_t *outside_fib;
722  fib_prefix_t pfx = {
724  .fp_len = 32,
725  .fp_addr = {
726  .ip4.as_u32 = ip->dst_address.as_u32,
727  },
728  };
729 
730  switch (vec_len (sm->outside_fibs))
731  {
732  case 0:
733  outside_fib_index = sm->outside_fib_index;
734  break;
735  case 1:
736  outside_fib_index = sm->outside_fibs[0].fib_index;
737  break;
738  default:
739  /* *INDENT-OFF* */
740  vec_foreach (outside_fib, sm->outside_fibs)
741  {
742  fei = fib_table_lookup (outside_fib->fib_index, &pfx);
743  if (FIB_NODE_INDEX_INVALID != fei)
744  {
745  if (fib_entry_get_resolving_interface (fei) != ~0)
746  {
747  outside_fib_index = outside_fib->fib_index;
748  break;
749  }
750  }
751  }
752  /* *INDENT-ON* */
753  break;
754  }
755  old_addr = ip->src_address.as_u32;
756 
757  make_ed_kv (&s_kv, &ip->src_address, &ip->dst_address, ip->protocol,
758  rx_fib_index, 0, 0);
759 
760  if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &s_kv, &s_value))
761  {
762  s = pool_elt_at_index (tsm->sessions, s_value.value);
763  new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32;
764  }
765  else
766  {
767  if (PREDICT_FALSE (maximum_sessions_exceeded (sm, thread_index)))
768  {
769  b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
771  nat_log_notice ("maximum sessions exceeded");
772  return 0;
773  }
774 
775  u = nat_user_get_or_create (sm, &ip->src_address, rx_fib_index,
776  thread_index);
777  if (!u)
778  {
779  nat_log_warn ("create NAT user failed");
780  return 0;
781  }
782 
783  make_sm_kv (&kv, &ip->src_address, 0, rx_fib_index, 0);
784 
785  /* Try to find static mapping first */
786  if (!clib_bihash_search_8_8 (&sm->static_mapping_by_local, &kv, &value))
787  {
788  m = pool_elt_at_index (sm->static_mappings, value.value);
789  new_addr = ip->src_address.as_u32 = m->external_addr.as_u32;
790  is_sm = 1;
791  goto create_ses;
792  }
793  /* Fallback to 3-tuple key */
794  else
795  {
796  /* Choose same out address as for TCP/UDP session to same destination */
797  head_index = u->sessions_per_user_list_head_index;
798  head = pool_elt_at_index (tsm->list_pool, head_index);
799  elt_index = head->next;
800  if (PREDICT_FALSE (elt_index == ~0))
801  ses_index = ~0;
802  else
803  {
804  elt = pool_elt_at_index (tsm->list_pool, elt_index);
805  ses_index = elt->value;
806  }
807 
808  while (ses_index != ~0)
809  {
810  s = pool_elt_at_index (tsm->sessions, ses_index);
811  elt_index = elt->next;
812  elt = pool_elt_at_index (tsm->list_pool, elt_index);
813  ses_index = elt->value;
814 
815  if (s->ext_host_addr.as_u32 == ip->dst_address.as_u32)
816  {
817  new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32;
818 
819  make_ed_kv (&s_kv, &s->out2in.addr, &ip->dst_address,
820  ip->protocol, outside_fib_index, 0, 0);
821  if (clib_bihash_search_16_8
822  (&tsm->out2in_ed, &s_kv, &s_value))
823  goto create_ses;
824 
825  break;
826  }
827  }
828 
829  for (i = 0; i < vec_len (sm->addresses); i++)
830  {
831  make_ed_kv (&s_kv, &sm->addresses[i].addr, &ip->dst_address,
832  ip->protocol, outside_fib_index, 0, 0);
833  if (clib_bihash_search_16_8 (&tsm->out2in_ed, &s_kv, &s_value))
834  {
835  new_addr = ip->src_address.as_u32 =
836  sm->addresses[i].addr.as_u32;
837  goto create_ses;
838  }
839  }
840  return 0;
841  }
842 
843  create_ses:
844  s = nat_ed_session_alloc (sm, u, thread_index, now);
845  if (!s)
846  {
847  nat44_delete_user_with_no_session (sm, u, thread_index);
848  nat_log_warn ("create NAT session failed");
849  return 0;
850  }
851 
852  s->ext_host_addr.as_u32 = ip->dst_address.as_u32;
855  s->out2in.addr.as_u32 = new_addr;
856  s->out2in.fib_index = outside_fib_index;
857  s->in2out.addr.as_u32 = old_addr;
858  s->in2out.fib_index = rx_fib_index;
859  s->in2out.port = s->out2in.port = ip->protocol;
860  if (is_sm)
862  user_session_increment (sm, u, is_sm);
863 
864  /* Add to lookup tables */
865  make_ed_kv (&s_kv, &s->in2out.addr, &ip->dst_address, ip->protocol,
866  rx_fib_index, 0, 0);
867  s_kv.value = s - tsm->sessions;
868  if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &s_kv, 1))
869  nat_log_notice ("in2out key add failed");
870 
871  make_ed_kv (&s_kv, &s->out2in.addr, &ip->dst_address, ip->protocol,
872  outside_fib_index, 0, 0);
873  s_kv.value = s - tsm->sessions;
874  if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &s_kv, 1))
875  nat_log_notice ("out2in key add failed");
876  }
877 
878  /* Update IP checksum */
879  sum = ip->checksum;
880  sum = ip_csum_update (sum, old_addr, new_addr, ip4_header_t, src_address);
881  ip->checksum = ip_csum_fold (sum);
882 
883  /* Accounting */
885  /* Per-user LRU list maintenance */
886  nat44_session_update_lru (sm, s, thread_index);
887 
888  /* Hairpinning */
889  if (vnet_buffer (b)->sw_if_index[VLIB_TX] == ~0)
891 
892  if (vnet_buffer (b)->sw_if_index[VLIB_TX] == ~0)
893  vnet_buffer (b)->sw_if_index[VLIB_TX] = outside_fib_index;
894 
895  return s;
896 }
897 
898 static inline uword
900  vlib_node_runtime_t * node,
901  vlib_frame_t * frame, int is_slow_path,
902  int is_output_feature)
903 {
904  u32 n_left_from, *from, *to_next, pkts_processed = 0, stats_node_index;
905  nat_in2out_ed_next_t next_index;
906  snat_main_t *sm = &snat_main;
907  f64 now = vlib_time_now (vm);
908  u32 thread_index = vm->thread_index;
909  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
910  u32 tcp_packets = 0, udp_packets = 0, icmp_packets = 0, other_packets =
911  0, fragments = 0;
912 
913  stats_node_index = is_slow_path ? nat44_ed_in2out_slowpath_node.index :
914  nat44_ed_in2out_node.index;
915 
916  from = vlib_frame_vector_args (frame);
917  n_left_from = frame->n_vectors;
918  next_index = node->cached_next_index;
919 
920  while (n_left_from > 0)
921  {
922  u32 n_left_to_next;
923 
924  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
925 
926  while (n_left_from >= 4 && n_left_to_next >= 2)
927  {
928  u32 bi0, bi1;
929  vlib_buffer_t *b0, *b1;
930  u32 next0, sw_if_index0, rx_fib_index0, iph_offset0 = 0, proto0,
931  new_addr0, old_addr0;
932  u32 next1, sw_if_index1, rx_fib_index1, iph_offset1 = 0, proto1,
933  new_addr1, old_addr1;
934  u16 old_port0, new_port0, old_port1, new_port1;
935  ip4_header_t *ip0, *ip1;
936  udp_header_t *udp0, *udp1;
937  tcp_header_t *tcp0, *tcp1;
938  icmp46_header_t *icmp0, *icmp1;
939  snat_session_t *s0 = 0, *s1 = 0;
940  clib_bihash_kv_16_8_t kv0, value0, kv1, value1;
941  ip_csum_t sum0, sum1;
942 
943  /* Prefetch next iteration. */
944  {
945  vlib_buffer_t *p2, *p3;
946 
947  p2 = vlib_get_buffer (vm, from[2]);
948  p3 = vlib_get_buffer (vm, from[3]);
949 
950  vlib_prefetch_buffer_header (p2, LOAD);
951  vlib_prefetch_buffer_header (p3, LOAD);
952 
955  }
956 
957  /* speculatively enqueue b0 and b1 to the current next frame */
958  to_next[0] = bi0 = from[0];
959  to_next[1] = bi1 = from[1];
960  from += 2;
961  to_next += 2;
962  n_left_from -= 2;
963  n_left_to_next -= 2;
964 
965  b0 = vlib_get_buffer (vm, bi0);
966  b1 = vlib_get_buffer (vm, bi1);
967 
969 
970  if (is_output_feature)
971  iph_offset0 = vnet_buffer (b0)->ip.save_rewrite_length;
972 
973  ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
974  iph_offset0);
975 
976  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
977  rx_fib_index0 =
979  sw_if_index0);
980 
981  if (PREDICT_FALSE (ip0->ttl == 1))
982  {
983  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
984  icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
985  ICMP4_time_exceeded_ttl_exceeded_in_transit,
986  0);
988  goto trace00;
989  }
990 
991  udp0 = ip4_next_header (ip0);
992  tcp0 = (tcp_header_t *) udp0;
993  icmp0 = (icmp46_header_t *) udp0;
994  proto0 = ip_proto_to_snat_proto (ip0->protocol);
995 
996  if (is_slow_path)
997  {
998  if (PREDICT_FALSE (proto0 == ~0))
999  {
1000  s0 = nat44_ed_in2out_unknown_proto (sm, b0, ip0,
1001  rx_fib_index0,
1002  thread_index, now, vm,
1003  node);
1004  if (!s0)
1005  next0 = NAT_IN2OUT_ED_NEXT_DROP;
1006  other_packets++;
1007  goto trace00;
1008  }
1009 
1010  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
1011  {
1012  next0 = icmp_in2out_ed_slow_path
1013  (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
1014  next0, now, thread_index, &s0);
1015  icmp_packets++;
1016  goto trace00;
1017  }
1018  }
1019  else
1020  {
1021  if (PREDICT_FALSE (proto0 == ~0))
1022  {
1024  goto trace00;
1025  }
1026 
1027  if (ip4_is_fragment (ip0))
1028  {
1029  next0 = NAT_IN2OUT_ED_NEXT_REASS;
1030  fragments++;
1031  goto trace00;
1032  }
1033 
1034  if (is_output_feature)
1035  {
1036  if (PREDICT_FALSE
1038  (sm, ip0, thread_index, now, vm, b0)))
1039  goto trace00;
1040  }
1041 
1042  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
1043  {
1045  goto trace00;
1046  }
1047  }
1048 
1049  make_ed_kv (&kv0, &ip0->src_address, &ip0->dst_address,
1050  ip0->protocol, rx_fib_index0, udp0->src_port,
1051  udp0->dst_port);
1052 
1053  if (clib_bihash_search_16_8 (&tsm->in2out_ed, &kv0, &value0))
1054  {
1055  if (is_slow_path)
1056  {
1057  if (is_output_feature)
1058  {
1059  if (PREDICT_FALSE
1061  (sm, ip0, ip0->protocol, udp0->src_port,
1062  udp0->dst_port, thread_index, sw_if_index0,
1063  vnet_buffer (b0)->sw_if_index[VLIB_TX])))
1064  goto trace00;
1065  }
1066  else
1067  {
1068  if (PREDICT_FALSE (nat44_ed_not_translate (sm, node,
1069  sw_if_index0,
1070  ip0, proto0,
1071  rx_fib_index0,
1072  thread_index)))
1073  goto trace00;
1074  }
1075 
1076  next0 =
1077  slow_path_ed (sm, b0, rx_fib_index0, &kv0, &s0, node,
1078  next0, thread_index, now, tcp0);
1079 
1080  if (PREDICT_FALSE (next0 == NAT_IN2OUT_ED_NEXT_DROP))
1081  goto trace00;
1082 
1083  if (PREDICT_FALSE (!s0))
1084  goto trace00;
1085  }
1086  else
1087  {
1089  goto trace00;
1090  }
1091  }
1092  else
1093  {
1094  s0 = pool_elt_at_index (tsm->sessions, value0.value);
1095  }
1096 
1097  b0->flags |= VNET_BUFFER_F_IS_NATED;
1098 
1099  if (!is_output_feature)
1100  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->out2in.fib_index;
1101 
1102  old_addr0 = ip0->src_address.as_u32;
1103  new_addr0 = ip0->src_address.as_u32 = s0->out2in.addr.as_u32;
1104  sum0 = ip0->checksum;
1105  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1106  src_address);
1108  sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1109  s0->ext_host_addr.as_u32, ip4_header_t,
1110  dst_address);
1111  ip0->checksum = ip_csum_fold (sum0);
1112 
1113  if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP))
1114  {
1115  old_port0 = tcp0->src_port;
1116  new_port0 = tcp0->src_port = s0->out2in.port;
1117 
1118  sum0 = tcp0->checksum;
1119  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1120  dst_address);
1121  sum0 = ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
1122  length);
1124  {
1125  sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1126  s0->ext_host_addr.as_u32,
1127  ip4_header_t, dst_address);
1128  sum0 = ip_csum_update (sum0, tcp0->dst_port,
1129  s0->ext_host_port, ip4_header_t,
1130  length);
1131  tcp0->dst_port = s0->ext_host_port;
1132  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1133  }
1134  mss_clamping (sm, tcp0, &sum0);
1135  tcp0->checksum = ip_csum_fold (sum0);
1136  tcp_packets++;
1138  (sm, s0, tcp0, thread_index))
1139  goto trace00;
1140  }
1141  else
1142  {
1143  udp0->src_port = s0->out2in.port;
1144  udp0->checksum = 0;
1146  {
1147  udp0->dst_port = s0->ext_host_port;
1148  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1149  }
1150  udp_packets++;
1151  }
1152 
1153  /* Accounting */
1156  b0));
1157  /* Per-user LRU list maintenance */
1158  nat44_session_update_lru (sm, s0, thread_index);
1159 
1160  trace00:
1162  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1163  {
1165  vlib_add_trace (vm, node, b0, sizeof (*t));
1166  t->is_slow_path = is_slow_path;
1167  t->sw_if_index = sw_if_index0;
1168  t->next_index = next0;
1169  t->session_index = ~0;
1170  if (s0)
1171  t->session_index = s0 - tsm->sessions;
1172  }
1173 
1174  pkts_processed += next0 == NAT_IN2OUT_ED_NEXT_LOOKUP;
1175 
1176 
1177  next1 = NAT_IN2OUT_ED_NEXT_LOOKUP;
1178 
1179  if (is_output_feature)
1180  iph_offset1 = vnet_buffer (b1)->ip.save_rewrite_length;
1181 
1182  ip1 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b1) +
1183  iph_offset1);
1184 
1185  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
1186  rx_fib_index1 =
1188  sw_if_index1);
1189 
1190  if (PREDICT_FALSE (ip1->ttl == 1))
1191  {
1192  vnet_buffer (b1)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1193  icmp4_error_set_vnet_buffer (b1, ICMP4_time_exceeded,
1194  ICMP4_time_exceeded_ttl_exceeded_in_transit,
1195  0);
1197  goto trace01;
1198  }
1199 
1200  udp1 = ip4_next_header (ip1);
1201  tcp1 = (tcp_header_t *) udp1;
1202  icmp1 = (icmp46_header_t *) udp1;
1203  proto1 = ip_proto_to_snat_proto (ip1->protocol);
1204 
1205  if (is_slow_path)
1206  {
1207  if (PREDICT_FALSE (proto1 == ~0))
1208  {
1209  s1 = nat44_ed_in2out_unknown_proto (sm, b1, ip1,
1210  rx_fib_index1,
1211  thread_index, now, vm,
1212  node);
1213  if (!s1)
1214  next1 = NAT_IN2OUT_ED_NEXT_DROP;
1215  other_packets++;
1216  goto trace01;
1217  }
1218 
1219  if (PREDICT_FALSE (proto1 == SNAT_PROTOCOL_ICMP))
1220  {
1221  next1 = icmp_in2out_ed_slow_path
1222  (sm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1, node,
1223  next1, now, thread_index, &s1);
1224  icmp_packets++;
1225  goto trace01;
1226  }
1227  }
1228  else
1229  {
1230  if (PREDICT_FALSE (proto1 == ~0))
1231  {
1233  goto trace01;
1234  }
1235 
1236  if (ip4_is_fragment (ip1))
1237  {
1238  next1 = NAT_IN2OUT_ED_NEXT_REASS;
1239  fragments++;
1240  goto trace01;
1241  }
1242 
1243  if (is_output_feature)
1244  {
1245  if (PREDICT_FALSE
1247  (sm, ip1, thread_index, now, vm, b1)))
1248  goto trace01;
1249  }
1250 
1251  if (PREDICT_FALSE (proto1 == SNAT_PROTOCOL_ICMP))
1252  {
1254  goto trace01;
1255  }
1256  }
1257 
1258  make_ed_kv (&kv1, &ip1->src_address, &ip1->dst_address,
1259  ip1->protocol, rx_fib_index1, udp1->src_port,
1260  udp1->dst_port);
1261 
1262  if (clib_bihash_search_16_8 (&tsm->in2out_ed, &kv1, &value1))
1263  {
1264  if (is_slow_path)
1265  {
1266  if (is_output_feature)
1267  {
1268  if (PREDICT_FALSE
1270  (sm, ip1, ip1->protocol, udp1->src_port,
1271  udp1->dst_port, thread_index, sw_if_index1,
1272  vnet_buffer (b1)->sw_if_index[VLIB_TX])))
1273  goto trace01;
1274  }
1275  else
1276  {
1277  if (PREDICT_FALSE (nat44_ed_not_translate (sm, node,
1278  sw_if_index1,
1279  ip1, proto1,
1280  rx_fib_index1,
1281  thread_index)))
1282  goto trace01;
1283  }
1284 
1285  next1 =
1286  slow_path_ed (sm, b1, rx_fib_index1, &kv1, &s1, node,
1287  next1, thread_index, now, tcp1);
1288 
1289  if (PREDICT_FALSE (next1 == NAT_IN2OUT_ED_NEXT_DROP))
1290  goto trace01;
1291 
1292  if (PREDICT_FALSE (!s1))
1293  goto trace01;
1294  }
1295  else
1296  {
1298  goto trace01;
1299  }
1300  }
1301  else
1302  {
1303  s1 = pool_elt_at_index (tsm->sessions, value1.value);
1304  }
1305 
1306  b1->flags |= VNET_BUFFER_F_IS_NATED;
1307 
1308  if (!is_output_feature)
1309  vnet_buffer (b1)->sw_if_index[VLIB_TX] = s1->out2in.fib_index;
1310 
1311  old_addr1 = ip1->src_address.as_u32;
1312  new_addr1 = ip1->src_address.as_u32 = s1->out2in.addr.as_u32;
1313  sum1 = ip1->checksum;
1314  sum1 = ip_csum_update (sum1, old_addr1, new_addr1, ip4_header_t,
1315  src_address);
1317  sum1 = ip_csum_update (sum1, ip1->dst_address.as_u32,
1318  s1->ext_host_addr.as_u32, ip4_header_t,
1319  dst_address);
1320  ip1->checksum = ip_csum_fold (sum1);
1321 
1322  if (PREDICT_TRUE (proto1 == SNAT_PROTOCOL_TCP))
1323  {
1324  old_port1 = tcp1->src_port;
1325  new_port1 = tcp1->src_port = s1->out2in.port;
1326 
1327  sum1 = tcp1->checksum;
1328  sum1 = ip_csum_update (sum1, old_addr1, new_addr1, ip4_header_t,
1329  dst_address);
1330  sum1 = ip_csum_update (sum1, old_port1, new_port1, ip4_header_t,
1331  length);
1333  {
1334  sum1 = ip_csum_update (sum1, ip1->dst_address.as_u32,
1335  s1->ext_host_addr.as_u32,
1336  ip4_header_t, dst_address);
1337  sum1 = ip_csum_update (sum1, tcp1->dst_port,
1338  s1->ext_host_port, ip4_header_t,
1339  length);
1340  tcp1->dst_port = s1->ext_host_port;
1341  ip1->dst_address.as_u32 = s1->ext_host_addr.as_u32;
1342  }
1343  tcp1->checksum = ip_csum_fold (sum1);
1344  mss_clamping (sm, tcp1, &sum1);
1345  tcp_packets++;
1347  (sm, s1, tcp1, thread_index))
1348  goto trace01;
1349  }
1350  else
1351  {
1352  udp1->src_port = s1->out2in.port;
1353  udp1->checksum = 0;
1355  {
1356  udp1->dst_port = s1->ext_host_port;
1357  ip1->dst_address.as_u32 = s1->ext_host_addr.as_u32;
1358  }
1359  udp_packets++;
1360  }
1361 
1362  /* Accounting */
1365  b1));
1366  /* Per-user LRU list maintenance */
1367  nat44_session_update_lru (sm, s1, thread_index);
1368 
1369  trace01:
1371  && (b1->flags & VLIB_BUFFER_IS_TRACED)))
1372  {
1374  vlib_add_trace (vm, node, b1, sizeof (*t));
1375  t->is_slow_path = is_slow_path;
1376  t->sw_if_index = sw_if_index1;
1377  t->next_index = next1;
1378  t->session_index = ~0;
1379  if (s1)
1380  t->session_index = s1 - tsm->sessions;
1381  }
1382 
1383  pkts_processed += next1 == NAT_IN2OUT_ED_NEXT_LOOKUP;
1384 
1385  /* verify speculative enqueues, maybe switch current next frame */
1386  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
1387  to_next, n_left_to_next,
1388  bi0, bi1, next0, next1);
1389  }
1390 
1391  while (n_left_from > 0 && n_left_to_next > 0)
1392  {
1393  u32 bi0;
1394  vlib_buffer_t *b0;
1395  u32 next0, sw_if_index0, rx_fib_index0, iph_offset0 = 0, proto0,
1396  new_addr0, old_addr0;
1397  u16 old_port0, new_port0;
1398  ip4_header_t *ip0;
1399  udp_header_t *udp0;
1400  tcp_header_t *tcp0;
1401  icmp46_header_t *icmp0;
1402  snat_session_t *s0 = 0;
1403  clib_bihash_kv_16_8_t kv0, value0;
1404  ip_csum_t sum0;
1405 
1406  /* speculatively enqueue b0 to the current next frame */
1407  bi0 = from[0];
1408  to_next[0] = bi0;
1409  from += 1;
1410  to_next += 1;
1411  n_left_from -= 1;
1412  n_left_to_next -= 1;
1413 
1414  b0 = vlib_get_buffer (vm, bi0);
1415  next0 = NAT_IN2OUT_ED_NEXT_LOOKUP;
1416 
1417  if (is_output_feature)
1418  iph_offset0 = vnet_buffer (b0)->ip.save_rewrite_length;
1419 
1420  ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
1421  iph_offset0);
1422 
1423  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1424  rx_fib_index0 =
1426  sw_if_index0);
1427 
1428  if (PREDICT_FALSE (ip0->ttl == 1))
1429  {
1430  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1431  icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
1432  ICMP4_time_exceeded_ttl_exceeded_in_transit,
1433  0);
1435  goto trace0;
1436  }
1437 
1438  udp0 = ip4_next_header (ip0);
1439  tcp0 = (tcp_header_t *) udp0;
1440  icmp0 = (icmp46_header_t *) udp0;
1441  proto0 = ip_proto_to_snat_proto (ip0->protocol);
1442 
1443  if (is_slow_path)
1444  {
1445  if (PREDICT_FALSE (proto0 == ~0))
1446  {
1447  s0 = nat44_ed_in2out_unknown_proto (sm, b0, ip0,
1448  rx_fib_index0,
1449  thread_index, now, vm,
1450  node);
1451  if (!s0)
1452  next0 = NAT_IN2OUT_ED_NEXT_DROP;
1453  other_packets++;
1454  goto trace0;
1455  }
1456 
1457  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
1458  {
1459  next0 = icmp_in2out_ed_slow_path
1460  (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
1461  next0, now, thread_index, &s0);
1462  icmp_packets++;
1463  goto trace0;
1464  }
1465  }
1466  else
1467  {
1468  if (PREDICT_FALSE (proto0 == ~0))
1469  {
1471  goto trace0;
1472  }
1473 
1474  if (ip4_is_fragment (ip0))
1475  {
1476  next0 = NAT_IN2OUT_ED_NEXT_REASS;
1477  fragments++;
1478  goto trace0;
1479  }
1480 
1481  if (is_output_feature)
1482  {
1483  if (PREDICT_FALSE
1485  (sm, ip0, thread_index, now, vm, b0)))
1486  goto trace0;
1487  }
1488 
1489  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
1490  {
1492  goto trace0;
1493  }
1494  }
1495 
1496  make_ed_kv (&kv0, &ip0->src_address, &ip0->dst_address,
1497  ip0->protocol, rx_fib_index0, udp0->src_port,
1498  udp0->dst_port);
1499 
1500  if (clib_bihash_search_16_8 (&tsm->in2out_ed, &kv0, &value0))
1501  {
1502  if (is_slow_path)
1503  {
1504  if (is_output_feature)
1505  {
1506  if (PREDICT_FALSE
1508  (sm, ip0, ip0->protocol, udp0->src_port,
1509  udp0->dst_port, thread_index, sw_if_index0,
1510  vnet_buffer (b0)->sw_if_index[VLIB_TX])))
1511  goto trace0;
1512  }
1513  else
1514  {
1515  if (PREDICT_FALSE (nat44_ed_not_translate (sm, node,
1516  sw_if_index0,
1517  ip0, proto0,
1518  rx_fib_index0,
1519  thread_index)))
1520  goto trace0;
1521  }
1522 
1523  next0 =
1524  slow_path_ed (sm, b0, rx_fib_index0, &kv0, &s0, node,
1525  next0, thread_index, now, tcp0);
1526 
1527  if (PREDICT_FALSE (next0 == NAT_IN2OUT_ED_NEXT_DROP))
1528  goto trace0;
1529 
1530  if (PREDICT_FALSE (!s0))
1531  goto trace0;
1532  }
1533  else
1534  {
1536  goto trace0;
1537  }
1538  }
1539  else
1540  {
1541  s0 = pool_elt_at_index (tsm->sessions, value0.value);
1542  }
1543 
1544  b0->flags |= VNET_BUFFER_F_IS_NATED;
1545 
1546  if (!is_output_feature)
1547  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->out2in.fib_index;
1548 
1549  old_addr0 = ip0->src_address.as_u32;
1550  new_addr0 = ip0->src_address.as_u32 = s0->out2in.addr.as_u32;
1551  sum0 = ip0->checksum;
1552  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1553  src_address);
1555  sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1556  s0->ext_host_addr.as_u32, ip4_header_t,
1557  dst_address);
1558  ip0->checksum = ip_csum_fold (sum0);
1559 
1560  if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP))
1561  {
1562  old_port0 = tcp0->src_port;
1563  new_port0 = tcp0->src_port = s0->out2in.port;
1564 
1565  sum0 = tcp0->checksum;
1566  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1567  dst_address);
1568  sum0 = ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
1569  length);
1571  {
1572  sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1573  s0->ext_host_addr.as_u32,
1574  ip4_header_t, dst_address);
1575  sum0 = ip_csum_update (sum0, tcp0->dst_port,
1576  s0->ext_host_port, ip4_header_t,
1577  length);
1578  tcp0->dst_port = s0->ext_host_port;
1579  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1580  }
1581  mss_clamping (sm, tcp0, &sum0);
1582  tcp0->checksum = ip_csum_fold (sum0);
1583  tcp_packets++;
1585  (sm, s0, tcp0, thread_index))
1586  goto trace0;
1587  }
1588  else
1589  {
1590  udp0->src_port = s0->out2in.port;
1591  udp0->checksum = 0;
1593  {
1594  udp0->dst_port = s0->ext_host_port;
1595  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1596  }
1597  udp_packets++;
1598  }
1599 
1600  /* Accounting */
1603  b0));
1604  /* Per-user LRU list maintenance */
1605  nat44_session_update_lru (sm, s0, thread_index);
1606 
1607  trace0:
1609  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1610  {
1612  vlib_add_trace (vm, node, b0, sizeof (*t));
1613  t->is_slow_path = is_slow_path;
1614  t->sw_if_index = sw_if_index0;
1615  t->next_index = next0;
1616  t->session_index = ~0;
1617  if (s0)
1618  t->session_index = s0 - tsm->sessions;
1619  }
1620 
1621  pkts_processed += next0 == NAT_IN2OUT_ED_NEXT_LOOKUP;
1622 
1623  /* verify speculative enqueue, maybe switch current next frame */
1624  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1625  to_next, n_left_to_next,
1626  bi0, next0);
1627  }
1628 
1629  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1630  }
1631 
1632  vlib_node_increment_counter (vm, stats_node_index,
1633  NAT_IN2OUT_ED_ERROR_IN2OUT_PACKETS,
1634  pkts_processed);
1635  vlib_node_increment_counter (vm, stats_node_index,
1636  NAT_IN2OUT_ED_ERROR_TCP_PACKETS, tcp_packets);
1637  vlib_node_increment_counter (vm, stats_node_index,
1638  NAT_IN2OUT_ED_ERROR_UDP_PACKETS, tcp_packets);
1639  vlib_node_increment_counter (vm, stats_node_index,
1640  NAT_IN2OUT_ED_ERROR_ICMP_PACKETS,
1641  icmp_packets);
1642  vlib_node_increment_counter (vm, stats_node_index,
1643  NAT_IN2OUT_ED_ERROR_OTHER_PACKETS,
1644  other_packets);
1645  vlib_node_increment_counter (vm, stats_node_index,
1646  NAT_IN2OUT_ED_ERROR_FRAGMENTS, fragments);
1647 
1648  return frame->n_vectors;
1649 }
1650 
1651 static uword
1653  vlib_node_runtime_t * node,
1654  vlib_frame_t * frame)
1655 {
1656  return nat44_ed_in2out_node_fn_inline (vm, node, frame, 0, 0);
1657 }
1658 
1659 /* *INDENT-OFF* */
1661  .function = nat44_ed_in2out_fast_path_fn,
1662  .name = "nat44-ed-in2out",
1663  .vector_size = sizeof (u32),
1664  .format_trace = format_nat_in2out_ed_trace,
1665  .type = VLIB_NODE_TYPE_INTERNAL,
1666  .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1667  .error_strings = nat_in2out_ed_error_strings,
1668  .runtime_data_bytes = sizeof (snat_runtime_t),
1669  .n_next_nodes = NAT_IN2OUT_ED_N_NEXT,
1670  .next_nodes = {
1671  [NAT_IN2OUT_ED_NEXT_DROP] = "error-drop",
1672  [NAT_IN2OUT_ED_NEXT_LOOKUP] = "ip4-lookup",
1673  [NAT_IN2OUT_ED_NEXT_SLOW_PATH] = "nat44-ed-in2out-slowpath",
1674  [NAT_IN2OUT_ED_NEXT_ICMP_ERROR] = "ip4-icmp-error",
1675  [NAT_IN2OUT_ED_NEXT_REASS] = "nat44-ed-in2out-reass",
1676  },
1677 };
1678 /* *INDENT-ON* */
1679 
1682 
1683 static uword
1685  vlib_node_runtime_t * node,
1686  vlib_frame_t * frame)
1687 {
1688  return nat44_ed_in2out_node_fn_inline (vm, node, frame, 0, 1);
1689 }
1690 
1691 /* *INDENT-OFF* */
1694  .name = "nat44-ed-in2out-output",
1695  .vector_size = sizeof (u32),
1696  .format_trace = format_nat_in2out_ed_trace,
1697  .type = VLIB_NODE_TYPE_INTERNAL,
1698  .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1699  .error_strings = nat_in2out_ed_error_strings,
1700  .runtime_data_bytes = sizeof (snat_runtime_t),
1701  .n_next_nodes = NAT_IN2OUT_ED_N_NEXT,
1702  .next_nodes = {
1703  [NAT_IN2OUT_ED_NEXT_DROP] = "error-drop",
1704  [NAT_IN2OUT_ED_NEXT_LOOKUP] = "interface-output",
1705  [NAT_IN2OUT_ED_NEXT_SLOW_PATH] = "nat44-ed-in2out-output-slowpath",
1706  [NAT_IN2OUT_ED_NEXT_ICMP_ERROR] = "ip4-icmp-error",
1707  [NAT_IN2OUT_ED_NEXT_REASS] = "nat44-ed-in2out-reass-output",
1708  },
1709 };
1710 /* *INDENT-ON* */
1711 
1714 
1715 static uword
1717  vlib_node_runtime_t * node,
1718  vlib_frame_t * frame)
1719 {
1720  return nat44_ed_in2out_node_fn_inline (vm, node, frame, 1, 0);
1721 }
1722 
1723 /* *INDENT-OFF* */
1725  .function = nat44_ed_in2out_slow_path_fn,
1726  .name = "nat44-ed-in2out-slowpath",
1727  .vector_size = sizeof (u32),
1728  .format_trace = format_nat_in2out_ed_trace,
1729  .type = VLIB_NODE_TYPE_INTERNAL,
1730  .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1731  .error_strings = nat_in2out_ed_error_strings,
1732  .runtime_data_bytes = sizeof (snat_runtime_t),
1733  .n_next_nodes = NAT_IN2OUT_ED_N_NEXT,
1734  .next_nodes = {
1735  [NAT_IN2OUT_ED_NEXT_DROP] = "error-drop",
1736  [NAT_IN2OUT_ED_NEXT_LOOKUP] = "ip4-lookup",
1737  [NAT_IN2OUT_ED_NEXT_SLOW_PATH] = "nat44-ed-in2out-slowpath",
1738  [NAT_IN2OUT_ED_NEXT_ICMP_ERROR] = "ip4-icmp-error",
1739  [NAT_IN2OUT_ED_NEXT_REASS] = "nat44-ed-in2out-reass",
1740  },
1741 };
1742 /* *INDENT-ON* */
1743 
1746 
1747 static uword
1749  vlib_node_runtime_t * node,
1750  vlib_frame_t * frame)
1751 {
1752  return nat44_ed_in2out_node_fn_inline (vm, node, frame, 1, 1);
1753 }
1754 
1755 /* *INDENT-OFF* */
1758  .name = "nat44-ed-in2out-output-slowpath",
1759  .vector_size = sizeof (u32),
1760  .format_trace = format_nat_in2out_ed_trace,
1761  .type = VLIB_NODE_TYPE_INTERNAL,
1762  .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1763  .error_strings = nat_in2out_ed_error_strings,
1764  .runtime_data_bytes = sizeof (snat_runtime_t),
1765  .n_next_nodes = NAT_IN2OUT_ED_N_NEXT,
1766  .next_nodes = {
1767  [NAT_IN2OUT_ED_NEXT_DROP] = "error-drop",
1768  [NAT_IN2OUT_ED_NEXT_LOOKUP] = "interface-output",
1769  [NAT_IN2OUT_ED_NEXT_SLOW_PATH] = "nat44-ed-in2out-output-slowpath",
1770  [NAT_IN2OUT_ED_NEXT_ICMP_ERROR] = "ip4-icmp-error",
1771  [NAT_IN2OUT_ED_NEXT_REASS] = "nat44-ed-in2out-reass",
1772  },
1773 };
1774 /* *INDENT-ON* */
1775 
1778 
1779 static inline uword
1781  vlib_node_runtime_t * node,
1782  vlib_frame_t * frame,
1783  int is_output_feature)
1784 {
1785  u32 n_left_from, *from, *to_next;
1786  nat_in2out_ed_next_t next_index;
1787  u32 pkts_processed = 0, cached_fragments = 0;
1788  snat_main_t *sm = &snat_main;
1789  f64 now = vlib_time_now (vm);
1790  u32 thread_index = vm->thread_index;
1791  snat_main_per_thread_data_t *per_thread_data =
1792  &sm->per_thread_data[thread_index];
1793  u32 *fragments_to_drop = 0;
1794  u32 *fragments_to_loopback = 0;
1795 
1796  from = vlib_frame_vector_args (frame);
1797  n_left_from = frame->n_vectors;
1798  next_index = node->cached_next_index;
1799 
1800  while (n_left_from > 0)
1801  {
1802  u32 n_left_to_next;
1803 
1804  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1805 
1806  while (n_left_from > 0 && n_left_to_next > 0)
1807  {
1808  u32 bi0, sw_if_index0, proto0, rx_fib_index0, new_addr0, old_addr0;
1809  u32 iph_offset0 = 0;
1810  vlib_buffer_t *b0;
1811  u32 next0;
1812  u8 cached0 = 0;
1813  ip4_header_t *ip0 = 0;
1814  nat_reass_ip4_t *reass0;
1815  udp_header_t *udp0;
1816  tcp_header_t *tcp0;
1817  icmp46_header_t *icmp0;
1818  clib_bihash_kv_16_8_t kv0, value0;
1819  snat_session_t *s0 = 0;
1820  u16 old_port0, new_port0;
1821  ip_csum_t sum0;
1822 
1823  /* speculatively enqueue b0 to the current next frame */
1824  bi0 = from[0];
1825  to_next[0] = bi0;
1826  from += 1;
1827  to_next += 1;
1828  n_left_from -= 1;
1829  n_left_to_next -= 1;
1830 
1831  b0 = vlib_get_buffer (vm, bi0);
1832 
1833  next0 = NAT_IN2OUT_ED_NEXT_LOOKUP;
1834 
1835  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1836  rx_fib_index0 =
1838  sw_if_index0);
1839 
1841  {
1842  next0 = NAT_IN2OUT_ED_NEXT_DROP;
1843  b0->error = node->errors[NAT_IN2OUT_ED_ERROR_DROP_FRAGMENT];
1844  goto trace0;
1845  }
1846 
1847  if (is_output_feature)
1848  iph_offset0 = vnet_buffer (b0)->ip.save_rewrite_length;
1849 
1850  ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
1851  iph_offset0);
1852 
1853  udp0 = ip4_next_header (ip0);
1854  tcp0 = (tcp_header_t *) udp0;
1855  icmp0 = (icmp46_header_t *) udp0;
1856  proto0 = ip_proto_to_snat_proto (ip0->protocol);
1857 
1859  ip0->dst_address,
1860  ip0->fragment_id,
1861  ip0->protocol,
1862  1, &fragments_to_drop);
1863 
1864  if (PREDICT_FALSE (!reass0))
1865  {
1866  next0 = NAT_IN2OUT_ED_NEXT_DROP;
1867  b0->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_REASS];
1868  nat_log_notice ("maximum reassemblies exceeded");
1869  goto trace0;
1870  }
1871 
1873  {
1874  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
1875  {
1876  if (is_output_feature)
1877  {
1878  if (PREDICT_FALSE
1880  (sm, ip0, thread_index, now, vm, b0)))
1881  reass0->flags |= NAT_REASS_FLAG_ED_DONT_TRANSLATE;
1882  goto trace0;
1883  }
1884 
1885  next0 = icmp_in2out_ed_slow_path
1886  (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
1887  next0, now, thread_index, &s0);
1888 
1889  if (PREDICT_TRUE (next0 != NAT_IN2OUT_ED_NEXT_DROP))
1890  {
1891  if (s0)
1892  reass0->sess_index = s0 - per_thread_data->sessions;
1893  else
1894  reass0->flags |= NAT_REASS_FLAG_ED_DONT_TRANSLATE;
1895  nat_ip4_reass_get_frags (reass0,
1896  &fragments_to_loopback);
1897  }
1898 
1899  goto trace0;
1900  }
1901 
1902  make_ed_kv (&kv0, &ip0->src_address, &ip0->dst_address,
1903  ip0->protocol, rx_fib_index0, udp0->src_port,
1904  udp0->dst_port);
1905 
1906  if (clib_bihash_search_16_8
1907  (&per_thread_data->in2out_ed, &kv0, &value0))
1908  {
1909  if (is_output_feature)
1910  {
1911  if (PREDICT_FALSE
1913  (sm, ip0, ip0->protocol, udp0->src_port,
1914  udp0->dst_port, thread_index, sw_if_index0,
1915  vnet_buffer (b0)->sw_if_index[VLIB_TX])))
1916  {
1917  reass0->flags |= NAT_REASS_FLAG_ED_DONT_TRANSLATE;
1918  nat_ip4_reass_get_frags (reass0,
1919  &fragments_to_loopback);
1920  goto trace0;
1921  }
1922  }
1923  else
1924  {
1925  if (PREDICT_FALSE (nat44_ed_not_translate (sm, node,
1926  sw_if_index0,
1927  ip0, proto0,
1928  rx_fib_index0,
1929  thread_index)))
1930  {
1931  reass0->flags |= NAT_REASS_FLAG_ED_DONT_TRANSLATE;
1932  nat_ip4_reass_get_frags (reass0,
1933  &fragments_to_loopback);
1934  goto trace0;
1935  }
1936  }
1937 
1938  next0 = slow_path_ed (sm, b0, rx_fib_index0, &kv0,
1939  &s0, node, next0, thread_index, now,
1940  tcp0);
1941 
1942  if (PREDICT_FALSE (next0 == NAT_IN2OUT_ED_NEXT_DROP))
1943  goto trace0;
1944 
1945  if (PREDICT_FALSE (!s0))
1946  {
1947  reass0->flags |= NAT_REASS_FLAG_ED_DONT_TRANSLATE;
1948  goto trace0;
1949  }
1950 
1951  reass0->sess_index = s0 - per_thread_data->sessions;
1952  }
1953  else
1954  {
1955  s0 = pool_elt_at_index (per_thread_data->sessions,
1956  value0.value);
1957  reass0->sess_index = value0.value;
1958  }
1959  nat_ip4_reass_get_frags (reass0, &fragments_to_loopback);
1960  }
1961  else
1962  {
1963  if (reass0->flags & NAT_REASS_FLAG_ED_DONT_TRANSLATE)
1964  goto trace0;
1965  if (PREDICT_FALSE (reass0->sess_index == (u32) ~ 0))
1966  {
1968  (reass0, bi0, &fragments_to_drop))
1969  {
1970  b0->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_FRAG];
1972  ("maximum fragments per reassembly exceeded");
1973  next0 = NAT_IN2OUT_ED_NEXT_DROP;
1974  goto trace0;
1975  }
1976  cached0 = 1;
1977  goto trace0;
1978  }
1979  s0 = pool_elt_at_index (per_thread_data->sessions,
1980  reass0->sess_index);
1981  }
1982 
1983  old_addr0 = ip0->src_address.as_u32;
1984  ip0->src_address = s0->out2in.addr;
1985  new_addr0 = ip0->src_address.as_u32;
1986  if (!is_output_feature)
1987  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->out2in.fib_index;
1988 
1989  sum0 = ip0->checksum;
1990  sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1991  ip4_header_t,
1992  src_address /* changed member */ );
1994  sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1995  s0->ext_host_addr.as_u32, ip4_header_t,
1996  dst_address);
1997  ip0->checksum = ip_csum_fold (sum0);
1998 
2000  {
2001  if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP))
2002  {
2003  old_port0 = tcp0->src_port;
2004  tcp0->src_port = s0->out2in.port;
2005  new_port0 = tcp0->src_port;
2006 
2007  sum0 = tcp0->checksum;
2008  sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
2009  ip4_header_t,
2010  dst_address /* changed member */ );
2011  sum0 = ip_csum_update (sum0, old_port0, new_port0,
2012  ip4_header_t /* cheat */ ,
2013  length /* changed member */ );
2015  {
2016  sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
2017  s0->ext_host_addr.as_u32,
2018  ip4_header_t, dst_address);
2019  sum0 = ip_csum_update (sum0, tcp0->dst_port,
2020  s0->ext_host_port, ip4_header_t,
2021  length);
2022  tcp0->dst_port = s0->ext_host_port;
2023  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
2024  }
2025  tcp0->checksum = ip_csum_fold (sum0);
2026  }
2027  else
2028  {
2029  old_port0 = udp0->src_port;
2030  udp0->src_port = s0->out2in.port;
2031  udp0->checksum = 0;
2033  {
2034  udp0->dst_port = s0->ext_host_port;
2035  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
2036  }
2037  }
2038  }
2039 
2040  /* Hairpinning */
2041  nat44_reass_hairpinning (sm, b0, ip0, s0->out2in.port,
2042  s0->ext_host_port, proto0, 1);
2043 
2044  /* Accounting */
2047  b0));
2048  /* Per-user LRU list maintenance */
2049  nat44_session_update_lru (sm, s0, thread_index);
2050 
2051  trace0:
2053  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
2054  {
2055  nat44_reass_trace_t *t =
2056  vlib_add_trace (vm, node, b0, sizeof (*t));
2057  t->cached = cached0;
2058  t->sw_if_index = sw_if_index0;
2059  t->next_index = next0;
2060  }
2061 
2062  if (cached0)
2063  {
2064  n_left_to_next++;
2065  to_next--;
2066  cached_fragments++;
2067  }
2068  else
2069  {
2070  pkts_processed += next0 != NAT_IN2OUT_ED_NEXT_DROP;
2071 
2072  /* verify speculative enqueue, maybe switch current next frame */
2073  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
2074  to_next, n_left_to_next,
2075  bi0, next0);
2076  }
2077 
2078  if (n_left_from == 0 && vec_len (fragments_to_loopback))
2079  {
2080  from = vlib_frame_vector_args (frame);
2081  u32 len = vec_len (fragments_to_loopback);
2082  if (len <= VLIB_FRAME_SIZE)
2083  {
2084  clib_memcpy_fast (from, fragments_to_loopback,
2085  sizeof (u32) * len);
2086  n_left_from = len;
2087  vec_reset_length (fragments_to_loopback);
2088  }
2089  else
2090  {
2091  clib_memcpy_fast (from, fragments_to_loopback +
2092  (len - VLIB_FRAME_SIZE),
2093  sizeof (u32) * VLIB_FRAME_SIZE);
2094  n_left_from = VLIB_FRAME_SIZE;
2095  _vec_len (fragments_to_loopback) = len - VLIB_FRAME_SIZE;
2096  }
2097  }
2098  }
2099 
2100  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2101  }
2102 
2104  NAT_IN2OUT_ED_ERROR_PROCESSED_FRAGMENTS,
2105  pkts_processed);
2107  NAT_IN2OUT_ED_ERROR_CACHED_FRAGMENTS,
2108  cached_fragments);
2109 
2110  nat_send_all_to_node (vm, fragments_to_drop, node,
2111  &node->errors[NAT_IN2OUT_ED_ERROR_DROP_FRAGMENT],
2113 
2114  vec_free (fragments_to_drop);
2115  vec_free (fragments_to_loopback);
2116  return frame->n_vectors;
2117 }
2118 
2119 static uword
2121  vlib_node_runtime_t * node,
2122  vlib_frame_t * frame)
2123 {
2124  return nat44_ed_in2out_reass_node_fn_inline (vm, node, frame, 0);
2125 }
2126 
2127 /* *INDENT-OFF* */
2129  .function = nat44_ed_in2out_reass_node_fn,
2130  .name = "nat44-ed-in2out-reass",
2131  .vector_size = sizeof (u32),
2132  .format_trace = format_nat44_reass_trace,
2133  .type = VLIB_NODE_TYPE_INTERNAL,
2134  .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
2135  .error_strings = nat_in2out_ed_error_strings,
2136  .n_next_nodes = NAT_IN2OUT_ED_N_NEXT,
2137  .next_nodes = {
2138  [NAT_IN2OUT_ED_NEXT_DROP] = "error-drop",
2139  [NAT_IN2OUT_ED_NEXT_LOOKUP] = "ip4-lookup",
2140  [NAT_IN2OUT_ED_NEXT_SLOW_PATH] = "nat44-in2out-slowpath",
2141  [NAT_IN2OUT_ED_NEXT_ICMP_ERROR] = "ip4-icmp-error",
2142  [NAT_IN2OUT_ED_NEXT_REASS] = "nat44-ed-in2out-reass",
2143  },
2144 };
2145 /* *INDENT-ON* */
2146 
2149 
2150 static uword
2152  vlib_node_runtime_t * node,
2153  vlib_frame_t * frame)
2154 {
2155  return nat44_ed_in2out_reass_node_fn_inline (vm, node, frame, 1);
2156 }
2157 
2158 /* *INDENT-OFF* */
2161  .name = "nat44-ed-in2out-reass-output",
2162  .vector_size = sizeof (u32),
2163  .format_trace = format_nat44_reass_trace,
2164  .type = VLIB_NODE_TYPE_INTERNAL,
2165  .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
2166  .error_strings = nat_in2out_ed_error_strings,
2167  .n_next_nodes = NAT_IN2OUT_ED_N_NEXT,
2168  .next_nodes = {
2169  [NAT_IN2OUT_ED_NEXT_DROP] = "error-drop",
2170  [NAT_IN2OUT_ED_NEXT_LOOKUP] = "interface-output",
2171  [NAT_IN2OUT_ED_NEXT_SLOW_PATH] = "nat44-in2out-slowpath",
2172  [NAT_IN2OUT_ED_NEXT_ICMP_ERROR] = "ip4-icmp-error",
2173  [NAT_IN2OUT_ED_NEXT_REASS] = "nat44-ed-in2out-reass",
2174  },
2175 };
2176 /* *INDENT-ON* */
2177 
2180 
2181 /*
2182  * fd.io coding-style-patch-verification: ON
2183  *
2184  * Local Variables:
2185  * eval: (c-set-style "gnu")
2186  * End:
2187  */
ip4_address_t external_addr
Definition: nat.h:330
void nat_ipfix_logging_max_sessions(u32 limit)
Generate maximum session entries exceeded event.
u32 next
Definition: dlist.h:30
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:212
nat_outside_fib_t * outside_fibs
Definition: nat.h:476
#define snat_is_session_static(s)
Check if SNAT session is created from static mapping.
Definition: nat.h:605
u32 sessions_per_user_list_head_index
Definition: nat.h:236
static uword nat44_ed_in2out_node_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_slow_path, int is_output_feature)
Definition: in2out_ed.c:899
vlib_node_registration_t nat44_ed_in2out_output_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_output_node)
Definition: in2out_ed.c:86
#define CLIB_UNUSED(x)
Definition: clib.h:82
a
Definition: bitmap.h:538
ip4_address_t src_address
Definition: ip4_packet.h:170
static u32 nat44_session_get_timeout(snat_main_t *sm, snat_session_t *s)
Definition: nat_inlines.h:273
static uword nat44_ed_in2out_output_fast_path_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: in2out_ed.c:1684
#define PREDICT_TRUE(x)
Definition: clib.h:112
static_always_inline u8 icmp_is_error_message(icmp46_header_t *icmp)
Definition: nat_inlines.h:53
unsigned long u64
Definition: types.h:89
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:232
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:956
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:332
u16 port_per_thread
Definition: nat.h:442
u32 thread_index
Definition: main.h:179
VLIB_NODE_FUNCTION_MULTIARCH(nat44_ed_in2out_node, nat44_ed_in2out_fast_path_fn)
#define nat_log_warn(...)
Definition: nat.h:694
int i
void nat_syslog_nat44_sdel(u32 ssubix, u32 sfibix, ip4_address_t *isaddr, u16 isport, ip4_address_t *idaddr, u16 idport, ip4_address_t *xsaddr, u16 xsport, ip4_address_t *xdaddr, u16 xdport, snat_protocol_t proto, u8 is_twicenat)
Definition: nat_syslog.c:211
uword ip_csum_t
Definition: ip_packet.h:181
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
#define nat44_is_ses_closed(s)
Check if NAT44 endpoint-dependent TCP session is closed.
Definition: nat.h:659
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:440
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:494
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:267
dlist_elt_t * list_pool
Definition: nat.h:399
struct _tcp_header tcp_header_t
#define snat_is_unk_proto_session(s)
Check if SNAT session for unknown protocol.
Definition: nat.h:611
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:699
u32 proto
Definition: nat.h:69
unsigned char u8
Definition: types.h:56
u16 l_port
Definition: nat.h:70
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
double f64
Definition: types.h:142
static int ip4_is_fragment(const ip4_header_t *i)
Definition: ip4_packet.h:213
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:410
u16 src_port
Definition: udp.api:41
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
Definition: ip4_fib.c:224
#define tcp_is_init(t)
Check if client initiating TCP connection (received SYN from client)
Definition: nat.h:689
#define static_always_inline
Definition: clib.h:99
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:490
u16 r_port
Definition: nat.h:71
u32 sw_if_index
Definition: vxlan_gbp.api:37
ip4_address_t dst_address
Definition: ip4_packet.h:170
lb_nat_type_t
Definition: nat.h:315
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:188
#define SNAT_SESSION_FLAG_OUTPUT_FEATURE
Definition: nat.h:178
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Aggregrate type for a prefix.
Definition: fib_types.h:203
u32 icmp_in2out(snat_main_t *sm, vlib_buffer_t *b0, ip4_header_t *ip0, icmp46_header_t *icmp0, u32 sw_if_index0, u32 rx_fib_index0, vlib_node_runtime_t *node, u32 next0, u32 thread_index, void *d, void *e)
Definition: in2out.c:635
#define is_fwd_bypass_session(s)
Check if NAT session is forwarding bypass.
Definition: nat.h:629
#define NAT_REASS_FLAG_ED_DONT_TRANSLATE
Definition: nat_reass.h:35
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:241
unsigned int u32
Definition: types.h:88
#define VLIB_FRAME_SIZE
Definition: node.h:401
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:66
u64 as_u64[2]
Definition: nat.h:73
static u8 maximum_sessions_exceeded(snat_main_t *sm, u32 thread_index)
Definition: nat_inlines.h:94
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:2287
static uword nat44_ed_in2out_fast_path_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: in2out_ed.c:1652
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:2249
static void nat44_delete_session(snat_main_t *sm, snat_session_t *ses, u32 thread_index)
Definition: nat_inlines.h:168
u32 max_translations
Definition: nat.h:516
static void mss_clamping(snat_main_t *sm, tcp_header_t *tcp, ip_csum_t *sum)
Definition: nat_inlines.h:347
int snat_alloc_outside_address_and_port(snat_address_t *addresses, u32 fib_index, u32 thread_index, snat_session_key_t *k, u16 port_per_thread, u32 snat_thread_index)
Alloc outside address and port.
Definition: nat.c:2432
u32 fib_index
Definition: nat.h:69
snat_user_t * nat_user_get_or_create(snat_main_t *sm, ip4_address_t *addr, u32 fib_index, u32 thread_index)
Find or create NAT user.
Definition: nat.c:291
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:511
void nat_free_session_data(snat_main_t *sm, snat_session_t *s, u32 thread_index)
Free NAT44 session data (lookup keys, external addrres port)
Definition: nat.c:178
u32 fib_index
Definition: nat.h:257
clib_bihash_16_8_t out2in_ed
Definition: nat.h:386
long ctx[MAX_CONNS]
Definition: main.c:144
static uword nat44_ed_in2out_output_slow_path_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: in2out_ed.c:1748
vlib_main_t * vlib_main
Definition: nat.h:546
vlib_node_registration_t nat44_ed_in2out_slowpath_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_slowpath_node)
Definition: in2out_ed.c:85
unsigned short u16
Definition: types.h:57
u16 protocol
Definition: nat.h:54
snat_session_t * nat_ed_session_alloc(snat_main_t *sm, snat_user_t *u, u32 thread_index, f64 now)
Allocate NAT endpoint-dependent session.
Definition: nat.c:411
snat_static_mapping_t * static_mappings
Definition: nat.h:455
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:214
void snat_ipfix_logging_nat44_ses_delete(u32 src_ip, u32 nat_src_ip, snat_protocol_t snat_proto, u16 src_port, u16 nat_src_port, u32 vrf_id)
Generate NAT44 session delete event.
void nat_syslog_nat44_sadd(u32 ssubix, u32 sfibix, ip4_address_t *isaddr, u16 isport, ip4_address_t *idaddr, u16 idport, ip4_address_t *xsaddr, u16 xsport, ip4_address_t *xdaddr, u16 xdport, snat_protocol_t proto, u8 is_twicenat)
Definition: nat_syslog.c:199
#define PREDICT_FALSE(x)
Definition: clib.h:111
void snat_ipfix_logging_nat44_ses_create(u32 src_ip, u32 nat_src_ip, snat_protocol_t snat_proto, u16 src_port, u16 nat_src_port, u32 vrf_id)
Generate NAT44 session create event.
static_always_inline int icmp_get_ed_key(ip4_header_t *ip0, nat_ed_ses_key_t *p_key0)
Definition: in2out_ed.c:109
vl_api_address_union_t src_address
Definition: ip_types.api:44
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Finish enqueueing two buffers forward in the graph.
Definition: buffer_node.h:70
#define SNAT_SESSION_FLAG_UNKNOWN_PROTO
Definition: nat.h:172
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:218
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:368
#define nat_log_notice(...)
Definition: nat.h:696
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:139
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1180
u8 len
Definition: ip_types.api:49
u32 fib_entry_get_resolving_interface(fib_node_index_t entry_index)
Definition: fib_entry.c:1451
static u8 * format_nat_in2out_ed_trace(u8 *s, va_list *args)
Definition: in2out_ed.c:91
snat_interface_t * output_feature_interfaces
Definition: nat.h:459
snat_main_t snat_main
Definition: nat.c:38
u64 value
the value
Definition: bihash_8_8.h:34
static void nat44_delete_user_with_no_session(snat_main_t *sm, snat_user_t *u, u32 thread_index)
Definition: nat_inlines.h:146
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
#define nat_log_debug(...)
Definition: nat.h:700
static u8 snat_proto_to_ip_proto(snat_protocol_t snat_proto)
Definition: nat_inlines.h:41
u16 n_vectors
Definition: node.h:420
u8 nat_reass_is_drop_frag(u8 is_ip6)
Get status of virtual fragmentation reassembly.
Definition: nat_reass.c:168
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:79
int nat44_o2i_ed_is_idle_session_cb(clib_bihash_kv_16_8_t *kv, void *arg)
Definition: out2in_ed.c:131
vlib_main_t * vm
Definition: buffer.c:301
vlib_node_registration_t nat44_ed_in2out_output_slowpath_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_output_slowpath_node)
Definition: in2out_ed.c:87
ip4_address_t l_addr
Definition: nat.h:67
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
void icmp4_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
Definition: icmp4.c:431
vlib_node_registration_t nat44_ed_in2out_reass_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_reass_node)
Definition: in2out_ed.c:88
static void nat44_session_update_counters(snat_session_t *s, f64 now, uword bytes)
Definition: nat_inlines.h:296
u32 outside_fib_index
Definition: nat.h:521
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:30
static uword nat44_ed_in2out_reass_output_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: in2out_ed.c:2151
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:31
#define ARRAY_LEN(x)
Definition: clib.h:62
ip4_address_t addr
Definition: nat.h:52
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:459
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:475
static void make_ed_kv(clib_bihash_kv_16_8_t *kv, ip4_address_t *l_addr, ip4_address_t *r_addr, u8 proto, u32 fib_index, u16 l_port, u16 r_port)
Definition: nat_inlines.h:315
ip4_address_t r_addr
Definition: nat.h:68
static int nat44_set_tcp_session_state_i2o(snat_main_t *sm, snat_session_t *ses, tcp_header_t *tcp, u32 thread_index)
Set TCP session state.
Definition: nat_inlines.h:204
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:538
nat_in2out_ed_error_t
Definition: in2out_ed.c:52
static uword nat44_ed_in2out_reass_node_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_output_feature)
Definition: in2out_ed.c:1780
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:305
static uword nat44_ed_in2out_reass_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: in2out_ed.c:2120
#define SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT
Definition: nat.h:175
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:247
ip4_address_t addr
Definition: nat.h:243
vlib_node_registration_t nat44_ed_in2out_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_node)
Definition: in2out_ed.c:84
snat_address_t * twice_nat_addresses
Definition: nat.h:479
u32 value
Definition: dlist.h:32
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:57
format_function_t format_snat_session
Definition: nat.h:591
struct _vlib_node_registration vlib_node_registration_t
Definition: defs.h:47
format_function_t format_nat44_reass_trace
Definition: nat.h:597
static int ip4_is_first_fragment(const ip4_header_t *i)
Definition: ip4_packet.h:220
static u32 ip_proto_to_snat_proto(u8 ip_proto)
The NAT inline functions.
Definition: nat_inlines.h:26
#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:158
static void user_session_increment(snat_main_t *sm, snat_user_t *u, u8 is_static)
Definition: nat_inlines.h:134
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u64 uword
Definition: types.h:112
snat_main_per_thread_data_t * per_thread_data
Definition: nat.h:446
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:274
#define ip_csum_update(sum, old, new, type, field)
Definition: ip_packet.h:231
NAT syslog logging.
nat_reass_ip4_t * nat_ip4_reass_find_or_create(ip4_address_t src, ip4_address_t dst, u16 frag_id, u8 proto, u8 reset_timeout, u32 **bi_to_drop)
Find or create reassembly.
Definition: nat_reass.c:220
snat_address_t * addresses
Definition: nat.h:462
#define vnet_buffer(b)
Definition: buffer.h:368
#define SNAT_SESSION_FLAG_STATIC_MAPPING
Definition: nat.h:171
nat_in2out_ed_next_t
Definition: in2out_ed.c:66
void nat44_ed_hairpinning_unknown_proto(snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip)
int nat_ip4_reass_add_fragment(nat_reass_ip4_t *reass, u32 bi, u32 **bi_to_drop)
Cache fragment.
Definition: nat_reass.c:338
u8 data[0]
Packet data.
Definition: buffer.h:176
u8 forwarding_enabled
Definition: nat.h:506
#define foreach_nat_in2out_ed_error
Definition: in2out_ed.c:33
#define vec_foreach(var, vec)
Vector iterator.
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:589
u16 flags
Copy of main node flags.
Definition: node.h:532
static void nat_send_all_to_node(vlib_main_t *vm, u32 *bi_vector, vlib_node_runtime_t *node, vlib_error_t *error, u32 next)
Definition: nat_inlines.h:104
#define is_twice_nat_session(s)
Check if NAT session is twice NAT.
Definition: nat.h:617
clib_bihash_16_8_t in2out_ed
Definition: nat.h:387
u16 dst_port
Definition: udp.api:42
void nat_ip4_reass_get_frags(nat_reass_ip4_t *reass, u32 **bi)
Get cached fragments.
Definition: nat_reass.c:370
NAT plugin virtual fragmentation reassembly.
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:326
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
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:117
static uword nat44_ed_in2out_slow_path_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: in2out_ed.c:1716
snat_session_t * sessions
Definition: nat.h:396
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:62
static char * nat_in2out_ed_error_strings[]
Definition: in2out_ed.c:60
#define SNAT_SESSION_FLAG_LOAD_BALANCING
Definition: nat.h:173
clib_bihash_8_8_t static_mapping_by_local
Definition: nat.h:449
vlib_node_registration_t nat44_ed_in2out_reass_output_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_reass_output_node)
Definition: in2out_ed.c:2159
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:237
void nat44_reass_hairpinning(snat_main_t *sm, vlib_buffer_t *b0, ip4_header_t *ip0, u16 sport, u16 dport, u32 proto0, int is_ed)
static u32 slow_path_ed(snat_main_t *sm, vlib_buffer_t *b, u32 rx_fib_index, clib_bihash_kv_16_8_t *kv, snat_session_t **sessionp, vlib_node_runtime_t *node, u32 next, u32 thread_index, f64 now, tcp_header_t *tcp)
Definition: in2out_ed.c:269
Definition: defs.h:46
u16 fib_index
Definition: nat.h:54
static_always_inline int nat44_ed_not_translate_output_feature(snat_main_t *sm, ip4_header_t *ip, u8 proto, u16 src_port, u16 dst_port, u32 thread_index, u32 rx_sw_if_index, u32 tx_sw_if_index)
Definition: in2out_ed.c:535