FD.io VPP  v18.10-32-g1161dda
Vector Packet Processing
out2in_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 outside to inside network translation
18  */
19 
20 #include <vlib/vlib.h>
21 #include <vnet/vnet.h>
22 #include <vnet/pg/pg.h>
23 #include <vnet/ip/ip.h>
24 #include <vnet/ethernet/ethernet.h>
25 #include <vnet/fib/ip4_fib.h>
26 #include <vnet/udp/udp.h>
27 #include <vppinfra/error.h>
28 #include <nat/nat.h>
29 #include <nat/nat_ipfix_logging.h>
30 #include <nat/nat_reass.h>
31 #include <nat/nat_inlines.h>
32 
33 #define foreach_nat_out2in_ed_error \
34 _(UNSUPPORTED_PROTOCOL, "Unsupported protocol") \
35 _(OUT2IN_PACKETS, "Good out2in packets processed") \
36 _(OUT_OF_PORTS, "Out of ports") \
37 _(BAD_ICMP_TYPE, "unsupported ICMP type") \
38 _(NO_TRANSLATION, "No translation") \
39 _(MAX_SESSIONS_EXCEEDED, "Maximum sessions exceeded") \
40 _(DROP_FRAGMENT, "Drop fragment") \
41 _(MAX_REASS, "Maximum reassemblies exceeded") \
42 _(MAX_FRAG, "Maximum fragments per reassembly exceeded")\
43 _(NON_SYN, "non-SYN packet try to create session")
44 
45 typedef enum
46 {
47 #define _(sym,str) NAT_OUT2IN_ED_ERROR_##sym,
49 #undef _
52 
53 static char *nat_out2in_ed_error_strings[] = {
54 #define _(sym,string) string,
56 #undef _
57 };
58 
59 typedef enum
60 {
69 
70 typedef struct
71 {
77 
81 
82 static u8 *
83 format_nat44_ed_out2in_trace (u8 * s, va_list * args)
84 {
85  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
86  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
87  nat44_ed_out2in_trace_t *t = va_arg (*args, nat44_ed_out2in_trace_t *);
88  char *tag;
89 
90  tag =
91  t->is_slow_path ? "NAT44_OUT2IN_ED_SLOW_PATH" :
92  "NAT44_OUT2IN_ED_FAST_PATH";
93 
94  s = format (s, "%s: sw_if_index %d, next index %d, session %d", tag,
96 
97  return s;
98 }
99 
100 static inline u32
102  ip4_header_t * ip0, icmp46_header_t * icmp0,
103  u32 sw_if_index0, u32 rx_fib_index0,
104  vlib_node_runtime_t * node, u32 next0, f64 now,
105  u32 thread_index, snat_session_t ** p_s0)
106 {
107  next0 = icmp_out2in (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
108  next0, thread_index, p_s0, 0);
109  snat_session_t *s0 = *p_s0;
110  if (PREDICT_TRUE (next0 != NAT44_ED_OUT2IN_NEXT_DROP && s0))
111  {
112  /* Accounting */
115  (sm->vlib_main, b0));
116  /* Per-user LRU list maintenance */
117  nat44_session_update_lru (sm, s0, thread_index);
118  }
119  return next0;
120 }
121 
122 int
124 {
125  snat_main_t *sm = &snat_main;
127  snat_session_t *s;
128  u64 sess_timeout_time;
129  nat_ed_ses_key_t ed_key;
130  clib_bihash_kv_16_8_t ed_kv;
131  int i;
132  snat_address_t *a;
133  snat_session_key_t key;
135  ctx->thread_index);
136 
137  s = pool_elt_at_index (tsm->sessions, kv->value);
138  sess_timeout_time = s->last_heard + (f64) nat44_session_get_timeout (sm, s);
139  if (ctx->now >= sess_timeout_time)
140  {
141  ed_key.l_addr = s->in2out.addr;
142  ed_key.r_addr = s->ext_host_addr;
143  ed_key.fib_index = s->in2out.fib_index;
145  {
146  ed_key.proto = s->in2out.port;
147  ed_key.r_port = 0;
148  ed_key.l_port = 0;
149  }
150  else
151  {
152  ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol);
153  ed_key.l_port = s->in2out.port;
154  ed_key.r_port = s->ext_host_port;
155  }
156  if (is_twice_nat_session (s))
157  {
158  ed_key.r_addr = s->ext_host_nat_addr;
159  ed_key.r_port = s->ext_host_nat_port;
160  }
161  ed_kv.key[0] = ed_key.as_u64[0];
162  ed_kv.key[1] = ed_key.as_u64[1];
163  if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0))
164  nat_log_warn ("in2out_ed key del failed");
165 
167  goto delete;
168 
169  snat_ipfix_logging_nat44_ses_delete (s->in2out.addr.as_u32,
170  s->out2in.addr.as_u32,
171  s->in2out.protocol,
172  s->in2out.port,
173  s->out2in.port,
174  s->in2out.fib_index);
175 
176  if (is_twice_nat_session (s))
177  {
178  for (i = 0; i < vec_len (sm->twice_nat_addresses); i++)
179  {
180  key.protocol = s->in2out.protocol;
181  key.port = s->ext_host_nat_port;
182  a = sm->twice_nat_addresses + i;
183  if (a->addr.as_u32 == s->ext_host_nat_addr.as_u32)
184  {
186  ctx->thread_index,
187  &key);
188  break;
189  }
190  }
191  }
192 
193  if (snat_is_session_static (s))
194  goto delete;
195 
197  &s->out2in);
198  delete:
199  nat44_delete_session (sm, s, ctx->thread_index);
200  return 1;
201  }
202 
203  return 0;
204 }
205 
206 static snat_session_t *
208  vlib_buffer_t * b,
209  snat_session_key_t l_key,
210  snat_session_key_t e_key,
211  vlib_node_runtime_t * node,
212  u32 thread_index,
213  twice_nat_type_t twice_nat,
214  lb_nat_type_t lb_nat, f64 now)
215 {
216  snat_session_t *s;
217  snat_user_t *u;
218  ip4_header_t *ip;
219  udp_header_t *udp;
220  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
222  snat_session_key_t eh_key;
224 
225  if (PREDICT_FALSE (maximum_sessions_exceeded (sm, thread_index)))
226  {
227  b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_SESSIONS_EXCEEDED];
228  nat_log_notice ("maximum sessions exceeded");
229  return 0;
230  }
231 
232  u = nat_user_get_or_create (sm, &l_key.addr, l_key.fib_index, thread_index);
233  if (!u)
234  {
235  nat_log_warn ("create NAT user failed");
236  return 0;
237  }
238 
239  s = nat_ed_session_alloc (sm, u, thread_index, now);
240  if (!s)
241  {
242  nat44_delete_user_with_no_session (sm, u, thread_index);
243  nat_log_warn ("create NAT session failed");
244  return 0;
245  }
246 
247  ip = vlib_buffer_get_current (b);
248  udp = ip4_next_header (ip);
249 
250  s->ext_host_addr.as_u32 = ip->src_address.as_u32;
251  s->ext_host_port = e_key.protocol == SNAT_PROTOCOL_ICMP ? 0 : udp->src_port;
253  if (lb_nat)
255  if (lb_nat == AFFINITY_LB_NAT)
256  s->flags |= SNAT_SESSION_FLAG_AFFINITY;
258  s->out2in = e_key;
259  s->in2out = l_key;
260  s->in2out.protocol = s->out2in.protocol;
261  user_session_increment (sm, u, 1);
262 
263  /* Add to lookup tables */
264  make_ed_kv (&kv, &e_key.addr, &s->ext_host_addr, ip->protocol,
265  e_key.fib_index, e_key.port, s->ext_host_port);
266  kv.value = s - tsm->sessions;
267  ctx.now = now;
268  ctx.thread_index = thread_index;
269  if (clib_bihash_add_or_overwrite_stale_16_8 (&tsm->out2in_ed, &kv,
271  &ctx))
272  nat_log_notice ("out2in-ed key add failed");
273 
274  if (twice_nat == TWICE_NAT || (twice_nat == TWICE_NAT_SELF &&
275  ip->src_address.as_u32 == l_key.addr.as_u32))
276  {
277  eh_key.protocol = e_key.protocol;
279  thread_index, &eh_key,
280  sm->port_per_thread,
281  tsm->snat_thread_index))
282  {
283  b->error = node->errors[NAT_OUT2IN_ED_ERROR_OUT_OF_PORTS];
284  nat44_delete_session (sm, s, thread_index);
285  if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &kv, 0))
286  nat_log_notice ("out2in-ed key del failed");
287  return 0;
288  }
289  s->ext_host_nat_addr.as_u32 = eh_key.addr.as_u32;
290  s->ext_host_nat_port = eh_key.port;
291  s->flags |= SNAT_SESSION_FLAG_TWICE_NAT;
292  make_ed_kv (&kv, &l_key.addr, &s->ext_host_nat_addr, ip->protocol,
293  l_key.fib_index, l_key.port, s->ext_host_nat_port);
294  }
295  else
296  {
297  make_ed_kv (&kv, &l_key.addr, &s->ext_host_addr, ip->protocol,
298  l_key.fib_index, l_key.port, s->ext_host_port);
299  }
300  kv.value = s - tsm->sessions;
301  if (clib_bihash_add_or_overwrite_stale_16_8 (&tsm->in2out_ed, &kv,
303  &ctx))
304  nat_log_notice ("in2out-ed key add failed");
305 
306  return s;
307 }
308 
311 {
312  icmp46_header_t *icmp0;
313  nat_ed_ses_key_t key0;
314  icmp_echo_header_t *echo0, *inner_echo0 = 0;
315  ip4_header_t *inner_ip0;
316  void *l4_header = 0;
317  icmp46_header_t *inner_icmp0;
318 
319  icmp0 = (icmp46_header_t *) ip4_next_header (ip0);
320  echo0 = (icmp_echo_header_t *) (icmp0 + 1);
321 
322  if (!icmp_is_error_message (icmp0))
323  {
324  key0.proto = IP_PROTOCOL_ICMP;
325  key0.l_addr = ip0->dst_address;
326  key0.r_addr = ip0->src_address;
327  key0.l_port = echo0->identifier;
328  key0.r_port = 0;
329  }
330  else
331  {
332  inner_ip0 = (ip4_header_t *) (echo0 + 1);
333  l4_header = ip4_next_header (inner_ip0);
334  key0.proto = inner_ip0->protocol;
335  key0.l_addr = inner_ip0->src_address;
336  key0.r_addr = inner_ip0->dst_address;
337  switch (ip_proto_to_snat_proto (inner_ip0->protocol))
338  {
339  case SNAT_PROTOCOL_ICMP:
340  inner_icmp0 = (icmp46_header_t *) l4_header;
341  inner_echo0 = (icmp_echo_header_t *) (inner_icmp0 + 1);
342  key0.l_port = inner_echo0->identifier;
343  key0.r_port = 0;
344  break;
345  case SNAT_PROTOCOL_UDP:
346  case SNAT_PROTOCOL_TCP:
347  key0.l_port = ((tcp_udp_header_t *) l4_header)->src_port;
348  key0.r_port = ((tcp_udp_header_t *) l4_header)->dst_port;
349  break;
350  default:
351  return -1;
352  }
353  }
354  *p_key0 = key0;
355  return 0;
356 }
357 
358 static int
360  u16 dst_port, u32 thread_index, u32 rx_fib_index)
361 {
362  clib_bihash_kv_16_8_t kv, value;
363  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
364 
365  make_ed_kv (&kv, &ip->src_address, &ip->dst_address, proto,
366  rx_fib_index, src_port, dst_port);
367  if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
368  return 1;
369 
370  return 0;
371 }
372 
373 static void
375  u32 thread_index)
376 {
377  nat_ed_ses_key_t key;
378  clib_bihash_kv_16_8_t kv, value;
379  udp_header_t *udp;
380  snat_user_t *u;
381  snat_session_t *s = 0;
382  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
383  f64 now = vlib_time_now (sm->vlib_main);
384 
385  if (ip->protocol == IP_PROTOCOL_ICMP)
386  {
387  if (icmp_get_ed_key (ip, &key))
388  return;
389  }
390  else if (ip->protocol == IP_PROTOCOL_UDP || ip->protocol == IP_PROTOCOL_TCP)
391  {
392  udp = ip4_next_header (ip);
393  key.r_addr = ip->src_address;
394  key.l_addr = ip->dst_address;
395  key.proto = ip->protocol;
396  key.l_port = udp->dst_port;
397  key.r_port = udp->src_port;
398  }
399  else
400  {
401  key.r_addr = ip->src_address;
402  key.l_addr = ip->dst_address;
403  key.proto = ip->protocol;
404  key.l_port = key.r_port = 0;
405  }
406  key.fib_index = 0;
407  kv.key[0] = key.as_u64[0];
408  kv.key[1] = key.as_u64[1];
409 
410  if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
411  {
412  s = pool_elt_at_index (tsm->sessions, value.value);
413  }
414  else
415  {
416  if (PREDICT_FALSE (maximum_sessions_exceeded (sm, thread_index)))
417  return;
418 
420  thread_index);
421  if (!u)
422  {
423  nat_log_warn ("create NAT user failed");
424  return;
425  }
426 
427  s = nat_ed_session_alloc (sm, u, thread_index, now);
428  if (!s)
429  {
430  nat44_delete_user_with_no_session (sm, u, thread_index);
431  nat_log_warn ("create NAT session failed");
432  return;
433  }
434 
435  s->ext_host_addr = key.r_addr;
436  s->ext_host_port = key.r_port;
437  s->flags |= SNAT_SESSION_FLAG_FWD_BYPASS;
438  s->out2in.addr = key.l_addr;
439  s->out2in.port = key.l_port;
440  s->out2in.protocol = ip_proto_to_snat_proto (key.proto);
441  s->out2in.fib_index = 0;
442  s->in2out = s->out2in;
443  user_session_increment (sm, u, 0);
444 
445  kv.value = s - tsm->sessions;
446  if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &kv, 1))
447  nat_log_notice ("in2out_ed key add failed");
448  }
449 
450  if (ip->protocol == IP_PROTOCOL_TCP)
451  {
452  tcp_header_t *tcp = ip4_next_header (ip);
453  if (nat44_set_tcp_session_state_o2i (sm, s, tcp, thread_index))
454  return;
455  }
456 
457  /* Accounting */
458  nat44_session_update_counters (s, now, 0);
459  /* Per-user LRU list maintenance */
460  nat44_session_update_lru (sm, s, thread_index);
461 }
462 
463 u32
465  u32 thread_index, vlib_buffer_t * b, ip4_header_t * ip,
466  u8 * p_proto, snat_session_key_t * p_value,
467  u8 * p_dont_translate, void *d, void *e)
468 {
469  u32 next = ~0, sw_if_index, rx_fib_index;
470  icmp46_header_t *icmp;
471  nat_ed_ses_key_t key;
472  clib_bihash_kv_16_8_t kv, value;
473  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
474  snat_session_t *s = 0;
475  u8 dont_translate = 0, is_addr_only, identity_nat;
476  snat_session_key_t e_key, l_key;
477 
478  icmp = (icmp46_header_t *) ip4_next_header (ip);
479  sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
481 
482  if (icmp_get_ed_key (ip, &key))
483  {
484  b->error = node->errors[NAT_OUT2IN_ED_ERROR_UNSUPPORTED_PROTOCOL];
486  goto out;
487  }
488  key.fib_index = rx_fib_index;
489  kv.key[0] = key.as_u64[0];
490  kv.key[1] = key.as_u64[1];
491 
492  if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
493  {
494  /* Try to match static mapping */
495  e_key.addr = ip->dst_address;
496  e_key.port = key.l_port;
497  e_key.protocol = ip_proto_to_snat_proto (key.proto);
498  e_key.fib_index = rx_fib_index;
500  (sm, e_key, &l_key, 1, &is_addr_only, 0, 0, 0, &identity_nat))
501  {
502  if (!sm->forwarding_enabled)
503  {
504  /* Don't NAT packet aimed at the intfc address */
506  ip->dst_address.as_u32)))
507  {
508  dont_translate = 1;
509  goto out;
510  }
511  b->error = node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
513  goto out;
514  }
515  else
516  {
517  dont_translate = 1;
518  if (next_src_nat (sm, ip, key.proto, key.l_port, key.r_port,
519  thread_index, rx_fib_index))
520  {
522  goto out;
523  }
524  create_bypass_for_fwd (sm, ip, rx_fib_index, thread_index);
525  goto out;
526  }
527  }
528 
529  if (PREDICT_FALSE (icmp->type != ICMP4_echo_reply &&
530  (icmp->type != ICMP4_echo_request || !is_addr_only)))
531  {
532  b->error = node->errors[NAT_OUT2IN_ED_ERROR_BAD_ICMP_TYPE];
534  goto out;
535  }
536 
537  if (PREDICT_FALSE (identity_nat))
538  {
539  dont_translate = 1;
540  goto out;
541  }
542 
543  /* Create session initiated by host from external network */
544  s = create_session_for_static_mapping_ed (sm, b, l_key, e_key, node,
545  thread_index, 0, 0,
547  (sm->vlib_main));
548 
549  if (!s)
550  {
552  goto out;
553  }
554  }
555  else
556  {
557  if (PREDICT_FALSE (icmp->type != ICMP4_echo_reply &&
558  icmp->type != ICMP4_echo_request &&
559  !icmp_is_error_message (icmp)))
560  {
561  b->error = node->errors[NAT_OUT2IN_ED_ERROR_BAD_ICMP_TYPE];
563  goto out;
564  }
565 
566  s = pool_elt_at_index (tsm->sessions, value.value);
567  }
568 
569  *p_proto = ip_proto_to_snat_proto (key.proto);
570 out:
571  if (s)
572  *p_value = s->in2out;
573  *p_dont_translate = dont_translate;
574  if (d)
575  *(snat_session_t **) d = s;
576  return next;
577 }
578 
579 static snat_session_t *
581  vlib_buffer_t * b,
582  ip4_header_t * ip,
583  u32 rx_fib_index,
584  u32 thread_index,
585  f64 now,
587 {
588  clib_bihash_kv_8_8_t kv, value;
589  clib_bihash_kv_16_8_t s_kv, s_value;
591  u32 old_addr, new_addr;
592  ip_csum_t sum;
593  snat_session_t *s;
594  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
595  snat_user_t *u;
596 
597  old_addr = ip->dst_address.as_u32;
598 
599  make_ed_kv (&s_kv, &ip->dst_address, &ip->src_address, ip->protocol,
600  rx_fib_index, 0, 0);
601 
602  if (!clib_bihash_search_16_8 (&tsm->out2in_ed, &s_kv, &s_value))
603  {
604  s = pool_elt_at_index (tsm->sessions, s_value.value);
605  new_addr = ip->dst_address.as_u32 = s->in2out.addr.as_u32;
606  }
607  else
608  {
609  if (PREDICT_FALSE (maximum_sessions_exceeded (sm, thread_index)))
610  {
611  b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_SESSIONS_EXCEEDED];
612  nat_log_notice ("maximum sessions exceeded");
613  return 0;
614  }
615 
616  make_sm_kv (&kv, &ip->dst_address, 0, 0, 0);
617  if (clib_bihash_search_8_8
618  (&sm->static_mapping_by_external, &kv, &value))
619  {
620  b->error = node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
621  return 0;
622  }
623 
624  m = pool_elt_at_index (sm->static_mappings, value.value);
625 
626  new_addr = ip->dst_address.as_u32 = m->local_addr.as_u32;
627 
629  thread_index);
630  if (!u)
631  {
632  nat_log_warn ("create NAT user failed");
633  return 0;
634  }
635 
636  /* Create a new session */
637  s = nat_ed_session_alloc (sm, u, thread_index, now);
638  if (!s)
639  {
640  nat44_delete_user_with_no_session (sm, u, thread_index);
641  nat_log_warn ("create NAT session failed");
642  return 0;
643  }
644 
645  s->ext_host_addr.as_u32 = ip->src_address.as_u32;
649  s->out2in.addr.as_u32 = old_addr;
650  s->out2in.fib_index = rx_fib_index;
651  s->in2out.addr.as_u32 = new_addr;
652  s->in2out.fib_index = m->fib_index;
653  s->in2out.port = s->out2in.port = ip->protocol;
654  user_session_increment (sm, u, 1);
655 
656  /* Add to lookup tables */
657  s_kv.value = s - tsm->sessions;
658  if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &s_kv, 1))
659  nat_log_notice ("out2in key add failed");
660 
661  make_ed_kv (&s_kv, &ip->dst_address, &ip->src_address, ip->protocol,
662  m->fib_index, 0, 0);
663  s_kv.value = s - tsm->sessions;
664  if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &s_kv, 1))
665  nat_log_notice ("in2out key add failed");
666  }
667 
668  /* Update IP checksum */
669  sum = ip->checksum;
670  sum = ip_csum_update (sum, old_addr, new_addr, ip4_header_t, dst_address);
671  ip->checksum = ip_csum_fold (sum);
672 
673  vnet_buffer (b)->sw_if_index[VLIB_TX] = s->in2out.fib_index;
674 
675  /* Accounting */
677  /* Per-user LRU list maintenance */
678  nat44_session_update_lru (sm, s, thread_index);
679 
680  return s;
681 }
682 
683 static inline uword
685  vlib_node_runtime_t * node,
686  vlib_frame_t * frame, int is_slow_path)
687 {
688  u32 n_left_from, *from, *to_next, pkts_processed = 0, stats_node_index;
689  nat44_ed_out2in_next_t next_index;
690  snat_main_t *sm = &snat_main;
691  f64 now = vlib_time_now (vm);
692  u32 thread_index = vm->thread_index;
693  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
694 
695  stats_node_index = is_slow_path ? nat44_ed_out2in_slowpath_node.index :
696  nat44_ed_out2in_node.index;
697 
698  from = vlib_frame_vector_args (frame);
699  n_left_from = frame->n_vectors;
700  next_index = node->cached_next_index;
701 
702  while (n_left_from > 0)
703  {
704  u32 n_left_to_next;
705 
706  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
707 
708  while (n_left_from >= 4 && n_left_to_next >= 2)
709  {
710  u32 bi0, bi1;
711  vlib_buffer_t *b0, *b1;
712  u32 next0, sw_if_index0, rx_fib_index0, proto0, old_addr0,
713  new_addr0;
714  u32 next1, sw_if_index1, rx_fib_index1, proto1, old_addr1,
715  new_addr1;
716  u16 old_port0, new_port0, old_port1, new_port1;
717  ip4_header_t *ip0, *ip1;
718  udp_header_t *udp0, *udp1;
719  tcp_header_t *tcp0, *tcp1;
720  icmp46_header_t *icmp0, *icmp1;
721  snat_session_t *s0 = 0, *s1 = 0;
722  clib_bihash_kv_16_8_t kv0, value0, kv1, value1;
723  ip_csum_t sum0, sum1;
724  snat_session_key_t e_key0, l_key0, e_key1, l_key1;
725  lb_nat_type_t lb_nat0, lb_nat1;
726  twice_nat_type_t twice_nat0, twice_nat1;
727  u8 identity_nat0, identity_nat1;
728 
729  /* Prefetch next iteration. */
730  {
731  vlib_buffer_t *p2, *p3;
732 
733  p2 = vlib_get_buffer (vm, from[2]);
734  p3 = vlib_get_buffer (vm, from[3]);
735 
736  vlib_prefetch_buffer_header (p2, LOAD);
737  vlib_prefetch_buffer_header (p3, LOAD);
738 
741  }
742 
743  /* speculatively enqueue b0 and b1 to the current next frame */
744  to_next[0] = bi0 = from[0];
745  to_next[1] = bi1 = from[1];
746  from += 2;
747  to_next += 2;
748  n_left_from -= 2;
749  n_left_to_next -= 2;
750 
751  b0 = vlib_get_buffer (vm, bi0);
752  b1 = vlib_get_buffer (vm, bi1);
753 
755  vnet_buffer (b0)->snat.flags = 0;
756  ip0 = vlib_buffer_get_current (b0);
757 
758  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
759  rx_fib_index0 =
761  sw_if_index0);
762 
763  if (PREDICT_FALSE (ip0->ttl == 1))
764  {
765  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
766  icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
767  ICMP4_time_exceeded_ttl_exceeded_in_transit,
768  0);
770  goto trace00;
771  }
772 
773  udp0 = ip4_next_header (ip0);
774  tcp0 = (tcp_header_t *) udp0;
775  icmp0 = (icmp46_header_t *) udp0;
776  proto0 = ip_proto_to_snat_proto (ip0->protocol);
777 
778  if (is_slow_path)
779  {
780  if (PREDICT_FALSE (proto0 == ~0))
781  {
782  s0 =
783  nat44_ed_out2in_unknown_proto (sm, b0, ip0, rx_fib_index0,
784  thread_index, now, vm,
785  node);
786  if (!sm->forwarding_enabled)
787  {
788  if (!s0)
790  goto trace00;
791  }
792  }
793 
794  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
795  {
797  (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
798  next0, now, thread_index, &s0);
799  goto trace00;
800  }
801  }
802  else
803  {
804  if (PREDICT_FALSE (proto0 == ~0))
805  {
807  goto trace00;
808  }
809 
810  if (ip4_is_fragment (ip0))
811  {
813  goto trace00;
814  }
815 
816  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
817  {
819  goto trace00;
820  }
821  }
822 
823  make_ed_kv (&kv0, &ip0->dst_address, &ip0->src_address,
824  ip0->protocol, rx_fib_index0, udp0->dst_port,
825  udp0->src_port);
826 
827  if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv0, &value0))
828  {
829  if (is_slow_path)
830  {
831  /* Try to match static mapping by external address and port,
832  destination address and port in packet */
833  e_key0.addr = ip0->dst_address;
834  e_key0.port = udp0->dst_port;
835  e_key0.protocol = proto0;
836  e_key0.fib_index = rx_fib_index0;
837  if (snat_static_mapping_match (sm, e_key0, &l_key0, 1, 0,
838  &twice_nat0, &lb_nat0,
839  &ip0->src_address,
840  &identity_nat0))
841  {
842  /*
843  * Send DHCP packets to the ipv4 stack, or we won't
844  * be able to use dhcp client on the outside interface
845  */
846  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_UDP
847  && (udp0->dst_port ==
848  clib_host_to_net_u16
849  (UDP_DST_PORT_dhcp_to_client))))
850  {
851  vnet_feature_next (&next0, b0);
852  goto trace00;
853  }
854 
855  if (!sm->forwarding_enabled)
856  {
857  b0->error =
858  node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
860  }
861  else
862  {
863  if (next_src_nat (sm, ip0, ip0->protocol,
864  udp0->src_port, udp0->dst_port,
865  thread_index, rx_fib_index0))
866  {
868  goto trace00;
869  }
870  create_bypass_for_fwd (sm, ip0, rx_fib_index0,
871  thread_index);
872  }
873  goto trace00;
874  }
875 
876  if (PREDICT_FALSE (identity_nat0))
877  goto trace00;
878 
879  if ((proto0 == SNAT_PROTOCOL_TCP) && !tcp_is_init (tcp0))
880  {
881  b0->error = node->errors[NAT_OUT2IN_ED_ERROR_NON_SYN];
883  goto trace00;
884  }
885 
886  /* Create session initiated by host from external network */
887  s0 = create_session_for_static_mapping_ed (sm, b0, l_key0,
888  e_key0, node,
889  thread_index,
890  twice_nat0,
891  lb_nat0, now);
892 
893  if (!s0)
894  {
896  goto trace00;
897  }
898  }
899  else
900  {
902  goto trace00;
903  }
904  }
905  else
906  {
907  s0 = pool_elt_at_index (tsm->sessions, value0.value);
908  }
909 
910  old_addr0 = ip0->dst_address.as_u32;
911  new_addr0 = ip0->dst_address.as_u32 = s0->in2out.addr.as_u32;
912  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
913 
914  sum0 = ip0->checksum;
915  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
916  dst_address);
918  sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
919  s0->ext_host_nat_addr.as_u32, ip4_header_t,
920  src_address);
921  ip0->checksum = ip_csum_fold (sum0);
922 
923  if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP))
924  {
925  old_port0 = tcp0->dst_port;
926  new_port0 = tcp0->dst_port = s0->in2out.port;
927 
928  sum0 = tcp0->checksum;
929  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
930  dst_address);
931  sum0 = ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
932  length);
933  if (is_twice_nat_session (s0))
934  {
935  sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
936  s0->ext_host_nat_addr.as_u32,
937  ip4_header_t, dst_address);
938  sum0 = ip_csum_update (sum0, tcp0->src_port,
939  s0->ext_host_nat_port, ip4_header_t,
940  length);
941  tcp0->src_port = s0->ext_host_nat_port;
942  ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
943  }
944  tcp0->checksum = ip_csum_fold (sum0);
946  (sm, s0, tcp0, thread_index))
947  goto trace00;
948  }
949  else
950  {
951  udp0->dst_port = s0->in2out.port;
952  if (is_twice_nat_session (s0))
953  {
954  udp0->src_port = s0->ext_host_nat_port;
955  ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
956  }
957  udp0->checksum = 0;
958  }
959 
960  /* Accounting */
963  b0));
964  /* Per-user LRU list maintenance */
965  nat44_session_update_lru (sm, s0, thread_index);
966 
967  trace00:
969  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
970  {
972  vlib_add_trace (vm, node, b0, sizeof (*t));
973  t->is_slow_path = is_slow_path;
974  t->sw_if_index = sw_if_index0;
975  t->next_index = next0;
976  t->session_index = ~0;
977  if (s0)
978  t->session_index = s0 - tsm->sessions;
979  }
980 
981  pkts_processed += next0 != NAT44_ED_OUT2IN_NEXT_DROP;
982 
984  vnet_buffer (b1)->snat.flags = 0;
985  ip1 = vlib_buffer_get_current (b1);
986 
987  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
988  rx_fib_index1 =
990  sw_if_index1);
991 
992  if (PREDICT_FALSE (ip1->ttl == 1))
993  {
994  vnet_buffer (b1)->sw_if_index[VLIB_TX] = (u32) ~ 0;
995  icmp4_error_set_vnet_buffer (b1, ICMP4_time_exceeded,
996  ICMP4_time_exceeded_ttl_exceeded_in_transit,
997  0);
999  goto trace01;
1000  }
1001 
1002  udp1 = ip4_next_header (ip1);
1003  tcp1 = (tcp_header_t *) udp1;
1004  icmp1 = (icmp46_header_t *) udp1;
1005  proto1 = ip_proto_to_snat_proto (ip1->protocol);
1006 
1007  if (is_slow_path)
1008  {
1009  if (PREDICT_FALSE (proto1 == ~0))
1010  {
1011  s1 =
1012  nat44_ed_out2in_unknown_proto (sm, b1, ip1, rx_fib_index1,
1013  thread_index, now, vm,
1014  node);
1015  if (!sm->forwarding_enabled)
1016  {
1017  if (!s1)
1018  next1 = NAT44_ED_OUT2IN_NEXT_DROP;
1019  goto trace01;
1020  }
1021  }
1022 
1023  if (PREDICT_FALSE (proto1 == SNAT_PROTOCOL_ICMP))
1024  {
1025  next1 = icmp_out2in_ed_slow_path
1026  (sm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1, node,
1027  next1, now, thread_index, &s1);
1028  goto trace01;
1029  }
1030  }
1031  else
1032  {
1033  if (PREDICT_FALSE (proto1 == ~0))
1034  {
1036  goto trace01;
1037  }
1038 
1039  if (ip4_is_fragment (ip1))
1040  {
1042  goto trace01;
1043  }
1044 
1045  if (PREDICT_FALSE (proto1 == SNAT_PROTOCOL_ICMP))
1046  {
1048  goto trace01;
1049  }
1050  }
1051 
1052  make_ed_kv (&kv1, &ip1->dst_address, &ip1->src_address,
1053  ip1->protocol, rx_fib_index1, udp1->dst_port,
1054  udp1->src_port);
1055 
1056  if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv1, &value1))
1057  {
1058  if (is_slow_path)
1059  {
1060  /* Try to match static mapping by external address and port,
1061  destination address and port in packet */
1062  e_key1.addr = ip1->dst_address;
1063  e_key1.port = udp1->dst_port;
1064  e_key1.protocol = proto1;
1065  e_key1.fib_index = rx_fib_index1;
1066  if (snat_static_mapping_match (sm, e_key1, &l_key1, 1, 0,
1067  &twice_nat1, &lb_nat1,
1068  &ip1->src_address,
1069  &identity_nat1))
1070  {
1071  /*
1072  * Send DHCP packets to the ipv4 stack, or we won't
1073  * be able to use dhcp client on the outside interface
1074  */
1075  if (PREDICT_FALSE (proto1 == SNAT_PROTOCOL_UDP
1076  && (udp1->dst_port ==
1077  clib_host_to_net_u16
1078  (UDP_DST_PORT_dhcp_to_client))))
1079  {
1080  vnet_feature_next (&next1, b1);
1081  goto trace01;
1082  }
1083 
1084  if (!sm->forwarding_enabled)
1085  {
1086  b1->error =
1087  node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
1088  next1 = NAT44_ED_OUT2IN_NEXT_DROP;
1089  }
1090  else
1091  {
1092  if (next_src_nat (sm, ip1, ip1->protocol,
1093  udp1->src_port, udp1->dst_port,
1094  thread_index, rx_fib_index1))
1095  {
1097  goto trace01;
1098  }
1099  create_bypass_for_fwd (sm, ip1, rx_fib_index1,
1100  thread_index);
1101  }
1102  goto trace01;
1103  }
1104 
1105  if (PREDICT_FALSE (identity_nat1))
1106  goto trace01;
1107 
1108  if ((proto1 == SNAT_PROTOCOL_TCP) && !tcp_is_init (tcp1))
1109  {
1110  b1->error = node->errors[NAT_OUT2IN_ED_ERROR_NON_SYN];
1111  next1 = NAT44_ED_OUT2IN_NEXT_DROP;
1112  goto trace01;
1113  }
1114 
1115  /* Create session initiated by host from external network */
1116  s1 = create_session_for_static_mapping_ed (sm, b1, l_key1,
1117  e_key1, node,
1118  thread_index,
1119  twice_nat1,
1120  lb_nat1, now);
1121 
1122  if (!s1)
1123  {
1124  next1 = NAT44_ED_OUT2IN_NEXT_DROP;
1125  goto trace01;
1126  }
1127  }
1128  else
1129  {
1131  goto trace01;
1132  }
1133  }
1134  else
1135  {
1136  s1 = pool_elt_at_index (tsm->sessions, value1.value);
1137  }
1138 
1139  old_addr1 = ip1->dst_address.as_u32;
1140  new_addr1 = ip1->dst_address.as_u32 = s1->in2out.addr.as_u32;
1141  vnet_buffer (b1)->sw_if_index[VLIB_TX] = s1->in2out.fib_index;
1142 
1143  sum1 = ip1->checksum;
1144  sum1 = ip_csum_update (sum1, old_addr1, new_addr1, ip4_header_t,
1145  dst_address);
1147  sum1 = ip_csum_update (sum1, ip1->src_address.as_u32,
1148  s1->ext_host_nat_addr.as_u32, ip4_header_t,
1149  src_address);
1150  ip1->checksum = ip_csum_fold (sum1);
1151 
1152  if (PREDICT_TRUE (proto1 == SNAT_PROTOCOL_TCP))
1153  {
1154  old_port1 = tcp1->dst_port;
1155  new_port1 = tcp1->dst_port = s1->in2out.port;
1156 
1157  sum1 = tcp1->checksum;
1158  sum1 = ip_csum_update (sum1, old_addr1, new_addr1, ip4_header_t,
1159  dst_address);
1160  sum1 = ip_csum_update (sum1, old_port1, new_port1, ip4_header_t,
1161  length);
1162  if (is_twice_nat_session (s1))
1163  {
1164  sum1 = ip_csum_update (sum1, ip1->src_address.as_u32,
1165  s1->ext_host_nat_addr.as_u32,
1166  ip4_header_t, dst_address);
1167  sum1 = ip_csum_update (sum1, tcp1->src_port,
1168  s1->ext_host_nat_port, ip4_header_t,
1169  length);
1170  tcp1->src_port = s1->ext_host_nat_port;
1171  ip1->src_address.as_u32 = s1->ext_host_nat_addr.as_u32;
1172  }
1173  tcp1->checksum = ip_csum_fold (sum1);
1175  (sm, s1, tcp1, thread_index))
1176  goto trace01;
1177  }
1178  else
1179  {
1180  udp1->dst_port = s1->in2out.port;
1181  if (is_twice_nat_session (s1))
1182  {
1183  udp1->src_port = s1->ext_host_nat_port;
1184  ip1->src_address.as_u32 = s1->ext_host_nat_addr.as_u32;
1185  }
1186  udp1->checksum = 0;
1187  }
1188 
1189  /* Accounting */
1192  b1));
1193  /* Per-user LRU list maintenance */
1194  nat44_session_update_lru (sm, s1, thread_index);
1195 
1196  trace01:
1198  && (b1->flags & VLIB_BUFFER_IS_TRACED)))
1199  {
1201  vlib_add_trace (vm, node, b1, sizeof (*t));
1202  t->is_slow_path = is_slow_path;
1203  t->sw_if_index = sw_if_index1;
1204  t->next_index = next1;
1205  t->session_index = ~0;
1206  if (s1)
1207  t->session_index = s1 - tsm->sessions;
1208  }
1209 
1210  pkts_processed += next1 != NAT44_ED_OUT2IN_NEXT_DROP;
1211 
1212  /* verify speculative enqueues, maybe switch current next frame */
1213  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
1214  to_next, n_left_to_next,
1215  bi0, bi1, next0, next1);
1216  }
1217 
1218  while (n_left_from > 0 && n_left_to_next > 0)
1219  {
1220  u32 bi0;
1221  vlib_buffer_t *b0;
1222  u32 next0, sw_if_index0, rx_fib_index0, proto0, old_addr0,
1223  new_addr0;
1224  u16 old_port0, new_port0;
1225  ip4_header_t *ip0;
1226  udp_header_t *udp0;
1227  tcp_header_t *tcp0;
1228  icmp46_header_t *icmp0;
1229  snat_session_t *s0 = 0;
1230  clib_bihash_kv_16_8_t kv0, value0;
1231  ip_csum_t sum0;
1232  snat_session_key_t e_key0, l_key0;
1233  lb_nat_type_t lb_nat0;
1234  twice_nat_type_t twice_nat0;
1235  u8 identity_nat0;
1236 
1237  /* speculatively enqueue b0 to the current next frame */
1238  bi0 = from[0];
1239  to_next[0] = bi0;
1240  from += 1;
1241  to_next += 1;
1242  n_left_from -= 1;
1243  n_left_to_next -= 1;
1244 
1245  b0 = vlib_get_buffer (vm, bi0);
1247  vnet_buffer (b0)->snat.flags = 0;
1248  ip0 = vlib_buffer_get_current (b0);
1249 
1250  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1251  rx_fib_index0 =
1253  sw_if_index0);
1254 
1255  if (PREDICT_FALSE (ip0->ttl == 1))
1256  {
1257  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1258  icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
1259  ICMP4_time_exceeded_ttl_exceeded_in_transit,
1260  0);
1262  goto trace0;
1263  }
1264 
1265  udp0 = ip4_next_header (ip0);
1266  tcp0 = (tcp_header_t *) udp0;
1267  icmp0 = (icmp46_header_t *) udp0;
1268  proto0 = ip_proto_to_snat_proto (ip0->protocol);
1269 
1270  if (is_slow_path)
1271  {
1272  if (PREDICT_FALSE (proto0 == ~0))
1273  {
1274  s0 =
1275  nat44_ed_out2in_unknown_proto (sm, b0, ip0, rx_fib_index0,
1276  thread_index, now, vm,
1277  node);
1278  if (!sm->forwarding_enabled)
1279  {
1280  if (!s0)
1281  next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1282  goto trace0;
1283  }
1284  }
1285 
1286  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
1287  {
1288  next0 = icmp_out2in_ed_slow_path
1289  (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
1290  next0, now, thread_index, &s0);
1291  goto trace0;
1292  }
1293  }
1294  else
1295  {
1296  if (PREDICT_FALSE (proto0 == ~0))
1297  {
1299  goto trace0;
1300  }
1301 
1302  if (ip4_is_fragment (ip0))
1303  {
1305  goto trace0;
1306  }
1307 
1308  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
1309  {
1311  goto trace0;
1312  }
1313  }
1314 
1315  make_ed_kv (&kv0, &ip0->dst_address, &ip0->src_address,
1316  ip0->protocol, rx_fib_index0, udp0->dst_port,
1317  udp0->src_port);
1318 
1319  if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv0, &value0))
1320  {
1321  if (is_slow_path)
1322  {
1323  /* Try to match static mapping by external address and port,
1324  destination address and port in packet */
1325  e_key0.addr = ip0->dst_address;
1326  e_key0.port = udp0->dst_port;
1327  e_key0.protocol = proto0;
1328  e_key0.fib_index = rx_fib_index0;
1329  if (snat_static_mapping_match (sm, e_key0, &l_key0, 1, 0,
1330  &twice_nat0, &lb_nat0,
1331  &ip0->src_address,
1332  &identity_nat0))
1333  {
1334  /*
1335  * Send DHCP packets to the ipv4 stack, or we won't
1336  * be able to use dhcp client on the outside interface
1337  */
1338  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_UDP
1339  && (udp0->dst_port ==
1340  clib_host_to_net_u16
1341  (UDP_DST_PORT_dhcp_to_client))))
1342  {
1343  vnet_feature_next (&next0, b0);
1344  goto trace0;
1345  }
1346 
1347  if (!sm->forwarding_enabled)
1348  {
1349  b0->error =
1350  node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
1351  next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1352  }
1353  else
1354  {
1355  if (next_src_nat (sm, ip0, ip0->protocol,
1356  udp0->src_port, udp0->dst_port,
1357  thread_index, rx_fib_index0))
1358  {
1360  goto trace0;
1361  }
1362  create_bypass_for_fwd (sm, ip0, rx_fib_index0,
1363  thread_index);
1364  }
1365  goto trace0;
1366  }
1367 
1368  if (PREDICT_FALSE (identity_nat0))
1369  goto trace0;
1370 
1371  if ((proto0 == SNAT_PROTOCOL_TCP) && !tcp_is_init (tcp0))
1372  {
1373  b0->error = node->errors[NAT_OUT2IN_ED_ERROR_NON_SYN];
1374  next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1375  goto trace0;
1376  }
1377 
1378  /* Create session initiated by host from external network */
1379  s0 = create_session_for_static_mapping_ed (sm, b0, l_key0,
1380  e_key0, node,
1381  thread_index,
1382  twice_nat0,
1383  lb_nat0, now);
1384 
1385  if (!s0)
1386  {
1387  next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1388  goto trace0;
1389  }
1390  }
1391  else
1392  {
1394  goto trace0;
1395  }
1396  }
1397  else
1398  {
1399  s0 = pool_elt_at_index (tsm->sessions, value0.value);
1400  }
1401 
1402  old_addr0 = ip0->dst_address.as_u32;
1403  new_addr0 = ip0->dst_address.as_u32 = s0->in2out.addr.as_u32;
1404  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
1405 
1406  sum0 = ip0->checksum;
1407  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1408  dst_address);
1410  sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
1411  s0->ext_host_nat_addr.as_u32, ip4_header_t,
1412  src_address);
1413  ip0->checksum = ip_csum_fold (sum0);
1414 
1415  if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP))
1416  {
1417  old_port0 = tcp0->dst_port;
1418  new_port0 = tcp0->dst_port = s0->in2out.port;
1419 
1420  sum0 = tcp0->checksum;
1421  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1422  dst_address);
1423  sum0 = ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
1424  length);
1425  if (is_twice_nat_session (s0))
1426  {
1427  sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
1428  s0->ext_host_nat_addr.as_u32,
1429  ip4_header_t, dst_address);
1430  sum0 = ip_csum_update (sum0, tcp0->src_port,
1431  s0->ext_host_nat_port, ip4_header_t,
1432  length);
1433  tcp0->src_port = s0->ext_host_nat_port;
1434  ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
1435  }
1436  tcp0->checksum = ip_csum_fold (sum0);
1438  (sm, s0, tcp0, thread_index))
1439  goto trace0;
1440  }
1441  else
1442  {
1443  udp0->dst_port = s0->in2out.port;
1444  if (is_twice_nat_session (s0))
1445  {
1446  udp0->src_port = s0->ext_host_nat_port;
1447  ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
1448  }
1449  udp0->checksum = 0;
1450  }
1451 
1452  /* Accounting */
1455  b0));
1456  /* Per-user LRU list maintenance */
1457  nat44_session_update_lru (sm, s0, thread_index);
1458 
1459  trace0:
1461  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1462  {
1464  vlib_add_trace (vm, node, b0, sizeof (*t));
1465  t->is_slow_path = is_slow_path;
1466  t->sw_if_index = sw_if_index0;
1467  t->next_index = next0;
1468  t->session_index = ~0;
1469  if (s0)
1470  t->session_index = s0 - tsm->sessions;
1471  }
1472 
1473  pkts_processed += next0 != NAT44_ED_OUT2IN_NEXT_DROP;
1474  /* verify speculative enqueue, maybe switch current next frame */
1475  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1476  to_next, n_left_to_next,
1477  bi0, next0);
1478  }
1479 
1480  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1481  }
1482 
1483  vlib_node_increment_counter (vm, stats_node_index,
1484  NAT_OUT2IN_ED_ERROR_OUT2IN_PACKETS,
1485  pkts_processed);
1486  return frame->n_vectors;
1487 }
1488 
1489 static uword
1491  vlib_node_runtime_t * node,
1492  vlib_frame_t * frame)
1493 {
1494  return nat44_ed_out2in_node_fn_inline (vm, node, frame, 0);
1495 }
1496 
1497 /* *INDENT-OFF* */
1499  .function = nat44_ed_out2in_fast_path_fn,
1500  .name = "nat44-ed-out2in",
1501  .vector_size = sizeof (u32),
1502  .format_trace = format_nat44_ed_out2in_trace,
1503  .type = VLIB_NODE_TYPE_INTERNAL,
1505  .error_strings = nat_out2in_ed_error_strings,
1506  .runtime_data_bytes = sizeof (snat_runtime_t),
1507  .n_next_nodes = NAT44_ED_OUT2IN_N_NEXT,
1508  .next_nodes = {
1509  [NAT44_ED_OUT2IN_NEXT_DROP] = "error-drop",
1510  [NAT44_ED_OUT2IN_NEXT_LOOKUP] = "ip4-lookup",
1511  [NAT44_ED_OUT2IN_NEXT_SLOW_PATH] = "nat44-ed-out2in-slowpath",
1512  [NAT44_ED_OUT2IN_NEXT_ICMP_ERROR] = "ip4-icmp-error",
1513  [NAT44_ED_OUT2IN_NEXT_IN2OUT] = "nat44-ed-in2out",
1514  [NAT44_ED_OUT2IN_NEXT_REASS] = "nat44-ed-out2in-reass",
1515  },
1516 };
1517 /* *INDENT-ON* */
1518 
1521 
1522 static uword
1524  vlib_node_runtime_t * node,
1525  vlib_frame_t * frame)
1526 {
1527  return nat44_ed_out2in_node_fn_inline (vm, node, frame, 1);
1528 }
1529 
1530 /* *INDENT-OFF* */
1532  .function = nat44_ed_out2in_slow_path_fn,
1533  .name = "nat44-ed-out2in-slowpath",
1534  .vector_size = sizeof (u32),
1535  .format_trace = format_nat44_ed_out2in_trace,
1536  .type = VLIB_NODE_TYPE_INTERNAL,
1538  .error_strings = nat_out2in_ed_error_strings,
1539  .runtime_data_bytes = sizeof (snat_runtime_t),
1540  .n_next_nodes = NAT44_ED_OUT2IN_N_NEXT,
1541  .next_nodes = {
1542  [NAT44_ED_OUT2IN_NEXT_DROP] = "error-drop",
1543  [NAT44_ED_OUT2IN_NEXT_LOOKUP] = "ip4-lookup",
1544  [NAT44_ED_OUT2IN_NEXT_SLOW_PATH] = "nat44-ed-out2in-slowpath",
1545  [NAT44_ED_OUT2IN_NEXT_ICMP_ERROR] = "ip4-icmp-error",
1546  [NAT44_ED_OUT2IN_NEXT_IN2OUT] = "nat44-ed-in2out",
1547  [NAT44_ED_OUT2IN_NEXT_REASS] = "nat44-ed-out2in-reass",
1548  },
1549 };
1550 /* *INDENT-ON* */
1551 
1554 
1555 static uword
1557  vlib_node_runtime_t * node,
1558  vlib_frame_t * frame)
1559 {
1560  u32 n_left_from, *from, *to_next;
1561  nat44_ed_out2in_next_t next_index;
1562  u32 pkts_processed = 0;
1563  snat_main_t *sm = &snat_main;
1564  f64 now = vlib_time_now (vm);
1565  u32 thread_index = vm->thread_index;
1566  snat_main_per_thread_data_t *per_thread_data =
1567  &sm->per_thread_data[thread_index];
1568  u32 *fragments_to_drop = 0;
1569  u32 *fragments_to_loopback = 0;
1570 
1571  from = vlib_frame_vector_args (frame);
1572  n_left_from = frame->n_vectors;
1573  next_index = node->cached_next_index;
1574 
1575  while (n_left_from > 0)
1576  {
1577  u32 n_left_to_next;
1578 
1579  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1580 
1581  while (n_left_from > 0 && n_left_to_next > 0)
1582  {
1583  u32 bi0, sw_if_index0, proto0, rx_fib_index0, new_addr0, old_addr0;
1584  vlib_buffer_t *b0;
1585  u32 next0;
1586  u8 cached0 = 0;
1587  ip4_header_t *ip0;
1588  nat_reass_ip4_t *reass0;
1589  udp_header_t *udp0;
1590  tcp_header_t *tcp0;
1591  icmp46_header_t *icmp0;
1592  clib_bihash_kv_16_8_t kv0, value0;
1593  snat_session_t *s0 = 0;
1594  u16 old_port0, new_port0;
1595  ip_csum_t sum0;
1596  snat_session_key_t e_key0, l_key0;
1597  lb_nat_type_t lb0;
1598  twice_nat_type_t twice_nat0;
1599  u8 identity_nat0;
1600 
1601  /* speculatively enqueue b0 to the current next frame */
1602  bi0 = from[0];
1603  to_next[0] = bi0;
1604  from += 1;
1605  to_next += 1;
1606  n_left_from -= 1;
1607  n_left_to_next -= 1;
1608 
1609  b0 = vlib_get_buffer (vm, bi0);
1611 
1612  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1613  rx_fib_index0 =
1615  sw_if_index0);
1616 
1618  {
1619  next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1620  b0->error = node->errors[NAT_OUT2IN_ED_ERROR_DROP_FRAGMENT];
1621  goto trace0;
1622  }
1623 
1624  ip0 = (ip4_header_t *) vlib_buffer_get_current (b0);
1625  udp0 = ip4_next_header (ip0);
1626  tcp0 = (tcp_header_t *) udp0;
1627  icmp0 = (icmp46_header_t *) udp0;
1628  proto0 = ip_proto_to_snat_proto (ip0->protocol);
1629 
1631  ip0->dst_address,
1632  ip0->fragment_id,
1633  ip0->protocol,
1634  1, &fragments_to_drop);
1635 
1636  if (PREDICT_FALSE (!reass0))
1637  {
1638  next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1639  b0->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_REASS];
1640  nat_log_notice ("maximum reassemblies exceeded");
1641  goto trace0;
1642  }
1643 
1645  {
1646  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
1647  {
1648  next0 = icmp_out2in_ed_slow_path
1649  (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
1650  next0, now, thread_index, &s0);
1651 
1652  if (PREDICT_TRUE (next0 != NAT44_ED_OUT2IN_NEXT_DROP))
1653  {
1654  if (s0)
1655  reass0->sess_index = s0 - per_thread_data->sessions;
1656  else
1657  reass0->flags |= NAT_REASS_FLAG_ED_DONT_TRANSLATE;
1658  reass0->thread_index = thread_index;
1659  nat_ip4_reass_get_frags (reass0,
1660  &fragments_to_loopback);
1661  }
1662 
1663  goto trace0;
1664  }
1665 
1666  make_ed_kv (&kv0, &ip0->dst_address, &ip0->src_address,
1667  ip0->protocol, rx_fib_index0, udp0->dst_port,
1668  udp0->src_port);
1669 
1670  if (clib_bihash_search_16_8
1671  (&per_thread_data->out2in_ed, &kv0, &value0))
1672  {
1673  /* Try to match static mapping by external address and port,
1674  destination address and port in packet */
1675  e_key0.addr = ip0->dst_address;
1676  e_key0.port = udp0->dst_port;
1677  e_key0.protocol = proto0;
1678  e_key0.fib_index = rx_fib_index0;
1679  if (snat_static_mapping_match (sm, e_key0, &l_key0, 1, 0,
1680  &twice_nat0, &lb0, 0,
1681  &identity_nat0))
1682  {
1683  /*
1684  * Send DHCP packets to the ipv4 stack, or we won't
1685  * be able to use dhcp client on the outside interface
1686  */
1687  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_UDP
1688  && (udp0->dst_port
1689  ==
1690  clib_host_to_net_u16
1691  (UDP_DST_PORT_dhcp_to_client))))
1692  {
1693  vnet_feature_next (&next0, b0);
1694  goto trace0;
1695  }
1696 
1697  if (!sm->forwarding_enabled)
1698  {
1699  b0->error =
1700  node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
1701  next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1702  }
1703  else
1704  {
1705  if (next_src_nat (sm, ip0, ip0->protocol,
1706  udp0->src_port, udp0->dst_port,
1707  thread_index, rx_fib_index0))
1708  {
1710  goto trace0;
1711  }
1712  create_bypass_for_fwd (sm, ip0, rx_fib_index0,
1713  thread_index);
1714  reass0->flags |= NAT_REASS_FLAG_ED_DONT_TRANSLATE;
1715  nat_ip4_reass_get_frags (reass0,
1716  &fragments_to_loopback);
1717  }
1718  goto trace0;
1719  }
1720 
1721  if (PREDICT_FALSE (identity_nat0))
1722  {
1723  reass0->flags |= NAT_REASS_FLAG_ED_DONT_TRANSLATE;
1724  goto trace0;
1725  }
1726 
1727  if ((proto0 == SNAT_PROTOCOL_TCP) && !tcp_is_init (tcp0))
1728  {
1729  b0->error = node->errors[NAT_OUT2IN_ED_ERROR_NON_SYN];
1730  next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1731  goto trace0;
1732  }
1733 
1734  /* Create session initiated by host from external network */
1735  s0 = create_session_for_static_mapping_ed (sm, b0, l_key0,
1736  e_key0, node,
1737  thread_index,
1738  twice_nat0, lb0,
1739  now);
1740  if (!s0)
1741  {
1742  b0->error =
1743  node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
1744  next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1745  goto trace0;
1746  }
1747  reass0->sess_index = s0 - per_thread_data->sessions;
1748  reass0->thread_index = thread_index;
1749  }
1750  else
1751  {
1752  s0 = pool_elt_at_index (per_thread_data->sessions,
1753  value0.value);
1754  reass0->sess_index = value0.value;
1755  }
1756  nat_ip4_reass_get_frags (reass0, &fragments_to_loopback);
1757  }
1758  else
1759  {
1760  if (reass0->flags & NAT_REASS_FLAG_ED_DONT_TRANSLATE)
1761  goto trace0;
1762  if (PREDICT_FALSE (reass0->sess_index == (u32) ~ 0))
1763  {
1765  (reass0, bi0, &fragments_to_drop))
1766  {
1767  b0->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_FRAG];
1769  ("maximum fragments per reassembly exceeded");
1770  next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1771  goto trace0;
1772  }
1773  cached0 = 1;
1774  goto trace0;
1775  }
1776  s0 = pool_elt_at_index (per_thread_data->sessions,
1777  reass0->sess_index);
1778  }
1779 
1780  old_addr0 = ip0->dst_address.as_u32;
1781  ip0->dst_address = s0->in2out.addr;
1782  new_addr0 = ip0->dst_address.as_u32;
1783  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
1784 
1785  sum0 = ip0->checksum;
1786  sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1787  ip4_header_t,
1788  dst_address /* changed member */ );
1790  sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
1791  s0->ext_host_nat_addr.as_u32, ip4_header_t,
1792  src_address);
1793  ip0->checksum = ip_csum_fold (sum0);
1794 
1796  {
1797  if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP))
1798  {
1799  old_port0 = tcp0->dst_port;
1800  tcp0->dst_port = s0->in2out.port;
1801  new_port0 = tcp0->dst_port;
1802 
1803  sum0 = tcp0->checksum;
1804  sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1805  ip4_header_t,
1806  dst_address /* changed member */ );
1807 
1808  sum0 = ip_csum_update (sum0, old_port0, new_port0,
1809  ip4_header_t /* cheat */ ,
1810  length /* changed member */ );
1811  if (is_twice_nat_session (s0))
1812  {
1813  sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
1814  s0->ext_host_nat_addr.as_u32,
1815  ip4_header_t, dst_address);
1816  sum0 = ip_csum_update (sum0, tcp0->src_port,
1817  s0->ext_host_nat_port,
1818  ip4_header_t, length);
1819  tcp0->src_port = s0->ext_host_nat_port;
1820  ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
1821  }
1822  tcp0->checksum = ip_csum_fold (sum0);
1823  }
1824  else
1825  {
1826  old_port0 = udp0->dst_port;
1827  udp0->dst_port = s0->in2out.port;
1828  if (is_twice_nat_session (s0))
1829  {
1830  udp0->src_port = s0->ext_host_nat_port;
1831  ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
1832  }
1833  udp0->checksum = 0;
1834  }
1835  }
1836 
1837  /* Accounting */
1840  b0));
1841  /* Per-user LRU list maintenance */
1842  nat44_session_update_lru (sm, s0, thread_index);
1843 
1844  trace0:
1846  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1847  {
1848  nat44_reass_trace_t *t =
1849  vlib_add_trace (vm, node, b0, sizeof (*t));
1850  t->cached = cached0;
1851  t->sw_if_index = sw_if_index0;
1852  t->next_index = next0;
1853  }
1854 
1855  if (cached0)
1856  {
1857  n_left_to_next++;
1858  to_next--;
1859  }
1860  else
1861  {
1862  pkts_processed += next0 != NAT44_ED_OUT2IN_NEXT_DROP;
1863 
1864  /* verify speculative enqueue, maybe switch current next frame */
1865  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1866  to_next, n_left_to_next,
1867  bi0, next0);
1868  }
1869 
1870  if (n_left_from == 0 && vec_len (fragments_to_loopback))
1871  {
1872  from = vlib_frame_vector_args (frame);
1873  u32 len = vec_len (fragments_to_loopback);
1874  if (len <= VLIB_FRAME_SIZE)
1875  {
1876  clib_memcpy (from, fragments_to_loopback,
1877  sizeof (u32) * len);
1878  n_left_from = len;
1879  vec_reset_length (fragments_to_loopback);
1880  }
1881  else
1882  {
1883  clib_memcpy (from,
1884  fragments_to_loopback + (len -
1885  VLIB_FRAME_SIZE),
1886  sizeof (u32) * VLIB_FRAME_SIZE);
1887  n_left_from = VLIB_FRAME_SIZE;
1888  _vec_len (fragments_to_loopback) = len - VLIB_FRAME_SIZE;
1889  }
1890  }
1891  }
1892 
1893  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1894  }
1895 
1897  NAT_OUT2IN_ED_ERROR_OUT2IN_PACKETS,
1898  pkts_processed);
1899 
1900  nat_send_all_to_node (vm, fragments_to_drop, node,
1901  &node->errors[NAT_OUT2IN_ED_ERROR_DROP_FRAGMENT],
1903 
1904  vec_free (fragments_to_drop);
1905  vec_free (fragments_to_loopback);
1906  return frame->n_vectors;
1907 }
1908 
1909 /* *INDENT-OFF* */
1911  .function = nat44_ed_out2in_reass_node_fn,
1912  .name = "nat44-ed-out2in-reass",
1913  .vector_size = sizeof (u32),
1914  .format_trace = format_nat44_reass_trace,
1915  .type = VLIB_NODE_TYPE_INTERNAL,
1917  .error_strings = nat_out2in_ed_error_strings,
1918  .n_next_nodes = NAT44_ED_OUT2IN_N_NEXT,
1919  .next_nodes = {
1920  [NAT44_ED_OUT2IN_NEXT_DROP] = "error-drop",
1921  [NAT44_ED_OUT2IN_NEXT_LOOKUP] = "ip4-lookup",
1922  [NAT44_ED_OUT2IN_NEXT_SLOW_PATH] = "nat44-ed-out2in-slowpath",
1923  [NAT44_ED_OUT2IN_NEXT_ICMP_ERROR] = "ip4-icmp-error",
1924  [NAT44_ED_OUT2IN_NEXT_IN2OUT] = "nat44-ed-in2out",
1925  [NAT44_ED_OUT2IN_NEXT_REASS] = "nat44-ed-out2in-reass",
1926  },
1927 };
1928 /* *INDENT-ON* */
1929 
1932 
1933 /*
1934  * fd.io coding-style-patch-verification: ON
1935  *
1936  * Local Variables:
1937  * eval: (c-set-style "gnu")
1938  * End:
1939  */
#define snat_is_session_static(s)
Check if SNAT session is created from static mapping.
Definition: nat.h:598
#define CLIB_UNUSED(x)
Definition: clib.h:81
u32 icmp_out2in(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: out2in.c:484
static int next_src_nat(snat_main_t *sm, ip4_header_t *ip, u8 proto, u16 src_port, u16 dst_port, u32 thread_index, u32 rx_fib_index)
Definition: out2in_ed.c:359
#define foreach_nat_out2in_ed_error
Definition: out2in_ed.c:33
a
Definition: bitmap.h:538
ip4_address_t src_address
Definition: ip4_packet.h:169
static u32 nat44_session_get_timeout(snat_main_t *sm, snat_session_t *s)
Definition: nat_inlines.h:269
#define PREDICT_TRUE(x)
Definition: clib.h:108
static_always_inline u8 icmp_is_error_message(icmp46_header_t *icmp)
Definition: nat_inlines.h:53
unsigned long u64
Definition: types.h:89
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:227
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:328
u16 port_per_thread
Definition: nat.h:439
u32 thread_index
Definition: main.h:179
#define nat_log_warn(...)
Definition: nat.h:687
int i
uword ip_csum_t
Definition: ip_packet.h:181
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
vlib_node_registration_t nat44_ed_out2in_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_out2in_node)
Definition: out2in_ed.c:78
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:472
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:263
struct _tcp_header tcp_header_t
#define snat_is_unk_proto_session(s)
Check if SNAT session for unknown protocol.
Definition: nat.h:604
u32 proto
Definition: nat.h:69
unsigned char u8
Definition: types.h:56
static int nat44_set_tcp_session_state_o2i(snat_main_t *sm, snat_session_t *ses, tcp_header_t *tcp, u32 thread_index)
Definition: nat_inlines.h:235
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:212
u16 src_port
Definition: udp.api:41
static u32 icmp_out2in_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: out2in_ed.c:101
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:682
#define static_always_inline
Definition: clib.h:95
static char * nat_out2in_ed_error_strings[]
Definition: out2in_ed.c:53
u16 r_port
Definition: nat.h:71
u32 sw_if_index
Definition: vxlan_gbp.api:39
ip4_address_t dst_address
Definition: ip4_packet.h:169
static uword nat44_ed_out2in_fast_path_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: out2in_ed.c:1490
lb_nat_type_t
Definition: nat.h:312
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:187
static_always_inline int icmp_get_ed_key(ip4_header_t *ip0, nat_ed_ses_key_t *p_key0)
Definition: out2in_ed.c:310
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
#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:240
unsigned int u32
Definition: types.h:88
ip4_address_t local_addr
Definition: nat.h:325
#define VLIB_FRAME_SIZE
Definition: node.h:382
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:2070
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:2032
static void nat44_delete_session(snat_main_t *sm, snat_session_t *ses, u32 thread_index)
Definition: nat_inlines.h:166
int nat44_o2i_ed_is_idle_session_cb(clib_bihash_kv_16_8_t *kv, void *arg)
Definition: out2in_ed.c:123
VLIB_NODE_FUNCTION_MULTIARCH(nat44_ed_out2in_node, nat44_ed_out2in_fast_path_fn)
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:2204
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:278
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:464
clib_bihash_16_8_t out2in_ed
Definition: nat.h:383
long ctx[MAX_CONNS]
Definition: main.c:144
vlib_main_t * vlib_main
Definition: nat.h:539
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:391
snat_static_mapping_t * static_mappings
Definition: nat.h:452
u32 inside_fib_index
Definition: nat.h:520
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:205
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.
#define PREDICT_FALSE(x)
Definition: clib.h:107
clib_bihash_8_8_t static_mapping_by_external
Definition: nat.h:449
vl_api_address_union_t src_address
Definition: ip_types.api:49
static void create_bypass_for_fwd(snat_main_t *sm, ip4_header_t *ip, u32 rx_fib_index, u32 thread_index)
Definition: out2in_ed.c:374
#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:364
#define nat_log_notice(...)
Definition: nat.h:689
vlib_node_registration_t nat44_ed_out2in_reass_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_out2in_reass_node)
Definition: out2in_ed.c:80
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:138
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1176
snat_main_t snat_main
Definition: nat.c:37
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:155
static u8 snat_proto_to_ip_proto(snat_protocol_t snat_proto)
Definition: nat_inlines.h:41
u16 n_vectors
Definition: node.h:401
nat_out2in_ed_error_t
Definition: out2in_ed.c:45
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
vlib_main_t * vm
Definition: buffer.c:294
ip4_address_t l_addr
Definition: nat.h:67
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:339
static_always_inline void vnet_feature_next(u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:246
void icmp4_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
Definition: icmp4.c:431
static u8 * format_nat44_ed_out2in_trace(u8 *s, va_list *args)
Definition: out2in_ed.c:83
static uword nat44_ed_out2in_node_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_slow_path)
Definition: out2in_ed.c:684
#define clib_memcpy(a, b, c)
Definition: string.h:75
static void nat44_session_update_counters(snat_session_t *s, f64 now, uword bytes)
Definition: nat_inlines.h:292
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:31
#define ARRAY_LEN(x)
Definition: clib.h:61
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:455
static uword nat44_ed_out2in_reass_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: out2in_ed.c:1556
vlib_node_registration_t nat44_ed_out2in_slowpath_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_out2in_slowpath_node)
Definition: out2in_ed.c:79
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:311
static snat_session_t * nat44_ed_out2in_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: out2in_ed.c:580
ip4_address_t r_addr
Definition: nat.h:68
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:513
Definition: nat.h:307
#define SNAT_SESSION_FLAG_TWICE_NAT
Definition: nat.h:174
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:301
static snat_session_t * create_session_for_static_mapping_ed(snat_main_t *sm, vlib_buffer_t *b, snat_session_key_t l_key, snat_session_key_t e_key, vlib_node_runtime_t *node, u32 thread_index, twice_nat_type_t twice_nat, lb_nat_type_t lb_nat, f64 now)
Definition: out2in_ed.c:207
#define SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT
Definition: nat.h:175
ip4_address_t addr
Definition: nat.h:240
snat_address_t * twice_nat_addresses
Definition: nat.h:476
static uword nat44_ed_out2in_slow_path_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: out2in_ed.c:1523
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
struct _vlib_node_registration vlib_node_registration_t
nat44_ed_out2in_next_t
Definition: out2in_ed.c:59
Definition: defs.h:47
format_function_t format_nat44_reass_trace
Definition: nat.h:590
static int ip4_is_first_fragment(const ip4_header_t *i)
Definition: ip4_packet.h:219
#define SNAT_SESSION_FLAG_FWD_BYPASS
Definition: nat.h:176
static u32 ip_proto_to_snat_proto(u8 ip_proto)
The NAT inline functions.
Definition: nat_inlines.h:26
int nat44_i2o_ed_is_idle_session_cb(clib_bihash_kv_16_8_t *kv, void *arg)
Definition: in2out_ed.c:149
static void user_session_increment(snat_main_t *sm, snat_user_t *u, u8 is_static)
Definition: nat_inlines.h:134
u32 icmp_match_out2in_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: out2in_ed.c:464
twice_nat_type_t
Definition: nat.h:302
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
#define SNAT_SESSION_FLAG_AFFINITY
Definition: nat.h:177
u64 uword
Definition: types.h:112
snat_main_per_thread_data_t * per_thread_data
Definition: nat.h:443
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:267
#define ip_csum_update(sum, old, new, type, field)
Definition: ip_packet.h:231
static u8 is_interface_addr(snat_main_t *sm, vlib_node_runtime_t *node, u32 sw_if_index0, u32 ip4_addr)
Definition: nat_inlines.h:69
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:459
#define vnet_buffer(b)
Definition: buffer.h:344
#define SNAT_SESSION_FLAG_STATIC_MAPPING
Definition: nat.h:171
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:175
u8 forwarding_enabled
Definition: nat.h:503
u16 flags
Copy of main node flags.
Definition: node.h:507
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:610
clib_bihash_16_8_t in2out_ed
Definition: nat.h:384
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:310
#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:116
snat_session_t * sessions
Definition: nat.h:393
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:58
#define SNAT_SESSION_FLAG_LOAD_BALANCING
Definition: nat.h:173
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:237
Definition: defs.h:46
u16 fib_index
Definition: nat.h:54