FD.io VPP  v19.08.1-401-g8e4ed521a
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  old_port0 = udp0->dst_port;
923  new_port0 = udp0->dst_port = s0->in2out.port;
924 
925  if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP))
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 if (udp0->checksum)
950  {
951  sum0 = udp0->checksum;
952  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
953  dst_address);
954  sum0 = ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
955  length);
957  {
958  sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
959  s0->ext_host_nat_addr.as_u32,
960  ip4_header_t, dst_address);
961  sum0 = ip_csum_update (sum0, udp0->src_port,
962  s0->ext_host_nat_port, ip4_header_t,
963  length);
964  udp0->src_port = s0->ext_host_nat_port;
965  ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
966  }
967  udp0->checksum = ip_csum_fold (sum0);
968  udp_packets++;
969  }
970  else
971  {
973  {
974  udp0->src_port = s0->ext_host_nat_port;
975  ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
976  }
977  udp_packets++;
978  }
979 
980  /* Accounting */
983  thread_index);
984  /* Per-user LRU list maintenance */
985  nat44_session_update_lru (sm, s0, thread_index);
986 
987  trace00:
989  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
990  {
992  vlib_add_trace (vm, node, b0, sizeof (*t));
993  t->is_slow_path = is_slow_path;
994  t->sw_if_index = sw_if_index0;
995  t->next_index = next0;
996  t->session_index = ~0;
997  if (s0)
998  t->session_index = s0 - tsm->sessions;
999  }
1000 
1001  pkts_processed += next0 == NAT44_ED_OUT2IN_NEXT_LOOKUP;
1002 
1004  vnet_buffer (b1)->snat.flags = 0;
1005  ip1 = vlib_buffer_get_current (b1);
1006 
1007  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
1008  rx_fib_index1 =
1010  sw_if_index1);
1011 
1012  if (PREDICT_FALSE (ip1->ttl == 1))
1013  {
1014  vnet_buffer (b1)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1015  icmp4_error_set_vnet_buffer (b1, ICMP4_time_exceeded,
1016  ICMP4_time_exceeded_ttl_exceeded_in_transit,
1017  0);
1019  goto trace01;
1020  }
1021 
1022  udp1 = ip4_next_header (ip1);
1023  tcp1 = (tcp_header_t *) udp1;
1024  icmp1 = (icmp46_header_t *) udp1;
1025  proto1 = ip_proto_to_snat_proto (ip1->protocol);
1026 
1027  if (is_slow_path)
1028  {
1029  if (PREDICT_FALSE (proto1 == ~0))
1030  {
1031  s1 =
1032  nat44_ed_out2in_unknown_proto (sm, b1, ip1, rx_fib_index1,
1033  thread_index, now, vm,
1034  node);
1035  other_packets++;
1036  if (!sm->forwarding_enabled)
1037  {
1038  if (!s1)
1039  next1 = NAT44_ED_OUT2IN_NEXT_DROP;
1040  goto trace01;
1041  }
1042  }
1043 
1044  if (PREDICT_FALSE (proto1 == SNAT_PROTOCOL_ICMP))
1045  {
1046  next1 = icmp_out2in_ed_slow_path
1047  (sm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1, node,
1048  next1, now, thread_index, &s1);
1049  icmp_packets++;
1050  goto trace01;
1051  }
1052  }
1053  else
1054  {
1055  if (PREDICT_FALSE (proto1 == ~0))
1056  {
1058  goto trace01;
1059  }
1060 
1061  if (ip4_is_fragment (ip1))
1062  {
1064  fragments++;
1065  goto trace01;
1066  }
1067 
1068  if (PREDICT_FALSE (proto1 == SNAT_PROTOCOL_ICMP))
1069  {
1071  goto trace01;
1072  }
1073  }
1074 
1075  make_ed_kv (&kv1, &ip1->dst_address, &ip1->src_address,
1076  ip1->protocol, rx_fib_index1, udp1->dst_port,
1077  udp1->src_port);
1078 
1079  if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv1, &value1))
1080  {
1081  if (is_slow_path)
1082  {
1083  /* Try to match static mapping by external address and port,
1084  destination address and port in packet */
1085  e_key1.addr = ip1->dst_address;
1086  e_key1.port = udp1->dst_port;
1087  e_key1.protocol = proto1;
1088  e_key1.fib_index = rx_fib_index1;
1089  if (snat_static_mapping_match (sm, e_key1, &l_key1, 1, 0,
1090  &twice_nat1, &lb_nat1,
1091  &ip1->src_address,
1092  &identity_nat1))
1093  {
1094  /*
1095  * Send DHCP packets to the ipv4 stack, or we won't
1096  * be able to use dhcp client on the outside interface
1097  */
1098  if (PREDICT_FALSE (proto1 == SNAT_PROTOCOL_UDP
1099  && (udp1->dst_port ==
1100  clib_host_to_net_u16
1101  (UDP_DST_PORT_dhcp_to_client))))
1102  {
1103  vnet_feature_next (&next1, b1);
1104  goto trace01;
1105  }
1106 
1107  if (!sm->forwarding_enabled)
1108  {
1109  b1->error =
1110  node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
1111  next1 = NAT44_ED_OUT2IN_NEXT_DROP;
1112  }
1113  else
1114  {
1115  if (next_src_nat (sm, ip1, ip1->protocol,
1116  udp1->src_port, udp1->dst_port,
1117  thread_index, rx_fib_index1))
1118  {
1120  goto trace01;
1121  }
1122  if (sm->num_workers > 1)
1124  rx_fib_index1);
1125  else
1126  create_bypass_for_fwd (sm, ip1, rx_fib_index1,
1127  thread_index);
1128  }
1129  goto trace01;
1130  }
1131 
1132  if (PREDICT_FALSE (identity_nat1))
1133  goto trace01;
1134 
1135  if ((proto1 == SNAT_PROTOCOL_TCP) && !tcp_is_init (tcp1))
1136  {
1137  b1->error = node->errors[NAT_OUT2IN_ED_ERROR_NON_SYN];
1138  next1 = NAT44_ED_OUT2IN_NEXT_DROP;
1139  goto trace01;
1140  }
1141 
1142  /* Create session initiated by host from external network */
1143  s1 = create_session_for_static_mapping_ed (sm, b1, l_key1,
1144  e_key1, node,
1145  thread_index,
1146  twice_nat1,
1147  lb_nat1, now);
1148 
1149  if (!s1)
1150  {
1151  next1 = NAT44_ED_OUT2IN_NEXT_DROP;
1152  goto trace01;
1153  }
1154  }
1155  else
1156  {
1158  goto trace01;
1159  }
1160  }
1161  else
1162  {
1163  s1 = pool_elt_at_index (tsm->sessions, value1.value);
1164  }
1165 
1166  old_addr1 = ip1->dst_address.as_u32;
1167  new_addr1 = ip1->dst_address.as_u32 = s1->in2out.addr.as_u32;
1168  vnet_buffer (b1)->sw_if_index[VLIB_TX] = s1->in2out.fib_index;
1169 
1170  sum1 = ip1->checksum;
1171  sum1 = ip_csum_update (sum1, old_addr1, new_addr1, ip4_header_t,
1172  dst_address);
1174  sum1 = ip_csum_update (sum1, ip1->src_address.as_u32,
1175  s1->ext_host_nat_addr.as_u32, ip4_header_t,
1176  src_address);
1177  ip1->checksum = ip_csum_fold (sum1);
1178 
1179  old_port1 = udp1->dst_port;
1180  new_port1 = udp1->dst_port = s1->in2out.port;
1181 
1182  if (PREDICT_TRUE (proto1 == SNAT_PROTOCOL_TCP))
1183  {
1184  sum1 = tcp1->checksum;
1185  sum1 = ip_csum_update (sum1, old_addr1, new_addr1, ip4_header_t,
1186  dst_address);
1187  sum1 = ip_csum_update (sum1, old_port1, new_port1, ip4_header_t,
1188  length);
1189  if (is_twice_nat_session (s1))
1190  {
1191  sum1 = ip_csum_update (sum1, ip1->src_address.as_u32,
1192  s1->ext_host_nat_addr.as_u32,
1193  ip4_header_t, dst_address);
1194  sum1 = ip_csum_update (sum1, tcp1->src_port,
1195  s1->ext_host_nat_port, ip4_header_t,
1196  length);
1197  tcp1->src_port = s1->ext_host_nat_port;
1198  ip1->src_address.as_u32 = s1->ext_host_nat_addr.as_u32;
1199  }
1200  tcp1->checksum = ip_csum_fold (sum1);
1201  tcp_packets++;
1203  (sm, s1, tcp1, thread_index))
1204  goto trace01;
1205  }
1206  else if (udp1->checksum)
1207  {
1208  sum1 = udp1->checksum;
1209  sum1 = ip_csum_update (sum1, old_addr1, new_addr1, ip4_header_t,
1210  dst_address);
1211  sum1 = ip_csum_update (sum1, old_port1, new_port1, ip4_header_t,
1212  length);
1214  {
1215  sum1 = ip_csum_update (sum1, ip1->src_address.as_u32,
1216  s1->ext_host_nat_addr.as_u32,
1217  ip4_header_t, dst_address);
1218  sum1 = ip_csum_update (sum1, udp1->src_port,
1219  s1->ext_host_nat_port, ip4_header_t,
1220  length);
1221  udp1->src_port = s1->ext_host_nat_port;
1222  ip1->src_address.as_u32 = s1->ext_host_nat_addr.as_u32;
1223  }
1224  udp1->checksum = ip_csum_fold (sum1);
1225  udp_packets++;
1226  }
1227  else
1228  {
1230  {
1231  udp1->src_port = s1->ext_host_nat_port;
1232  ip1->src_address.as_u32 = s1->ext_host_nat_addr.as_u32;
1233  }
1234  udp_packets++;
1235  }
1236 
1237  /* Accounting */
1239  vlib_buffer_length_in_chain (vm, b1),
1240  thread_index);
1241  /* Per-user LRU list maintenance */
1242  nat44_session_update_lru (sm, s1, thread_index);
1243 
1244  trace01:
1246  && (b1->flags & VLIB_BUFFER_IS_TRACED)))
1247  {
1249  vlib_add_trace (vm, node, b1, sizeof (*t));
1250  t->is_slow_path = is_slow_path;
1251  t->sw_if_index = sw_if_index1;
1252  t->next_index = next1;
1253  t->session_index = ~0;
1254  if (s1)
1255  t->session_index = s1 - tsm->sessions;
1256  }
1257 
1258  pkts_processed += next1 == NAT44_ED_OUT2IN_NEXT_LOOKUP;
1259 
1260  /* verify speculative enqueues, maybe switch current next frame */
1261  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
1262  to_next, n_left_to_next,
1263  bi0, bi1, next0, next1);
1264  }
1265 
1266  while (n_left_from > 0 && n_left_to_next > 0)
1267  {
1268  u32 bi0;
1269  vlib_buffer_t *b0;
1270  u32 next0, sw_if_index0, rx_fib_index0, proto0, old_addr0,
1271  new_addr0;
1272  u16 old_port0, new_port0;
1273  ip4_header_t *ip0;
1274  udp_header_t *udp0;
1275  tcp_header_t *tcp0;
1276  icmp46_header_t *icmp0;
1277  snat_session_t *s0 = 0;
1278  clib_bihash_kv_16_8_t kv0, value0;
1279  ip_csum_t sum0;
1280  snat_session_key_t e_key0, l_key0;
1281  lb_nat_type_t lb_nat0;
1282  twice_nat_type_t twice_nat0;
1283  u8 identity_nat0;
1284 
1285  /* speculatively enqueue b0 to the current next frame */
1286  bi0 = from[0];
1287  to_next[0] = bi0;
1288  from += 1;
1289  to_next += 1;
1290  n_left_from -= 1;
1291  n_left_to_next -= 1;
1292 
1293  b0 = vlib_get_buffer (vm, bi0);
1295  vnet_buffer (b0)->snat.flags = 0;
1296  ip0 = vlib_buffer_get_current (b0);
1297 
1298  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1299  rx_fib_index0 =
1301  sw_if_index0);
1302 
1303  if (PREDICT_FALSE (ip0->ttl == 1))
1304  {
1305  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1306  icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
1307  ICMP4_time_exceeded_ttl_exceeded_in_transit,
1308  0);
1310  goto trace0;
1311  }
1312 
1313  udp0 = ip4_next_header (ip0);
1314  tcp0 = (tcp_header_t *) udp0;
1315  icmp0 = (icmp46_header_t *) udp0;
1316  proto0 = ip_proto_to_snat_proto (ip0->protocol);
1317 
1318  if (is_slow_path)
1319  {
1320  if (PREDICT_FALSE (proto0 == ~0))
1321  {
1322  s0 =
1323  nat44_ed_out2in_unknown_proto (sm, b0, ip0, rx_fib_index0,
1324  thread_index, now, vm,
1325  node);
1326  other_packets++;
1327  if (!sm->forwarding_enabled)
1328  {
1329  if (!s0)
1330  next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1331  goto trace0;
1332  }
1333  }
1334 
1335  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
1336  {
1337  next0 = icmp_out2in_ed_slow_path
1338  (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
1339  next0, now, thread_index, &s0);
1340  icmp_packets++;
1341  goto trace0;
1342  }
1343  }
1344  else
1345  {
1346  if (PREDICT_FALSE (proto0 == ~0))
1347  {
1349  goto trace0;
1350  }
1351 
1352  if (ip4_is_fragment (ip0))
1353  {
1355  fragments++;
1356  goto trace0;
1357  }
1358 
1359  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
1360  {
1362  goto trace0;
1363  }
1364  }
1365 
1366  make_ed_kv (&kv0, &ip0->dst_address, &ip0->src_address,
1367  ip0->protocol, rx_fib_index0, udp0->dst_port,
1368  udp0->src_port);
1369 
1370  if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv0, &value0))
1371  {
1372  if (is_slow_path)
1373  {
1374  /* Try to match static mapping by external address and port,
1375  destination address and port in packet */
1376  e_key0.addr = ip0->dst_address;
1377  e_key0.port = udp0->dst_port;
1378  e_key0.protocol = proto0;
1379  e_key0.fib_index = rx_fib_index0;
1380  if (snat_static_mapping_match (sm, e_key0, &l_key0, 1, 0,
1381  &twice_nat0, &lb_nat0,
1382  &ip0->src_address,
1383  &identity_nat0))
1384  {
1385  /*
1386  * Send DHCP packets to the ipv4 stack, or we won't
1387  * be able to use dhcp client on the outside interface
1388  */
1389  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_UDP
1390  && (udp0->dst_port ==
1391  clib_host_to_net_u16
1392  (UDP_DST_PORT_dhcp_to_client))))
1393  {
1394  vnet_feature_next (&next0, b0);
1395  goto trace0;
1396  }
1397 
1398  if (!sm->forwarding_enabled)
1399  {
1400  b0->error =
1401  node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
1402  next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1403  }
1404  else
1405  {
1406  if (next_src_nat (sm, ip0, ip0->protocol,
1407  udp0->src_port, udp0->dst_port,
1408  thread_index, rx_fib_index0))
1409  {
1411  goto trace0;
1412  }
1413  if (sm->num_workers > 1)
1415  rx_fib_index0);
1416  else
1417  create_bypass_for_fwd (sm, ip0, rx_fib_index0,
1418  thread_index);
1419  }
1420  goto trace0;
1421  }
1422 
1423  if (PREDICT_FALSE (identity_nat0))
1424  goto trace0;
1425 
1426  if ((proto0 == SNAT_PROTOCOL_TCP) && !tcp_is_init (tcp0))
1427  {
1428  b0->error = node->errors[NAT_OUT2IN_ED_ERROR_NON_SYN];
1429  next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1430  goto trace0;
1431  }
1432 
1433  /* Create session initiated by host from external network */
1434  s0 = create_session_for_static_mapping_ed (sm, b0, l_key0,
1435  e_key0, node,
1436  thread_index,
1437  twice_nat0,
1438  lb_nat0, now);
1439 
1440  if (!s0)
1441  {
1442  next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1443  goto trace0;
1444  }
1445  }
1446  else
1447  {
1449  goto trace0;
1450  }
1451  }
1452  else
1453  {
1454  s0 = pool_elt_at_index (tsm->sessions, value0.value);
1455  }
1456 
1457  old_addr0 = ip0->dst_address.as_u32;
1458  new_addr0 = ip0->dst_address.as_u32 = s0->in2out.addr.as_u32;
1459  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
1460 
1461  sum0 = ip0->checksum;
1462  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1463  dst_address);
1465  sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
1466  s0->ext_host_nat_addr.as_u32, ip4_header_t,
1467  src_address);
1468  ip0->checksum = ip_csum_fold (sum0);
1469 
1470  old_port0 = udp0->dst_port;
1471  new_port0 = udp0->dst_port = s0->in2out.port;
1472 
1473  if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP))
1474  {
1475  sum0 = tcp0->checksum;
1476  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1477  dst_address);
1478  sum0 = ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
1479  length);
1480  if (is_twice_nat_session (s0))
1481  {
1482  sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
1483  s0->ext_host_nat_addr.as_u32,
1484  ip4_header_t, dst_address);
1485  sum0 = ip_csum_update (sum0, tcp0->src_port,
1486  s0->ext_host_nat_port, ip4_header_t,
1487  length);
1488  tcp0->src_port = s0->ext_host_nat_port;
1489  ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
1490  }
1491  tcp0->checksum = ip_csum_fold (sum0);
1492  tcp_packets++;
1494  (sm, s0, tcp0, thread_index))
1495  goto trace0;
1496  }
1497  else if (udp0->checksum)
1498  {
1499  sum0 = udp0->checksum;
1500  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1501  dst_address);
1502  sum0 = ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
1503  length);
1505  {
1506  sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
1507  s0->ext_host_nat_addr.as_u32,
1508  ip4_header_t, dst_address);
1509  sum0 = ip_csum_update (sum0, udp0->src_port,
1510  s0->ext_host_nat_port, ip4_header_t,
1511  length);
1512  udp0->src_port = s0->ext_host_nat_port;
1513  ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
1514  }
1515  udp0->checksum = ip_csum_fold (sum0);
1516  udp_packets++;
1517  }
1518  else
1519  {
1521  {
1522  udp0->src_port = s0->ext_host_nat_port;
1523  ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
1524  }
1525  udp_packets++;
1526  }
1527 
1528  /* Accounting */
1530  vlib_buffer_length_in_chain (vm, b0),
1531  thread_index);
1532  /* Per-user LRU list maintenance */
1533  nat44_session_update_lru (sm, s0, thread_index);
1534 
1535  trace0:
1537  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1538  {
1540  vlib_add_trace (vm, node, b0, sizeof (*t));
1541  t->is_slow_path = is_slow_path;
1542  t->sw_if_index = sw_if_index0;
1543  t->next_index = next0;
1544  t->session_index = ~0;
1545  if (s0)
1546  t->session_index = s0 - tsm->sessions;
1547  }
1548 
1549  pkts_processed += next0 == NAT44_ED_OUT2IN_NEXT_LOOKUP;
1550  /* verify speculative enqueue, maybe switch current next frame */
1551  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1552  to_next, n_left_to_next,
1553  bi0, next0);
1554  }
1555 
1556  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1557  }
1558 
1559  vlib_node_increment_counter (vm, stats_node_index,
1560  NAT_OUT2IN_ED_ERROR_OUT2IN_PACKETS,
1561  pkts_processed);
1562  vlib_node_increment_counter (vm, stats_node_index,
1563  NAT_OUT2IN_ED_ERROR_TCP_PACKETS, tcp_packets);
1564  vlib_node_increment_counter (vm, stats_node_index,
1565  NAT_OUT2IN_ED_ERROR_UDP_PACKETS, udp_packets);
1566  vlib_node_increment_counter (vm, stats_node_index,
1567  NAT_OUT2IN_ED_ERROR_ICMP_PACKETS,
1568  icmp_packets);
1569  vlib_node_increment_counter (vm, stats_node_index,
1570  NAT_OUT2IN_ED_ERROR_OTHER_PACKETS,
1571  other_packets);
1572  vlib_node_increment_counter (vm, stats_node_index,
1573  NAT_OUT2IN_ED_ERROR_FRAGMENTS, fragments);
1574  return frame->n_vectors;
1575 }
1576 
1578  vlib_node_runtime_t * node,
1579  vlib_frame_t * frame)
1580 {
1581  return nat44_ed_out2in_node_fn_inline (vm, node, frame, 0);
1582 }
1583 
1584 /* *INDENT-OFF* */
1586  .name = "nat44-ed-out2in",
1587  .vector_size = sizeof (u32),
1588  .format_trace = format_nat44_ed_out2in_trace,
1591  .error_strings = nat_out2in_ed_error_strings,
1592  .runtime_data_bytes = sizeof (snat_runtime_t),
1593  .n_next_nodes = NAT44_ED_OUT2IN_N_NEXT,
1594  .next_nodes = {
1595  [NAT44_ED_OUT2IN_NEXT_DROP] = "error-drop",
1596  [NAT44_ED_OUT2IN_NEXT_LOOKUP] = "ip4-lookup",
1597  [NAT44_ED_OUT2IN_NEXT_SLOW_PATH] = "nat44-ed-out2in-slowpath",
1598  [NAT44_ED_OUT2IN_NEXT_ICMP_ERROR] = "ip4-icmp-error",
1599  [NAT44_ED_OUT2IN_NEXT_IN2OUT] = "nat44-ed-in2out",
1600  [NAT44_ED_OUT2IN_NEXT_REASS] = "nat44-ed-out2in-reass",
1601  },
1602 };
1603 /* *INDENT-ON* */
1604 
1606  vlib_node_runtime_t * node,
1607  vlib_frame_t * frame)
1608 {
1609  return nat44_ed_out2in_node_fn_inline (vm, node, frame, 1);
1610 }
1611 
1612 /* *INDENT-OFF* */
1614  .name = "nat44-ed-out2in-slowpath",
1615  .vector_size = sizeof (u32),
1616  .format_trace = format_nat44_ed_out2in_trace,
1619  .error_strings = nat_out2in_ed_error_strings,
1620  .runtime_data_bytes = sizeof (snat_runtime_t),
1621  .n_next_nodes = NAT44_ED_OUT2IN_N_NEXT,
1622  .next_nodes = {
1623  [NAT44_ED_OUT2IN_NEXT_DROP] = "error-drop",
1624  [NAT44_ED_OUT2IN_NEXT_LOOKUP] = "ip4-lookup",
1625  [NAT44_ED_OUT2IN_NEXT_SLOW_PATH] = "nat44-ed-out2in-slowpath",
1626  [NAT44_ED_OUT2IN_NEXT_ICMP_ERROR] = "ip4-icmp-error",
1627  [NAT44_ED_OUT2IN_NEXT_IN2OUT] = "nat44-ed-in2out",
1628  [NAT44_ED_OUT2IN_NEXT_REASS] = "nat44-ed-out2in-reass",
1629  },
1630 };
1631 /* *INDENT-ON* */
1632 
1634  vlib_node_runtime_t * node,
1635  vlib_frame_t * frame)
1636 {
1637  u32 n_left_from, *from, *to_next;
1638  nat44_ed_out2in_next_t next_index;
1639  u32 pkts_processed = 0;
1640  snat_main_t *sm = &snat_main;
1641  f64 now = vlib_time_now (vm);
1642  u32 thread_index = vm->thread_index;
1644  &sm->per_thread_data[thread_index];
1645  u32 *fragments_to_drop = 0;
1646  u32 *fragments_to_loopback = 0;
1647 
1648  from = vlib_frame_vector_args (frame);
1649  n_left_from = frame->n_vectors;
1650  next_index = node->cached_next_index;
1651 
1652  while (n_left_from > 0)
1653  {
1654  u32 n_left_to_next;
1655 
1656  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1657 
1658  while (n_left_from > 0 && n_left_to_next > 0)
1659  {
1660  u32 bi0, sw_if_index0, proto0, rx_fib_index0, new_addr0, old_addr0;
1661  vlib_buffer_t *b0;
1662  u32 next0;
1663  u8 cached0 = 0;
1664  ip4_header_t *ip0;
1665  nat_reass_ip4_t *reass0;
1666  udp_header_t *udp0;
1667  tcp_header_t *tcp0;
1668  icmp46_header_t *icmp0;
1669  clib_bihash_kv_16_8_t kv0, value0;
1670  snat_session_t *s0 = 0;
1671  u16 old_port0, new_port0;
1672  ip_csum_t sum0;
1673  snat_session_key_t e_key0, l_key0;
1674  lb_nat_type_t lb0;
1675  twice_nat_type_t twice_nat0;
1676  u8 identity_nat0;
1677 
1678  /* speculatively enqueue b0 to the current next frame */
1679  bi0 = from[0];
1680  to_next[0] = bi0;
1681  from += 1;
1682  to_next += 1;
1683  n_left_from -= 1;
1684  n_left_to_next -= 1;
1685 
1686  b0 = vlib_get_buffer (vm, bi0);
1688 
1689  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1690  rx_fib_index0 =
1692  sw_if_index0);
1693 
1695  {
1696  next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1697  b0->error = node->errors[NAT_OUT2IN_ED_ERROR_DROP_FRAGMENT];
1698  goto trace0;
1699  }
1700 
1701  ip0 = (ip4_header_t *) vlib_buffer_get_current (b0);
1702  udp0 = ip4_next_header (ip0);
1703  tcp0 = (tcp_header_t *) udp0;
1704  icmp0 = (icmp46_header_t *) udp0;
1705  proto0 = ip_proto_to_snat_proto (ip0->protocol);
1706 
1708  ip0->dst_address,
1709  ip0->fragment_id,
1710  ip0->protocol,
1711  1, &fragments_to_drop);
1712 
1713  if (PREDICT_FALSE (!reass0))
1714  {
1715  next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1716  b0->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_REASS];
1717  nat_elog_notice ("maximum reassemblies exceeded");
1718  goto trace0;
1719  }
1720 
1722  {
1723  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
1724  {
1725  next0 = icmp_out2in_ed_slow_path
1726  (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
1727  next0, now, thread_index, &s0);
1728 
1729  if (PREDICT_TRUE (next0 != NAT44_ED_OUT2IN_NEXT_DROP))
1730  {
1731  if (s0)
1732  reass0->sess_index = s0 - per_thread_data->sessions;
1733  else
1734  reass0->flags |= NAT_REASS_FLAG_ED_DONT_TRANSLATE;
1735  reass0->thread_index = thread_index;
1736  nat_ip4_reass_get_frags (reass0,
1737  &fragments_to_loopback);
1738  }
1739 
1740  goto trace0;
1741  }
1742 
1743  make_ed_kv (&kv0, &ip0->dst_address, &ip0->src_address,
1744  ip0->protocol, rx_fib_index0, udp0->dst_port,
1745  udp0->src_port);
1746 
1747  if (clib_bihash_search_16_8
1748  (&per_thread_data->out2in_ed, &kv0, &value0))
1749  {
1750  /* Try to match static mapping by external address and port,
1751  destination address and port in packet */
1752  e_key0.addr = ip0->dst_address;
1753  e_key0.port = udp0->dst_port;
1754  e_key0.protocol = proto0;
1755  e_key0.fib_index = rx_fib_index0;
1756  if (snat_static_mapping_match (sm, e_key0, &l_key0, 1, 0,
1757  &twice_nat0, &lb0, 0,
1758  &identity_nat0))
1759  {
1760  /*
1761  * Send DHCP packets to the ipv4 stack, or we won't
1762  * be able to use dhcp client on the outside interface
1763  */
1764  if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_UDP
1765  && (udp0->dst_port
1766  ==
1767  clib_host_to_net_u16
1768  (UDP_DST_PORT_dhcp_to_client))))
1769  {
1770  vnet_feature_next (&next0, b0);
1771  goto trace0;
1772  }
1773 
1774  if (!sm->forwarding_enabled)
1775  {
1776  b0->error =
1777  node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
1778  next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1779  }
1780  else
1781  {
1782  if (next_src_nat (sm, ip0, ip0->protocol,
1783  udp0->src_port, udp0->dst_port,
1784  thread_index, rx_fib_index0))
1785  {
1787  goto trace0;
1788  }
1789  if (sm->num_workers > 1)
1791  rx_fib_index0);
1792  else
1793  create_bypass_for_fwd (sm, ip0, rx_fib_index0,
1794  thread_index);
1795  reass0->flags |= NAT_REASS_FLAG_ED_DONT_TRANSLATE;
1796  nat_ip4_reass_get_frags (reass0,
1797  &fragments_to_loopback);
1798  }
1799  goto trace0;
1800  }
1801 
1802  if (PREDICT_FALSE (identity_nat0))
1803  {
1804  reass0->flags |= NAT_REASS_FLAG_ED_DONT_TRANSLATE;
1805  goto trace0;
1806  }
1807 
1808  if ((proto0 == SNAT_PROTOCOL_TCP) && !tcp_is_init (tcp0))
1809  {
1810  b0->error = node->errors[NAT_OUT2IN_ED_ERROR_NON_SYN];
1811  next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1812  goto trace0;
1813  }
1814 
1815  /* Create session initiated by host from external network */
1816  s0 = create_session_for_static_mapping_ed (sm, b0, l_key0,
1817  e_key0, node,
1818  thread_index,
1819  twice_nat0, lb0,
1820  now);
1821  if (!s0)
1822  {
1823  b0->error =
1824  node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION];
1825  next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1826  goto trace0;
1827  }
1828  reass0->sess_index = s0 - per_thread_data->sessions;
1829  reass0->thread_index = thread_index;
1830  }
1831  else
1832  {
1833  s0 = pool_elt_at_index (per_thread_data->sessions,
1834  value0.value);
1835  reass0->sess_index = value0.value;
1836  }
1837  nat_ip4_reass_get_frags (reass0, &fragments_to_loopback);
1838  }
1839  else
1840  {
1841  if (reass0->flags & NAT_REASS_FLAG_ED_DONT_TRANSLATE)
1842  goto trace0;
1843  if (PREDICT_FALSE (reass0->sess_index == (u32) ~ 0))
1844  {
1846  (thread_index, reass0, bi0, &fragments_to_drop))
1847  {
1848  b0->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_FRAG];
1850  ("maximum fragments per reassembly exceeded");
1851  next0 = NAT44_ED_OUT2IN_NEXT_DROP;
1852  goto trace0;
1853  }
1854  cached0 = 1;
1855  goto trace0;
1856  }
1857  s0 = pool_elt_at_index (per_thread_data->sessions,
1858  reass0->sess_index);
1859  }
1860 
1861  old_addr0 = ip0->dst_address.as_u32;
1862  ip0->dst_address = s0->in2out.addr;
1863  new_addr0 = ip0->dst_address.as_u32;
1864  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
1865 
1866  sum0 = ip0->checksum;
1867  sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1868  ip4_header_t,
1869  dst_address /* changed member */ );
1871  sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
1872  s0->ext_host_nat_addr.as_u32, ip4_header_t,
1873  src_address);
1874  ip0->checksum = ip_csum_fold (sum0);
1875 
1877  {
1878  old_port0 = udp0->dst_port;
1879  new_port0 = udp0->dst_port = s0->in2out.port;
1880 
1881  if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP))
1882  {
1883  sum0 = tcp0->checksum;
1884  sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1885  ip4_header_t,
1886  dst_address /* changed member */ );
1887 
1888  sum0 = ip_csum_update (sum0, old_port0, new_port0,
1889  ip4_header_t /* cheat */ ,
1890  length /* changed member */ );
1891  if (is_twice_nat_session (s0))
1892  {
1893  sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
1894  s0->ext_host_nat_addr.as_u32,
1895  ip4_header_t, dst_address);
1896  sum0 = ip_csum_update (sum0, tcp0->src_port,
1897  s0->ext_host_nat_port,
1898  ip4_header_t, length);
1899  tcp0->src_port = s0->ext_host_nat_port;
1900  ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
1901  }
1902  tcp0->checksum = ip_csum_fold (sum0);
1903  }
1904  else if (udp0->checksum)
1905  {
1906  sum0 = udp0->checksum;
1907  sum0 =
1908  ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1909  dst_address);
1910  sum0 =
1911  ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
1912  length);
1914  {
1915  sum0 = ip_csum_update (sum0, ip0->src_address.as_u32,
1916  s0->ext_host_nat_addr.as_u32,
1917  ip4_header_t, dst_address);
1918  sum0 = ip_csum_update (sum0, udp0->src_port,
1919  s0->ext_host_nat_port,
1920  ip4_header_t, length);
1921  udp0->src_port = s0->ext_host_nat_port;
1922  ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
1923  }
1924  udp0->checksum = ip_csum_fold (sum0);
1925  }
1926  else
1927  {
1929  {
1930  udp0->src_port = s0->ext_host_nat_port;
1931  ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
1932  }
1933  }
1934  }
1935 
1936  /* Accounting */
1938  vlib_buffer_length_in_chain (vm, b0),
1939  thread_index);
1940  /* Per-user LRU list maintenance */
1941  nat44_session_update_lru (sm, s0, thread_index);
1942 
1943  trace0:
1944  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
1945  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1946  {
1947  nat44_reass_trace_t *t =
1948  vlib_add_trace (vm, node, b0, sizeof (*t));
1949  t->cached = cached0;
1950  t->sw_if_index = sw_if_index0;
1951  t->next_index = next0;
1952  }
1953 
1954  if (cached0)
1955  {
1956  n_left_to_next++;
1957  to_next--;
1958  }
1959  else
1960  {
1961  pkts_processed += next0 != NAT44_ED_OUT2IN_NEXT_DROP;
1962 
1963  /* verify speculative enqueue, maybe switch current next frame */
1964  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1965  to_next, n_left_to_next,
1966  bi0, next0);
1967  }
1968 
1969  if (n_left_from == 0 && vec_len (fragments_to_loopback))
1970  {
1971  from = vlib_frame_vector_args (frame);
1972  u32 len = vec_len (fragments_to_loopback);
1973  if (len <= VLIB_FRAME_SIZE)
1974  {
1975  clib_memcpy_fast (from, fragments_to_loopback,
1976  sizeof (u32) * len);
1977  n_left_from = len;
1978  vec_reset_length (fragments_to_loopback);
1979  }
1980  else
1981  {
1982  clib_memcpy_fast (from, fragments_to_loopback +
1983  (len - VLIB_FRAME_SIZE),
1984  sizeof (u32) * VLIB_FRAME_SIZE);
1985  n_left_from = VLIB_FRAME_SIZE;
1986  _vec_len (fragments_to_loopback) = len - VLIB_FRAME_SIZE;
1987  }
1988  }
1989  }
1990 
1991  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1992  }
1993 
1995  NAT_OUT2IN_ED_ERROR_OUT2IN_PACKETS,
1996  pkts_processed);
1997 
1998  nat_send_all_to_node (vm, fragments_to_drop, node,
1999  &node->errors[NAT_OUT2IN_ED_ERROR_DROP_FRAGMENT],
2001 
2002  vec_free (fragments_to_drop);
2003  vec_free (fragments_to_loopback);
2004  return frame->n_vectors;
2005 }
2006 
2007 /* *INDENT-OFF* */
2009  .name = "nat44-ed-out2in-reass",
2010  .vector_size = sizeof (u32),
2011  .format_trace = format_nat44_reass_trace,
2014  .error_strings = nat_out2in_ed_error_strings,
2015  .n_next_nodes = NAT44_ED_OUT2IN_N_NEXT,
2016  .next_nodes = {
2017  [NAT44_ED_OUT2IN_NEXT_DROP] = "error-drop",
2018  [NAT44_ED_OUT2IN_NEXT_LOOKUP] = "ip4-lookup",
2019  [NAT44_ED_OUT2IN_NEXT_SLOW_PATH] = "nat44-ed-out2in-slowpath",
2020  [NAT44_ED_OUT2IN_NEXT_ICMP_ERROR] = "ip4-icmp-error",
2021  [NAT44_ED_OUT2IN_NEXT_IN2OUT] = "nat44-ed-in2out",
2022  [NAT44_ED_OUT2IN_NEXT_REASS] = "nat44-ed-out2in-reass",
2023  },
2024 };
2025 /* *INDENT-ON* */
2026 
2027 /*
2028  * fd.io coding-style-patch-verification: ON
2029  *
2030  * Local Variables:
2031  * eval: (c-set-style "gnu")
2032  * End:
2033  */
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:270
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:279
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:972
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:334
u16 port_per_thread
Definition: nat.h:521
u32 thread_index
Definition: main.h:218
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:1585
#define VLIB_NODE_FN(node)
Definition: node.h:202
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:470
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:238
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:399
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:378
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:2522
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:2448
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:2681
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:2008
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:397
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:323
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:302
static void nat44_session_update_counters(snat_session_t *s, f64 now, uword bytes, u32 thread_index)
Definition: nat_inlines.h:293
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:456
vlib_node_registration_t nat44_ed_out2in_slowpath_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_out2in_slowpath_node)
Definition: out2in_ed.c:1613
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:317
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:515
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:307
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:247
#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:365
#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:509
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:302
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
snat_session_t * sessions
Definition: nat.h:472
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: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
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.