FD.io VPP  v20.05.1-5-g09f167997
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_inlines.h>
31 #include <nat/nat44/inlines.h>
32 #include <nat/nat_syslog.h>
33 #include <nat/nat_ha.h>
34 #include <nat/nat44/ed_inlines.h>
35 
36 static char *nat_out2in_ed_error_strings[] = {
37 #define _(sym,string) string,
39 #undef _
40 };
41 
42 typedef struct
43 {
49 
50 static u8 *
51 format_nat44_ed_out2in_trace (u8 * s, va_list * args)
52 {
53  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
54  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
55  nat44_ed_out2in_trace_t *t = va_arg (*args, nat44_ed_out2in_trace_t *);
56  char *tag;
57 
58  tag =
59  t->is_slow_path ? "NAT44_OUT2IN_ED_SLOW_PATH" :
60  "NAT44_OUT2IN_ED_FAST_PATH";
61 
62  s = format (s, "%s: sw_if_index %d, next index %d, session %d", tag,
64 
65  return s;
66 }
67 
68 static inline u32
70  ip4_header_t * ip0, icmp46_header_t * icmp0,
71  u32 sw_if_index0, u32 rx_fib_index0,
72  vlib_node_runtime_t * node, u32 next0, f64 now,
73  u32 thread_index, snat_session_t ** p_s0)
74 {
75  vlib_main_t *vm = vlib_get_main ();
76 
77  next0 = icmp_out2in (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
78  next0, thread_index, p_s0, 0);
79  snat_session_t *s0 = *p_s0;
80  if (PREDICT_TRUE (next0 != NAT_NEXT_DROP && s0))
81  {
82  /* Accounting */
85  (vm, b0), thread_index);
86  /* Per-user LRU list maintenance */
87  nat44_session_update_lru (sm, s0, thread_index);
88  }
89  return next0;
90 }
91 
92 #ifndef CLIB_MARCH_VARIANT
93 int
95 {
96  snat_main_t *sm = &snat_main;
98  snat_session_t *s;
99  u64 sess_timeout_time;
100  u8 proto;
101  u16 r_port, l_port;
102  ip4_address_t *l_addr, *r_addr;
103  u32 fib_index;
104  clib_bihash_kv_16_8_t ed_kv;
105  int i;
106  snat_address_t *a;
109  ctx->thread_index);
110 
111  s = pool_elt_at_index (tsm->sessions, kv->value);
112  sess_timeout_time = s->last_heard + (f64) nat44_session_get_timeout (sm, s);
113  if (ctx->now >= sess_timeout_time)
114  {
115  l_addr = &s->in2out.addr;
116  r_addr = &s->ext_host_addr;
117  fib_index = s->in2out.fib_index;
119  {
120  proto = s->in2out.port;
121  r_port = 0;
122  l_port = 0;
123  }
124  else
125  {
126  proto = nat_proto_to_ip_proto (s->in2out.protocol);
127  l_port = s->in2out.port;
128  r_port = s->ext_host_port;
129  }
130  if (is_twice_nat_session (s))
131  {
132  r_addr = &s->ext_host_nat_addr;
133  r_port = s->ext_host_nat_port;
134  }
135  make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL,
136  &ed_kv);
137  if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0))
138  nat_elog_warn ("in2out_ed key del failed");
139 
141  goto delete;
142 
144  s->in2out.addr.as_u32,
145  s->out2in.addr.as_u32,
146  s->in2out.protocol,
147  s->in2out.port,
148  s->out2in.port,
149  s->in2out.fib_index);
150 
151  nat_syslog_nat44_sdel (s->user_index, s->in2out.fib_index,
152  &s->in2out.addr, s->in2out.port,
153  &s->ext_host_nat_addr, s->ext_host_nat_port,
154  &s->out2in.addr, s->out2in.port,
155  &s->ext_host_addr, s->ext_host_port,
156  s->in2out.protocol, is_twice_nat_session (s));
157 
158  nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
159  s->ext_host_port, s->out2in.protocol, s->out2in.fib_index,
160  ctx->thread_index);
161 
162  if (is_twice_nat_session (s))
163  {
164  for (i = 0; i < vec_len (sm->twice_nat_addresses); i++)
165  {
166  key.protocol = s->in2out.protocol;
167  key.port = s->ext_host_nat_port;
168  a = sm->twice_nat_addresses + i;
169  if (a->addr.as_u32 == s->ext_host_nat_addr.as_u32)
170  {
172  ctx->thread_index,
173  &key);
174  break;
175  }
176  }
177  }
178 
179  if (snat_is_session_static (s))
180  goto delete;
181 
183  &s->out2in);
184  delete:
185  nat_ed_session_delete (sm, s, ctx->thread_index, 1);
186  return 1;
187  }
188 
189  return 0;
190 }
191 #endif
192 
193 static snat_session_t *
195  vlib_buffer_t * b,
196  snat_session_key_t l_key,
197  snat_session_key_t e_key,
199  u32 rx_fib_index,
200  u32 thread_index,
201  twice_nat_type_t twice_nat,
202  lb_nat_type_t lb_nat, f64 now)
203 {
204  snat_session_t *s;
205  ip4_header_t *ip;
206  udp_header_t *udp;
207  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
209  snat_session_key_t eh_key;
211 
212  if (PREDICT_FALSE
213  (nat44_ed_maximum_sessions_exceeded (sm, rx_fib_index, thread_index)))
214  {
215  b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_SESSIONS_EXCEEDED];
216  nat_elog_notice ("maximum sessions exceeded");
217  return 0;
218  }
219 
220  s = nat_ed_session_alloc (sm, thread_index, now, e_key.protocol);
221  if (!s)
222  {
223  b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_USER_SESS_EXCEEDED];
224  nat_elog_warn ("create NAT session failed");
225  return 0;
226  }
227 
228  ip = vlib_buffer_get_current (b);
229  udp = ip4_next_header (ip);
230 
231  s->ext_host_addr.as_u32 = ip->src_address.as_u32;
232  s->ext_host_port = e_key.protocol == NAT_PROTOCOL_ICMP ? 0 : udp->src_port;
234  if (lb_nat)
236  if (lb_nat == AFFINITY_LB_NAT)
237  s->flags |= SNAT_SESSION_FLAG_AFFINITY;
239  s->out2in = e_key;
240  s->in2out = l_key;
241  s->in2out.protocol = s->out2in.protocol;
242 
243  /* Add to lookup tables */
244  make_ed_kv (&e_key.addr, &s->ext_host_addr, ip->protocol,
245  e_key.fib_index, e_key.port, s->ext_host_port,
246  s - tsm->sessions, &kv);
247  ctx.now = now;
248  ctx.thread_index = thread_index;
249  if (clib_bihash_add_or_overwrite_stale_16_8 (&tsm->out2in_ed, &kv,
251  &ctx))
252  nat_elog_notice ("out2in-ed key add failed");
253 
254  if (twice_nat == TWICE_NAT || (twice_nat == TWICE_NAT_SELF &&
255  ip->src_address.as_u32 == l_key.addr.as_u32))
256  {
257  eh_key.protocol = e_key.protocol;
259  thread_index, &eh_key,
260  sm->port_per_thread,
261  tsm->snat_thread_index))
262  {
263  b->error = node->errors[NAT_OUT2IN_ED_ERROR_OUT_OF_PORTS];
264  nat_ed_session_delete (sm, s, thread_index, 1);
265  if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &kv, 0))
266  nat_elog_notice ("out2in-ed key del failed");
267  return 0;
268  }
269  s->ext_host_nat_addr.as_u32 = eh_key.addr.as_u32;
270  s->ext_host_nat_port = eh_key.port;
271  s->flags |= SNAT_SESSION_FLAG_TWICE_NAT;
272  make_ed_kv (&l_key.addr, &s->ext_host_nat_addr, ip->protocol,
273  l_key.fib_index, l_key.port, s->ext_host_nat_port,
274  s - tsm->sessions, &kv);
275  }
276  else
277  {
278  make_ed_kv (&l_key.addr, &s->ext_host_addr, ip->protocol,
279  l_key.fib_index, l_key.port, s->ext_host_port,
280  s - tsm->sessions, &kv);
281  }
282  if (clib_bihash_add_or_overwrite_stale_16_8 (&tsm->in2out_ed, &kv,
284  &ctx))
285  nat_elog_notice ("in2out-ed key add failed");
286 
288  s->in2out.addr.as_u32,
289  s->out2in.addr.as_u32,
290  s->in2out.protocol,
291  s->in2out.port,
292  s->out2in.port, s->in2out.fib_index);
293 
294  nat_syslog_nat44_sadd (s->user_index, s->in2out.fib_index,
295  &s->in2out.addr, s->in2out.port,
296  &s->ext_host_nat_addr, s->ext_host_nat_port,
297  &s->out2in.addr, s->out2in.port,
298  &s->ext_host_addr, s->ext_host_port,
299  s->in2out.protocol, is_twice_nat_session (s));
300 
301  nat_ha_sadd (&s->in2out.addr, s->in2out.port, &s->out2in.addr,
302  s->out2in.port, &s->ext_host_addr, s->ext_host_port,
303  &s->ext_host_nat_addr, s->ext_host_nat_port,
304  s->in2out.protocol, s->in2out.fib_index, s->flags,
305  thread_index, 0);
306 
307  return s;
308 }
309 
310 static int
312  u16 dst_port, u32 thread_index, u32 rx_fib_index)
313 {
315  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
316 
317  make_ed_kv (&ip->src_address, &ip->dst_address, ip->protocol,
318  rx_fib_index, src_port, dst_port, ~0ULL, &kv);
319  if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
320  return 1;
321 
322  return 0;
323 }
324 
325 static void
327  u32 rx_fib_index, u32 thread_index)
328 {
330  udp_header_t *udp;
331  snat_session_t *s = 0;
332  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
333  vlib_main_t *vm = vlib_get_main ();
334  f64 now = vlib_time_now (vm);
335  u16 l_port, r_port;
336 
337  if (ip->protocol == IP_PROTOCOL_ICMP)
338  {
340  (b, ip, rx_fib_index, ~0ULL, 0, &l_port, &r_port, &kv))
341  return;
342  }
343  else
344  {
345  if (ip->protocol == IP_PROTOCOL_UDP || ip->protocol == IP_PROTOCOL_TCP)
346  {
347  udp = ip4_next_header (ip);
348  l_port = udp->dst_port;
349  r_port = udp->src_port;
350  }
351  else
352  {
353  l_port = 0;
354  r_port = 0;
355  }
356  make_ed_kv (&ip->dst_address, &ip->src_address, ip->protocol,
357  rx_fib_index, l_port, r_port, ~0ULL, &kv);
358  }
359 
360  if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
361  {
362  s = pool_elt_at_index (tsm->sessions, value.value);
363  }
364  else
365  {
366  u32 proto;
367 
368  if (PREDICT_FALSE
370  (sm, rx_fib_index, thread_index)))
371  return;
372 
373  s = nat_ed_session_alloc (sm, thread_index, now, ip->protocol);
374  if (!s)
375  {
376  nat_elog_warn ("create NAT session failed");
377  return;
378  }
379 
380  proto = ip_proto_to_nat_proto (ip->protocol);
381 
382  s->ext_host_addr = ip->src_address;
383  s->ext_host_port = r_port;
384  s->flags |= SNAT_SESSION_FLAG_FWD_BYPASS;
385  s->out2in.addr = ip->dst_address;
386  s->out2in.port = l_port;
387  s->out2in.protocol = proto;
388  if (proto == NAT_PROTOCOL_OTHER)
389  {
391  s->out2in.port = ip->protocol;
392  }
393  s->out2in.fib_index = 0;
394  s->in2out = s->out2in;
395 
396  kv.value = s - tsm->sessions;
397  if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &kv, 1))
398  nat_elog_notice ("in2out_ed key add failed");
399  }
400 
401  if (ip->protocol == IP_PROTOCOL_TCP)
402  {
403  tcp_header_t *tcp = ip4_next_header (ip);
405  (sm, now, s, tcp->flags, tcp->ack_number, tcp->seq_number,
406  thread_index))
407  return;
408  }
409 
410  /* Accounting */
411  nat44_session_update_counters (s, now, 0, thread_index);
412  /* Per-user LRU list maintenance */
413  nat44_session_update_lru (sm, s, thread_index);
414 }
415 
416 static inline void
418  ip4_header_t * ip, u32 rx_fib_index)
419 {
420  ip4_header_t ip_wkr = {
421  .src_address = ip->dst_address,
422  };
423  u32 thread_index = sm->worker_in2out_cb (&ip_wkr, rx_fib_index, 0);
424 
425  create_bypass_for_fwd (sm, b, ip, rx_fib_index, thread_index);
426 }
427 
428 #ifndef CLIB_MARCH_VARIANT
429 u32
431  u32 thread_index, vlib_buffer_t * b, ip4_header_t * ip,
432  u8 * p_proto, snat_session_key_t * p_value,
433  u8 * p_dont_translate, void *d, void *e)
434 {
435  u32 next = ~0, sw_if_index, rx_fib_index;
437  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
438  snat_session_t *s = 0;
439  u8 dont_translate = 0, is_addr_only, identity_nat;
440  snat_session_key_t e_key, l_key;
441  u16 l_port, r_port;
442  vlib_main_t *vm = vlib_get_main ();
443 
444  sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
446 
448  (b, ip, rx_fib_index, ~0ULL, p_proto, &l_port, &r_port, &kv))
449  {
450  b->error = node->errors[NAT_OUT2IN_ED_ERROR_UNSUPPORTED_PROTOCOL];
451  next = NAT_NEXT_DROP;
452  goto out;
453  }
454 
455  if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
456  {
457  /* Try to match static mapping */
458  e_key.addr = ip->dst_address;
459  e_key.port = l_port;
461  e_key.fib_index = rx_fib_index;
463  (sm, e_key, &l_key, 1, &is_addr_only, 0, 0, 0, &identity_nat))
464  {
465  if (!sm->forwarding_enabled)
466  {
467  /* Don't NAT packet aimed at the intfc address */
469  ip->dst_address.as_u32)))
470  {
471  dont_translate = 1;
472  goto out;
473  }
474  b->error = node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
475  next = NAT_NEXT_DROP;
476  goto out;
477  }
478  else
479  {
480  dont_translate = 1;
481  if (next_src_nat (sm, ip, l_port, r_port,
482  thread_index, rx_fib_index))
483  {
485  goto out;
486  }
487  if (sm->num_workers > 1)
488  create_bypass_for_fwd_worker (sm, b, ip, rx_fib_index);
489  else
490  create_bypass_for_fwd (sm, b, ip, rx_fib_index, thread_index);
491  goto out;
492  }
493  }
494 
495  if (PREDICT_FALSE
496  (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags !=
497  ICMP4_echo_reply
498  && (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags !=
499  ICMP4_echo_request || !is_addr_only)))
500  {
501  b->error = node->errors[NAT_OUT2IN_ED_ERROR_BAD_ICMP_TYPE];
502  next = NAT_NEXT_DROP;
503  goto out;
504  }
505 
506  if (PREDICT_FALSE (identity_nat))
507  {
508  dont_translate = 1;
509  goto out;
510  }
511 
512  /* Create session initiated by host from external network */
513  s = create_session_for_static_mapping_ed (sm, b, l_key, e_key, node,
514  rx_fib_index, thread_index, 0,
515  0, vlib_time_now (vm));
516 
517  if (!s)
518  {
519  next = NAT_NEXT_DROP;
520  goto out;
521  }
522  }
523  else
524  {
525  if (PREDICT_FALSE
526  (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags !=
527  ICMP4_echo_reply
528  && vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags !=
529  ICMP4_echo_request
531  reass.icmp_type_or_tcp_flags)))
532  {
533  b->error = node->errors[NAT_OUT2IN_ED_ERROR_BAD_ICMP_TYPE];
534  next = NAT_NEXT_DROP;
535  goto out;
536  }
537 
538  s = pool_elt_at_index (tsm->sessions, value.value);
539  }
540 out:
541  if (s)
542  *p_value = s->in2out;
543  *p_dont_translate = dont_translate;
544  if (d)
545  *(snat_session_t **) d = s;
546  return next;
547 }
548 #endif
549 
550 static snat_session_t *
552  vlib_buffer_t * b,
553  ip4_header_t * ip,
554  u32 rx_fib_index,
555  u32 thread_index,
556  f64 now,
558 {
560  clib_bihash_kv_16_8_t s_kv, s_value;
562  u32 old_addr, new_addr;
563  ip_csum_t sum;
564  snat_session_t *s;
565  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
566 
567  old_addr = ip->dst_address.as_u32;
568 
569  make_ed_kv (&ip->dst_address, &ip->src_address, ip->protocol, rx_fib_index,
570  0, 0, ~0ULL, &s_kv);
571 
572  if (!clib_bihash_search_16_8 (&tsm->out2in_ed, &s_kv, &s_value))
573  {
574  s = pool_elt_at_index (tsm->sessions, s_value.value);
575  new_addr = ip->dst_address.as_u32 = s->in2out.addr.as_u32;
576  }
577  else
578  {
579  if (PREDICT_FALSE
581  (sm, rx_fib_index, thread_index)))
582  {
583  b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_SESSIONS_EXCEEDED];
584  nat_elog_notice ("maximum sessions exceeded");
585  return 0;
586  }
587 
588  make_sm_kv (&kv, &ip->dst_address, 0, 0, 0);
589  if (clib_bihash_search_8_8
590  (&sm->static_mapping_by_external, &kv, &value))
591  {
592  b->error = node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
593  return 0;
594  }
595 
596  m = pool_elt_at_index (sm->static_mappings, value.value);
597 
598  new_addr = ip->dst_address.as_u32 = m->local_addr.as_u32;
599 
600  /* Create a new session */
601  s = nat_ed_session_alloc (sm, thread_index, now, ip->protocol);
602  if (!s)
603  {
604  b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_USER_SESS_EXCEEDED];
605  nat_elog_warn ("create NAT session failed");
606  return 0;
607  }
608 
609  s->ext_host_addr.as_u32 = ip->src_address.as_u32;
613  s->out2in.addr.as_u32 = old_addr;
614  s->out2in.fib_index = rx_fib_index;
615  s->in2out.addr.as_u32 = new_addr;
616  s->in2out.fib_index = m->fib_index;
617  s->in2out.port = s->out2in.port = ip->protocol;
618 
619  /* Add to lookup tables */
620  s_kv.value = s - tsm->sessions;
621  if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &s_kv, 1))
622  nat_elog_notice ("out2in key add failed");
623 
624  make_ed_kv (&ip->dst_address, &ip->src_address, ip->protocol,
625  m->fib_index, 0, 0, s - tsm->sessions, &s_kv);
626  if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &s_kv, 1))
627  nat_elog_notice ("in2out key add failed");
628  }
629 
630  /* Update IP checksum */
631  sum = ip->checksum;
632  sum = ip_csum_update (sum, old_addr, new_addr, ip4_header_t, dst_address);
633  ip->checksum = ip_csum_fold (sum);
634 
635  vnet_buffer (b)->sw_if_index[VLIB_TX] = s->in2out.fib_index;
636 
637  /* Accounting */
639  thread_index);
640  /* Per-user LRU list maintenance */
641  nat44_session_update_lru (sm, s, thread_index);
642 
643  return s;
644 }
645 
646 static inline uword
650 {
651  u32 n_left_from, *from, *to_next, pkts_processed = 0, stats_node_index;
652  nat_next_t next_index;
653  snat_main_t *sm = &snat_main;
654  f64 now = vlib_time_now (vm);
655  u32 thread_index = vm->thread_index;
656  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
657  u32 tcp_packets = 0, udp_packets = 0, icmp_packets = 0, other_packets =
658  0, fragments = 0;
659 
660  stats_node_index = sm->ed_out2in_node_index;
661 
662  from = vlib_frame_vector_args (frame);
663  n_left_from = frame->n_vectors;
664  next_index = node->cached_next_index;
665 
666  while (n_left_from > 0)
667  {
668  u32 n_left_to_next;
669 
670  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
671 
672  while (n_left_from > 0 && n_left_to_next > 0)
673  {
674  u32 bi0;
675  vlib_buffer_t *b0;
676  u32 next0, sw_if_index0, rx_fib_index0, proto0, old_addr0,
677  new_addr0;
678  u16 old_port0, new_port0;
679  ip4_header_t *ip0;
680  udp_header_t *udp0;
681  tcp_header_t *tcp0;
682  snat_session_t *s0 = 0;
683  clib_bihash_kv_16_8_t kv0, value0;
684  ip_csum_t sum0;
685 
686  /* speculatively enqueue b0 to the current next frame */
687  bi0 = from[0];
688  to_next[0] = bi0;
689  from += 1;
690  to_next += 1;
691  n_left_from -= 1;
692  n_left_to_next -= 1;
693 
694  b0 = vlib_get_buffer (vm, bi0);
695  next0 = vnet_buffer2 (b0)->nat.arc_next;
696 
697  vnet_buffer (b0)->snat.flags = 0;
698  ip0 = vlib_buffer_get_current (b0);
699 
700  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
701  rx_fib_index0 =
703  sw_if_index0);
704 
705  if (PREDICT_FALSE (ip0->ttl == 1))
706  {
707  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
708  icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
709  ICMP4_time_exceeded_ttl_exceeded_in_transit,
710  0);
711  next0 = NAT_NEXT_ICMP_ERROR;
712  goto trace0;
713  }
714 
715  udp0 = ip4_next_header (ip0);
716  tcp0 = (tcp_header_t *) udp0;
717  proto0 = ip_proto_to_nat_proto (ip0->protocol);
718 
719  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_OTHER))
720  {
722  goto trace0;
723  }
724 
725  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP))
726  {
728  goto trace0;
729  }
730 
731  make_ed_kv (&ip0->dst_address, &ip0->src_address,
732  ip0->protocol, rx_fib_index0,
733  vnet_buffer (b0)->ip.reass.l4_dst_port,
734  vnet_buffer (b0)->ip.reass.l4_src_port, ~0ULL, &kv0);
735 
736  if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv0, &value0))
737  {
739  goto trace0;
740  }
741  s0 = pool_elt_at_index (tsm->sessions, value0.value);
742 
743  if (s0->tcp_closed_timestamp)
744  {
745  if (now >= s0->tcp_closed_timestamp)
746  {
747  // session is closed, go slow path
749  }
750  else
751  {
752  // session in transitory timeout, drop
753  b0->error = node->errors[NAT_OUT2IN_ED_ERROR_TCP_CLOSED];
754  next0 = NAT_NEXT_DROP;
755  }
756  goto trace0;
757  }
758 
759  // drop if session expired
760  u64 sess_timeout_time;
761  sess_timeout_time = s0->last_heard +
762  (f64) nat44_session_get_timeout (sm, s0);
763  if (now >= sess_timeout_time)
764  {
765  // session is closed, go slow path
766  nat_free_session_data (sm, s0, thread_index, 0);
767  nat_ed_session_delete (sm, s0, thread_index, 1);
769  goto trace0;
770  }
771  //
772 
773  old_addr0 = ip0->dst_address.as_u32;
774  new_addr0 = ip0->dst_address.as_u32 = s0->in2out.addr.as_u32;
775  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
776 
777  sum0 = ip0->checksum;
778  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
779  dst_address);
781  sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
782  s0->ext_host_nat_addr.as_u32, ip4_header_t,
783  src_address);
784  ip0->checksum = ip_csum_fold (sum0);
785 
786  old_port0 = vnet_buffer (b0)->ip.reass.l4_dst_port;
787 
788  if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP))
789  {
790  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
791  {
792  new_port0 = udp0->dst_port = s0->in2out.port;
793  sum0 = tcp0->checksum;
794  sum0 =
795  ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
796  dst_address);
797  sum0 =
798  ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
799  length);
800  if (is_twice_nat_session (s0))
801  {
802  sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
803  s0->ext_host_nat_addr.as_u32,
804  ip4_header_t, dst_address);
805  sum0 =
806  ip_csum_update (sum0,
807  vnet_buffer (b0)->ip.
808  reass.l4_src_port,
809  s0->ext_host_nat_port, ip4_header_t,
810  length);
811  tcp0->src_port = s0->ext_host_nat_port;
812  ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
813  }
814  tcp0->checksum = ip_csum_fold (sum0);
815  }
816  tcp_packets++;
818  (sm, now, s0,
819  vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags,
820  vnet_buffer (b0)->ip.reass.tcp_ack_number,
821  vnet_buffer (b0)->ip.reass.tcp_seq_number, thread_index))
822  goto trace0;
823  }
824  else if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment
825  && udp0->checksum)
826  {
827  new_port0 = udp0->dst_port = s0->in2out.port;
828  sum0 = udp0->checksum;
829  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
830  dst_address);
831  sum0 = ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
832  length);
834  {
835  sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
836  s0->ext_host_nat_addr.as_u32,
837  ip4_header_t, dst_address);
838  sum0 =
839  ip_csum_update (sum0,
840  vnet_buffer (b0)->ip.reass.l4_src_port,
841  s0->ext_host_nat_port, ip4_header_t,
842  length);
843  udp0->src_port = s0->ext_host_nat_port;
844  ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
845  }
846  udp0->checksum = ip_csum_fold (sum0);
847  udp_packets++;
848  }
849  else
850  {
851  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
852  {
853  new_port0 = udp0->dst_port = s0->in2out.port;
855  {
856  udp0->src_port = s0->ext_host_nat_port;
857  ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
858  }
859  }
860  udp_packets++;
861  }
862 
863  /* Accounting */
866  thread_index);
867  /* Per-user LRU list maintenance */
868  nat44_session_update_lru (sm, s0, thread_index);
869 
870  trace0:
872  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
873  {
875  vlib_add_trace (vm, node, b0, sizeof (*t));
876  t->sw_if_index = sw_if_index0;
877  t->next_index = next0;
878  t->is_slow_path = 0;
879 
880  if (s0)
881  t->session_index = s0 - tsm->sessions;
882  else
883  t->session_index = ~0;
884  }
885 
886  pkts_processed += next0 == vnet_buffer2 (b0)->nat.arc_next;
887  /* verify speculative enqueue, maybe switch current next frame */
888  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
889  to_next, n_left_to_next,
890  bi0, next0);
891  }
892 
893  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
894  }
895 
896  vlib_node_increment_counter (vm, stats_node_index,
897  NAT_OUT2IN_ED_ERROR_OUT2IN_PACKETS,
898  pkts_processed);
899  vlib_node_increment_counter (vm, stats_node_index,
900  NAT_OUT2IN_ED_ERROR_TCP_PACKETS, tcp_packets);
901  vlib_node_increment_counter (vm, stats_node_index,
902  NAT_OUT2IN_ED_ERROR_UDP_PACKETS, udp_packets);
903  vlib_node_increment_counter (vm, stats_node_index,
904  NAT_OUT2IN_ED_ERROR_ICMP_PACKETS,
905  icmp_packets);
906  vlib_node_increment_counter (vm, stats_node_index,
907  NAT_OUT2IN_ED_ERROR_OTHER_PACKETS,
908  other_packets);
909  vlib_node_increment_counter (vm, stats_node_index,
910  NAT_OUT2IN_ED_ERROR_FRAGMENTS, fragments);
911  return frame->n_vectors;
912 }
913 
914 static inline uword
918 {
919  u32 n_left_from, *from, *to_next, pkts_processed = 0, stats_node_index;
920  nat_next_t next_index;
921  snat_main_t *sm = &snat_main;
922  // HERE
923  f64 now = vlib_time_now (vm);
924  u32 thread_index = vm->thread_index;
925  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
926  u32 tcp_packets = 0, udp_packets = 0, icmp_packets = 0, other_packets =
927  0, fragments = 0;
928 
929  stats_node_index = sm->ed_out2in_slowpath_node_index;
930 
931  from = vlib_frame_vector_args (frame);
932  n_left_from = frame->n_vectors;
933  next_index = node->cached_next_index;
934 
935  while (n_left_from > 0)
936  {
937  u32 n_left_to_next;
938 
939  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
940 
941  while (n_left_from > 0 && n_left_to_next > 0)
942  {
943  u32 bi0;
944  vlib_buffer_t *b0;
945  u32 next0, sw_if_index0, rx_fib_index0, proto0, old_addr0,
946  new_addr0;
947  u16 old_port0, new_port0;
948  ip4_header_t *ip0;
949  udp_header_t *udp0;
950  tcp_header_t *tcp0;
951  icmp46_header_t *icmp0;
952  snat_session_t *s0 = 0;
953  clib_bihash_kv_16_8_t kv0, value0;
954  ip_csum_t sum0;
955  snat_session_key_t e_key0, l_key0;
956  lb_nat_type_t lb_nat0;
957  twice_nat_type_t twice_nat0;
958  u8 identity_nat0;
959 
960  /* speculatively enqueue b0 to the current next frame */
961  bi0 = from[0];
962  to_next[0] = bi0;
963  from += 1;
964  to_next += 1;
965  n_left_from -= 1;
966  n_left_to_next -= 1;
967 
968  b0 = vlib_get_buffer (vm, bi0);
969  next0 = vnet_buffer2 (b0)->nat.arc_next;
970 
971  vnet_buffer (b0)->snat.flags = 0;
972  ip0 = vlib_buffer_get_current (b0);
973 
974  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
975  rx_fib_index0 =
977  sw_if_index0);
978 
979  if (PREDICT_FALSE (ip0->ttl == 1))
980  {
981  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
982  icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
983  ICMP4_time_exceeded_ttl_exceeded_in_transit,
984  0);
985  next0 = NAT_NEXT_ICMP_ERROR;
986  goto trace0;
987  }
988 
989  udp0 = ip4_next_header (ip0);
990  tcp0 = (tcp_header_t *) udp0;
991  icmp0 = (icmp46_header_t *) udp0;
992  proto0 = ip_proto_to_nat_proto (ip0->protocol);
993 
994  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_OTHER))
995  {
996  s0 =
997  nat44_ed_out2in_unknown_proto (sm, b0, ip0, rx_fib_index0,
998  thread_index, now, vm, node);
999  if (!sm->forwarding_enabled)
1000  {
1001  if (!s0)
1002  next0 = NAT_NEXT_DROP;
1003  }
1004  other_packets++;
1005  goto trace0;
1006  }
1007 
1008  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP))
1009  {
1010  next0 = icmp_out2in_ed_slow_path
1011  (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
1012  next0, now, thread_index, &s0);
1013  icmp_packets++;
1014  goto trace0;
1015  }
1016 
1017  make_ed_kv (&ip0->dst_address, &ip0->src_address,
1018  ip0->protocol, rx_fib_index0,
1019  vnet_buffer (b0)->ip.reass.l4_dst_port,
1020  vnet_buffer (b0)->ip.reass.l4_src_port, ~0ULL, &kv0);
1021 
1022  s0 = NULL;
1023  if (!clib_bihash_search_16_8 (&tsm->out2in_ed, &kv0, &value0))
1024  {
1025  s0 = pool_elt_at_index (tsm->sessions, value0.value);
1026 
1027  if (s0->tcp_closed_timestamp && now >= s0->tcp_closed_timestamp)
1028  {
1029  nat_free_session_data (sm, s0, thread_index, 0);
1030  nat_ed_session_delete (sm, s0, thread_index, 1);
1031  s0 = NULL;
1032  }
1033  }
1034 
1035  if (!s0)
1036  {
1037  /* Try to match static mapping by external address and port,
1038  destination address and port in packet */
1039  e_key0.addr = ip0->dst_address;
1040  e_key0.port = vnet_buffer (b0)->ip.reass.l4_dst_port;
1041  e_key0.protocol = proto0;
1042  e_key0.fib_index = rx_fib_index0;
1043 
1044  if (snat_static_mapping_match (sm, e_key0, &l_key0, 1, 0,
1045  &twice_nat0, &lb_nat0,
1046  &ip0->src_address,
1047  &identity_nat0))
1048  {
1049  /*
1050  * Send DHCP packets to the ipv4 stack, or we won't
1051  * be able to use dhcp client on the outside interface
1052  */
1053  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_UDP
1054  && (vnet_buffer (b0)->ip.
1055  reass.l4_dst_port ==
1056  clib_host_to_net_u16
1057  (UDP_DST_PORT_dhcp_to_client))))
1058  {
1059  goto trace0;
1060  }
1061 
1062  if (!sm->forwarding_enabled)
1063  {
1064  b0->error =
1065  node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
1066  next0 = NAT_NEXT_DROP;
1067  }
1068  else
1069  {
1070  if (next_src_nat
1071  (sm, ip0, vnet_buffer (b0)->ip.reass.l4_src_port,
1072  vnet_buffer (b0)->ip.reass.l4_dst_port,
1073  thread_index, rx_fib_index0))
1074  {
1076  goto trace0;
1077  }
1078  if (sm->num_workers > 1)
1079  create_bypass_for_fwd_worker (sm, b0, ip0,
1080  rx_fib_index0);
1081  else
1082  create_bypass_for_fwd (sm, b0, ip0, rx_fib_index0,
1083  thread_index);
1084  }
1085  goto trace0;
1086  }
1087 
1088  if (PREDICT_FALSE (identity_nat0))
1089  goto trace0;
1090 
1091  if ((proto0 == NAT_PROTOCOL_TCP)
1092  && !tcp_flags_is_init (vnet_buffer (b0)->ip.
1093  reass.icmp_type_or_tcp_flags))
1094  {
1095  b0->error = node->errors[NAT_OUT2IN_ED_ERROR_NON_SYN];
1096  next0 = NAT_NEXT_DROP;
1097  goto trace0;
1098  }
1099 
1100  /* Create session initiated by host from external network */
1101  s0 = create_session_for_static_mapping_ed (sm, b0, l_key0,
1102  e_key0, node,
1103  rx_fib_index0,
1104  thread_index,
1105  twice_nat0,
1106  lb_nat0, now);
1107  if (!s0)
1108  {
1109  next0 = NAT_NEXT_DROP;
1110  goto trace0;
1111  }
1112  }
1113 
1114  old_addr0 = ip0->dst_address.as_u32;
1115  new_addr0 = ip0->dst_address.as_u32 = s0->in2out.addr.as_u32;
1116  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
1117 
1118  sum0 = ip0->checksum;
1119  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1120  dst_address);
1122  sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
1123  s0->ext_host_nat_addr.as_u32, ip4_header_t,
1124  src_address);
1125  ip0->checksum = ip_csum_fold (sum0);
1126 
1127  old_port0 = vnet_buffer (b0)->ip.reass.l4_dst_port;
1128 
1129  if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP))
1130  {
1131  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1132  {
1133  new_port0 = udp0->dst_port = s0->in2out.port;
1134  sum0 = tcp0->checksum;
1135  sum0 =
1136  ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1137  dst_address);
1138  sum0 =
1139  ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
1140  length);
1141  if (is_twice_nat_session (s0))
1142  {
1143  sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
1144  s0->ext_host_nat_addr.as_u32,
1145  ip4_header_t, dst_address);
1146  sum0 =
1147  ip_csum_update (sum0,
1148  vnet_buffer (b0)->ip.
1149  reass.l4_src_port,
1150  s0->ext_host_nat_port, ip4_header_t,
1151  length);
1152  tcp0->src_port = s0->ext_host_nat_port;
1153  ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
1154  }
1155  tcp0->checksum = ip_csum_fold (sum0);
1156  }
1157  tcp_packets++;
1159  (sm, now, s0,
1160  vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags,
1161  vnet_buffer (b0)->ip.reass.tcp_ack_number,
1162  vnet_buffer (b0)->ip.reass.tcp_seq_number, thread_index))
1163  goto trace0;
1164  }
1165  else if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment
1166  && udp0->checksum)
1167  {
1168  new_port0 = udp0->dst_port = s0->in2out.port;
1169  sum0 = udp0->checksum;
1170  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1171  dst_address);
1172  sum0 = ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
1173  length);
1175  {
1176  sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
1177  s0->ext_host_nat_addr.as_u32,
1178  ip4_header_t, dst_address);
1179  sum0 =
1180  ip_csum_update (sum0,
1181  vnet_buffer (b0)->ip.reass.l4_src_port,
1182  s0->ext_host_nat_port, ip4_header_t,
1183  length);
1184  udp0->src_port = s0->ext_host_nat_port;
1185  ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
1186  }
1187  udp0->checksum = ip_csum_fold (sum0);
1188  udp_packets++;
1189  }
1190  else
1191  {
1192  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1193  {
1194  new_port0 = udp0->dst_port = s0->in2out.port;
1196  {
1197  udp0->src_port = s0->ext_host_nat_port;
1198  ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
1199  }
1200  }
1201  udp_packets++;
1202  }
1203 
1204  /* Accounting */
1206  vlib_buffer_length_in_chain (vm, b0),
1207  thread_index);
1208  /* Per-user LRU list maintenance */
1209  nat44_session_update_lru (sm, s0, thread_index);
1210 
1211  trace0:
1213  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1214  {
1216  vlib_add_trace (vm, node, b0, sizeof (*t));
1217  t->sw_if_index = sw_if_index0;
1218  t->next_index = next0;
1219  t->is_slow_path = 1;
1220 
1221  if (s0)
1222  t->session_index = s0 - tsm->sessions;
1223  else
1224  t->session_index = ~0;
1225  }
1226 
1227  pkts_processed += next0 == vnet_buffer2 (b0)->nat.arc_next;
1228  /* verify speculative enqueue, maybe switch current next frame */
1229  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1230  to_next, n_left_to_next,
1231  bi0, next0);
1232  }
1233 
1234  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1235  }
1236 
1237  vlib_node_increment_counter (vm, stats_node_index,
1238  NAT_OUT2IN_ED_ERROR_OUT2IN_PACKETS,
1239  pkts_processed);
1240  vlib_node_increment_counter (vm, stats_node_index,
1241  NAT_OUT2IN_ED_ERROR_TCP_PACKETS, tcp_packets);
1242  vlib_node_increment_counter (vm, stats_node_index,
1243  NAT_OUT2IN_ED_ERROR_UDP_PACKETS, udp_packets);
1244  vlib_node_increment_counter (vm, stats_node_index,
1245  NAT_OUT2IN_ED_ERROR_ICMP_PACKETS,
1246  icmp_packets);
1247  vlib_node_increment_counter (vm, stats_node_index,
1248  NAT_OUT2IN_ED_ERROR_OTHER_PACKETS,
1249  other_packets);
1250  vlib_node_increment_counter (vm, stats_node_index,
1251  NAT_OUT2IN_ED_ERROR_FRAGMENTS, fragments);
1252  return frame->n_vectors;
1253 }
1254 
1257  vlib_frame_t * frame)
1258 {
1260 }
1261 
1262 /* *INDENT-OFF* */
1264  .name = "nat44-ed-out2in",
1265  .vector_size = sizeof (u32),
1266  .sibling_of = "nat-default",
1267  .format_trace = format_nat44_ed_out2in_trace,
1270  .error_strings = nat_out2in_ed_error_strings,
1271  .runtime_data_bytes = sizeof (snat_runtime_t),
1272 };
1273 /* *INDENT-ON* */
1274 
1277  vlib_frame_t * frame)
1278 {
1280 }
1281 
1282 /* *INDENT-OFF* */
1284  .name = "nat44-ed-out2in-slowpath",
1285  .vector_size = sizeof (u32),
1286  .sibling_of = "nat-default",
1287  .format_trace = format_nat44_ed_out2in_trace,
1290  .error_strings = nat_out2in_ed_error_strings,
1291  .runtime_data_bytes = sizeof (snat_runtime_t),
1292 };
1293 /* *INDENT-ON* */
1294 
1295 static u8 *
1296 format_nat_pre_trace (u8 * s, va_list * args)
1297 {
1298  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1299  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1300  nat_pre_trace_t *t = va_arg (*args, nat_pre_trace_t *);
1301  return format (s, "out2in next_index %d arc_next_index %d", t->next_index,
1302  t->arc_next_index);
1303 }
1304 
1307  vlib_frame_t * frame)
1308 {
1309  return nat_pre_node_fn_inline (vm, node, frame,
1311 }
1312 
1313 /* *INDENT-OFF* */
1315  .name = "nat-pre-out2in",
1316  .vector_size = sizeof (u32),
1317  .sibling_of = "nat-default",
1318  .format_trace = format_nat_pre_trace,
1320  .n_errors = 0,
1321  };
1322 /* *INDENT-ON* */
1323 
1324 /*
1325  * fd.io coding-style-patch-verification: ON
1326  *
1327  * Local Variables:
1328  * eval: (c-set-style "gnu")
1329  * End:
1330  */
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
#define snat_is_session_static(s)
Check if SNAT session is created from static mapping.
Definition: nat.h:728
static uword nat44_ed_out2in_fast_path_node_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: out2in_ed.c:647
#define CLIB_UNUSED(x)
Definition: clib.h:86
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:525
u32 arc_next_index
Definition: nat.h:68
a
Definition: bitmap.h:538
ip4_address_t src_address
Definition: ip4_packet.h:170
#define vnet_buffer2(b)
Definition: buffer.h:482
static u32 nat44_session_get_timeout(snat_main_t *sm, snat_session_t *s)
Definition: nat_inlines.h:385
u32 ed_out2in_node_index
Definition: nat.h:607
#define nat_elog_notice(nat_elog_str)
Definition: nat.h:986
#define PREDICT_TRUE(x)
Definition: clib.h:119
unsigned long u64
Definition: types.h:89
void nat_syslog_nat44_sadd(u32 ssubix, u32 sfibix, ip4_address_t *isaddr, u16 isport, ip4_address_t *idaddr, u16 idport, ip4_address_t *xsaddr, u16 xsport, ip4_address_t *xdaddr, u16 xdport, nat_protocol_t proto, u8 is_twicenat)
Definition: nat_syslog.c:197
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:291
u32 fib_table_get_index_for_sw_if_index(fib_protocol_t proto, u32 sw_if_index)
Get the index of the FIB bound to the interface.
Definition: fib_table.c:989
static void make_sm_kv(clib_bihash_kv_8_8_t *kv, ip4_address_t *addr, u8 proto, u32 fib_index, u16 port)
Definition: nat_inlines.h:489
u16 port_per_thread
Definition: nat.h:532
u32 thread_index
Definition: main.h:218
void nat_free_session_data(snat_main_t *sm, snat_session_t *s, u32 thread_index, u8 is_ha)
Free NAT44 session data (lookup keys, external address port)
Definition: nat.c:198
u32 ed_out2in_slowpath_node_index
Definition: nat.h:608
uword ip_csum_t
Definition: ip_packet.h:244
#define nat_elog_warn(nat_elog_str)
Definition: nat.h:988
void nat_ha_sadd(ip4_address_t *in_addr, u16 in_port, ip4_address_t *out_addr, u16 out_port, ip4_address_t *eh_addr, u16 eh_port, ip4_address_t *ehn_addr, u16 ehn_port, u8 proto, u32 fib_index, u16 flags, u32 thread_index, u8 is_resync)
Create session add HA event.
Definition: nat_ha.c:689
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
vlib_node_registration_t nat44_ed_out2in_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_out2in_node)
Definition: out2in_ed.c:1263
#define VLIB_NODE_FN(node)
Definition: node.h:202
static void nat_ed_session_delete(snat_main_t *sm, snat_session_t *ses, u32 thread_index, int lru_delete)
Definition: ed_inlines.h:55
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:472
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:402
void snat_ipfix_logging_nat44_ses_create(u32 thread_index, u32 src_ip, u32 nat_src_ip, nat_protocol_t nat_proto, u16 src_port, u16 nat_src_port, u32 vrf_id)
Generate NAT44 session create event.
struct _tcp_header tcp_header_t
#define snat_is_unk_proto_session(s)
Check if SNAT session for unknown protocol.
Definition: nat.h:734
unsigned char u8
Definition: types.h:56
double f64
Definition: types.h:142
u32 next_index
Definition: nat.h:67
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:69
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
Definition: ip4_fib.c:230
static char * nat_out2in_ed_error_strings[]
Definition: out2in_ed.c:36
static nat_protocol_t ip_proto_to_nat_proto(u8 ip_proto)
Common NAT inline functions.
Definition: inlines.h:22
vl_api_interface_index_t sw_if_index
Definition: gre.api:53
ip4_address_t dst_address
Definition: ip4_packet.h:170
lb_nat_type_t
Definition: nat.h:386
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
static_always_inline u8 icmp_type_is_error_message(u8 icmp_type)
Definition: inlines.h:53
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:399
int snat_static_mapping_match(snat_main_t *sm, snat_session_key_t match, snat_session_key_t *mapping, u8 by_external, u8 *is_addr_only, twice_nat_type_t *twice_nat, lb_nat_type_t *lb, ip4_address_t *ext_host_addr, u8 *is_identity_nat)
Match NAT44 static mapping.
Definition: nat.c:2741
void snat_free_outside_address_and_port(snat_address_t *addresses, u32 thread_index, snat_session_key_t *k)
Free outside address and port pair.
Definition: nat.c:2669
vl_api_fib_path_type_t type
Definition: fib_types.api:123
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:136
int nat44_o2i_ed_is_idle_session_cb(clib_bihash_kv_16_8_t *kv, void *arg)
Definition: out2in_ed.c:94
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:2900
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:534
#define foreach_nat_out2in_ed_error
Definition: nat.h:193
clib_bihash_16_8_t out2in_ed
Definition: nat.h:457
vl_api_ip_proto_t proto
Definition: acl_types.api:50
long ctx[MAX_CONNS]
Definition: main.c:144
unsigned short u16
Definition: types.h:57
u16 protocol
Definition: nat.h:80
snat_static_mapping_t * static_mappings
Definition: nat.h:545
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
vlib_node_registration_t nat_pre_out2in_node
(constructor) VLIB_REGISTER_NODE (nat_pre_out2in_node)
Definition: out2in_ed.c:1314
nat_next_t
Definition: nat.h:51
#define PREDICT_FALSE(x)
Definition: clib.h:118
clib_bihash_8_8_t static_mapping_by_external
Definition: nat.h:542
vl_api_address_union_t src_address
Definition: ip_types.api:99
#define SNAT_SESSION_FLAG_UNKNOWN_PROTO
Definition: nat.h:233
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:224
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:338
static_always_inline snat_session_t * nat_ed_session_alloc(snat_main_t *sm, u32 thread_index, f64 now, u8 proto)
Definition: ed_inlines.h:126
vlib_main_t * vm
Definition: in2out_ed.c:1599
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1150
snat_main_t snat_main
Definition: nat.c:41
u64 value
the value
Definition: bihash_8_8.h:42
static int nat44_set_tcp_session_state_o2i(snat_main_t *sm, f64 now, snat_session_t *ses, u8 tcp_flags, u32 tcp_ack_number, u32 tcp_seq_number, u32 thread_index)
Definition: nat_inlines.h:340
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u16 n_vectors
Definition: node.h:399
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
static void nat44_session_update_counters(snat_session_t *s, f64 now, uword bytes, u32 thread_index)
Definition: nat_inlines.h:408
static u8 * format_nat44_ed_out2in_trace(u8 *s, va_list *args)
Definition: out2in_ed.c:51
static u8 * format_nat_pre_trace(u8 *s, va_list *args)
Definition: out2in_ed.c:1296
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:39
#define ARRAY_LEN(x)
Definition: clib.h:66
ip4_address_t addr
Definition: nat.h:78
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:483
vlib_node_registration_t nat44_ed_out2in_slowpath_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_out2in_slowpath_node)
Definition: out2in_ed.c:1283
static uword nat_pre_node_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, u32 def_next)
The NAT inline functions.
Definition: nat_inlines.h:27
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1599
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:551
void nat_syslog_nat44_sdel(u32 ssubix, u32 sfibix, ip4_address_t *isaddr, u16 isport, ip4_address_t *idaddr, u16 idport, ip4_address_t *xsaddr, u16 xsport, ip4_address_t *xdaddr, u16 xdport, nat_protocol_t proto, u8 is_twicenat)
Definition: nat_syslog.c:209
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:517
u8 value
Definition: qos.api:54
u32 num_workers
Definition: nat.h:527
Definition: nat.h:381
#define SNAT_SESSION_FLAG_TWICE_NAT
Definition: nat.h:235
static void nat44_session_update_lru(snat_main_t *sm, snat_session_t *s, u32 thread_index)
Per-user LRU list maintenance.
Definition: nat_inlines.h:422
#define SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT
Definition: nat.h:236
void snat_ipfix_logging_nat44_ses_delete(u32 thread_index, u32 src_ip, u32 nat_src_ip, nat_protocol_t nat_proto, u16 src_port, u16 nat_src_port, u32 vrf_id)
Generate NAT44 session delete event.
ip4_address_t addr
Definition: nat.h:314
snat_address_t * twice_nat_addresses
Definition: nat.h:569
static_always_inline u8 nat44_ed_maximum_sessions_exceeded(snat_main_t *sm, u32 fib_index, u32 thread_index)
Definition: inlines.h:35
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
void nat_ha_sdel(ip4_address_t *out_addr, u16 out_port, ip4_address_t *eh_addr, u16 eh_port, u8 proto, u32 fib_index, u32 thread_index)
Create session delete HA event.
Definition: nat_ha.c:715
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
typedef key
Definition: ipsec_types.api:85
Definition: defs.h:47
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 rx_fib_index, u32 thread_index, twice_nat_type_t twice_nat, lb_nat_type_t lb_nat, f64 now)
Definition: out2in_ed.c:194
vl_api_address_t ip
Definition: l2.api:501
#define SNAT_SESSION_FLAG_FWD_BYPASS
Definition: nat.h:237
int nat44_i2o_ed_is_idle_session_cb(clib_bihash_kv_16_8_t *kv, void *arg)
Definition: in2out_ed.c:70
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:430
twice_nat_type_t
Definition: nat.h:376
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
#define SNAT_SESSION_FLAG_AFFINITY
Definition: nat.h:238
static_always_inline u8 nat_proto_to_ip_proto(nat_protocol_t nat_proto)
Definition: inlines.h:35
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
snat_main_per_thread_data_t * per_thread_data
Definition: nat.h:536
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:244
#define ip_csum_update(sum, old, new, type, field)
Definition: ip_packet.h:294
NAT syslog logging.
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:150
static void create_bypass_for_fwd(snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, u32 rx_fib_index, u32 thread_index)
Definition: out2in_ed.c:326
snat_address_t * addresses
Definition: nat.h:552
static_always_inline int get_icmp_o2i_ed_key(vlib_buffer_t *b, ip4_header_t *ip0, u32 rx_fib_index, u64 value, u8 *nat_proto, u16 *l_port, u16 *r_port, clib_bihash_kv_16_8_t *kv)
Definition: nat_inlines.h:568
snat_get_worker_in2out_function_t * worker_in2out_cb
Definition: nat.h:530
#define vnet_buffer(b)
Definition: buffer.h:417
#define SNAT_SESSION_FLAG_STATIC_MAPPING
Definition: nat.h:232
u8 forwarding_enabled
Definition: nat.h:624
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1600
static void create_bypass_for_fwd_worker(snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, u32 rx_fib_index)
Definition: out2in_ed.c:417
u16 flags
Copy of main node flags.
Definition: node.h:511
#define is_twice_nat_session(s)
Check if NAT session is twice NAT.
Definition: nat.h:740
clib_bihash_16_8_t in2out_ed
Definition: nat.h:458
u16 dst_port
Definition: udp.api:42
static uword nat44_ed_out2in_slow_path_node_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: out2in_ed.c:915
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:304
static int next_src_nat(snat_main_t *sm, ip4_header_t *ip, u16 src_port, u16 dst_port, u32 thread_index, u32 rx_fib_index)
Definition: out2in_ed.c:311
snat_session_t * sessions
Definition: nat.h:467
static_always_inline void icmp4_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
Definition: icmp4.h:51
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
#define SNAT_SESSION_FLAG_LOAD_BALANCING
Definition: nat.h:234
static void make_ed_kv(ip4_address_t *l_addr, ip4_address_t *r_addr, u8 proto, u32 fib_index, u16 l_port, u16 r_port, u64 value, clib_bihash_kv_16_8_t *kv)
Definition: nat_inlines.h:447
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:300
Definition: defs.h:46
NAT active-passive HA.
u16 fib_index
Definition: nat.h:80
static bool tcp_flags_is_init(u8 f)
Check if client initiating TCP connection (received SYN from client)
Definition: nat.h:813