FD.io VPP  v18.11-rc0-18-g2a3fb1a
Vector Packet Processing
nat.c
Go to the documentation of this file.
1 /*
2  * snat.c - simple nat plugin
3  *
4  * Copyright (c) 2016 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <vnet/vnet.h>
19 #include <vnet/ip/ip.h>
20 #include <vnet/ip/ip4.h>
21 #include <vnet/plugin/plugin.h>
22 #include <nat/nat.h>
23 #include <nat/nat_dpo.h>
24 #include <nat/nat_ipfix_logging.h>
25 #include <nat/nat_det.h>
26 #include <nat/nat64.h>
27 #include <nat/nat66.h>
28 #include <nat/dslite.h>
29 #include <nat/nat_reass.h>
30 #include <nat/nat_inlines.h>
31 #include <vnet/fib/fib_table.h>
32 #include <vnet/fib/ip4_fib.h>
33 
34 #include <vpp/app/version.h>
35 
37 
38 
39 /* Hook up input features */
40 VNET_FEATURE_INIT (ip4_snat_in2out, static) = {
41  .arc_name = "ip4-unicast",
42  .node_name = "nat44-in2out",
43  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
44 };
45 VNET_FEATURE_INIT (ip4_snat_out2in, static) = {
46  .arc_name = "ip4-unicast",
47  .node_name = "nat44-out2in",
48  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
49  "ip4-dhcp-client-detect"),
50 };
51 VNET_FEATURE_INIT (ip4_nat_classify, static) = {
52  .arc_name = "ip4-unicast",
53  .node_name = "nat44-classify",
54  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
55 };
56 VNET_FEATURE_INIT (ip4_snat_det_in2out, static) = {
57  .arc_name = "ip4-unicast",
58  .node_name = "nat44-det-in2out",
59  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
60 };
61 VNET_FEATURE_INIT (ip4_snat_det_out2in, static) = {
62  .arc_name = "ip4-unicast",
63  .node_name = "nat44-det-out2in",
64  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
65  "ip4-dhcp-client-detect"),
66 };
67 VNET_FEATURE_INIT (ip4_nat_det_classify, static) = {
68  .arc_name = "ip4-unicast",
69  .node_name = "nat44-det-classify",
70  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
71 };
72 VNET_FEATURE_INIT (ip4_nat44_ed_in2out, static) = {
73  .arc_name = "ip4-unicast",
74  .node_name = "nat44-ed-in2out",
75  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
76 };
77 VNET_FEATURE_INIT (ip4_nat44_ed_out2in, static) = {
78  .arc_name = "ip4-unicast",
79  .node_name = "nat44-ed-out2in",
80  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
81  "ip4-dhcp-client-detect"),
82 };
83 VNET_FEATURE_INIT (ip4_nat44_ed_classify, static) = {
84  .arc_name = "ip4-unicast",
85  .node_name = "nat44-ed-classify",
86  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
87 };
88 VNET_FEATURE_INIT (ip4_snat_in2out_worker_handoff, static) = {
89  .arc_name = "ip4-unicast",
90  .node_name = "nat44-in2out-worker-handoff",
91  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
92 };
93 VNET_FEATURE_INIT (ip4_snat_out2in_worker_handoff, static) = {
94  .arc_name = "ip4-unicast",
95  .node_name = "nat44-out2in-worker-handoff",
96  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
97  "ip4-dhcp-client-detect"),
98 };
99 VNET_FEATURE_INIT (ip4_nat_handoff_classify, static) = {
100  .arc_name = "ip4-unicast",
101  .node_name = "nat44-handoff-classify",
102  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
103 };
104 VNET_FEATURE_INIT (ip4_snat_in2out_fast, static) = {
105  .arc_name = "ip4-unicast",
106  .node_name = "nat44-in2out-fast",
107  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
108 };
109 VNET_FEATURE_INIT (ip4_snat_out2in_fast, static) = {
110  .arc_name = "ip4-unicast",
111  .node_name = "nat44-out2in-fast",
112  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
113  "ip4-dhcp-client-detect"),
114 };
115 VNET_FEATURE_INIT (ip4_snat_hairpin_dst, static) = {
116  .arc_name = "ip4-unicast",
117  .node_name = "nat44-hairpin-dst",
118  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
119 };
120 VNET_FEATURE_INIT (ip4_nat44_ed_hairpin_dst, static) = {
121  .arc_name = "ip4-unicast",
122  .node_name = "nat44-ed-hairpin-dst",
123  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
124 };
125 
126 /* Hook up output features */
127 VNET_FEATURE_INIT (ip4_snat_in2out_output, static) = {
128  .arc_name = "ip4-output",
129  .node_name = "nat44-in2out-output",
130  .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
131 };
132 VNET_FEATURE_INIT (ip4_snat_in2out_output_worker_handoff, static) = {
133  .arc_name = "ip4-output",
134  .node_name = "nat44-in2out-output-worker-handoff",
135  .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
136 };
137 VNET_FEATURE_INIT (ip4_snat_hairpin_src, static) = {
138  .arc_name = "ip4-output",
139  .node_name = "nat44-hairpin-src",
140  .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
141 };
142 VNET_FEATURE_INIT (ip4_nat44_ed_in2out_output, static) = {
143  .arc_name = "ip4-output",
144  .node_name = "nat44-ed-in2out-output",
145  .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
146 };
147 VNET_FEATURE_INIT (ip4_nat44_ed_hairpin_src, static) = {
148  .arc_name = "ip4-output",
149  .node_name = "nat44-ed-hairpin-src",
150  .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
151 };
152 
153 /* Hook up ip4-local features */
154 VNET_FEATURE_INIT (ip4_nat_hairpinning, static) =
155 {
156  .arc_name = "ip4-local",
157  .node_name = "nat44-hairpinning",
158  .runs_before = VNET_FEATURES("ip4-local-end-of-arc"),
159 };
160 VNET_FEATURE_INIT (ip4_nat44_ed_hairpinning, static) =
161 {
162  .arc_name = "ip4-local",
163  .node_name = "nat44-ed-hairpinning",
164  .runs_before = VNET_FEATURES("ip4-local-end-of-arc"),
165 };
166 
167 
168 /* *INDENT-OFF* */
170  .version = VPP_BUILD_VER,
171  .description = "Network Address Translation",
172 };
173 /* *INDENT-ON* */
174 
179 
180 typedef enum {
185 
186 void
187 nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index)
188 {
189  snat_session_key_t key;
191  nat_ed_ses_key_t ed_key;
192  clib_bihash_kv_16_8_t ed_kv;
193  int i;
194  snat_address_t *a;
196  vec_elt_at_index (sm->per_thread_data, thread_index);
197 
198  if (is_fwd_bypass_session (s))
199  {
200  ed_key.l_addr = s->in2out.addr;
201  ed_key.r_addr = s->ext_host_addr;
202  ed_key.l_port = s->in2out.port;
203  ed_key.r_port = s->ext_host_port;
204  ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol);
205  ed_key.fib_index = 0;
206  ed_kv.key[0] = ed_key.as_u64[0];
207  ed_kv.key[1] = ed_key.as_u64[1];
208  if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0))
209  nat_log_warn ("in2out_ed key del failed");
210  return;
211  }
212 
213  /* session lookup tables */
214  if (is_ed_session (s))
215  {
216  ed_key.l_addr = s->out2in.addr;
217  ed_key.r_addr = s->ext_host_addr;
218  ed_key.fib_index = s->out2in.fib_index;
220  {
221  ed_key.proto = s->in2out.port;
222  ed_key.r_port = 0;
223  ed_key.l_port = 0;
224  }
225  else
226  {
227  ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol);
228  ed_key.l_port = s->out2in.port;
229  ed_key.r_port = s->ext_host_port;
230  }
231  ed_kv.key[0] = ed_key.as_u64[0];
232  ed_kv.key[1] = ed_key.as_u64[1];
233  if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &ed_kv, 0))
234  nat_log_warn ("out2in_ed key del failed");
235 
236  ed_key.l_addr = s->in2out.addr;
237  ed_key.fib_index = s->in2out.fib_index;
238  if (!snat_is_unk_proto_session (s))
239  ed_key.l_port = s->in2out.port;
240  if (is_twice_nat_session (s))
241  {
242  ed_key.r_addr = s->ext_host_nat_addr;
243  ed_key.r_port = s->ext_host_nat_port;
244  }
245  ed_kv.key[0] = ed_key.as_u64[0];
246  ed_kv.key[1] = ed_key.as_u64[1];
247  if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0))
248  nat_log_warn ("in2out_ed key del failed");
249  }
250  else
251  {
252  kv.key = s->in2out.as_u64;
253  if (clib_bihash_add_del_8_8 (&tsm->in2out, &kv, 0))
254  nat_log_warn ("in2out key del failed");
255  kv.key = s->out2in.as_u64;
256  if (clib_bihash_add_del_8_8 (&tsm->out2in, &kv, 0))
257  nat_log_warn ("out2in key del failed");
258  }
259 
261  return;
262 
263  /* log NAT event */
264  snat_ipfix_logging_nat44_ses_delete(s->in2out.addr.as_u32,
265  s->out2in.addr.as_u32,
266  s->in2out.protocol,
267  s->in2out.port,
268  s->out2in.port,
269  s->in2out.fib_index);
270 
271  /* Twice NAT address and port for external host */
272  if (is_twice_nat_session (s))
273  {
274  for (i = 0; i < vec_len (sm->twice_nat_addresses); i++)
275  {
276  key.protocol = s->in2out.protocol;
277  key.port = s->ext_host_nat_port;
278  a = sm->twice_nat_addresses + i;
279  if (a->addr.as_u32 == s->ext_host_nat_addr.as_u32)
280  {
282  thread_index, &key, i);
283  break;
284  }
285  }
286  }
287 
288  if (snat_is_session_static (s))
289  return;
290 
291  if (s->outside_address_index != ~0)
293  &s->out2in, s->outside_address_index);
294 }
295 
296 snat_user_t *
298  u32 thread_index)
299 {
300  snat_user_t *u = 0;
301  snat_user_key_t user_key;
302  clib_bihash_kv_8_8_t kv, value;
303  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
304  dlist_elt_t * per_user_list_head_elt;
305 
306  user_key.addr.as_u32 = addr->as_u32;
307  user_key.fib_index = fib_index;
308  kv.key = user_key.as_u64;
309 
310  /* Ever heard of the "user" = src ip4 address before? */
311  if (clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
312  {
313  /* no, make a new one */
314  pool_get (tsm->users, u);
315  memset (u, 0, sizeof (*u));
316  u->addr.as_u32 = addr->as_u32;
317  u->fib_index = fib_index;
318 
319  pool_get (tsm->list_pool, per_user_list_head_elt);
320 
321  u->sessions_per_user_list_head_index = per_user_list_head_elt -
322  tsm->list_pool;
323 
325 
326  kv.value = u - tsm->users;
327 
328  /* add user */
329  if (clib_bihash_add_del_8_8 (&tsm->user_hash, &kv, 1))
330  nat_log_warn ("user_hash keay add failed");
331  }
332  else
333  {
334  u = pool_elt_at_index (tsm->users, value.value);
335  }
336 
337  return u;
338 }
339 
340 snat_session_t *
342 {
343  snat_session_t *s;
344  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
345  u32 oldest_per_user_translation_list_index, session_index;
346  dlist_elt_t * oldest_per_user_translation_list_elt;
347  dlist_elt_t * per_user_translation_list_elt;
348 
349  /* Over quota? Recycle the least recently used translation */
351  {
352  oldest_per_user_translation_list_index =
355 
356  ASSERT (oldest_per_user_translation_list_index != ~0);
357 
358  /* Add it back to the end of the LRU list */
361  oldest_per_user_translation_list_index);
362  /* Get the list element */
363  oldest_per_user_translation_list_elt =
365  oldest_per_user_translation_list_index);
366 
367  /* Get the session index from the list element */
368  session_index = oldest_per_user_translation_list_elt->value;
369 
370  /* Get the session */
371  s = pool_elt_at_index (tsm->sessions, session_index);
372  nat_free_session_data (sm, s, thread_index);
373  if (snat_is_session_static(s))
374  u->nstaticsessions--;
375  else
376  u->nsessions--;
377  s->outside_address_index = ~0;
378  s->flags = 0;
379  s->total_bytes = 0;
380  s->total_pkts = 0;
381  s->state = 0;
382  s->ext_host_addr.as_u32 = 0;
383  s->ext_host_port = 0;
384  s->ext_host_nat_addr.as_u32 = 0;
385  s->ext_host_nat_port = 0;
386  }
387  else
388  {
389  pool_get (tsm->sessions, s);
390  memset (s, 0, sizeof (*s));
391  s->outside_address_index = ~0;
392 
393  /* Create list elts */
394  pool_get (tsm->list_pool, per_user_translation_list_elt);
396  per_user_translation_list_elt - tsm->list_pool);
397 
398  per_user_translation_list_elt->value = s - tsm->sessions;
399  s->per_user_index = per_user_translation_list_elt - tsm->list_pool;
400  s->per_user_list_head_index = u->sessions_per_user_list_head_index;
401 
403  s->per_user_list_head_index,
404  per_user_translation_list_elt - tsm->list_pool);
405  }
406 
407  return s;
408 }
409 
410 typedef struct {
413 
414 static u8 * format_nat44_classify_trace (u8 * s, va_list * args)
415 {
416  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
417  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
418  nat44_classify_trace_t *t = va_arg (*args, nat44_classify_trace_t *);
419  char *next;
420 
421  next = t->next_in2out ? "nat44-in2out" : "nat44-out2in";
422 
423  s = format (s, "nat44-classify: next %s", next);
424 
425  return s;
426 }
427 
428 static inline uword
430  vlib_node_runtime_t * node,
431  vlib_frame_t * frame)
432 {
433  u32 n_left_from, * from, * to_next;
434  nat44_classify_next_t next_index;
435  snat_main_t *sm = &snat_main;
437 
438  from = vlib_frame_vector_args (frame);
439  n_left_from = frame->n_vectors;
440  next_index = node->cached_next_index;
441 
442  while (n_left_from > 0)
443  {
444  u32 n_left_to_next;
445 
446  vlib_get_next_frame (vm, node, next_index,
447  to_next, n_left_to_next);
448 
449  while (n_left_from > 0 && n_left_to_next > 0)
450  {
451  u32 bi0;
452  vlib_buffer_t *b0;
454  ip4_header_t *ip0;
455  snat_address_t *ap;
456  snat_session_key_t m_key0;
457  clib_bihash_kv_8_8_t kv0, value0;
458 
459  /* speculatively enqueue b0 to the current next frame */
460  bi0 = from[0];
461  to_next[0] = bi0;
462  from += 1;
463  to_next += 1;
464  n_left_from -= 1;
465  n_left_to_next -= 1;
466 
467  b0 = vlib_get_buffer (vm, bi0);
468  ip0 = vlib_buffer_get_current (b0);
469 
470  vec_foreach (ap, sm->addresses)
471  {
472  if (ip0->dst_address.as_u32 == ap->addr.as_u32)
473  {
475  goto enqueue0;
476  }
477  }
478 
480  {
481  m_key0.addr = ip0->dst_address;
482  m_key0.port = 0;
483  m_key0.protocol = 0;
484  m_key0.fib_index = sm->outside_fib_index;
485  kv0.key = m_key0.as_u64;
486  if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv0, &value0))
487  {
488  m = pool_elt_at_index (sm->static_mappings, value0.value);
489  if (m->local_addr.as_u32 != m->external_addr.as_u32)
491  goto enqueue0;
492  }
493  udp_header_t * udp0 = ip4_next_header (ip0);
494  m_key0.port = clib_net_to_host_u16 (udp0->dst_port);
495  m_key0.protocol = ip_proto_to_snat_proto (ip0->protocol);
496  kv0.key = m_key0.as_u64;
497  if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv0, &value0))
498  {
499  m = pool_elt_at_index (sm->static_mappings, value0.value);
500  if (m->local_addr.as_u32 != m->external_addr.as_u32)
502  }
503  }
504 
505  enqueue0:
507  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
508  {
510  vlib_add_trace (vm, node, b0, sizeof (*t));
511  t->next_in2out = next0 == NAT44_CLASSIFY_NEXT_IN2OUT ? 1 : 0;
512  }
513 
514  /* verify speculative enqueue, maybe switch current next frame */
515  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
516  to_next, n_left_to_next,
517  bi0, next0);
518  }
519 
520  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
521  }
522 
523  return frame->n_vectors;
524 }
525 
526 static uword
528  vlib_node_runtime_t * node,
529  vlib_frame_t * frame)
530 {
531  return nat44_classify_node_fn_inline (vm, node, frame);
532 };
533 
535  .function = nat44_classify_node_fn,
536  .name = "nat44-classify",
537  .vector_size = sizeof (u32),
538  .format_trace = format_nat44_classify_trace,
539  .type = VLIB_NODE_TYPE_INTERNAL,
540  .n_next_nodes = NAT44_CLASSIFY_N_NEXT,
541  .next_nodes = {
542  [NAT44_CLASSIFY_NEXT_IN2OUT] = "nat44-in2out",
543  [NAT44_CLASSIFY_NEXT_OUT2IN] = "nat44-out2in",
544  },
545 };
546 
549 static uword
551  vlib_node_runtime_t * node,
552  vlib_frame_t * frame)
553 {
554  return nat44_classify_node_fn_inline (vm, node, frame);
555 };
556 
558  .function = nat44_ed_classify_node_fn,
559  .name = "nat44-ed-classify",
560  .vector_size = sizeof (u32),
561  .format_trace = format_nat44_classify_trace,
562  .type = VLIB_NODE_TYPE_INTERNAL,
563  .n_next_nodes = NAT44_CLASSIFY_N_NEXT,
564  .next_nodes = {
565  [NAT44_CLASSIFY_NEXT_IN2OUT] = "nat44-ed-in2out",
566  [NAT44_CLASSIFY_NEXT_OUT2IN] = "nat44-ed-out2in",
567  },
568 };
569 
572 
573 static uword
575  vlib_node_runtime_t * node,
576  vlib_frame_t * frame)
577 {
578  return nat44_classify_node_fn_inline (vm, node, frame);
579 };
580 
582  .function = nat44_det_classify_node_fn,
583  .name = "nat44-det-classify",
584  .vector_size = sizeof (u32),
585  .format_trace = format_nat44_classify_trace,
586  .type = VLIB_NODE_TYPE_INTERNAL,
587  .n_next_nodes = NAT44_CLASSIFY_N_NEXT,
588  .next_nodes = {
589  [NAT44_CLASSIFY_NEXT_IN2OUT] = "nat44-det-in2out",
590  [NAT44_CLASSIFY_NEXT_OUT2IN] = "nat44-det-out2in",
591  },
592 };
593 
596 
597 static uword
599  vlib_node_runtime_t * node,
600  vlib_frame_t * frame)
601 {
602  return nat44_classify_node_fn_inline (vm, node, frame);
603 };
604 
606  .function = nat44_handoff_classify_node_fn,
607  .name = "nat44-handoff-classify",
608  .vector_size = sizeof (u32),
609  .format_trace = format_nat44_classify_trace,
610  .type = VLIB_NODE_TYPE_INTERNAL,
611  .n_next_nodes = NAT44_CLASSIFY_N_NEXT,
612  .next_nodes = {
613  [NAT44_CLASSIFY_NEXT_IN2OUT] = "nat44-in2out-worker-handoff",
614  [NAT44_CLASSIFY_NEXT_OUT2IN] = "nat44-out2in-worker-handoff",
615  },
616 };
617 
620 
621 /**
622  * @brief Add/del NAT address to FIB.
623  *
624  * Add the external NAT address to the FIB as receive entries. This ensures
625  * that VPP will reply to ARP for this address and we don't need to enable
626  * proxy ARP on the outside interface.
627  *
628  * @param addr IPv4 address.
629  * @param plen address prefix length
630  * @param sw_if_index Interface.
631  * @param is_add If 0 delete, otherwise add.
632  */
633 void
635  int is_add)
636 {
637  fib_prefix_t prefix = {
638  .fp_len = p_len,
639  .fp_proto = FIB_PROTOCOL_IP4,
640  .fp_addr = {
641  .ip4.as_u32 = addr->as_u32,
642  },
643  };
644  u32 fib_index = ip4_fib_table_get_index_for_sw_if_index(sw_if_index);
645 
646  if (is_add)
648  &prefix,
654  NULL,
655  sw_if_index,
656  ~0,
657  1,
658  NULL,
660  else
661  fib_table_entry_delete(fib_index,
662  &prefix,
664 }
665 
667  u8 twice_nat)
668 {
669  snat_address_t * ap;
672 
673  if (twice_nat && !sm->endpoint_dependent)
674  return VNET_API_ERROR_FEATURE_DISABLED;
675 
676  /* Check if address already exists */
677  vec_foreach (ap, twice_nat ? sm->twice_nat_addresses : sm->addresses)
678  {
679  if (ap->addr.as_u32 == addr->as_u32)
680  return VNET_API_ERROR_VALUE_EXIST;
681  }
682 
683  if (twice_nat)
684  vec_add2 (sm->twice_nat_addresses, ap, 1);
685  else
686  vec_add2 (sm->addresses, ap, 1);
687 
688  ap->addr = *addr;
689  if (vrf_id != ~0)
690  ap->fib_index =
693  else
694  ap->fib_index = ~0;
695 #define _(N, i, n, s) \
696  clib_bitmap_alloc (ap->busy_##n##_port_bitmap, 65535); \
697  ap->busy_##n##_ports = 0; \
698  vec_validate_init_empty (ap->busy_##n##_ports_per_thread, tm->n_vlib_mains - 1, 0);
700 #undef _
701 
702  if (twice_nat)
703  return 0;
704 
705  /* Add external address to FIB */
706  pool_foreach (i, sm->interfaces,
707  ({
708  if (nat_interface_is_inside(i) || sm->out2in_dpo)
709  continue;
710 
711  snat_add_del_addr_to_fib(addr, 32, i->sw_if_index, 1);
712  break;
713  }));
715  ({
716  if (nat_interface_is_inside(i) || sm->out2in_dpo)
717  continue;
718 
719  snat_add_del_addr_to_fib(addr, 32, i->sw_if_index, 1);
720  break;
721  }));
722 
723  return 0;
724 }
725 
728 {
731  ({
732  if (m->external_addr.as_u32 == addr.as_u32)
733  return 1;
734  }));
735 
736  return 0;
737 }
738 
740 {
741  u32 v;
742 
743  v = clib_net_to_host_u32(a->as_u32) + 1;
744  a->as_u32 = clib_host_to_net_u32(v);
745 }
746 
747 static void
749  ip4_address_t l_addr,
750  u16 l_port,
751  u32 sw_if_index,
752  u16 e_port,
753  u32 vrf_id,
754  snat_protocol_t proto,
755  int addr_only,
756  int is_add,
757  u8 * tag)
758 {
760 
761  vec_add2 (sm->to_resolve, rp, 1);
762  rp->l_addr.as_u32 = l_addr.as_u32;
763  rp->l_port = l_port;
764  rp->sw_if_index = sw_if_index;
765  rp->e_port = e_port;
766  rp->vrf_id = vrf_id;
767  rp->proto = proto;
768  rp->addr_only = addr_only;
769  rp->is_add = is_add;
770  rp->tag = vec_dup (tag);
771 }
772 
773 /**
774  * @brief Add static mapping.
775  *
776  * Create static mapping between local addr+port and external addr+port.
777  *
778  * @param l_addr Local IPv4 address.
779  * @param e_addr External IPv4 address.
780  * @param l_port Local port number.
781  * @param e_port External port number.
782  * @param vrf_id VRF ID.
783  * @param addr_only If 0 address port and pair mapping, otherwise address only.
784  * @param sw_if_index External port instead of specific IP address.
785  * @param is_add If 0 delete static mapping, otherwise add.
786  * @param twice_nat If value is TWICE_NAT then translate external host address
787  * and port.
788  * If value is TWICE_NAT_SELF then translate external host
789  * address and port whenever external host address equals
790  * local address of internal host.
791  * @param out2in_only If 1 rule match only out2in direction
792  * @param tag - opaque string tag
793  *
794  * @returns
795  */
797  u16 l_port, u16 e_port, u32 vrf_id, int addr_only,
798  u32 sw_if_index, snat_protocol_t proto, int is_add,
799  twice_nat_type_t twice_nat, u8 out2in_only,
800  u8 * tag)
801 {
802  snat_main_t * sm = &snat_main;
804  snat_session_key_t m_key;
805  clib_bihash_kv_8_8_t kv, value;
806  snat_address_t *a = 0;
807  u32 fib_index = ~0;
808  uword * p;
809  snat_interface_t *interface;
810  int i;
812  snat_user_key_t u_key;
813  snat_user_t *u;
814  dlist_elt_t * head, * elt;
815  u32 elt_index, head_index;
816  u32 ses_index;
817  u64 user_index;
818  snat_session_t * s;
819  snat_static_map_resolve_t *rp, *rp_match = 0;
820 
821  if (!sm->endpoint_dependent)
822  {
823  if (twice_nat || out2in_only)
824  return VNET_API_ERROR_FEATURE_DISABLED;
825  }
826 
827  /* If the external address is a specific interface address */
828  if (sw_if_index != ~0)
829  {
830  ip4_address_t * first_int_addr;
831 
832  for (i = 0; i < vec_len (sm->to_resolve); i++)
833  {
834  rp = sm->to_resolve + i;
835  if (rp->sw_if_index != sw_if_index ||
836  rp->l_addr.as_u32 != l_addr.as_u32 ||
837  rp->vrf_id != vrf_id || rp->addr_only != addr_only)
838  continue;
839 
840  if (!addr_only)
841  {
842  if (rp->l_port != l_port || rp->e_port != e_port || rp->proto != proto)
843  continue;
844  }
845 
846  rp_match = rp;
847  break;
848  }
849 
850  /* Might be already set... */
851  first_int_addr = ip4_interface_first_address
852  (sm->ip4_main, sw_if_index, 0 /* just want the address*/);
853 
854  if (is_add)
855  {
856  if (rp_match)
857  return VNET_API_ERROR_VALUE_EXIST;
858 
860  (sm, l_addr, l_port, sw_if_index, e_port, vrf_id, proto,
861  addr_only, is_add, tag);
862 
863  /* DHCP resolution required? */
864  if (first_int_addr == 0)
865  {
866  return 0;
867  }
868  else
869  {
870  e_addr.as_u32 = first_int_addr->as_u32;
871  /* Identity mapping? */
872  if (l_addr.as_u32 == 0)
873  l_addr.as_u32 = e_addr.as_u32;
874  }
875  }
876  else
877  {
878  if (!rp_match)
879  return VNET_API_ERROR_NO_SUCH_ENTRY;
880 
881  vec_del1 (sm->to_resolve, i);
882 
883  if (first_int_addr)
884  {
885  e_addr.as_u32 = first_int_addr->as_u32;
886  /* Identity mapping? */
887  if (l_addr.as_u32 == 0)
888  l_addr.as_u32 = e_addr.as_u32;
889  }
890  else
891  return 0;
892  }
893  }
894 
895  m_key.addr = e_addr;
896  m_key.port = addr_only ? 0 : e_port;
897  m_key.protocol = addr_only ? 0 : proto;
898  m_key.fib_index = 0;
899  kv.key = m_key.as_u64;
900  if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
901  m = 0;
902  else
903  m = pool_elt_at_index (sm->static_mappings, value.value);
904 
905  if (is_add)
906  {
907  if (m)
908  return VNET_API_ERROR_VALUE_EXIST;
909 
910  if (twice_nat && addr_only)
911  return VNET_API_ERROR_UNSUPPORTED;
912 
913  /* Convert VRF id to FIB index */
914  if (vrf_id != ~0)
915  {
916  p = hash_get (sm->ip4_main->fib_index_by_table_id, vrf_id);
917  if (!p)
918  return VNET_API_ERROR_NO_SUCH_FIB;
919  fib_index = p[0];
920  }
921  /* If not specified use inside VRF id from SNAT plugin startup config */
922  else
923  {
924  fib_index = sm->inside_fib_index;
925  vrf_id = sm->inside_vrf_id;
926  }
927 
928  if (!out2in_only)
929  {
930  m_key.addr = l_addr;
931  m_key.port = addr_only ? 0 : l_port;
932  m_key.protocol = addr_only ? 0 : proto;
933  m_key.fib_index = fib_index;
934  kv.key = m_key.as_u64;
935  if (!clib_bihash_search_8_8 (&sm->static_mapping_by_local, &kv, &value))
936  return VNET_API_ERROR_VALUE_EXIST;
937  }
938 
939  /* Find external address in allocated addresses and reserve port for
940  address and port pair mapping when dynamic translations enabled */
941  if (!(addr_only || sm->static_mapping_only || out2in_only))
942  {
943  for (i = 0; i < vec_len (sm->addresses); i++)
944  {
945  if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
946  {
947  a = sm->addresses + i;
948  /* External port must be unused */
949  switch (proto)
950  {
951 #define _(N, j, n, s) \
952  case SNAT_PROTOCOL_##N: \
953  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, e_port)) \
954  return VNET_API_ERROR_INVALID_VALUE; \
955  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 1); \
956  if (e_port > 1024) \
957  { \
958  a->busy_##n##_ports++; \
959  a->busy_##n##_ports_per_thread[(e_port - 1024) / sm->port_per_thread]++; \
960  } \
961  break;
963 #undef _
964  default:
965  nat_log_info ("unknown protocol");
966  return VNET_API_ERROR_INVALID_VALUE_2;
967  }
968  break;
969  }
970  }
971  /* External address must be allocated */
972  if (!a && (l_addr.as_u32 != e_addr.as_u32))
973  {
974  if (sw_if_index != ~0)
975  {
976  for (i = 0; i < vec_len (sm->to_resolve); i++)
977  {
978  rp = sm->to_resolve + i;
979  if (rp->addr_only)
980  continue;
981  if (rp->sw_if_index != sw_if_index &&
982  rp->l_addr.as_u32 != l_addr.as_u32 &&
983  rp->vrf_id != vrf_id && rp->l_port != l_port &&
984  rp->e_port != e_port && rp->proto != proto)
985  continue;
986 
987  vec_del1 (sm->to_resolve, i);
988  break;
989  }
990  }
991  return VNET_API_ERROR_NO_SUCH_ENTRY;
992  }
993  }
994 
995  pool_get (sm->static_mappings, m);
996  memset (m, 0, sizeof (*m));
997  m->tag = vec_dup (tag);
998  m->local_addr = l_addr;
999  m->external_addr = e_addr;
1000  m->addr_only = addr_only;
1001  m->vrf_id = vrf_id;
1002  m->fib_index = fib_index;
1003  m->twice_nat = twice_nat;
1004  m->out2in_only = out2in_only;
1005  if (!addr_only)
1006  {
1007  m->local_port = l_port;
1008  m->external_port = e_port;
1009  m->proto = proto;
1010  }
1011 
1012  if (sm->num_workers > 1)
1013  {
1014  ip4_header_t ip = {
1015  .src_address = m->local_addr,
1016  };
1017  vec_add1 (m->workers, sm->worker_in2out_cb (&ip, m->fib_index));
1018  tsm = vec_elt_at_index (sm->per_thread_data, m->workers[0]);
1019  }
1020  else
1021  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1022 
1023  m_key.addr = m->local_addr;
1024  m_key.port = m->local_port;
1025  m_key.protocol = m->proto;
1026  m_key.fib_index = m->fib_index;
1027  kv.key = m_key.as_u64;
1028  kv.value = m - sm->static_mappings;
1029  if (!out2in_only)
1030  clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 1);
1031 
1032  m_key.addr = m->external_addr;
1033  m_key.port = m->external_port;
1034  m_key.fib_index = 0;
1035  kv.key = m_key.as_u64;
1036  kv.value = m - sm->static_mappings;
1037  clib_bihash_add_del_8_8(&sm->static_mapping_by_external, &kv, 1);
1038 
1039  /* Delete dynamic sessions matching local address (+ local port) */
1040  if (!(sm->static_mapping_only))
1041  {
1042  u_key.addr = m->local_addr;
1043  u_key.fib_index = m->fib_index;
1044  kv.key = u_key.as_u64;
1045  if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
1046  {
1047  user_index = value.value;
1048  u = pool_elt_at_index (tsm->users, user_index);
1049  if (u->nsessions)
1050  {
1051  head_index = u->sessions_per_user_list_head_index;
1052  head = pool_elt_at_index (tsm->list_pool, head_index);
1053  elt_index = head->next;
1054  elt = pool_elt_at_index (tsm->list_pool, elt_index);
1055  ses_index = elt->value;
1056  while (ses_index != ~0)
1057  {
1058  s = pool_elt_at_index (tsm->sessions, ses_index);
1059  elt = pool_elt_at_index (tsm->list_pool, elt->next);
1060  ses_index = elt->value;
1061 
1062  if (snat_is_session_static (s))
1063  continue;
1064 
1065  if (!addr_only && (clib_net_to_host_u16 (s->in2out.port) != m->local_port))
1066  continue;
1067 
1068  nat_free_session_data (sm, s, tsm - sm->per_thread_data);
1069  nat44_delete_session (sm, s, tsm - sm->per_thread_data);
1070 
1071  if (!addr_only)
1072  break;
1073  }
1074  }
1075  }
1076  }
1077  }
1078  else
1079  {
1080  if (!m)
1081  {
1082  if (sw_if_index != ~0)
1083  return 0;
1084  else
1085  return VNET_API_ERROR_NO_SUCH_ENTRY;
1086  }
1087 
1088  /* Free external address port */
1089  if (!(addr_only || sm->static_mapping_only || out2in_only))
1090  {
1091  for (i = 0; i < vec_len (sm->addresses); i++)
1092  {
1093  if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
1094  {
1095  a = sm->addresses + i;
1096  switch (proto)
1097  {
1098 #define _(N, j, n, s) \
1099  case SNAT_PROTOCOL_##N: \
1100  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 0); \
1101  if (e_port > 1024) \
1102  { \
1103  a->busy_##n##_ports--; \
1104  a->busy_##n##_ports_per_thread[(e_port - 1024) / sm->port_per_thread]--; \
1105  } \
1106  break;
1108 #undef _
1109  default:
1110  nat_log_info ("unknown protocol");
1111  return VNET_API_ERROR_INVALID_VALUE_2;
1112  }
1113  break;
1114  }
1115  }
1116  }
1117 
1118  if (sm->num_workers > 1)
1119  tsm = vec_elt_at_index (sm->per_thread_data, m->workers[0]);
1120  else
1121  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1122 
1123  m_key.addr = m->local_addr;
1124  m_key.port = m->local_port;
1125  m_key.protocol = m->proto;
1126  m_key.fib_index = m->fib_index;
1127  kv.key = m_key.as_u64;
1128  if (!out2in_only)
1129  clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 0);
1130 
1131  m_key.addr = m->external_addr;
1132  m_key.port = m->external_port;
1133  m_key.fib_index = 0;
1134  kv.key = m_key.as_u64;
1135  clib_bihash_add_del_8_8(&sm->static_mapping_by_external, &kv, 0);
1136 
1137  /* Delete session(s) for static mapping if exist */
1138  if (!(sm->static_mapping_only) ||
1140  {
1141  u_key.addr = m->local_addr;
1142  u_key.fib_index = m->fib_index;
1143  kv.key = u_key.as_u64;
1144  if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
1145  {
1146  user_index = value.value;
1147  u = pool_elt_at_index (tsm->users, user_index);
1148  if (u->nstaticsessions)
1149  {
1150  head_index = u->sessions_per_user_list_head_index;
1151  head = pool_elt_at_index (tsm->list_pool, head_index);
1152  elt_index = head->next;
1153  elt = pool_elt_at_index (tsm->list_pool, elt_index);
1154  ses_index = elt->value;
1155  while (ses_index != ~0)
1156  {
1157  s = pool_elt_at_index (tsm->sessions, ses_index);
1158  elt = pool_elt_at_index (tsm->list_pool, elt->next);
1159  ses_index = elt->value;
1160 
1161  if (!addr_only)
1162  {
1163  if ((s->out2in.addr.as_u32 != e_addr.as_u32) &&
1164  (clib_net_to_host_u16 (s->out2in.port) != e_port))
1165  continue;
1166  }
1167 
1168  if (is_lb_session (s))
1169  continue;
1170 
1171  if (!snat_is_session_static (s))
1172  continue;
1173 
1174  nat_free_session_data (sm, s, tsm - sm->per_thread_data);
1175  nat44_delete_session (sm, s, tsm - sm->per_thread_data);
1176 
1177  if (!addr_only)
1178  break;
1179  }
1180  if (addr_only && (u->nstaticsessions == 0) && (u->nsessions == 0))
1181  {
1182  pool_put (tsm->users, u);
1183  clib_bihash_add_del_8_8 (&tsm->user_hash, &kv, 0);
1184  }
1185  }
1186  }
1187  }
1188 
1189  vec_free (m->tag);
1190  vec_free (m->workers);
1191  /* Delete static mapping from pool */
1192  pool_put (sm->static_mappings, m);
1193  }
1194 
1195  if (!addr_only || (l_addr.as_u32 == e_addr.as_u32))
1196  return 0;
1197 
1198  /* Add/delete external address to FIB */
1199  pool_foreach (interface, sm->interfaces,
1200  ({
1201  if (nat_interface_is_inside(interface) || sm->out2in_dpo)
1202  continue;
1203 
1204  snat_add_del_addr_to_fib(&e_addr, 32, interface->sw_if_index, is_add);
1205  break;
1206  }));
1207  pool_foreach (interface, sm->output_feature_interfaces,
1208  ({
1209  if (nat_interface_is_inside(interface) || sm->out2in_dpo)
1210  continue;
1211 
1212  snat_add_del_addr_to_fib(&e_addr, 32, interface->sw_if_index, is_add);
1213  break;
1214  }));
1215 
1216  return 0;
1217 }
1218 
1220  snat_protocol_t proto, u32 vrf_id,
1221  nat44_lb_addr_port_t *locals, u8 is_add,
1222  twice_nat_type_t twice_nat, u8 out2in_only,
1223  u8 *tag)
1224 {
1225  snat_main_t * sm = &snat_main;
1227  snat_session_key_t m_key;
1228  clib_bihash_kv_8_8_t kv, value;
1229  u32 fib_index;
1230  snat_address_t *a = 0;
1231  int i;
1232  nat44_lb_addr_port_t *local;
1233  u32 elt_index, head_index, ses_index;
1235  snat_user_key_t u_key;
1236  snat_user_t *u;
1237  snat_session_t * s;
1238  dlist_elt_t * head, * elt;
1239  uword *bitmap = 0;
1240 
1241  if (!sm->endpoint_dependent)
1242  return VNET_API_ERROR_FEATURE_DISABLED;
1243 
1244  m_key.addr = e_addr;
1245  m_key.port = e_port;
1246  m_key.protocol = proto;
1247  m_key.fib_index = 0;
1248  kv.key = m_key.as_u64;
1249  if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
1250  m = 0;
1251  else
1252  m = pool_elt_at_index (sm->static_mappings, value.value);
1253 
1254  if (is_add)
1255  {
1256  if (m)
1257  return VNET_API_ERROR_VALUE_EXIST;
1258 
1259  if (vec_len (locals) < 2)
1260  return VNET_API_ERROR_INVALID_VALUE;
1261 
1263  vrf_id,
1265 
1266  /* Find external address in allocated addresses and reserve port for
1267  address and port pair mapping when dynamic translations enabled */
1268  if (!(sm->static_mapping_only || out2in_only))
1269  {
1270  for (i = 0; i < vec_len (sm->addresses); i++)
1271  {
1272  if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
1273  {
1274  a = sm->addresses + i;
1275  /* External port must be unused */
1276  switch (proto)
1277  {
1278 #define _(N, j, n, s) \
1279  case SNAT_PROTOCOL_##N: \
1280  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, e_port)) \
1281  return VNET_API_ERROR_INVALID_VALUE; \
1282  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 1); \
1283  if (e_port > 1024) \
1284  { \
1285  a->busy_##n##_ports++; \
1286  a->busy_##n##_ports_per_thread[(e_port - 1024) / sm->port_per_thread]++; \
1287  } \
1288  break;
1290 #undef _
1291  default:
1292  nat_log_info ("unknown protocol");
1293  return VNET_API_ERROR_INVALID_VALUE_2;
1294  }
1295  break;
1296  }
1297  }
1298  /* External address must be allocated */
1299  if (!a)
1300  return VNET_API_ERROR_NO_SUCH_ENTRY;
1301  }
1302 
1303  pool_get (sm->static_mappings, m);
1304  memset (m, 0, sizeof (*m));
1305  m->tag = vec_dup (tag);
1306  m->external_addr = e_addr;
1307  m->addr_only = 0;
1308  m->vrf_id = vrf_id;
1309  m->fib_index = fib_index;
1310  m->external_port = e_port;
1311  m->proto = proto;
1312  m->twice_nat = twice_nat;
1313  m->out2in_only = out2in_only;
1314 
1315  m_key.addr = m->external_addr;
1316  m_key.port = m->external_port;
1317  m_key.protocol = m->proto;
1318  m_key.fib_index = 0;
1319  kv.key = m_key.as_u64;
1320  kv.value = m - sm->static_mappings;
1321  if (clib_bihash_add_del_8_8(&sm->static_mapping_by_external, &kv, 1))
1322  {
1323  nat_log_err ("static_mapping_by_external key add failed");
1324  return VNET_API_ERROR_UNSPECIFIED;
1325  }
1326 
1327  m_key.fib_index = m->fib_index;
1328  for (i = 0; i < vec_len (locals); i++)
1329  {
1330  m_key.addr = locals[i].addr;
1331  if (!out2in_only)
1332  {
1333  m_key.port = locals[i].port;
1334  kv.key = m_key.as_u64;
1335  kv.value = m - sm->static_mappings;
1336  clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 1);
1337  }
1338  locals[i].prefix = (i == 0) ? locals[i].probability :\
1339  (locals[i - 1].prefix + locals[i].probability);
1340  vec_add1 (m->locals, locals[i]);
1341  if (sm->num_workers > 1)
1342  {
1343  ip4_header_t ip = {
1344  .src_address = locals[i].addr,
1345  };
1346  bitmap = clib_bitmap_set (
1347  bitmap, sm->worker_in2out_cb (&ip, m->fib_index), 1);
1348  }
1349  }
1350 
1351  /* Assign workers */
1352  if (sm->num_workers > 1)
1353  {
1354  clib_bitmap_foreach (i, bitmap,
1355  ({
1356  vec_add1(m->workers, i);
1357  }));
1358  }
1359  }
1360  else
1361  {
1362  if (!m)
1363  return VNET_API_ERROR_NO_SUCH_ENTRY;
1364 
1366 
1367  /* Free external address port */
1368  if (!(sm->static_mapping_only || out2in_only))
1369  {
1370  for (i = 0; i < vec_len (sm->addresses); i++)
1371  {
1372  if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
1373  {
1374  a = sm->addresses + i;
1375  switch (proto)
1376  {
1377 #define _(N, j, n, s) \
1378  case SNAT_PROTOCOL_##N: \
1379  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 0); \
1380  if (e_port > 1024) \
1381  { \
1382  a->busy_##n##_ports--; \
1383  a->busy_##n##_ports_per_thread[(e_port - 1024) / sm->port_per_thread]--; \
1384  } \
1385  break;
1387 #undef _
1388  default:
1389  nat_log_info ("unknown protocol");
1390  return VNET_API_ERROR_INVALID_VALUE_2;
1391  }
1392  break;
1393  }
1394  }
1395  }
1396 
1397  m_key.addr = m->external_addr;
1398  m_key.port = m->external_port;
1399  m_key.protocol = m->proto;
1400  m_key.fib_index = 0;
1401  kv.key = m_key.as_u64;
1402  if (clib_bihash_add_del_8_8(&sm->static_mapping_by_external, &kv, 0))
1403  {
1404  nat_log_err ("static_mapping_by_external key del failed");
1405  return VNET_API_ERROR_UNSPECIFIED;
1406  }
1407 
1408  vec_foreach (local, m->locals)
1409  {
1410  m_key.addr = local->addr;
1411  if (!out2in_only)
1412  {
1413  m_key.port = local->port;
1414  m_key.fib_index = m->fib_index;
1415  kv.key = m_key.as_u64;
1416  if (clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 0))
1417  {
1418  nat_log_err ("static_mapping_by_local key del failed");
1419  return VNET_API_ERROR_UNSPECIFIED;
1420  }
1421  }
1422 
1423  if (sm->num_workers > 1)
1424  {
1425  ip4_header_t ip = {
1426  .src_address = local->addr,
1427  };
1428  tsm = vec_elt_at_index (sm->per_thread_data,
1429  sm->worker_in2out_cb (&ip, m->fib_index));
1430  }
1431  else
1432  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1433 
1434  /* Delete sessions */
1435  u_key.addr = local->addr;
1436  u_key.fib_index = m->fib_index;
1437  kv.key = u_key.as_u64;
1438  if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
1439  {
1440  u = pool_elt_at_index (tsm->users, value.value);
1441  if (u->nstaticsessions)
1442  {
1443  head_index = u->sessions_per_user_list_head_index;
1444  head = pool_elt_at_index (tsm->list_pool, head_index);
1445  elt_index = head->next;
1446  elt = pool_elt_at_index (tsm->list_pool, elt_index);
1447  ses_index = elt->value;
1448  while (ses_index != ~0)
1449  {
1450  s = pool_elt_at_index (tsm->sessions, ses_index);
1451  elt = pool_elt_at_index (tsm->list_pool, elt->next);
1452  ses_index = elt->value;
1453 
1454  if (!(is_lb_session (s)))
1455  continue;
1456 
1457  if ((s->in2out.addr.as_u32 != local->addr.as_u32) &&
1458  (clib_net_to_host_u16 (s->in2out.port) != local->port))
1459  continue;
1460 
1461  nat_free_session_data (sm, s, tsm - sm->per_thread_data);
1462  nat44_delete_session (sm, s, tsm - sm->per_thread_data);
1463  }
1464  }
1465  }
1466  }
1467  vec_free(m->locals);
1468  vec_free(m->tag);
1469  vec_free(m->workers);
1470 
1471  pool_put (sm->static_mappings, m);
1472  }
1473 
1474  return 0;
1475 }
1476 
1477 int
1479  u8 twice_nat)
1480 {
1481  snat_address_t *a = 0;
1482  snat_session_t *ses;
1483  u32 *ses_to_be_removed = 0, *ses_index;
1486  snat_interface_t *interface;
1487  int i;
1488  snat_address_t *addresses = twice_nat ? sm->twice_nat_addresses : sm->addresses;
1489 
1490  /* Find SNAT address */
1491  for (i=0; i < vec_len (addresses); i++)
1492  {
1493  if (addresses[i].addr.as_u32 == addr.as_u32)
1494  {
1495  a = addresses + i;
1496  break;
1497  }
1498  }
1499  if (!a)
1500  return VNET_API_ERROR_NO_SUCH_ENTRY;
1501 
1502  if (delete_sm)
1503  {
1504  pool_foreach (m, sm->static_mappings,
1505  ({
1506  if (m->external_addr.as_u32 == addr.as_u32)
1507  (void) snat_add_static_mapping (m->local_addr, m->external_addr,
1508  m->local_port, m->external_port,
1509  m->vrf_id, m->addr_only, ~0,
1510  m->proto, 0, m->twice_nat,
1511  m->out2in_only, m->tag);
1512  }));
1513  }
1514  else
1515  {
1516  /* Check if address is used in some static mapping */
1518  {
1519  nat_log_notice ("address used in static mapping");
1520  return VNET_API_ERROR_UNSPECIFIED;
1521  }
1522  }
1523 
1524  if (a->fib_index != ~0)
1527 
1528  /* Delete sessions using address */
1529  if (a->busy_tcp_ports || a->busy_udp_ports || a->busy_icmp_ports)
1530  {
1531  vec_foreach (tsm, sm->per_thread_data)
1532  {
1533  pool_foreach (ses, tsm->sessions, ({
1534  if (ses->out2in.addr.as_u32 == addr.as_u32)
1535  {
1536  ses->outside_address_index = ~0;
1537  nat_free_session_data (sm, ses, tsm - sm->per_thread_data);
1538  vec_add1 (ses_to_be_removed, ses - tsm->sessions);
1539  }
1540  }));
1541 
1542  vec_foreach (ses_index, ses_to_be_removed)
1543  {
1544  ses = pool_elt_at_index (tsm->sessions, ses_index[0]);
1545  nat44_delete_session (sm, ses, tsm - sm->per_thread_data);
1546  }
1547 
1548  vec_free (ses_to_be_removed);
1549  }
1550  }
1551 
1552  if (twice_nat)
1553  {
1554  vec_del1 (sm->twice_nat_addresses, i);
1555  return 0;
1556  }
1557  else
1558  vec_del1 (sm->addresses, i);
1559 
1560  /* Delete external address from FIB */
1561  pool_foreach (interface, sm->interfaces,
1562  ({
1563  if (nat_interface_is_inside(interface) || sm->out2in_dpo)
1564  continue;
1565 
1566  snat_add_del_addr_to_fib(&addr, 32, interface->sw_if_index, 0);
1567  break;
1568  }));
1569  pool_foreach (interface, sm->output_feature_interfaces,
1570  ({
1571  if (nat_interface_is_inside(interface) || sm->out2in_dpo)
1572  continue;
1573 
1574  snat_add_del_addr_to_fib(&addr, 32, interface->sw_if_index, 0);
1575  break;
1576  }));
1577 
1578  return 0;
1579 }
1580 
1581 int snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del)
1582 {
1583  snat_main_t *sm = &snat_main;
1585  const char * feature_name, *del_feature_name;
1586  snat_address_t * ap;
1588  snat_det_map_t * dm;
1589  nat_outside_fib_t *outside_fib;
1591  sw_if_index);
1592 
1593  if (sm->out2in_dpo && !is_inside)
1594  return VNET_API_ERROR_UNSUPPORTED;
1595 
1597  ({
1598  if (i->sw_if_index == sw_if_index)
1599  return VNET_API_ERROR_VALUE_EXIST;
1600  }));
1601 
1603  feature_name = is_inside ? "nat44-in2out-fast" : "nat44-out2in-fast";
1604  else
1605  {
1606  if (sm->num_workers > 1 && !sm->deterministic)
1607  feature_name = is_inside ? "nat44-in2out-worker-handoff" : "nat44-out2in-worker-handoff";
1608  else if (sm->deterministic)
1609  feature_name = is_inside ? "nat44-det-in2out" : "nat44-det-out2in";
1610  else if (sm->endpoint_dependent)
1611  feature_name = is_inside ? "nat44-ed-in2out" : "nat44-ed-out2in";
1612  else
1613  feature_name = is_inside ? "nat44-in2out" : "nat44-out2in";
1614  }
1615 
1616  if (sm->fq_in2out_index == ~0 && !sm->deterministic && sm->num_workers > 1)
1618  NAT_FQ_NELTS);
1619 
1620  if (sm->fq_out2in_index == ~0 && !sm->deterministic && sm->num_workers > 1)
1622  NAT_FQ_NELTS);
1623 
1624  if (!is_inside)
1625  {
1626  vec_foreach (outside_fib, sm->outside_fibs)
1627  {
1628  if (outside_fib->fib_index == fib_index)
1629  {
1630  if (is_del)
1631  {
1632  outside_fib->refcount--;
1633  if (!outside_fib->refcount)
1634  vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs);
1635  }
1636  else
1637  outside_fib->refcount++;
1638  goto feature_set;
1639  }
1640  }
1641  if (!is_del)
1642  {
1643  vec_add2 (sm->outside_fibs, outside_fib, 1);
1644  outside_fib->refcount = 1;
1645  outside_fib->fib_index = fib_index;
1646  }
1647  }
1648 feature_set:
1649  pool_foreach (i, sm->interfaces,
1650  ({
1651  if (i->sw_if_index == sw_if_index)
1652  {
1653  if (is_del)
1654  {
1655  if (nat_interface_is_inside(i) && nat_interface_is_outside(i))
1656  {
1657  if (is_inside)
1658  i->flags &= ~NAT_INTERFACE_FLAG_IS_INSIDE;
1659  else
1660  i->flags &= ~NAT_INTERFACE_FLAG_IS_OUTSIDE;
1661 
1662  if (sm->num_workers > 1 && !sm->deterministic)
1663  {
1664  del_feature_name = "nat44-handoff-classify";
1665  feature_name = !is_inside ? "nat44-in2out-worker-handoff" :
1666  "nat44-out2in-worker-handoff";
1667  }
1668  else if (sm->deterministic)
1669  {
1670  del_feature_name = "nat44-det-classify";
1671  feature_name = !is_inside ? "nat44-det-in2out" :
1672  "nat44-det-out2in";
1673  }
1674  else if (sm->endpoint_dependent)
1675  {
1676  del_feature_name = "nat44-ed-classify";
1677  feature_name = !is_inside ? "nat44-ed-in2out" :
1678  "nat44-ed-out2in";
1679  }
1680  else
1681  {
1682  del_feature_name = "nat44-classify";
1683  feature_name = !is_inside ? "nat44-in2out" : "nat44-out2in";
1684  }
1685 
1686  vnet_feature_enable_disable ("ip4-unicast", del_feature_name,
1687  sw_if_index, 0, 0, 0);
1688  vnet_feature_enable_disable ("ip4-unicast", feature_name,
1689  sw_if_index, 1, 0, 0);
1690  if (!is_inside)
1691  {
1692  if (sm->endpoint_dependent)
1693  vnet_feature_enable_disable ("ip4-local",
1694  "nat44-ed-hairpinning",
1695  sw_if_index, 1, 0, 0);
1696  else
1697  vnet_feature_enable_disable ("ip4-local",
1698  "nat44-hairpinning",
1699  sw_if_index, 1, 0, 0);
1700  }
1701  }
1702  else
1703  {
1704  vnet_feature_enable_disable ("ip4-unicast", feature_name,
1705  sw_if_index, 0, 0, 0);
1706  pool_put (sm->interfaces, i);
1707  if (is_inside)
1708  {
1709  if (sm->endpoint_dependent)
1710  vnet_feature_enable_disable ("ip4-local",
1711  "nat44-ed-hairpinning",
1712  sw_if_index, 0, 0, 0);
1713  else
1714  vnet_feature_enable_disable ("ip4-local",
1715  "nat44-hairpinning",
1716  sw_if_index, 0, 0, 0);
1717  }
1718  }
1719  }
1720  else
1721  {
1722  if ((nat_interface_is_inside(i) && is_inside) ||
1723  (nat_interface_is_outside(i) && !is_inside))
1724  return 0;
1725 
1726  if (sm->num_workers > 1 && !sm->deterministic)
1727  {
1728  del_feature_name = !is_inside ? "nat44-in2out-worker-handoff" :
1729  "nat44-out2in-worker-handoff";
1730  feature_name = "nat44-handoff-classify";
1731  }
1732  else if (sm->deterministic)
1733  {
1734  del_feature_name = !is_inside ? "nat44-det-in2out" :
1735  "nat44-det-out2in";
1736  feature_name = "nat44-det-classify";
1737  }
1738  else if (sm->endpoint_dependent)
1739  {
1740  del_feature_name = !is_inside ? "nat44-ed-in2out" :
1741  "nat44-ed-out2in";
1742  feature_name = "nat44-ed-classify";
1743  }
1744  else
1745  {
1746  del_feature_name = !is_inside ? "nat44-in2out" : "nat44-out2in";
1747  feature_name = "nat44-classify";
1748  }
1749 
1750  vnet_feature_enable_disable ("ip4-unicast", del_feature_name,
1751  sw_if_index, 0, 0, 0);
1752  vnet_feature_enable_disable ("ip4-unicast", feature_name,
1753  sw_if_index, 1, 0, 0);
1754  if (!is_inside)
1755  {
1756  if (sm->endpoint_dependent)
1757  vnet_feature_enable_disable ("ip4-local", "nat44-ed-hairpinning",
1758  sw_if_index, 0, 0, 0);
1759  else
1760  vnet_feature_enable_disable ("ip4-local", "nat44-hairpinning",
1761  sw_if_index, 0, 0, 0);
1762  }
1763  goto set_flags;
1764  }
1765 
1766  goto fib;
1767  }
1768  }));
1769 
1770  if (is_del)
1771  return VNET_API_ERROR_NO_SUCH_ENTRY;
1772 
1773  pool_get (sm->interfaces, i);
1774  i->sw_if_index = sw_if_index;
1775  i->flags = 0;
1776  vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, 1, 0, 0);
1777 
1778  if (is_inside && !sm->out2in_dpo)
1779  {
1780  if (sm->endpoint_dependent)
1781  vnet_feature_enable_disable ("ip4-local", "nat44-ed-hairpinning",
1782  sw_if_index, 1, 0, 0);
1783  else
1784  vnet_feature_enable_disable ("ip4-local", "nat44-hairpinning",
1785  sw_if_index, 1, 0, 0);
1786  }
1787 
1788 set_flags:
1789  if (is_inside)
1790  {
1791  i->flags |= NAT_INTERFACE_FLAG_IS_INSIDE;
1792  return 0;
1793  }
1794  else
1795  i->flags |= NAT_INTERFACE_FLAG_IS_OUTSIDE;
1796 
1797  /* Add/delete external addresses to FIB */
1798 fib:
1799  vec_foreach (ap, sm->addresses)
1800  snat_add_del_addr_to_fib(&ap->addr, 32, sw_if_index, !is_del);
1801 
1802  pool_foreach (m, sm->static_mappings,
1803  ({
1804  if (!(m->addr_only) || (m->local_addr.as_u32 == m->external_addr.as_u32))
1805  continue;
1806 
1807  snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
1808  }));
1809 
1810  pool_foreach (dm, sm->det_maps,
1811  ({
1812  snat_add_del_addr_to_fib(&dm->out_addr, dm->out_plen, sw_if_index, !is_del);
1813  }));
1814 
1815  return 0;
1816 }
1817 
1819  u8 is_inside,
1820  int is_del)
1821 {
1822  snat_main_t *sm = &snat_main;
1824  snat_address_t * ap;
1826 
1827  if (sm->deterministic ||
1829  return VNET_API_ERROR_UNSUPPORTED;
1830 
1831  pool_foreach (i, sm->interfaces,
1832  ({
1833  if (i->sw_if_index == sw_if_index)
1834  return VNET_API_ERROR_VALUE_EXIST;
1835  }));
1836 
1837  if (is_inside)
1838  {
1839  if (sm->endpoint_dependent)
1840  {
1841  vnet_feature_enable_disable ("ip4-unicast", "nat44-ed-hairpin-dst",
1842  sw_if_index, !is_del, 0, 0);
1843  vnet_feature_enable_disable ("ip4-output", "nat44-ed-hairpin-src",
1844  sw_if_index, !is_del, 0, 0);
1845  }
1846  else
1847  {
1848  vnet_feature_enable_disable ("ip4-unicast", "nat44-hairpin-dst",
1849  sw_if_index, !is_del, 0, 0);
1850  vnet_feature_enable_disable ("ip4-output", "nat44-hairpin-src",
1851  sw_if_index, !is_del, 0, 0);
1852  }
1853  goto fq;
1854  }
1855 
1856  if (sm->num_workers > 1)
1857  {
1858  vnet_feature_enable_disable ("ip4-unicast",
1859  "nat44-out2in-worker-handoff",
1860  sw_if_index, !is_del, 0, 0);
1861  vnet_feature_enable_disable ("ip4-output",
1862  "nat44-in2out-output-worker-handoff",
1863  sw_if_index, !is_del, 0, 0);
1864  }
1865  else
1866  {
1867  if (sm->endpoint_dependent)
1868  {
1869  vnet_feature_enable_disable ("ip4-unicast", "nat44-ed-out2in",
1870  sw_if_index, !is_del, 0, 0);
1871  vnet_feature_enable_disable ("ip4-output", "nat44-ed-in2out-output",
1872  sw_if_index, !is_del, 0, 0);
1873  }
1874  else
1875  {
1876  vnet_feature_enable_disable ("ip4-unicast", "nat44-out2in",
1877  sw_if_index, !is_del, 0, 0);
1878  vnet_feature_enable_disable ("ip4-output", "nat44-in2out-output",
1879  sw_if_index, !is_del, 0, 0);
1880  }
1881  }
1882 
1883 fq:
1884  if (sm->fq_in2out_output_index == ~0 && sm->num_workers > 1)
1887 
1888  if (sm->fq_out2in_index == ~0 && sm->num_workers > 1)
1890 
1892  ({
1893  if (i->sw_if_index == sw_if_index)
1894  {
1895  if (is_del)
1896  pool_put (sm->output_feature_interfaces, i);
1897  else
1898  return VNET_API_ERROR_VALUE_EXIST;
1899 
1900  goto fib;
1901  }
1902  }));
1903 
1904  if (is_del)
1905  return VNET_API_ERROR_NO_SUCH_ENTRY;
1906 
1907  pool_get (sm->output_feature_interfaces, i);
1908  i->sw_if_index = sw_if_index;
1909  i->flags = 0;
1910  if (is_inside)
1911  i->flags |= NAT_INTERFACE_FLAG_IS_INSIDE;
1912  else
1913  i->flags |= NAT_INTERFACE_FLAG_IS_OUTSIDE;
1914 
1915  /* Add/delete external addresses to FIB */
1916 fib:
1917  if (is_inside)
1918  return 0;
1919 
1920  vec_foreach (ap, sm->addresses)
1921  snat_add_del_addr_to_fib(&ap->addr, 32, sw_if_index, !is_del);
1922 
1923  pool_foreach (m, sm->static_mappings,
1924  ({
1925  if (!(m->addr_only) || (m->local_addr.as_u32 == m->external_addr.as_u32))
1926  continue;
1927 
1928  snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
1929  }));
1930 
1931  return 0;
1932 }
1933 
1934 int snat_set_workers (uword * bitmap)
1935 {
1936  snat_main_t *sm = &snat_main;
1937  int i, j = 0;
1938 
1939  if (sm->num_workers < 2)
1940  return VNET_API_ERROR_FEATURE_DISABLED;
1941 
1942  if (clib_bitmap_last_set (bitmap) >= sm->num_workers)
1943  return VNET_API_ERROR_INVALID_WORKER;
1944 
1945  vec_free (sm->workers);
1946  clib_bitmap_foreach (i, bitmap,
1947  ({
1948  vec_add1(sm->workers, i);
1950  j++;
1951  }));
1952 
1953  sm->port_per_thread = (0xffff - 1024) / _vec_len (sm->workers);
1954  sm->num_snat_thread = _vec_len (sm->workers);
1955 
1956  return 0;
1957 }
1958 
1959 
1960 static void
1962  uword opaque,
1963  u32 sw_if_index,
1964  ip4_address_t * address,
1966  u32 if_address_index,
1967  u32 is_delete);
1968 
1969 static void
1971  uword opaque,
1972  u32 sw_if_index,
1973  ip4_address_t * address,
1975  u32 if_address_index,
1976  u32 is_delete);
1977 
1978 static int
1980  u32 fib_index,
1981  u32 thread_index,
1982  snat_session_key_t * k,
1983  u32 * address_indexp,
1984  u16 port_per_thread,
1985  u32 snat_thread_index);
1986 
1988 {
1989  snat_main_t * sm = &snat_main;
1990  clib_error_t * error = 0;
1991  ip4_main_t * im = &ip4_main;
1992  ip_lookup_main_t * lm = &im->lookup_main;
1993  uword *p;
1996  uword *bitmap = 0;
1997  u32 i;
1999  vlib_node_t * error_drop_node;
2000 
2001  sm->vlib_main = vm;
2002  sm->vnet_main = vnet_get_main();
2003  sm->ip4_main = im;
2004  sm->ip4_lookup_main = lm;
2005  sm->api_main = &api_main;
2006  sm->first_worker_index = 0;
2007  sm->num_workers = 0;
2008  sm->num_snat_thread = 1;
2009  sm->workers = 0;
2010  sm->port_per_thread = 0xffff - 1024;
2011  sm->fq_in2out_index = ~0;
2012  sm->fq_out2in_index = ~0;
2018  sm->forwarding_enabled = 0;
2019  sm->log_class = vlib_log_register_class ("nat", 0);
2020  error_drop_node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
2021  sm->error_node_index = error_drop_node->index;
2022 
2023  p = hash_get_mem (tm->thread_registrations_by_name, "workers");
2024  if (p)
2025  {
2026  tr = (vlib_thread_registration_t *) p[0];
2027  if (tr)
2028  {
2029  sm->num_workers = tr->count;
2030  sm->first_worker_index = tr->first_index;
2031  }
2032  }
2033 
2034  vec_validate (sm->per_thread_data, tm->n_vlib_mains - 1);
2035 
2036  /* Use all available workers by default */
2037  if (sm->num_workers > 1)
2038  {
2039  for (i=0; i < sm->num_workers; i++)
2040  bitmap = clib_bitmap_set (bitmap, i, 1);
2041  snat_set_workers(bitmap);
2042  clib_bitmap_free (bitmap);
2043  }
2044  else
2045  {
2047  }
2048 
2049  error = snat_api_init(vm, sm);
2050  if (error)
2051  return error;
2052 
2053  /* Set up the interface address add/del callback */
2055  cb4.function_opaque = 0;
2056 
2058 
2060  cb4.function_opaque = 0;
2061 
2063 
2065 
2066  /* Init IPFIX logging */
2068 
2069  /* Init NAT64 */
2070  error = nat64_init(vm);
2071  if (error)
2072  return error;
2073 
2074  dslite_init(vm);
2075 
2076  nat66_init();
2077 
2078  /* Init virtual fragmenentation reassembly */
2079  return nat_reass_init(vm);
2080 }
2081 
2083 
2085  u32 thread_index,
2086  snat_session_key_t * k,
2087  u32 address_index)
2088 {
2089  snat_address_t *a;
2090  u16 port_host_byte_order = clib_net_to_host_u16 (k->port);
2091 
2092  ASSERT (address_index < vec_len (addresses));
2093 
2094  a = addresses + address_index;
2095 
2096  switch (k->protocol)
2097  {
2098 #define _(N, i, n, s) \
2099  case SNAT_PROTOCOL_##N: \
2100  ASSERT (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, \
2101  port_host_byte_order) == 1); \
2102  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, \
2103  port_host_byte_order, 0); \
2104  a->busy_##n##_ports--; \
2105  a->busy_##n##_ports_per_thread[thread_index]--; \
2106  break;
2108 #undef _
2109  default:
2110  nat_log_info ("unknown protocol");
2111  return;
2112  }
2113 }
2114 
2115 /**
2116  * @brief Match NAT44 static mapping.
2117  *
2118  * @param sm NAT main.
2119  * @param match Address and port to match.
2120  * @param mapping External or local address and port of the matched mapping.
2121  * @param by_external If 0 match by local address otherwise match by external
2122  * address.
2123  * @param is_addr_only If matched mapping is address only
2124  * @param twice_nat If matched mapping is twice NAT.
2125  * @param lb If matched mapping is load-balanced.
2126  *
2127  * @returns 0 if match found otherwise 1.
2128  */
2130  snat_session_key_t match,
2131  snat_session_key_t * mapping,
2132  u8 by_external,
2133  u8 *is_addr_only,
2134  twice_nat_type_t *twice_nat,
2135  u8 *lb)
2136 {
2137  clib_bihash_kv_8_8_t kv, value;
2139  snat_session_key_t m_key;
2140  clib_bihash_8_8_t *mapping_hash = &sm->static_mapping_by_local;
2141  u32 rand, lo = 0, hi, mid;
2142 
2143  m_key.fib_index = match.fib_index;
2144  if (by_external)
2145  {
2146  mapping_hash = &sm->static_mapping_by_external;
2147  m_key.fib_index = 0;
2148  }
2149 
2150  m_key.addr = match.addr;
2151  m_key.port = clib_net_to_host_u16 (match.port);
2152  m_key.protocol = match.protocol;
2153 
2154  kv.key = m_key.as_u64;
2155 
2156  if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
2157  {
2158  /* Try address only mapping */
2159  m_key.port = 0;
2160  m_key.protocol = 0;
2161  kv.key = m_key.as_u64;
2162  if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
2163  return 1;
2164  }
2165 
2166  m = pool_elt_at_index (sm->static_mappings, value.value);
2167 
2168  if (by_external)
2169  {
2170  if (vec_len (m->locals))
2171  {
2172 get_local:
2173  hi = vec_len (m->locals) - 1;
2174  rand = 1 + (random_u32 (&sm->random_seed) % m->locals[hi].prefix);
2175  while (lo < hi)
2176  {
2177  mid = ((hi - lo) >> 1) + lo;
2178  (rand > m->locals[mid].prefix) ? (lo = mid + 1) : (hi = mid);
2179  }
2180  if (!(m->locals[lo].prefix >= rand))
2181  return 1;
2182  if (PREDICT_FALSE (sm->num_workers > 1))
2183  {
2184  ip4_header_t ip = {
2185  .src_address = m->locals[lo].addr,
2186  };
2187  if (sm->worker_in2out_cb (&ip, m->fib_index) != vlib_get_thread_index ())
2188  goto get_local;
2189  }
2190  mapping->addr = m->locals[lo].addr;
2191  mapping->port = clib_host_to_net_u16 (m->locals[lo].port);
2192  }
2193  else
2194  {
2195  mapping->addr = m->local_addr;
2196  /* Address only mapping doesn't change port */
2197  mapping->port = m->addr_only ? match.port
2198  : clib_host_to_net_u16 (m->local_port);
2199  }
2200  mapping->fib_index = m->fib_index;
2201  mapping->protocol = m->proto;
2202  }
2203  else
2204  {
2205  mapping->addr = m->external_addr;
2206  /* Address only mapping doesn't change port */
2207  mapping->port = m->addr_only ? match.port
2208  : clib_host_to_net_u16 (m->external_port);
2209  mapping->fib_index = sm->outside_fib_index;
2210  }
2211 
2212  if (PREDICT_FALSE(is_addr_only != 0))
2213  *is_addr_only = m->addr_only;
2214 
2215  if (PREDICT_FALSE(twice_nat != 0))
2216  *twice_nat = m->twice_nat;
2217 
2218  if (PREDICT_FALSE(lb != 0))
2219  *lb = vec_len (m->locals) > 0;
2220 
2221  return 0;
2222 }
2223 
2226 {
2227  snat_main_t *sm = &snat_main;
2228  return min + random_u32 (&sm->random_seed) /
2229  (random_u32_max() / (max - min + 1) + 1);
2230 }
2231 
2232 int
2234  u32 fib_index,
2235  u32 thread_index,
2236  snat_session_key_t * k,
2237  u32 * address_indexp,
2238  u16 port_per_thread,
2239  u32 snat_thread_index)
2240 {
2241  snat_main_t *sm = &snat_main;
2242 
2243  return sm->alloc_addr_and_port(addresses, fib_index, thread_index, k,
2244  address_indexp, port_per_thread,
2245  snat_thread_index);
2246 }
2247 
2248 static int
2250  u32 fib_index,
2251  u32 thread_index,
2252  snat_session_key_t * k,
2253  u32 * address_indexp,
2254  u16 port_per_thread,
2255  u32 snat_thread_index)
2256 {
2257  int i, gi = 0;
2258  snat_address_t *a, *ga = 0;
2259  u32 portnum;
2260 
2261  for (i = 0; i < vec_len (addresses); i++)
2262  {
2263  a = addresses + i;
2264  switch (k->protocol)
2265  {
2266 #define _(N, j, n, s) \
2267  case SNAT_PROTOCOL_##N: \
2268  if (a->busy_##n##_ports_per_thread[thread_index] < port_per_thread) \
2269  { \
2270  if (a->fib_index == fib_index) \
2271  { \
2272  while (1) \
2273  { \
2274  portnum = (port_per_thread * \
2275  snat_thread_index) + \
2276  snat_random_port(1, port_per_thread) + 1024; \
2277  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \
2278  continue; \
2279  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \
2280  a->busy_##n##_ports_per_thread[thread_index]++; \
2281  a->busy_##n##_ports++; \
2282  k->addr = a->addr; \
2283  k->port = clib_host_to_net_u16(portnum); \
2284  *address_indexp = i; \
2285  return 0; \
2286  } \
2287  } \
2288  else if (a->fib_index == ~0) \
2289  { \
2290  ga = a; \
2291  gi = i; \
2292  } \
2293  } \
2294  break;
2296 #undef _
2297  default:
2298  nat_log_info ("unknown protocol");
2299  return 1;
2300  }
2301 
2302  }
2303 
2304  if (ga)
2305  {
2306  a = ga;
2307  switch (k->protocol)
2308  {
2309 #define _(N, j, n, s) \
2310  case SNAT_PROTOCOL_##N: \
2311  while (1) \
2312  { \
2313  portnum = (port_per_thread * \
2314  snat_thread_index) + \
2315  snat_random_port(1, port_per_thread) + 1024; \
2316  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \
2317  continue; \
2318  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \
2319  a->busy_##n##_ports_per_thread[thread_index]++; \
2320  a->busy_##n##_ports++; \
2321  k->addr = a->addr; \
2322  k->port = clib_host_to_net_u16(portnum); \
2323  *address_indexp = gi; \
2324  return 0; \
2325  }
2326  break;
2328 #undef _
2329  default:
2330  nat_log_info ("unknown protocol");
2331  return 1;
2332  }
2333  }
2334 
2335  /* Totally out of translations to use... */
2337  return 1;
2338 }
2339 
2340 static int
2342  u32 fib_index,
2343  u32 thread_index,
2344  snat_session_key_t * k,
2345  u32 * address_indexp,
2346  u16 port_per_thread,
2347  u32 snat_thread_index)
2348 {
2349  snat_main_t *sm = &snat_main;
2350  snat_address_t *a = addresses;
2351  u16 m, ports, portnum, A, j;
2352  m = 16 - (sm->psid_offset + sm->psid_length);
2353  ports = (1 << (16 - sm->psid_length)) - (1 << m);
2354 
2355  if (!vec_len (addresses))
2356  goto exhausted;
2357 
2358  switch (k->protocol)
2359  {
2360 #define _(N, i, n, s) \
2361  case SNAT_PROTOCOL_##N: \
2362  if (a->busy_##n##_ports < ports) \
2363  { \
2364  while (1) \
2365  { \
2366  A = snat_random_port(1, pow2_mask(sm->psid_offset)); \
2367  j = snat_random_port(0, pow2_mask(m)); \
2368  portnum = A | (sm->psid << sm->psid_offset) | (j << (16 - m)); \
2369  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \
2370  continue; \
2371  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \
2372  a->busy_##n##_ports++; \
2373  k->addr = a->addr; \
2374  k->port = clib_host_to_net_u16 (portnum); \
2375  *address_indexp = i; \
2376  return 0; \
2377  } \
2378  } \
2379  break;
2381 #undef _
2382  default:
2383  nat_log_info ("unknown protocol");
2384  return 1;
2385  }
2386 
2387 exhausted:
2388  /* Totally out of translations to use... */
2390  return 1;
2391 }
2392 
2393 void
2395 {
2396  dpo_id_t dpo_v4 = DPO_INVALID;
2397  fib_prefix_t pfx = {
2399  .fp_len = 32,
2400  .fp_addr.ip4.as_u32 = addr.as_u32,
2401  };
2402 
2403  if (is_add)
2404  {
2405  nat_dpo_create (DPO_PROTO_IP4, 0, &dpo_v4);
2407  FIB_ENTRY_FLAG_EXCLUSIVE, &dpo_v4);
2408  dpo_reset (&dpo_v4);
2409  }
2410  else
2411  {
2413  }
2414 }
2415 
2416 uword
2417 unformat_snat_protocol (unformat_input_t * input, va_list * args)
2418 {
2419  u32 *r = va_arg (*args, u32 *);
2420 
2421  if (0);
2422 #define _(N, i, n, s) else if (unformat (input, s)) *r = SNAT_PROTOCOL_##N;
2424 #undef _
2425  else
2426  return 0;
2427  return 1;
2428 }
2429 
2430 u8 *
2431 format_snat_protocol (u8 * s, va_list * args)
2432 {
2433  u32 i = va_arg (*args, u32);
2434  u8 *t = 0;
2435 
2436  switch (i)
2437  {
2438 #define _(N, j, n, str) case SNAT_PROTOCOL_##N: t = (u8 *) str; break;
2440 #undef _
2441  default:
2442  s = format (s, "unknown");
2443  return s;
2444  }
2445  s = format (s, "%s", t);
2446  return s;
2447 }
2448 
2449 u8 * format_snat_key (u8 * s, va_list * args);
2450 
2451 u8 *
2452 format_session_kvp (u8 * s, va_list * args)
2453 {
2454  clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
2456 
2457  k.as_u64 = v->key;
2458 
2459  s = format (s, "%U session-index %llu", format_snat_key, &k, v->value);
2460 
2461  return s;
2462 }
2463 
2464 u8 *
2465 format_static_mapping_kvp (u8 * s, va_list * args)
2466 {
2467  clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
2469 
2470  k.as_u64 = v->key;
2471 
2472  s = format (s, "%U static-mapping-index %llu", format_snat_key, &k, v->value);
2473 
2474  return s;
2475 }
2476 
2477 u8 *
2478 format_user_kvp (u8 * s, va_list * args)
2479 {
2480  clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
2481  snat_user_key_t k;
2482 
2483  k.as_u64 = v->key;
2484 
2485  s = format (s, "%U fib %d user-index %llu", format_ip4_address, &k.addr,
2486  k.fib_index, v->value);
2487 
2488  return s;
2489 }
2490 
2491 u8 *
2492 format_ed_session_kvp (u8 * s, va_list * args)
2493 {
2494  clib_bihash_kv_16_8_t *v = va_arg (*args, clib_bihash_kv_16_8_t *);
2495  nat_ed_ses_key_t k;
2496 
2497  k.as_u64[0] = v->key[0];
2498  k.as_u64[1] = v->key[1];
2499 
2500  s = format (s, "local %U:%d remote %U:%d proto %U fib %d session-index %llu",
2501  format_ip4_address, &k.l_addr, clib_net_to_host_u16 (k.l_port),
2502  format_ip4_address, &k.r_addr, clib_net_to_host_u16 (k.r_port),
2504 
2505  return s;
2506 }
2507 
2508 static u32
2510 {
2511  snat_main_t *sm = &snat_main;
2512  u32 next_worker_index = 0;
2513  u32 hash;
2514 
2515  next_worker_index = sm->first_worker_index;
2516  hash = ip0->src_address.as_u32 + (ip0->src_address.as_u32 >> 8) +
2517  (ip0->src_address.as_u32 >> 16) + (ip0->src_address.as_u32 >>24);
2518 
2519  if (PREDICT_TRUE (is_pow2 (_vec_len (sm->workers))))
2520  next_worker_index += sm->workers[hash & (_vec_len (sm->workers) - 1)];
2521  else
2522  next_worker_index += sm->workers[hash % _vec_len (sm->workers)];
2523 
2524  return next_worker_index;
2525 }
2526 
2527 static u32
2529 {
2530  snat_main_t *sm = &snat_main;
2531  udp_header_t *udp;
2532  u16 port;
2533  snat_session_key_t m_key;
2534  clib_bihash_kv_8_8_t kv, value;
2536  u32 proto;
2537  u32 next_worker_index = 0;
2538 
2539  /* first try static mappings without port */
2541  {
2542  m_key.addr = ip0->dst_address;
2543  m_key.port = 0;
2544  m_key.protocol = 0;
2545  m_key.fib_index = rx_fib_index0;
2546  kv.key = m_key.as_u64;
2547  if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
2548  {
2549  m = pool_elt_at_index (sm->static_mappings, value.value);
2550  return m->workers[0];
2551  }
2552  }
2553 
2554  proto = ip_proto_to_snat_proto (ip0->protocol);
2555  udp = ip4_next_header (ip0);
2556  port = udp->dst_port;
2557 
2558  if (PREDICT_FALSE (ip4_is_fragment (ip0)))
2559  {
2561  return vlib_get_thread_index ();
2562 
2563  if (PREDICT_TRUE (!ip4_is_first_fragment (ip0)))
2564  {
2565  nat_reass_ip4_t *reass;
2566 
2567  reass = nat_ip4_reass_find (ip0->src_address, ip0->dst_address,
2568  ip0->fragment_id, ip0->protocol);
2569 
2570  if (reass && (reass->thread_index != (u32) ~ 0))
2571  return reass->thread_index;
2572  else
2573  return vlib_get_thread_index ();
2574  }
2575  }
2576 
2577  /* unknown protocol */
2578  if (PREDICT_FALSE (proto == ~0))
2579  {
2580  /* use current thread */
2581  return vlib_get_thread_index ();
2582  }
2583 
2584  if (PREDICT_FALSE (ip0->protocol == IP_PROTOCOL_ICMP))
2585  {
2586  icmp46_header_t * icmp = (icmp46_header_t *) udp;
2587  icmp_echo_header_t *echo = (icmp_echo_header_t *)(icmp + 1);
2588  if (!icmp_is_error_message (icmp))
2589  port = echo->identifier;
2590  else
2591  {
2592  ip4_header_t *inner_ip = (ip4_header_t *)(echo + 1);
2593  proto = ip_proto_to_snat_proto (inner_ip->protocol);
2594  void *l4_header = ip4_next_header (inner_ip);
2595  switch (proto)
2596  {
2597  case SNAT_PROTOCOL_ICMP:
2598  icmp = (icmp46_header_t*)l4_header;
2599  echo = (icmp_echo_header_t *)(icmp + 1);
2600  port = echo->identifier;
2601  break;
2602  case SNAT_PROTOCOL_UDP:
2603  case SNAT_PROTOCOL_TCP:
2604  port = ((tcp_udp_header_t*)l4_header)->src_port;
2605  break;
2606  default:
2607  return vlib_get_thread_index ();
2608  }
2609  }
2610  }
2611 
2612  /* try static mappings with port */
2613  if (PREDICT_FALSE (pool_elts (sm->static_mappings)))
2614  {
2615  m_key.addr = ip0->dst_address;
2616  m_key.port = clib_net_to_host_u16 (port);
2617  m_key.protocol = proto;
2618  m_key.fib_index = rx_fib_index0;
2619  kv.key = m_key.as_u64;
2620  if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
2621  {
2622  m = pool_elt_at_index (sm->static_mappings, value.value);
2623  return m->workers[0];
2624  }
2625  }
2626 
2627  /* worker by outside port */
2628  next_worker_index = sm->first_worker_index;
2629  next_worker_index +=
2630  sm->workers[(clib_net_to_host_u16 (port) - 1024) / sm->port_per_thread];
2631  return next_worker_index;
2632 }
2633 
2634 static u32
2636 {
2637  snat_main_t *sm = &snat_main;
2638  clib_bihash_kv_8_8_t kv, value;
2639  u32 proto, next_worker_index = 0;
2640  udp_header_t *udp;
2641  u16 port;
2643  u32 hash;
2644 
2645  /* first try static mappings without port */
2647  {
2648  make_sm_kv (&kv, &ip->dst_address, 0, rx_fib_index, 0);
2649  if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
2650  {
2651  m = pool_elt_at_index (sm->static_mappings, value.value);
2652  return m->workers[0];
2653  }
2654  }
2655 
2656  proto = ip_proto_to_snat_proto (ip->protocol);
2657 
2658  /* unknown protocol */
2659  if (PREDICT_FALSE (proto == ~0))
2660  {
2661  /* use current thread */
2662  return vlib_get_thread_index ();
2663  }
2664 
2665  udp = ip4_next_header (ip);
2666  port = udp->dst_port;
2667 
2668  if (PREDICT_FALSE (ip->protocol == IP_PROTOCOL_ICMP))
2669  {
2670  icmp46_header_t * icmp = (icmp46_header_t *) udp;
2671  icmp_echo_header_t *echo = (icmp_echo_header_t *)(icmp + 1);
2672  if (!icmp_is_error_message (icmp))
2673  port = echo->identifier;
2674  else
2675  {
2676  ip4_header_t *inner_ip = (ip4_header_t *)(echo + 1);
2677  proto = ip_proto_to_snat_proto (inner_ip->protocol);
2678  void *l4_header = ip4_next_header (inner_ip);
2679  switch (proto)
2680  {
2681  case SNAT_PROTOCOL_ICMP:
2682  icmp = (icmp46_header_t*)l4_header;
2683  echo = (icmp_echo_header_t *)(icmp + 1);
2684  port = echo->identifier;
2685  break;
2686  case SNAT_PROTOCOL_UDP:
2687  case SNAT_PROTOCOL_TCP:
2688  port = ((tcp_udp_header_t*)l4_header)->src_port;
2689  break;
2690  default:
2691  return vlib_get_thread_index ();
2692  }
2693  }
2694  }
2695 
2696  /* try static mappings with port */
2697  if (PREDICT_FALSE (pool_elts (sm->static_mappings)))
2698  {
2699  make_sm_kv (&kv, &ip->dst_address, proto, rx_fib_index,
2700  clib_net_to_host_u16 (port));
2701  if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
2702  {
2703  m = pool_elt_at_index (sm->static_mappings, value.value);
2704  if (!vec_len(m->locals))
2705  return m->workers[0];
2706 
2707  hash = ip->src_address.as_u32 + (ip->src_address.as_u32 >> 8) +
2708  (ip->src_address.as_u32 >> 16) + (ip->src_address.as_u32 >>24);
2709 
2710  if (PREDICT_TRUE (is_pow2 (_vec_len (m->workers))))
2711  return m->workers[hash & (_vec_len (m->workers) - 1)];
2712  else
2713  return m->workers[hash % _vec_len (m->workers)];
2714  }
2715  }
2716 
2717  /* worker by outside port */
2718  next_worker_index = sm->first_worker_index;
2719  next_worker_index +=
2720  sm->workers[(clib_net_to_host_u16 (port) - 1024) / sm->port_per_thread];
2721 
2722  return next_worker_index;
2723 }
2724 
2725 static clib_error_t *
2727 {
2728  snat_main_t * sm = &snat_main;
2729  nat66_main_t * nm = &nat66_main;
2730  u32 translation_buckets = 1024;
2731  u32 translation_memory_size = 128<<20;
2732  u32 user_buckets = 128;
2733  u32 user_memory_size = 64<<20;
2734  u32 max_translations_per_user = 100;
2735  u32 outside_vrf_id = 0;
2736  u32 outside_ip6_vrf_id = 0;
2737  u32 inside_vrf_id = 0;
2738  u32 static_mapping_buckets = 1024;
2739  u32 static_mapping_memory_size = 64<<20;
2740  u32 nat64_bib_buckets = 1024;
2741  u32 nat64_bib_memory_size = 128 << 20;
2742  u32 nat64_st_buckets = 2048;
2743  u32 nat64_st_memory_size = 256 << 20;
2744  u8 static_mapping_only = 0;
2745  u8 static_mapping_connection_tracking = 0;
2747  dslite_main_t * dm = &dslite_main;
2748 
2749  sm->deterministic = 0;
2750  sm->out2in_dpo = 0;
2751  sm->endpoint_dependent = 0;
2752 
2753  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2754  {
2755  if (unformat (input, "translation hash buckets %d", &translation_buckets))
2756  ;
2757  else if (unformat (input, "translation hash memory %d",
2758  &translation_memory_size));
2759  else if (unformat (input, "user hash buckets %d", &user_buckets))
2760  ;
2761  else if (unformat (input, "user hash memory %d",
2762  &user_memory_size))
2763  ;
2764  else if (unformat (input, "max translations per user %d",
2765  &max_translations_per_user))
2766  ;
2767  else if (unformat (input, "outside VRF id %d",
2768  &outside_vrf_id))
2769  ;
2770  else if (unformat (input, "outside ip6 VRF id %d",
2771  &outside_ip6_vrf_id))
2772  ;
2773  else if (unformat (input, "inside VRF id %d",
2774  &inside_vrf_id))
2775  ;
2776  else if (unformat (input, "static mapping only"))
2777  {
2778  static_mapping_only = 1;
2779  if (unformat (input, "connection tracking"))
2780  static_mapping_connection_tracking = 1;
2781  }
2782  else if (unformat (input, "deterministic"))
2783  sm->deterministic = 1;
2784  else if (unformat (input, "nat64 bib hash buckets %d",
2785  &nat64_bib_buckets))
2786  ;
2787  else if (unformat (input, "nat64 bib hash memory %d",
2788  &nat64_bib_memory_size))
2789  ;
2790  else if (unformat (input, "nat64 st hash buckets %d", &nat64_st_buckets))
2791  ;
2792  else if (unformat (input, "nat64 st hash memory %d",
2793  &nat64_st_memory_size))
2794  ;
2795  else if (unformat (input, "out2in dpo"))
2796  sm->out2in_dpo = 1;
2797  else if (unformat (input, "dslite ce"))
2798  dslite_set_ce(dm, 1);
2799  else if (unformat (input, "endpoint-dependent"))
2800  sm->endpoint_dependent = 1;
2801  else
2802  return clib_error_return (0, "unknown input '%U'",
2803  format_unformat_error, input);
2804  }
2805 
2806  /* for show commands, etc. */
2807  sm->translation_buckets = translation_buckets;
2808  sm->translation_memory_size = translation_memory_size;
2809  /* do not exceed load factor 10 */
2810  sm->max_translations = 10 * translation_buckets;
2811  sm->user_buckets = user_buckets;
2812  sm->user_memory_size = user_memory_size;
2813  sm->max_translations_per_user = max_translations_per_user;
2814  sm->outside_vrf_id = outside_vrf_id;
2816  outside_vrf_id,
2818  nm->outside_vrf_id = outside_ip6_vrf_id;
2820  outside_ip6_vrf_id,
2822  sm->inside_vrf_id = inside_vrf_id;
2824  inside_vrf_id,
2826  sm->static_mapping_only = static_mapping_only;
2827  sm->static_mapping_connection_tracking = static_mapping_connection_tracking;
2828 
2829  nat64_set_hash(nat64_bib_buckets, nat64_bib_memory_size, nat64_st_buckets,
2830  nat64_st_memory_size);
2831 
2832  if (sm->deterministic)
2833  {
2835  sm->in2out_output_node_index = ~0;
2839  }
2840  else
2841  {
2842  if (sm->endpoint_dependent)
2843  {
2851  }
2852  else
2853  {
2856  sm->in2out_node_index = snat_in2out_node.index;
2858  sm->out2in_node_index = snat_out2in_node.index;
2861  }
2862  if (!static_mapping_only ||
2863  (static_mapping_only && static_mapping_connection_tracking))
2864  {
2865  vec_foreach (tsm, sm->per_thread_data)
2866  {
2867  if (sm->endpoint_dependent)
2868  {
2869  clib_bihash_init_16_8 (&tsm->in2out_ed, "in2out-ed",
2870  translation_buckets,
2871  translation_memory_size);
2872  clib_bihash_set_kvp_format_fn_16_8 (&tsm->in2out_ed,
2874 
2875  clib_bihash_init_16_8 (&tsm->out2in_ed, "out2in-ed",
2876  translation_buckets,
2877  translation_memory_size);
2878  clib_bihash_set_kvp_format_fn_16_8 (&tsm->out2in_ed,
2880  }
2881  else
2882  {
2883  clib_bihash_init_8_8 (&tsm->in2out, "in2out",
2884  translation_buckets,
2885  translation_memory_size);
2886  clib_bihash_set_kvp_format_fn_8_8 (&tsm->in2out,
2888 
2889  clib_bihash_init_8_8 (&tsm->out2in, "out2in",
2890  translation_buckets,
2891  translation_memory_size);
2892  clib_bihash_set_kvp_format_fn_8_8 (&tsm->out2in,
2894  }
2895 
2896  clib_bihash_init_8_8 (&tsm->user_hash, "users", user_buckets,
2897  user_memory_size);
2898  clib_bihash_set_kvp_format_fn_8_8 (&tsm->user_hash,
2899  format_user_kvp);
2900  }
2901 
2902  }
2903  else
2904  {
2907  }
2908  clib_bihash_init_8_8 (&sm->static_mapping_by_local,
2909  "static_mapping_by_local", static_mapping_buckets,
2910  static_mapping_memory_size);
2911  clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_local,
2913 
2914  clib_bihash_init_8_8 (&sm->static_mapping_by_external,
2915  "static_mapping_by_external", static_mapping_buckets,
2916  static_mapping_memory_size);
2917  clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_external,
2919  }
2920 
2921  return 0;
2922 }
2923 
2925 
2926 u8 * format_snat_session_state (u8 * s, va_list * args)
2927 {
2928  u32 i = va_arg (*args, u32);
2929  u8 *t = 0;
2930 
2931  switch (i)
2932  {
2933 #define _(v, N, str) case SNAT_SESSION_##N: t = (u8 *) str; break;
2935 #undef _
2936  default:
2937  t = format (t, "unknown");
2938  }
2939  s = format (s, "%s", t);
2940  return s;
2941 }
2942 
2943 u8 * format_snat_key (u8 * s, va_list * args)
2944 {
2945  snat_session_key_t * key = va_arg (*args, snat_session_key_t *);
2946 
2947  s = format (s, "%U proto %U port %d fib %d",
2948  format_ip4_address, &key->addr,
2950  clib_net_to_host_u16 (key->port), key->fib_index);
2951  return s;
2952 }
2953 
2954 u8 * format_snat_session (u8 * s, va_list * args)
2955 {
2957  snat_session_t * sess = va_arg (*args, snat_session_t *);
2958 
2959  if (snat_is_unk_proto_session (sess))
2960  {
2961  s = format (s, " i2o %U proto %u fib %u\n",
2962  format_ip4_address, &sess->in2out.addr,
2963  clib_net_to_host_u16 (sess->in2out.port),
2964  sess->in2out.fib_index);
2965  s = format (s, " o2i %U proto %u fib %u\n",
2966  format_ip4_address, &sess->out2in.addr,
2967  clib_net_to_host_u16 (sess->out2in.port),
2968  sess->out2in.fib_index);
2969  }
2970  else
2971  {
2972  s = format (s, " i2o %U\n", format_snat_key, &sess->in2out);
2973  s = format (s, " o2i %U\n", format_snat_key, &sess->out2in);
2974  }
2975  if (is_ed_session (sess) || is_fwd_bypass_session (sess))
2976  {
2977  if (is_twice_nat_session (sess))
2978  {
2979  s = format (s, " external host o2i %U:%d i2o %U:%d\n",
2980  format_ip4_address, &sess->ext_host_addr,
2981  clib_net_to_host_u16 (sess->ext_host_port),
2982  format_ip4_address, &sess->ext_host_nat_addr,
2983  clib_net_to_host_u16 (sess->ext_host_nat_port));
2984  }
2985  else
2986  {
2987  if (sess->ext_host_addr.as_u32)
2988  s = format (s, " external host %U:%u\n",
2989  format_ip4_address, &sess->ext_host_addr,
2990  clib_net_to_host_u16 (sess->ext_host_port));
2991  }
2992  }
2993  s = format (s, " index %llu\n", sess - sm->sessions);
2994  s = format (s, " last heard %.2f\n", sess->last_heard);
2995  s = format (s, " total pkts %d, total bytes %lld\n",
2996  sess->total_pkts, sess->total_bytes);
2997  if (snat_is_session_static (sess))
2998  s = format (s, " static translation\n");
2999  else
3000  s = format (s, " dynamic translation\n");
3001  if (is_fwd_bypass_session (sess))
3002  s = format (s, " forwarding-bypass\n");
3003  if (is_lb_session (sess))
3004  s = format (s, " load-balancing\n");
3005  if (is_twice_nat_session (sess))
3006  s = format (s, " twice-nat\n");
3007 
3008  return s;
3009 }
3010 
3011 u8 * format_snat_user (u8 * s, va_list * args)
3012 {
3014  snat_user_t * u = va_arg (*args, snat_user_t *);
3015  int verbose = va_arg (*args, int);
3016  dlist_elt_t * head, * elt;
3017  u32 elt_index, head_index;
3018  u32 session_index;
3019  snat_session_t * sess;
3020 
3021  s = format (s, "%U: %d dynamic translations, %d static translations\n",
3023 
3024  if (verbose == 0)
3025  return s;
3026 
3027  if (u->nsessions || u->nstaticsessions)
3028  {
3029  head_index = u->sessions_per_user_list_head_index;
3030  head = pool_elt_at_index (sm->list_pool, head_index);
3031 
3032  elt_index = head->next;
3033  elt = pool_elt_at_index (sm->list_pool, elt_index);
3034  session_index = elt->value;
3035 
3036  while (session_index != ~0)
3037  {
3038  sess = pool_elt_at_index (sm->sessions, session_index);
3039 
3040  s = format (s, " %U\n", format_snat_session, sm, sess);
3041 
3042  elt_index = elt->next;
3043  elt = pool_elt_at_index (sm->list_pool, elt_index);
3044  session_index = elt->value;
3045  }
3046  }
3047 
3048  return s;
3049 }
3050 
3051 u8 * format_snat_static_mapping (u8 * s, va_list * args)
3052 {
3053  snat_static_mapping_t *m = va_arg (*args, snat_static_mapping_t *);
3054  nat44_lb_addr_port_t *local;
3055 
3056  if (m->addr_only)
3057  s = format (s, "local %U external %U vrf %d %s %s",
3060  m->vrf_id,
3061  m->twice_nat == TWICE_NAT ? "twice-nat" :
3062  m->twice_nat == TWICE_NAT_SELF ? "self-twice-nat" : "",
3063  m->out2in_only ? "out2in-only" : "");
3064  else
3065  {
3066  if (vec_len (m->locals))
3067  {
3068  s = format (s, "%U vrf %d external %U:%d %s %s",
3070  m->vrf_id,
3072  m->twice_nat == TWICE_NAT ? "twice-nat" :
3073  m->twice_nat == TWICE_NAT_SELF ? "self-twice-nat" : "",
3074  m->out2in_only ? "out2in-only" : "");
3075  vec_foreach (local, m->locals)
3076  s = format (s, "\n local %U:%d probability %d\%",
3077  format_ip4_address, &local->addr, local->port,
3078  local->probability);
3079  }
3080  else
3081  s = format (s, "%U local %U:%d external %U:%d vrf %d %s %s",
3085  m->vrf_id,
3086  m->twice_nat == TWICE_NAT ? "twice-nat" :
3087  m->twice_nat == TWICE_NAT_SELF ? "self-twice-nat" : "",
3088  m->out2in_only ? "out2in-only" : "");
3089  }
3090  return s;
3091 }
3092 
3093 u8 * format_snat_static_map_to_resolve (u8 * s, va_list * args)
3094 {
3096  vnet_main_t *vnm = vnet_get_main();
3097 
3098  if (m->addr_only)
3099  s = format (s, "local %U external %U vrf %d",
3102  m->vrf_id);
3103  else
3104  s = format (s, "%U local %U:%d external %U:%d vrf %d",
3106  format_ip4_address, &m->l_addr, m->l_port,
3108  m->e_port, m->vrf_id);
3109 
3110  return s;
3111 }
3112 
3113 u8 * format_det_map_ses (u8 * s, va_list * args)
3114 {
3115  snat_det_map_t * det_map = va_arg (*args, snat_det_map_t *);
3116  ip4_address_t in_addr, out_addr;
3117  u32 in_offset, out_offset;
3118  snat_det_session_t * ses = va_arg (*args, snat_det_session_t *);
3119  u32 * i = va_arg (*args, u32 *);
3120 
3121  u32 user_index = *i / SNAT_DET_SES_PER_USER;
3122  in_addr.as_u32 = clib_host_to_net_u32 (
3123  clib_net_to_host_u32(det_map->in_addr.as_u32) + user_index);
3124  in_offset = clib_net_to_host_u32(in_addr.as_u32) -
3125  clib_net_to_host_u32(det_map->in_addr.as_u32);
3126  out_offset = in_offset / det_map->sharing_ratio;
3127  out_addr.as_u32 = clib_host_to_net_u32(
3128  clib_net_to_host_u32(det_map->out_addr.as_u32) + out_offset);
3129  s = format (s, "in %U:%d out %U:%d external host %U:%d state: %U expire: %d\n",
3130  format_ip4_address, &in_addr,
3131  clib_net_to_host_u16 (ses->in_port),
3132  format_ip4_address, &out_addr,
3133  clib_net_to_host_u16 (ses->out.out_port),
3135  clib_net_to_host_u16 (ses->out.ext_host_port),
3137  ses->expire);
3138 
3139  return s;
3140 }
3141 
3142 static void
3144  uword opaque,
3145  u32 sw_if_index,
3146  ip4_address_t * address,
3148  u32 if_address_index,
3149  u32 is_delete)
3150 {
3151  snat_main_t *sm = &snat_main;
3154  snat_session_key_t m_key;
3155  clib_bihash_kv_8_8_t kv, value;
3156  int i, rv;
3157  ip4_address_t l_addr;
3158 
3159  for (i = 0; i < vec_len (sm->to_resolve); i++)
3160  {
3161  rp = sm->to_resolve + i;
3162  if (rp->addr_only == 0)
3163  continue;
3164  if (rp->sw_if_index == sw_if_index)
3165  goto match;
3166  }
3167 
3168  return;
3169 
3170 match:
3171  m_key.addr.as_u32 = address->as_u32;
3172  m_key.port = rp->addr_only ? 0 : rp->e_port;
3173  m_key.protocol = rp->addr_only ? 0 : rp->proto;
3174  m_key.fib_index = sm->outside_fib_index;
3175  kv.key = m_key.as_u64;
3176  if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
3177  m = 0;
3178  else
3179  m = pool_elt_at_index (sm->static_mappings, value.value);
3180 
3181  if (!is_delete)
3182  {
3183  /* Don't trip over lease renewal, static config */
3184  if (m)
3185  return;
3186  }
3187  else
3188  {
3189  if (!m)
3190  return;
3191  }
3192 
3193  /* Indetity mapping? */
3194  if (rp->l_addr.as_u32 == 0)
3195  l_addr.as_u32 = address[0].as_u32;
3196  else
3197  l_addr.as_u32 = rp->l_addr.as_u32;
3198  /* Add the static mapping */
3199  rv = snat_add_static_mapping (l_addr,
3200  address[0],
3201  rp->l_port,
3202  rp->e_port,
3203  rp->vrf_id,
3204  rp->addr_only,
3205  ~0 /* sw_if_index */,
3206  rp->proto,
3207  !is_delete,
3208  0, 0, rp->tag);
3209  if (rv)
3210  nat_log_notice ("snat_add_static_mapping returned %d", rv);
3211 }
3212 
3213 static void
3215  uword opaque,
3216  u32 sw_if_index,
3217  ip4_address_t * address,
3219  u32 if_address_index,
3220  u32 is_delete)
3221 {
3222  snat_main_t *sm = &snat_main;
3224  ip4_address_t l_addr;
3225  int i, j;
3226  int rv;
3227  u8 twice_nat = 0;
3228  snat_address_t *addresses = sm->addresses;
3229 
3230  for (i = 0; i < vec_len(sm->auto_add_sw_if_indices); i++)
3231  {
3232  if (sw_if_index == sm->auto_add_sw_if_indices[i])
3233  goto match;
3234  }
3235 
3236  for (i = 0; i < vec_len(sm->auto_add_sw_if_indices_twice_nat); i++)
3237  {
3238  twice_nat = 1;
3239  addresses = sm->twice_nat_addresses;
3240  if (sw_if_index == sm->auto_add_sw_if_indices_twice_nat[i])
3241  goto match;
3242  }
3243 
3244  return;
3245 
3246 match:
3247  if (!is_delete)
3248  {
3249  /* Don't trip over lease renewal, static config */
3250  for (j = 0; j < vec_len(addresses); j++)
3251  if (addresses[j].addr.as_u32 == address->as_u32)
3252  return;
3253 
3254  (void) snat_add_address (sm, address, ~0, twice_nat);
3255  /* Scan static map resolution vector */
3256  for (j = 0; j < vec_len (sm->to_resolve); j++)
3257  {
3258  rp = sm->to_resolve + j;
3259  if (rp->addr_only)
3260  continue;
3261  /* On this interface? */
3262  if (rp->sw_if_index == sw_if_index)
3263  {
3264  /* Indetity mapping? */
3265  if (rp->l_addr.as_u32 == 0)
3266  l_addr.as_u32 = address[0].as_u32;
3267  else
3268  l_addr.as_u32 = rp->l_addr.as_u32;
3269  /* Add the static mapping */
3270  rv = snat_add_static_mapping (l_addr,
3271  address[0],
3272  rp->l_port,
3273  rp->e_port,
3274  rp->vrf_id,
3275  rp->addr_only,
3276  ~0 /* sw_if_index */,
3277  rp->proto,
3278  rp->is_add,
3279  0, 0, rp->tag);
3280  if (rv)
3281  nat_log_notice ("snat_add_static_mapping returned %d", rv);
3282  }
3283  }
3284  return;
3285  }
3286  else
3287  {
3288  (void) snat_del_address(sm, address[0], 1, twice_nat);
3289  return;
3290  }
3291 }
3292 
3293 
3294 int snat_add_interface_address (snat_main_t *sm, u32 sw_if_index, int is_del,
3295  u8 twice_nat)
3296 {
3297  ip4_main_t * ip4_main = sm->ip4_main;
3298  ip4_address_t * first_int_addr;
3300  u32 *indices_to_delete = 0;
3301  int i, j;
3302  u32 *auto_add_sw_if_indices =
3304 
3305  first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index,
3306  0 /* just want the address*/);
3307 
3308  for (i = 0; i < vec_len(auto_add_sw_if_indices); i++)
3309  {
3310  if (auto_add_sw_if_indices[i] == sw_if_index)
3311  {
3312  if (is_del)
3313  {
3314  /* if have address remove it */
3315  if (first_int_addr)
3316  (void) snat_del_address (sm, first_int_addr[0], 1, twice_nat);
3317  else
3318  {
3319  for (j = 0; j < vec_len (sm->to_resolve); j++)
3320  {
3321  rp = sm->to_resolve + j;
3322  if (rp->sw_if_index == sw_if_index)
3323  vec_add1 (indices_to_delete, j);
3324  }
3325  if (vec_len(indices_to_delete))
3326  {
3327  for (j = vec_len(indices_to_delete)-1; j >= 0; j--)
3328  vec_del1(sm->to_resolve, j);
3329  vec_free(indices_to_delete);
3330  }
3331  }
3332  if (twice_nat)
3334  else
3336  }
3337  else
3338  return VNET_API_ERROR_VALUE_EXIST;
3339 
3340  return 0;
3341  }
3342  }
3343 
3344  if (is_del)
3345  return VNET_API_ERROR_NO_SUCH_ENTRY;
3346 
3347  /* add to the auto-address list */
3348  if (twice_nat)
3349  vec_add1(sm->auto_add_sw_if_indices_twice_nat, sw_if_index);
3350  else
3351  vec_add1(sm->auto_add_sw_if_indices, sw_if_index);
3352 
3353  /* If the address is already bound - or static - add it now */
3354  if (first_int_addr)
3355  (void) snat_add_address (sm, first_int_addr, ~0, twice_nat);
3356 
3357  return 0;
3358 }
3359 
3360 int
3362  snat_protocol_t proto, u32 vrf_id, int is_in)
3363 {
3365  clib_bihash_kv_8_8_t kv, value;
3366  ip4_header_t ip;
3367  u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
3368  snat_session_key_t key;
3369  snat_session_t *s;
3370  clib_bihash_8_8_t *t;
3371 
3372  if (sm->endpoint_dependent)
3373  return VNET_API_ERROR_UNSUPPORTED;
3374 
3375  ip.dst_address.as_u32 = ip.src_address.as_u32 = addr->as_u32;
3376  if (sm->num_workers > 1)
3377  tsm =
3379  sm->worker_in2out_cb (&ip, fib_index));
3380  else
3381  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
3382 
3383  key.addr.as_u32 = addr->as_u32;
3384  key.port = clib_host_to_net_u16 (port);
3385  key.protocol = proto;
3386  key.fib_index = fib_index;
3387  kv.key = key.as_u64;
3388  t = is_in ? &tsm->in2out : &tsm->out2in;
3389  if (!clib_bihash_search_8_8 (t, &kv, &value))
3390  {
3391  if (pool_is_free_index (tsm->sessions, value.value))
3392  return VNET_API_ERROR_UNSPECIFIED;
3393 
3394  s = pool_elt_at_index (tsm->sessions, value.value);
3395  nat_free_session_data (sm, s, tsm - sm->per_thread_data);
3396  nat44_delete_session (sm, s, tsm - sm->per_thread_data);
3397  return 0;
3398  }
3399 
3400  return VNET_API_ERROR_NO_SUCH_ENTRY;
3401 }
3402 
3403 int
3405  ip4_address_t *eh_addr, u16 eh_port, u8 proto,
3406  u32 vrf_id, int is_in)
3407 {
3408  ip4_header_t ip;
3409  clib_bihash_16_8_t *t;
3410  nat_ed_ses_key_t key;
3411  clib_bihash_kv_16_8_t kv, value;
3412  u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
3413  snat_session_t *s;
3415 
3416  if (!sm->endpoint_dependent)
3417  return VNET_API_ERROR_FEATURE_DISABLED;
3418 
3419  ip.dst_address.as_u32 = ip.src_address.as_u32 = addr->as_u32;
3420  if (sm->num_workers > 1)
3421  tsm =
3423  sm->worker_in2out_cb (&ip, fib_index));
3424  else
3425  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
3426 
3427  t = is_in ? &tsm->in2out_ed : &tsm->out2in_ed;
3428  key.l_addr.as_u32 = addr->as_u32;
3429  key.r_addr.as_u32 = eh_addr->as_u32;
3430  key.l_port = clib_host_to_net_u16 (port);
3431  key.r_port = clib_host_to_net_u16 (eh_port);
3432  key.proto = proto;
3433  key.fib_index = clib_host_to_net_u32 (fib_index);
3434  kv.key[0] = key.as_u64[0];
3435  kv.key[1] = key.as_u64[1];
3436  if (clib_bihash_search_16_8 (t, &kv, &value))
3437  return VNET_API_ERROR_NO_SUCH_ENTRY;
3438 
3439  if (pool_is_free_index (tsm->sessions, value.value))
3440  return VNET_API_ERROR_UNSPECIFIED;
3441  s = pool_elt_at_index (tsm->sessions, value.value);
3442  nat_free_session_data (sm, s, tsm - sm->per_thread_data);
3443  nat44_delete_session (sm, s, tsm - sm->per_thread_data);
3444  return 0;
3445 }
3446 
3447 void
3448 nat_set_alloc_addr_and_port_mape (u16 psid, u16 psid_offset, u16 psid_length)
3449 {
3450  snat_main_t *sm = &snat_main;
3451 
3453  sm->psid = psid;
3454  sm->psid_offset = psid_offset;
3455  sm->psid_length = psid_length;
3456 }
3457 
3458 void
3460 {
3461  snat_main_t *sm = &snat_main;
3462 
3464 }
3465 
ip4_address_t external_addr
Definition: nat.h:244
u32 user_memory_size
Definition: nat.h:401
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:221
u8 * format_snat_user(u8 *s, va_list *args)
Definition: nat.c:3011
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:437
clib_error_t * snat_api_init(vlib_main_t *vm, snat_main_t *sm)
Definition: nat_api.c:3145
void dslite_set_ce(dslite_main_t *dm, u8 set)
Definition: dslite.c:74
u32 next
Definition: dlist.h:30
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:197
nat_outside_fib_t * outside_fibs
Definition: nat.h:359
vmrglw vmrglh hi
format_function_t format_ip_protocol
Definition: format.h:45
#define nat_log_info(...)
Definition: nat.h:532
#define snat_is_session_static(s)
Check if SNAT session is created from static mapping.
Definition: nat.h:491
u32 sessions_per_user_list_head_index
Definition: nat.h:189
#define CLIB_UNUSED(x)
Definition: clib.h:79
int snat_del_address(snat_main_t *sm, ip4_address_t addr, u8 delete_sm, u8 twice_nat)
Definition: nat.c:1478
int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port, u32 vrf_id, int addr_only, u32 sw_if_index, snat_protocol_t proto, int is_add, twice_nat_type_t twice_nat, u8 out2in_only, u8 *tag)
Add static mapping.
Definition: nat.c:796
vlib_node_registration_t nat44_handoff_classify_node
(constructor) VLIB_REGISTER_NODE (nat44_handoff_classify_node)
Definition: nat.c:178
u16 ext_host_port
Definition: nat.h:82
void dslite_init(vlib_main_t *vm)
Definition: dslite.c:22
u16 out_port
Definition: nat.h:83
ip4_add_del_interface_address_callback_t * add_del_interface_address_callbacks
Functions to call when interface address changes.
Definition: ip4.h:129
VLIB_NODE_FUNCTION_MULTIARCH(nat44_classify_node, nat44_classify_node_fn)
a
Definition: bitmap.h:538
u8 * format_snat_protocol(u8 *s, va_list *args)
Definition: nat.c:2431
static void clib_dlist_init(dlist_elt_t *pool, u32 index)
Definition: dlist.h:36
u32 icmp_timeout
Definition: nat.h:412
ip4_address_t src_address
Definition: ip4_packet.h:169
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
static int nat_alloc_addr_and_port_mape(snat_address_t *addresses, u32 fib_index, u32 thread_index, snat_session_key_t *k, u32 *address_indexp, u16 port_per_thread, u32 snat_thread_index)
Definition: nat.c:2341
u32 fq_in2out_output_index
Definition: nat.h:376
clib_error_t * nat_reass_init(vlib_main_t *vm)
Initialize NAT virtual fragmentation reassembly.
Definition: nat_reass.c:585
vlib_node_registration_t nat44_ed_in2out_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_node)
Definition: in2out.c:119
#define SNAT_TCP_ESTABLISHED_TIMEOUT
Definition: nat.h:37
#define PREDICT_TRUE(x)
Definition: clib.h:106
u32 nsessions
Definition: nat.h:190
#define is_ed_session(s)
Check if NAT session is endpoint dependent.
Definition: nat.h:521
static_always_inline u8 icmp_is_error_message(icmp46_header_t *icmp)
Definition: nat_inlines.h:52
unsigned long u64
Definition: types.h:89
ip4_address_t addr
Definition: nat.h:230
#define NULL
Definition: clib.h:55
u32 index
Definition: node.h:273
snat_protocol_t proto
Definition: nat.h:252
ip4_address_t * ip4_interface_first_address(ip4_main_t *im, u32 sw_if_index, ip_interface_address_t **result_ia)
Definition: ip4_forward.c:320
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:948
int nat44_add_del_lb_static_mapping(ip4_address_t e_addr, u16 e_port, snat_protocol_t proto, u32 vrf_id, nat44_lb_addr_port_t *locals, u8 is_add, twice_nat_type_t twice_nat, u8 out2in_only, u8 *tag)
Definition: nat.c:1219
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:260
u16 port_per_thread
Definition: nat.h:332
u32 vlib_frame_queue_main_init(u32 node_index, u32 frame_queue_nelts)
Definition: threads.c:1778
nat_reass_ip4_t * nat_ip4_reass_find(ip4_address_t src, ip4_address_t dst, u16 frag_id, u8 proto)
Find reassembly.
Definition: nat_reass.c:199
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:523
#define nat_log_warn(...)
Definition: nat.h:528
u32 nstaticsessions
Definition: nat.h:191
u32 icmp_match_out2in_slow(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation and create session if needed...
Definition: out2in.c:286
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:562
#define NAT_INTERFACE_FLAG_IS_OUTSIDE
Definition: nat.h:147
int i
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap. ...
Definition: bitmap.h:167
u8 * format_user_kvp(u8 *s, va_list *args)
Definition: nat.c:2478
ip_lookup_main_t lookup_main
Definition: ip4.h:97
vlib_node_registration_t nat44_ed_in2out_output_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_output_node)
Definition: in2out.c:121
vlib_node_registration_t snat_det_out2in_node
(constructor) VLIB_REGISTER_NODE (snat_det_out2in_node)
Definition: out2in.c:3292
void nat64_set_hash(u32 bib_buckets, u32 bib_memory_size, u32 st_buckets, u32 st_memory_size)
Set NAT64 hash tables configuration.
Definition: nat64.c:252
int nat44_del_ed_session(snat_main_t *sm, ip4_address_t *addr, u16 port, ip4_address_t *eh_addr, u16 eh_port, u8 proto, u32 vrf_id, int is_in)
Definition: nat.c:3404
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
u32 fib_index
Definition: nat.h:188
void snat_add_del_addr_to_fib(ip4_address_t *addr, u8 p_len, u32 sw_if_index, int is_add)
Add/del NAT address to FIB.
Definition: nat.c:634
nat_alloc_out_addr_and_port_function_t * alloc_addr_and_port
Definition: nat.h:353
static void snat_ip4_add_del_interface_address_cb(ip4_main_t *im, uword opaque, u32 sw_if_index, ip4_address_t *address, u32 address_length, u32 if_address_index, u32 is_delete)
Definition: nat.c:3214
u32 num_snat_thread
Definition: nat.h:333
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:228
dlist_elt_t * list_pool
Definition: nat.h:295
#define snat_is_unk_proto_session(s)
Check if SNAT session for unknown protocol.
Definition: nat.h:497
u8 * format_snat_static_mapping(u8 *s, va_list *args)
Definition: nat.c:3051
vhost_vring_addr_t addr
Definition: vhost_user.h:116
u32 proto
Definition: nat.h:67
u32 icmp_match_in2out_fast(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation.
Definition: in2out.c:604
format_function_t format_vnet_sw_if_index_name
unsigned char u8
Definition: types.h:56
u8 deterministic
Definition: nat.h:394
int snat_interface_add_del(u32 sw_if_index, u8 is_inside, int is_del)
Definition: nat.c:1581
static uword nat44_classify_node_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: nat.c:429
u32 icmp_match_out2in_ed(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Definition: out2in.c:1822
u16 l_port
Definition: nat.h:69
nat44_lb_addr_port_t * locals
Definition: nat.h:255
void nat66_init(void)
Definition: nat66.c:43
u32 user_buckets
Definition: nat.h:400
clib_bihash_8_8_t user_hash
Definition: nat.h:286
u16 identifier
Definition: nat.h:544
fib_node_index_t fib_table_entry_update_one_path(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, dpo_proto_t next_hop_proto, const ip46_address_t *next_hop, u32 next_hop_sw_if_index, u32 next_hop_fib_index, u32 next_hop_weight, fib_mpls_label_t *next_hop_labels, fib_route_path_flags_t path_flags)
Update the entry to have just one path.
Definition: fib_table.c:772
u32 max_translations_per_user
Definition: nat.h:402
static void snat_add_static_mapping_when_resolved(snat_main_t *sm, ip4_address_t l_addr, u16 l_port, u32 sw_if_index, u16 e_port, u32 vrf_id, snat_protocol_t proto, int addr_only, int is_add, u8 *tag)
Definition: nat.c:748
clib_bihash_8_8_t in2out
Definition: nat.h:279
nat66_main_t nat66_main
Definition: nat66.c:23
u32 in2out_output_node_index
Definition: nat.h:381
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
Definition: ip4_fib.c:224
format_function_t format_ip4_address
Definition: format.h:81
#define static_always_inline
Definition: clib.h:93
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:443
u16 r_port
Definition: nat.h:70
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:156
vlib_node_registration_t snat_out2in_node
(constructor) VLIB_REGISTER_NODE (snat_out2in_node)
Definition: out2in.c:1225
ip4_address_t ext_host_addr
Definition: nat.h:81
void fib_table_entry_special_remove(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source)
Remove a &#39;special&#39; entry from the FIB.
Definition: fib_table.c:407
u8 * format_static_mapping_kvp(u8 *s, va_list *args)
Definition: nat.c:2465
ip4_address_t dst_address
Definition: ip4_packet.h:169
static u32 snat_get_worker_in2out_cb(ip4_header_t *ip0, u32 rx_fib_index0)
Definition: nat.c:2509
int snat_add_address(snat_main_t *sm, ip4_address_t *addr, u32 vrf_id, u8 twice_nat)
Definition: nat.c:666
u32 translation_buckets
Definition: nat.h:397
u8 * format_ed_session_kvp(u8 *s, va_list *args)
Definition: nat.c:2492
#define nat_log_err(...)
Definition: nat.h:526
ip4_address_t addr
Definition: nat.h:187
#define SNAT_DET_SES_PER_USER
Definition: nat_det.h:30
A high priority source a plugin can use.
Definition: fib_entry.h:62
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, u8 *lb)
Match NAT44 static mapping.
Definition: nat.c:2129
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Aggregrate type for a prefix.
Definition: fib_types.h:188
#define clib_error_return(e, args...)
Definition: error.h:99
#define is_fwd_bypass_session(s)
Check if NAT session is forwarding bypass.
Definition: nat.h:515
void snat_ipfix_logging_init(vlib_main_t *vm)
Initialize NAT plugin IPFIX logging.
ip4_main_t * ip4_main
Definition: nat.h:423
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:240
unsigned int u32
Definition: types.h:88
nat44_classify_next_t
Definition: nat.c:180
u32 fib_table_find(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1056
ip4_address_t local_addr
Definition: nat.h:243
static void nat_ip4_add_del_addr_only_sm_cb(ip4_main_t *im, uword opaque, u32 sw_if_index, ip4_address_t *address, u32 address_length, u32 if_address_index, u32 is_delete)
Definition: nat.c:3143
u64 as_u64[2]
Definition: nat.h:72
static uword nat44_det_classify_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: nat.c:574
snat_protocol_t proto
Definition: nat.h:269
u32 icmp_match_out2in_det(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation and create session if needed...
Definition: out2in.c:3330
static void nat44_delete_session(snat_main_t *sm, snat_session_t *ses, u32 thread_index)
Definition: nat_inlines.h:144
static int ip4_is_fragment(ip4_header_t *i)
Definition: ip4_packet.h:212
twice_nat_type_t twice_nat
Definition: nat.h:248
VNET_FEATURE_INIT(ip4_snat_in2out, static)
u32 max_translations
Definition: nat.h:399
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:168
u32 * auto_add_sw_if_indices_twice_nat
Definition: nat.h:366
Definition: fib_entry.h:275
vlib_node_registration_t nat44_ed_out2in_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_out2in_node)
Definition: out2in.c:2767
u32 fib_index
Definition: nat.h:67
#define hash_get(h, key)
Definition: hash.h:249
snat_user_t * nat_user_get_or_create(snat_main_t *sm, ip4_address_t *addr, u32 fib_index, u32 thread_index)
Definition: nat.c:297
Definition: fib_entry.h:274
#define clib_bitmap_foreach(i, ai, body)
Macro to iterate across set bits in a bitmap.
Definition: bitmap.h:361
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:464
void nat_free_session_data(snat_main_t *sm, snat_session_t *s, u32 thread_index)
Definition: nat.c:187
u32 fib_index
Definition: nat.h:206
void nat_dpo_module_init(void)
Definition: nat_dpo.c:68
uword * fib_index_by_table_id
Hash table mapping table id to fib index.
Definition: ip4.h:121
clib_bihash_16_8_t out2in_ed
Definition: nat.h:282
static uword clib_bitmap_last_set(uword *ai)
Return the higest numbered set bit in a bitmap.
Definition: bitmap.h:423
u64 key
the key
Definition: bihash_8_8.h:35
u8 address_length
Definition: ip_types.api:42
lo
vlib_main_t * vlib_main
Definition: nat.h:421
static void clib_dlist_addtail(dlist_elt_t *pool, u32 head_index, u32 new_index)
Definition: dlist.h:43
#define v
Definition: acl.c:491
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
u16 protocol
Definition: nat.h:53
u8 out2in_dpo
Definition: nat.h:395
#define SNAT_UDP_TIMEOUT
Definition: nat.h:34
snat_static_mapping_t * static_mappings
Definition: nat.h:345
u32 inside_fib_index
Definition: nat.h:406
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:202
void snat_ipfix_logging_nat44_ses_delete(u32 src_ip, u32 nat_src_ip, snat_protocol_t snat_proto, u16 src_port, u16 nat_src_port, u32 vrf_id)
Generate NAT44 session delete event.
vlib_node_registration_t nat44_classify_node
(constructor) VLIB_REGISTER_NODE (nat44_classify_node)
Definition: nat.c:175
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:274
u32 udp_timeout
Definition: nat.h:409
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:373
u8 static_mapping_only
Definition: nat.h:392
#define NAT_FQ_NELTS
Definition: nat.h:41
#define PREDICT_FALSE(x)
Definition: clib.h:105
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:164
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:806
clib_bihash_8_8_t static_mapping_by_external
Definition: nat.h:342
u8 psid_offset
Definition: nat.h:354
#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
void nat_set_alloc_addr_and_port_default(void)
Definition: nat.c:3459
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:364
#define nat_log_notice(...)
Definition: nat.h:530
api_main_t * api_main
Definition: nat.h:425
void fib_table_unlock(u32 fib_index, fib_protocol_t proto, fib_source_t source)
Take a reference counting lock on the table.
Definition: fib_table.c:1228
u8 psid_length
Definition: nat.h:355
u32 refcount
Definition: nat.h:207
vnet_main_t * vnet_main
Definition: nat.h:422
u32 inside_vrf_id
Definition: nat.h:405
#define is_lb_session(s)
Check if NAT session is load-balancing.
Definition: nat.h:509
u32 fq_out2in_index
Definition: nat.h:377
snat_interface_t * output_feature_interfaces
Definition: nat.h:349
static uword nat44_handoff_classify_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: nat.c:598
snat_main_t snat_main
Definition: nat.c:36
u64 value
the value
Definition: bihash_8_8.h:36
snat_user_t * users
Definition: nat.h:289
u32 random_seed
Definition: nat.h:372
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:153
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
static u32 nat44_ed_get_worker_out2in_cb(ip4_header_t *ip, u32 rx_fib_index)
Definition: nat.c:2635
static u8 snat_proto_to_ip_proto(snat_protocol_t snat_proto)
Definition: nat_inlines.h:40
u16 n_vectors
Definition: node.h:380
void snat_free_outside_address_and_port(snat_address_t *addresses, u32 thread_index, snat_session_key_t *k, u32 address_index)
Definition: nat.c:2084
clib_bihash_8_8_t out2in
Definition: nat.h:278
static u32 random_u32_max(void)
Maximum value returned by random_u32()
Definition: random.h:80
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:221
u8 nat_reass_is_drop_frag(u8 is_ip6)
Get status of virtual fragmentation reassembly.
Definition: nat_reass.c:168
vlib_main_t * vm
Definition: buffer.c:294
u32 outside_vrf_id
Definition: nat.h:403
void nat44_add_del_address_dpo(ip4_address_t addr, u8 is_add)
Definition: nat.c:2394
vlib_node_registration_t snat_in2out_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_node)
Definition: in2out.c:107
ip4_address_t l_addr
Definition: nat.h:65
u8 static_mapping_connection_tracking
Definition: nat.h:393
snat_get_worker_function_t * worker_in2out_cb
Definition: nat.h:330
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:339
void fib_table_entry_delete(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source)
Delete a FIB entry.
Definition: fib_table.c:853
ip4_add_del_interface_address_function_t * function
Definition: ip4.h:72
deterministic NAT definitions
u32 error_node_index
Definition: nat.h:383
VLIB_PLUGIN_REGISTER()
int snat_interface_add_del_output_feature(u32 sw_if_index, u8 is_inside, int is_del)
Definition: nat.c:1818
static int ip4_is_first_fragment(ip4_header_t *i)
Definition: ip4_packet.h:219
u32 sharing_ratio
Definition: nat.h:222
ip4_address_t out_addr
Definition: nat.h:220
u16 psid
Definition: nat.h:356
static uword nat44_classify_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: nat.c:527
dslite_main_t dslite_main
Definition: dslite.c:19
u32 outside_fib_index
Definition: nat.h:404
u8 * format_session_kvp(u8 *s, va_list *args)
Definition: nat.c:2452
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:271
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:33
ip4_address_t addr
Definition: nat.h:51
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:454
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
u32 icmp_match_in2out_slow(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation and create session if needed...
Definition: in2out.c:500
u32 tcp_transitory_timeout
Definition: nat.h:411
ip4_address_t r_addr
Definition: nat.h:66
u32 * auto_add_sw_if_indices
Definition: nat.h:365
fib_node_index_t fib_table_entry_special_dpo_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, const dpo_id_t *dpo)
Add a &#39;special&#39; entry to the FIB that links to the DPO passed A special entry is an entry that the FI...
Definition: fib_table.c:307
static_always_inline u16 snat_random_port(u16 min, u16 max)
Definition: nat.c:2225
static int nat_alloc_addr_and_port_default(snat_address_t *addresses, u32 fib_index, u32 thread_index, snat_session_key_t *k, u32 *address_indexp, u16 port_per_thread, u32 snat_thread_index)
Definition: nat.c:2249
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:492
#define ASSERT(truth)
#define NAT_INTERFACE_FLAG_IS_INSIDE
Definition: nat.h:146
u8 * format_snat_static_map_to_resolve(u8 *s, va_list *args)
Definition: nat.c:3093
u32 num_workers
Definition: nat.h:327
Definition: nat.h:238
u32 first_worker_index
Definition: nat.h:328
snat_get_worker_function_t * worker_out2in_cb
Definition: nat.h:331
ip4_address_t l_addr
Definition: nat.h:264
snat_icmp_match_function_t * icmp_match_out2in_cb
Definition: nat.h:325
vlib_log_class_t log_class
Definition: nat.h:418
IPv4 main type.
Definition: ip4.h:95
u64 as_u64
Definition: nat.h:97
u32 fib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id, fib_source_t src)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1115
ip4_address_t addr
Definition: nat.h:94
ip4_address_t in_addr
Definition: nat.h:218
#define clib_bitmap_free(v)
Free a bitmap.
Definition: bitmap.h:92
u32 fq_in2out_index
Definition: nat.h:375
uword * thread_registrations_by_name
Definition: threads.h:297
u32 out2in_node_index
Definition: nat.h:382
ip4_address_t addr
Definition: nat.h:195
int nat44_del_session(snat_main_t *sm, ip4_address_t *addr, u16 port, snat_protocol_t proto, u32 vrf_id, int is_in)
Definition: nat.c:3361
snat_address_t * twice_nat_addresses
Definition: nat.h:362
#define VNET_FEATURES(...)
Definition: feature.h:391
static clib_error_t * snat_init(vlib_main_t *vm)
Definition: nat.c:1987
static uword is_pow2(uword x)
Definition: clib.h:229
u32 value
Definition: dlist.h:32
snat_session_t * nat_session_alloc_or_recycle(snat_main_t *sm, snat_user_t *u, u32 thread_index)
Definition: nat.c:341
vlib_node_registration_t snat_det_in2out_node
(constructor) VLIB_REGISTER_NODE (snat_det_in2out_node)
Definition: in2out.c:111
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
u32 icmp_match_out2in_fast(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation.
Definition: out2in.c:404
clib_error_t * nat64_init(vlib_main_t *vm)
Initialize NAT64.
Definition: nat64.c:212
struct _vlib_node_registration vlib_node_registration_t
NAT64 global declarations.
void increment_v4_address(ip4_address_t *a)
Definition: nat.c:739
static u32 ip_proto_to_snat_proto(u8 ip_proto)
The NAT inline functions.
Definition: nat_inlines.h:25
int snat_alloc_outside_address_and_port(snat_address_t *addresses, u32 fib_index, u32 thread_index, snat_session_key_t *k, u32 *address_indexp, u16 port_per_thread, u32 snat_thread_index)
Definition: nat.c:2233
twice_nat_type_t
Definition: nat.h:236
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u32 outside_fib_index
Definition: nat66.h:60
Definition: fib_entry.h:271
void snat_ipfix_logging_addresses_exhausted(u32 pool_id)
Generate NAT addresses exhausted event.
u32 * workers
Definition: nat.h:329
u64 uword
Definition: types.h:112
snat_main_per_thread_data_t * per_thread_data
Definition: nat.h:336
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:267
snat_protocol_t
Definition: nat.h:107
snat_det_out_key_t out
Definition: nat.h:212
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:195
u32 fib_index
Definition: nat.h:95
static uword nat44_ed_classify_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: nat.c:550
snat_address_t * addresses
Definition: nat.h:352
void nat_dpo_create(dpo_proto_t dproto, u32 aftr_index, dpo_id_t *dpo)
Definition: nat_dpo.c:22
typedef prefix
Definition: ip_types.api:40
int snat_add_interface_address(snat_main_t *sm, u32 sw_if_index, int is_del, u8 twice_nat)
Definition: nat.c:3294
u32 icmp_match_in2out_det(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation and create session if needed...
Definition: in2out.c:4396
u8 * format_snat_session(u8 *s, va_list *args)
Definition: nat.c:2954
#define hash_get_mem(h, key)
Definition: hash.h:269
u8 * format_det_map_ses(u8 *s, va_list *args)
Definition: nat.c:3113
u32 in2out_node_index
Definition: nat.h:380
#define SNAT_ICMP_TIMEOUT
Definition: nat.h:39
uword unformat_snat_protocol(unformat_input_t *input, va_list *args)
Definition: nat.c:2417
snat_static_map_resolve_t * to_resolve
Definition: nat.h:369
static u32 random_u32(u32 *seed)
32-bit random number generator
Definition: random.h:69
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
u32 icmp_match_in2out_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: in2out.c:2642
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:832
u8 * format_snat_key(u8 *s, va_list *args)
Definition: nat.c:2943
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
u32 outside_vrf_id
Definition: nat66.h:59
static u8 * format_nat44_classify_trace(u8 *s, va_list *args)
Definition: nat.c:414
u8 forwarding_enabled
Definition: nat.h:389
u32 translation_memory_size
Definition: nat.h:398
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:231
#define vec_foreach(var, vec)
Vector iterator.
vlib_node_registration_t snat_in2out_output_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_output_node)
Definition: in2out.c:112
vlib_node_registration_t nat44_ed_classify_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_classify_node)
Definition: nat.c:176
vlib_node_registration_t nat44_det_classify_node
(constructor) VLIB_REGISTER_NODE (nat44_det_classify_node)
Definition: nat.c:177
int snat_set_workers(uword *bitmap)
Definition: nat.c:1934
u16 flags
Copy of main node flags.
Definition: node.h:486
#define is_twice_nat_session(s)
Check if NAT session is twice NAT.
Definition: nat.h:503
clib_bihash_16_8_t in2out_ed
Definition: nat.h:283
u8 endpoint_dependent
Definition: nat.h:396
static clib_error_t * snat_config(vlib_main_t *vm, unformat_input_t *input)
Definition: nat.c:2726
NAT plugin virtual fragmentation reassembly.
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:295
void nat_set_alloc_addr_and_port_mape(u16 psid, u16 psid_offset, u16 psid_length)
Definition: nat.c:3448
NAT66 global declarations.
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:111
#define SNAT_TCP_TRANSITORY_TIMEOUT
Definition: nat.h:36
ip_lookup_main_t * ip4_lookup_main
Definition: nat.h:424
api_main_t api_main
Definition: api_shared.c:35
static int is_snat_address_used_in_static_mapping(snat_main_t *sm, ip4_address_t addr)
Definition: nat.c:726
snat_session_t * sessions
Definition: nat.h:292
u8 * format_snat_session_state(u8 *s, va_list *args)
Definition: nat.c:2926
A low (below routing) priority source a plugin can use.
Definition: fib_entry.h:78
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
snat_icmp_match_function_t * icmp_match_in2out_cb
Definition: nat.h:324
clib_bihash_8_8_t static_mapping_by_local
Definition: nat.h:339
static u32 snat_get_worker_out2in_cb(ip4_header_t *ip0, u32 rx_fib_index0)
Definition: nat.c:2528
u32 fib_index
Definition: nat.h:196
snat_interface_t * interfaces
Definition: nat.h:348
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
u16 fib_index
Definition: nat.h:53
int vnet_feature_enable_disable(const char *arc_name, const char *node_name, u32 sw_if_index, int enable_disable, void *feature_config, u32 n_feature_config_bytes)
Definition: feature.c:233
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
static u32 clib_dlist_remove_head(dlist_elt_t *pool, u32 head_index)
Definition: dlist.h:117
u32 tcp_established_timeout
Definition: nat.h:410
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128