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