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