FD.io VPP  v18.07-rc0-415-g6c78436
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 = sm->outside_fib_index;
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 = sm->outside_fib_index;
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 = sm->outside_fib_index;
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 = sm->outside_fib_index;
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 = sm->outside_fib_index;
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 = sm->outside_fib_index;
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 
1590  if (sm->out2in_dpo && !is_inside)
1591  return VNET_API_ERROR_UNSUPPORTED;
1592 
1594  ({
1595  if (i->sw_if_index == sw_if_index)
1596  return VNET_API_ERROR_VALUE_EXIST;
1597  }));
1598 
1600  feature_name = is_inside ? "nat44-in2out-fast" : "nat44-out2in-fast";
1601  else
1602  {
1603  if (sm->num_workers > 1 && !sm->deterministic)
1604  feature_name = is_inside ? "nat44-in2out-worker-handoff" : "nat44-out2in-worker-handoff";
1605  else if (sm->deterministic)
1606  feature_name = is_inside ? "nat44-det-in2out" : "nat44-det-out2in";
1607  else if (sm->endpoint_dependent)
1608  feature_name = is_inside ? "nat44-ed-in2out" : "nat44-ed-out2in";
1609  else
1610  feature_name = is_inside ? "nat44-in2out" : "nat44-out2in";
1611  }
1612 
1613  if (sm->fq_in2out_index == ~0 && !sm->deterministic && sm->num_workers > 1)
1615  NAT_FQ_NELTS);
1616 
1617  if (sm->fq_out2in_index == ~0 && !sm->deterministic && sm->num_workers > 1)
1619  NAT_FQ_NELTS);
1620 
1621  pool_foreach (i, sm->interfaces,
1622  ({
1623  if (i->sw_if_index == sw_if_index)
1624  {
1625  if (is_del)
1626  {
1627  if (nat_interface_is_inside(i) && nat_interface_is_outside(i))
1628  {
1629  if (is_inside)
1630  i->flags &= ~NAT_INTERFACE_FLAG_IS_INSIDE;
1631  else
1632  i->flags &= ~NAT_INTERFACE_FLAG_IS_OUTSIDE;
1633 
1634  if (sm->num_workers > 1 && !sm->deterministic)
1635  {
1636  del_feature_name = "nat44-handoff-classify";
1637  feature_name = !is_inside ? "nat44-in2out-worker-handoff" :
1638  "nat44-out2in-worker-handoff";
1639  }
1640  else if (sm->deterministic)
1641  {
1642  del_feature_name = "nat44-det-classify";
1643  feature_name = !is_inside ? "nat44-det-in2out" :
1644  "nat44-det-out2in";
1645  }
1646  else if (sm->endpoint_dependent)
1647  {
1648  del_feature_name = "nat44-ed-classify";
1649  feature_name = !is_inside ? "nat44-ed-in2out" :
1650  "nat44-ed-out2in";
1651  }
1652  else
1653  {
1654  del_feature_name = "nat44-classify";
1655  feature_name = !is_inside ? "nat44-in2out" : "nat44-out2in";
1656  }
1657 
1658  vnet_feature_enable_disable ("ip4-unicast", del_feature_name,
1659  sw_if_index, 0, 0, 0);
1660  vnet_feature_enable_disable ("ip4-unicast", feature_name,
1661  sw_if_index, 1, 0, 0);
1662  if (!is_inside)
1663  {
1664  if (sm->endpoint_dependent)
1665  vnet_feature_enable_disable ("ip4-local",
1666  "nat44-ed-hairpinning",
1667  sw_if_index, 1, 0, 0);
1668  else
1669  vnet_feature_enable_disable ("ip4-local",
1670  "nat44-hairpinning",
1671  sw_if_index, 1, 0, 0);
1672  }
1673  }
1674  else
1675  {
1676  vnet_feature_enable_disable ("ip4-unicast", feature_name,
1677  sw_if_index, 0, 0, 0);
1678  pool_put (sm->interfaces, i);
1679  if (is_inside)
1680  {
1681  if (sm->endpoint_dependent)
1682  vnet_feature_enable_disable ("ip4-local",
1683  "nat44-ed-hairpinning",
1684  sw_if_index, 0, 0, 0);
1685  else
1686  vnet_feature_enable_disable ("ip4-local",
1687  "nat44-hairpinning",
1688  sw_if_index, 0, 0, 0);
1689  }
1690  }
1691  }
1692  else
1693  {
1694  if ((nat_interface_is_inside(i) && is_inside) ||
1695  (nat_interface_is_outside(i) && !is_inside))
1696  return 0;
1697 
1698  if (sm->num_workers > 1 && !sm->deterministic)
1699  {
1700  del_feature_name = !is_inside ? "nat44-in2out-worker-handoff" :
1701  "nat44-out2in-worker-handoff";
1702  feature_name = "nat44-handoff-classify";
1703  }
1704  else if (sm->deterministic)
1705  {
1706  del_feature_name = !is_inside ? "nat44-det-in2out" :
1707  "nat44-det-out2in";
1708  feature_name = "nat44-det-classify";
1709  }
1710  else if (sm->endpoint_dependent)
1711  {
1712  del_feature_name = !is_inside ? "nat44-ed-in2out" :
1713  "nat44-ed-out2in";
1714  feature_name = "nat44-ed-classify";
1715  }
1716  else
1717  {
1718  del_feature_name = !is_inside ? "nat44-in2out" : "nat44-out2in";
1719  feature_name = "nat44-classify";
1720  }
1721 
1722  vnet_feature_enable_disable ("ip4-unicast", del_feature_name,
1723  sw_if_index, 0, 0, 0);
1724  vnet_feature_enable_disable ("ip4-unicast", feature_name,
1725  sw_if_index, 1, 0, 0);
1726  if (!is_inside)
1727  {
1728  if (sm->endpoint_dependent)
1729  vnet_feature_enable_disable ("ip4-local", "nat44-ed-hairpinning",
1730  sw_if_index, 0, 0, 0);
1731  else
1732  vnet_feature_enable_disable ("ip4-local", "nat44-hairpinning",
1733  sw_if_index, 0, 0, 0);
1734  }
1735  goto set_flags;
1736  }
1737 
1738  goto fib;
1739  }
1740  }));
1741 
1742  if (is_del)
1743  return VNET_API_ERROR_NO_SUCH_ENTRY;
1744 
1745  pool_get (sm->interfaces, i);
1746  i->sw_if_index = sw_if_index;
1747  i->flags = 0;
1748  vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, 1, 0, 0);
1749 
1750  if (is_inside && !sm->out2in_dpo)
1751  {
1752  if (sm->endpoint_dependent)
1753  vnet_feature_enable_disable ("ip4-local", "nat44-ed-hairpinning",
1754  sw_if_index, 1, 0, 0);
1755  else
1756  vnet_feature_enable_disable ("ip4-local", "nat44-hairpinning",
1757  sw_if_index, 1, 0, 0);
1758  }
1759 
1760 set_flags:
1761  if (is_inside)
1762  {
1763  i->flags |= NAT_INTERFACE_FLAG_IS_INSIDE;
1764  return 0;
1765  }
1766  else
1767  i->flags |= NAT_INTERFACE_FLAG_IS_OUTSIDE;
1768 
1769  /* Add/delete external addresses to FIB */
1770 fib:
1771  vec_foreach (ap, sm->addresses)
1772  snat_add_del_addr_to_fib(&ap->addr, 32, sw_if_index, !is_del);
1773 
1774  pool_foreach (m, sm->static_mappings,
1775  ({
1776  if (!(m->addr_only) || (m->local_addr.as_u32 == m->external_addr.as_u32))
1777  continue;
1778 
1779  snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
1780  }));
1781 
1782  pool_foreach (dm, sm->det_maps,
1783  ({
1784  snat_add_del_addr_to_fib(&dm->out_addr, dm->out_plen, sw_if_index, !is_del);
1785  }));
1786 
1787  return 0;
1788 }
1789 
1791  u8 is_inside,
1792  int is_del)
1793 {
1794  snat_main_t *sm = &snat_main;
1796  snat_address_t * ap;
1798 
1799  if (sm->deterministic ||
1801  return VNET_API_ERROR_UNSUPPORTED;
1802 
1803  pool_foreach (i, sm->interfaces,
1804  ({
1805  if (i->sw_if_index == sw_if_index)
1806  return VNET_API_ERROR_VALUE_EXIST;
1807  }));
1808 
1809  if (is_inside)
1810  {
1811  if (sm->endpoint_dependent)
1812  {
1813  vnet_feature_enable_disable ("ip4-unicast", "nat44-ed-hairpin-dst",
1814  sw_if_index, !is_del, 0, 0);
1815  vnet_feature_enable_disable ("ip4-output", "nat44-ed-hairpin-src",
1816  sw_if_index, !is_del, 0, 0);
1817  }
1818  else
1819  {
1820  vnet_feature_enable_disable ("ip4-unicast", "nat44-hairpin-dst",
1821  sw_if_index, !is_del, 0, 0);
1822  vnet_feature_enable_disable ("ip4-output", "nat44-hairpin-src",
1823  sw_if_index, !is_del, 0, 0);
1824  }
1825  goto fq;
1826  }
1827 
1828  if (sm->num_workers > 1)
1829  {
1830  vnet_feature_enable_disable ("ip4-unicast",
1831  "nat44-out2in-worker-handoff",
1832  sw_if_index, !is_del, 0, 0);
1833  vnet_feature_enable_disable ("ip4-output",
1834  "nat44-in2out-output-worker-handoff",
1835  sw_if_index, !is_del, 0, 0);
1836  }
1837  else
1838  {
1839  if (sm->endpoint_dependent)
1840  {
1841  vnet_feature_enable_disable ("ip4-unicast", "nat44-ed-out2in",
1842  sw_if_index, !is_del, 0, 0);
1843  vnet_feature_enable_disable ("ip4-output", "nat44-ed-in2out-output",
1844  sw_if_index, !is_del, 0, 0);
1845  }
1846  else
1847  {
1848  vnet_feature_enable_disable ("ip4-unicast", "nat44-out2in",
1849  sw_if_index, !is_del, 0, 0);
1850  vnet_feature_enable_disable ("ip4-output", "nat44-in2out-output",
1851  sw_if_index, !is_del, 0, 0);
1852  }
1853  }
1854 
1855 fq:
1856  if (sm->fq_in2out_output_index == ~0 && sm->num_workers > 1)
1859 
1860  if (sm->fq_out2in_index == ~0 && sm->num_workers > 1)
1862 
1864  ({
1865  if (i->sw_if_index == sw_if_index)
1866  {
1867  if (is_del)
1868  pool_put (sm->output_feature_interfaces, i);
1869  else
1870  return VNET_API_ERROR_VALUE_EXIST;
1871 
1872  goto fib;
1873  }
1874  }));
1875 
1876  if (is_del)
1877  return VNET_API_ERROR_NO_SUCH_ENTRY;
1878 
1879  pool_get (sm->output_feature_interfaces, i);
1880  i->sw_if_index = sw_if_index;
1881  i->flags = 0;
1882  if (is_inside)
1883  i->flags |= NAT_INTERFACE_FLAG_IS_INSIDE;
1884  else
1885  i->flags |= NAT_INTERFACE_FLAG_IS_OUTSIDE;
1886 
1887  /* Add/delete external addresses to FIB */
1888 fib:
1889  if (is_inside)
1890  return 0;
1891 
1892  vec_foreach (ap, sm->addresses)
1893  snat_add_del_addr_to_fib(&ap->addr, 32, sw_if_index, !is_del);
1894 
1895  pool_foreach (m, sm->static_mappings,
1896  ({
1897  if (!(m->addr_only) || (m->local_addr.as_u32 == m->external_addr.as_u32))
1898  continue;
1899 
1900  snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
1901  }));
1902 
1903  return 0;
1904 }
1905 
1906 int snat_set_workers (uword * bitmap)
1907 {
1908  snat_main_t *sm = &snat_main;
1909  int i, j = 0;
1910 
1911  if (sm->num_workers < 2)
1912  return VNET_API_ERROR_FEATURE_DISABLED;
1913 
1914  if (clib_bitmap_last_set (bitmap) >= sm->num_workers)
1915  return VNET_API_ERROR_INVALID_WORKER;
1916 
1917  vec_free (sm->workers);
1918  clib_bitmap_foreach (i, bitmap,
1919  ({
1920  vec_add1(sm->workers, i);
1922  j++;
1923  }));
1924 
1925  sm->port_per_thread = (0xffff - 1024) / _vec_len (sm->workers);
1926  sm->num_snat_thread = _vec_len (sm->workers);
1927 
1928  return 0;
1929 }
1930 
1931 
1932 static void
1934  uword opaque,
1935  u32 sw_if_index,
1936  ip4_address_t * address,
1937  u32 address_length,
1938  u32 if_address_index,
1939  u32 is_delete);
1940 
1941 static void
1943  uword opaque,
1944  u32 sw_if_index,
1945  ip4_address_t * address,
1946  u32 address_length,
1947  u32 if_address_index,
1948  u32 is_delete);
1949 
1950 static int
1952  u32 fib_index,
1953  u32 thread_index,
1954  snat_session_key_t * k,
1955  u32 * address_indexp,
1956  u16 port_per_thread,
1957  u32 snat_thread_index);
1958 
1960 {
1961  snat_main_t * sm = &snat_main;
1962  clib_error_t * error = 0;
1963  ip4_main_t * im = &ip4_main;
1964  ip_lookup_main_t * lm = &im->lookup_main;
1965  uword *p;
1968  uword *bitmap = 0;
1969  u32 i;
1971  vlib_node_t * error_drop_node;
1972 
1973  sm->vlib_main = vm;
1974  sm->vnet_main = vnet_get_main();
1975  sm->ip4_main = im;
1976  sm->ip4_lookup_main = lm;
1977  sm->api_main = &api_main;
1978  sm->first_worker_index = 0;
1979  sm->num_workers = 0;
1980  sm->num_snat_thread = 1;
1981  sm->workers = 0;
1982  sm->port_per_thread = 0xffff - 1024;
1983  sm->fq_in2out_index = ~0;
1984  sm->fq_out2in_index = ~0;
1990  sm->forwarding_enabled = 0;
1991  sm->log_class = vlib_log_register_class ("nat", 0);
1992  error_drop_node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
1993  sm->error_node_index = error_drop_node->index;
1994 
1995  p = hash_get_mem (tm->thread_registrations_by_name, "workers");
1996  if (p)
1997  {
1998  tr = (vlib_thread_registration_t *) p[0];
1999  if (tr)
2000  {
2001  sm->num_workers = tr->count;
2002  sm->first_worker_index = tr->first_index;
2003  }
2004  }
2005 
2006  vec_validate (sm->per_thread_data, tm->n_vlib_mains - 1);
2007 
2008  /* Use all available workers by default */
2009  if (sm->num_workers > 1)
2010  {
2011  for (i=0; i < sm->num_workers; i++)
2012  bitmap = clib_bitmap_set (bitmap, i, 1);
2013  snat_set_workers(bitmap);
2014  clib_bitmap_free (bitmap);
2015  }
2016  else
2017  {
2019  }
2020 
2021  error = snat_api_init(vm, sm);
2022  if (error)
2023  return error;
2024 
2025  /* Set up the interface address add/del callback */
2027  cb4.function_opaque = 0;
2028 
2030 
2032  cb4.function_opaque = 0;
2033 
2035 
2037 
2038  /* Init IPFIX logging */
2040 
2041  /* Init NAT64 */
2042  error = nat64_init(vm);
2043  if (error)
2044  return error;
2045 
2046  dslite_init(vm);
2047 
2048  nat66_init();
2049 
2050  /* Init virtual fragmenentation reassembly */
2051  return nat_reass_init(vm);
2052 }
2053 
2055 
2057  u32 thread_index,
2058  snat_session_key_t * k,
2059  u32 address_index)
2060 {
2061  snat_address_t *a;
2062  u16 port_host_byte_order = clib_net_to_host_u16 (k->port);
2063 
2064  ASSERT (address_index < vec_len (addresses));
2065 
2066  a = addresses + address_index;
2067 
2068  switch (k->protocol)
2069  {
2070 #define _(N, i, n, s) \
2071  case SNAT_PROTOCOL_##N: \
2072  ASSERT (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, \
2073  port_host_byte_order) == 1); \
2074  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, \
2075  port_host_byte_order, 0); \
2076  a->busy_##n##_ports--; \
2077  a->busy_##n##_ports_per_thread[thread_index]--; \
2078  break;
2080 #undef _
2081  default:
2082  nat_log_info ("unknown protocol");
2083  return;
2084  }
2085 }
2086 
2087 /**
2088  * @brief Match NAT44 static mapping.
2089  *
2090  * @param sm NAT main.
2091  * @param match Address and port to match.
2092  * @param mapping External or local address and port of the matched mapping.
2093  * @param by_external If 0 match by local address otherwise match by external
2094  * address.
2095  * @param is_addr_only If matched mapping is address only
2096  * @param twice_nat If matched mapping is twice NAT.
2097  * @param lb If matched mapping is load-balanced.
2098  *
2099  * @returns 0 if match found otherwise 1.
2100  */
2102  snat_session_key_t match,
2103  snat_session_key_t * mapping,
2104  u8 by_external,
2105  u8 *is_addr_only,
2106  twice_nat_type_t *twice_nat,
2107  u8 *lb)
2108 {
2109  clib_bihash_kv_8_8_t kv, value;
2111  snat_session_key_t m_key;
2112  clib_bihash_8_8_t *mapping_hash = &sm->static_mapping_by_local;
2113  u32 rand, lo = 0, hi, mid;
2114 
2115  if (by_external)
2116  mapping_hash = &sm->static_mapping_by_external;
2117 
2118  m_key.addr = match.addr;
2119  m_key.port = clib_net_to_host_u16 (match.port);
2120  m_key.protocol = match.protocol;
2121  m_key.fib_index = match.fib_index;
2122 
2123  kv.key = m_key.as_u64;
2124 
2125  if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
2126  {
2127  /* Try address only mapping */
2128  m_key.port = 0;
2129  m_key.protocol = 0;
2130  kv.key = m_key.as_u64;
2131  if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
2132  return 1;
2133  }
2134 
2135  m = pool_elt_at_index (sm->static_mappings, value.value);
2136 
2137  if (by_external)
2138  {
2139  if (vec_len (m->locals))
2140  {
2141 get_local:
2142  hi = vec_len (m->locals) - 1;
2143  rand = 1 + (random_u32 (&sm->random_seed) % m->locals[hi].prefix);
2144  while (lo < hi)
2145  {
2146  mid = ((hi - lo) >> 1) + lo;
2147  (rand > m->locals[mid].prefix) ? (lo = mid + 1) : (hi = mid);
2148  }
2149  if (!(m->locals[lo].prefix >= rand))
2150  return 1;
2151  if (PREDICT_FALSE (sm->num_workers > 1))
2152  {
2153  ip4_header_t ip = {
2154  .src_address = m->locals[lo].addr,
2155  };
2156  if (sm->worker_in2out_cb (&ip, m->fib_index) != vlib_get_thread_index ())
2157  goto get_local;
2158  }
2159  mapping->addr = m->locals[lo].addr;
2160  mapping->port = clib_host_to_net_u16 (m->locals[lo].port);
2161  }
2162  else
2163  {
2164  mapping->addr = m->local_addr;
2165  /* Address only mapping doesn't change port */
2166  mapping->port = m->addr_only ? match.port
2167  : clib_host_to_net_u16 (m->local_port);
2168  }
2169  mapping->fib_index = m->fib_index;
2170  mapping->protocol = m->proto;
2171  }
2172  else
2173  {
2174  mapping->addr = m->external_addr;
2175  /* Address only mapping doesn't change port */
2176  mapping->port = m->addr_only ? match.port
2177  : clib_host_to_net_u16 (m->external_port);
2178  mapping->fib_index = sm->outside_fib_index;
2179  }
2180 
2181  if (PREDICT_FALSE(is_addr_only != 0))
2182  *is_addr_only = m->addr_only;
2183 
2184  if (PREDICT_FALSE(twice_nat != 0))
2185  *twice_nat = m->twice_nat;
2186 
2187  if (PREDICT_FALSE(lb != 0))
2188  *lb = vec_len (m->locals) > 0;
2189 
2190  return 0;
2191 }
2192 
2195 {
2196  snat_main_t *sm = &snat_main;
2197  return min + random_u32 (&sm->random_seed) /
2198  (random_u32_max() / (max - min + 1) + 1);
2199 }
2200 
2201 int
2203  u32 fib_index,
2204  u32 thread_index,
2205  snat_session_key_t * k,
2206  u32 * address_indexp,
2207  u16 port_per_thread,
2208  u32 snat_thread_index)
2209 {
2210  snat_main_t *sm = &snat_main;
2211 
2212  return sm->alloc_addr_and_port(addresses, fib_index, thread_index, k,
2213  address_indexp, port_per_thread,
2214  snat_thread_index);
2215 }
2216 
2217 static int
2219  u32 fib_index,
2220  u32 thread_index,
2221  snat_session_key_t * k,
2222  u32 * address_indexp,
2223  u16 port_per_thread,
2224  u32 snat_thread_index)
2225 {
2226  int i, gi = 0;
2227  snat_address_t *a, *ga = 0;
2228  u32 portnum;
2229 
2230  for (i = 0; i < vec_len (addresses); i++)
2231  {
2232  a = addresses + i;
2233  switch (k->protocol)
2234  {
2235 #define _(N, j, n, s) \
2236  case SNAT_PROTOCOL_##N: \
2237  if (a->busy_##n##_ports_per_thread[thread_index] < port_per_thread) \
2238  { \
2239  if (a->fib_index == fib_index) \
2240  { \
2241  while (1) \
2242  { \
2243  portnum = (port_per_thread * \
2244  snat_thread_index) + \
2245  snat_random_port(1, port_per_thread) + 1024; \
2246  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \
2247  continue; \
2248  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \
2249  a->busy_##n##_ports_per_thread[thread_index]++; \
2250  a->busy_##n##_ports++; \
2251  k->addr = a->addr; \
2252  k->port = clib_host_to_net_u16(portnum); \
2253  *address_indexp = i; \
2254  return 0; \
2255  } \
2256  } \
2257  else if (a->fib_index == ~0) \
2258  { \
2259  ga = a; \
2260  gi = i; \
2261  } \
2262  } \
2263  break;
2265 #undef _
2266  default:
2267  nat_log_info ("unknown protocol");
2268  return 1;
2269  }
2270 
2271  }
2272 
2273  if (ga)
2274  {
2275  a = ga;
2276  switch (k->protocol)
2277  {
2278 #define _(N, j, n, s) \
2279  case SNAT_PROTOCOL_##N: \
2280  while (1) \
2281  { \
2282  portnum = (port_per_thread * \
2283  snat_thread_index) + \
2284  snat_random_port(1, port_per_thread) + 1024; \
2285  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \
2286  continue; \
2287  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \
2288  a->busy_##n##_ports_per_thread[thread_index]++; \
2289  a->busy_##n##_ports++; \
2290  k->addr = a->addr; \
2291  k->port = clib_host_to_net_u16(portnum); \
2292  *address_indexp = gi; \
2293  return 0; \
2294  }
2295  break;
2297 #undef _
2298  default:
2299  nat_log_info ("unknown protocol");
2300  return 1;
2301  }
2302  }
2303 
2304  /* Totally out of translations to use... */
2306  return 1;
2307 }
2308 
2309 static int
2311  u32 fib_index,
2312  u32 thread_index,
2313  snat_session_key_t * k,
2314  u32 * address_indexp,
2315  u16 port_per_thread,
2316  u32 snat_thread_index)
2317 {
2318  snat_main_t *sm = &snat_main;
2319  snat_address_t *a = addresses;
2320  u16 m, ports, portnum, A, j;
2321  m = 16 - (sm->psid_offset + sm->psid_length);
2322  ports = (1 << (16 - sm->psid_length)) - (1 << m);
2323 
2324  if (!vec_len (addresses))
2325  goto exhausted;
2326 
2327  switch (k->protocol)
2328  {
2329 #define _(N, i, n, s) \
2330  case SNAT_PROTOCOL_##N: \
2331  if (a->busy_##n##_ports < ports) \
2332  { \
2333  while (1) \
2334  { \
2335  A = snat_random_port(1, pow2_mask(sm->psid_offset)); \
2336  j = snat_random_port(0, pow2_mask(m)); \
2337  portnum = A | (sm->psid << sm->psid_offset) | (j << (16 - m)); \
2338  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \
2339  continue; \
2340  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \
2341  a->busy_##n##_ports++; \
2342  k->addr = a->addr; \
2343  k->port = clib_host_to_net_u16 (portnum); \
2344  *address_indexp = i; \
2345  return 0; \
2346  } \
2347  } \
2348  break;
2350 #undef _
2351  default:
2352  nat_log_info ("unknown protocol");
2353  return 1;
2354  }
2355 
2356 exhausted:
2357  /* Totally out of translations to use... */
2359  return 1;
2360 }
2361 
2362 void
2364 {
2365  dpo_id_t dpo_v4 = DPO_INVALID;
2366  fib_prefix_t pfx = {
2368  .fp_len = 32,
2369  .fp_addr.ip4.as_u32 = addr.as_u32,
2370  };
2371 
2372  if (is_add)
2373  {
2374  nat_dpo_create (DPO_PROTO_IP4, 0, &dpo_v4);
2376  FIB_ENTRY_FLAG_EXCLUSIVE, &dpo_v4);
2377  dpo_reset (&dpo_v4);
2378  }
2379  else
2380  {
2382  }
2383 }
2384 
2385 uword
2386 unformat_snat_protocol (unformat_input_t * input, va_list * args)
2387 {
2388  u32 *r = va_arg (*args, u32 *);
2389 
2390  if (0);
2391 #define _(N, i, n, s) else if (unformat (input, s)) *r = SNAT_PROTOCOL_##N;
2393 #undef _
2394  else
2395  return 0;
2396  return 1;
2397 }
2398 
2399 u8 *
2400 format_snat_protocol (u8 * s, va_list * args)
2401 {
2402  u32 i = va_arg (*args, u32);
2403  u8 *t = 0;
2404 
2405  switch (i)
2406  {
2407 #define _(N, j, n, str) case SNAT_PROTOCOL_##N: t = (u8 *) str; break;
2409 #undef _
2410  default:
2411  s = format (s, "unknown");
2412  return s;
2413  }
2414  s = format (s, "%s", t);
2415  return s;
2416 }
2417 
2418 u8 * format_snat_key (u8 * s, va_list * args);
2419 
2420 u8 *
2421 format_session_kvp (u8 * s, va_list * args)
2422 {
2423  clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
2425 
2426  k.as_u64 = v->key;
2427 
2428  s = format (s, "%U session-index %llu", format_snat_key, &k, v->value);
2429 
2430  return s;
2431 }
2432 
2433 u8 *
2434 format_static_mapping_kvp (u8 * s, va_list * args)
2435 {
2436  clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
2438 
2439  k.as_u64 = v->key;
2440 
2441  s = format (s, "%U static-mapping-index %llu", format_snat_key, &k, v->value);
2442 
2443  return s;
2444 }
2445 
2446 u8 *
2447 format_user_kvp (u8 * s, va_list * args)
2448 {
2449  clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
2450  snat_user_key_t k;
2451 
2452  k.as_u64 = v->key;
2453 
2454  s = format (s, "%U fib %d user-index %llu", format_ip4_address, &k.addr,
2455  k.fib_index, v->value);
2456 
2457  return s;
2458 }
2459 
2460 u8 *
2461 format_ed_session_kvp (u8 * s, va_list * args)
2462 {
2463  clib_bihash_kv_16_8_t *v = va_arg (*args, clib_bihash_kv_16_8_t *);
2464  nat_ed_ses_key_t k;
2465 
2466  k.as_u64[0] = v->key[0];
2467  k.as_u64[1] = v->key[1];
2468 
2469  s = format (s, "local %U:%d remote %U:%d proto %U fib %d session-index %llu",
2470  format_ip4_address, &k.l_addr, clib_net_to_host_u16 (k.l_port),
2471  format_ip4_address, &k.r_addr, clib_net_to_host_u16 (k.r_port),
2473 
2474  return s;
2475 }
2476 
2477 static u32
2479 {
2480  snat_main_t *sm = &snat_main;
2481  u32 next_worker_index = 0;
2482  u32 hash;
2483 
2484  next_worker_index = sm->first_worker_index;
2485  hash = ip0->src_address.as_u32 + (ip0->src_address.as_u32 >> 8) +
2486  (ip0->src_address.as_u32 >> 16) + (ip0->src_address.as_u32 >>24);
2487 
2488  if (PREDICT_TRUE (is_pow2 (_vec_len (sm->workers))))
2489  next_worker_index += sm->workers[hash & (_vec_len (sm->workers) - 1)];
2490  else
2491  next_worker_index += sm->workers[hash % _vec_len (sm->workers)];
2492 
2493  return next_worker_index;
2494 }
2495 
2496 static u32
2498 {
2499  snat_main_t *sm = &snat_main;
2500  udp_header_t *udp;
2501  u16 port;
2502  snat_session_key_t m_key;
2503  clib_bihash_kv_8_8_t kv, value;
2505  u32 proto;
2506  u32 next_worker_index = 0;
2507 
2508  /* first try static mappings without port */
2510  {
2511  m_key.addr = ip0->dst_address;
2512  m_key.port = 0;
2513  m_key.protocol = 0;
2514  m_key.fib_index = rx_fib_index0;
2515  kv.key = m_key.as_u64;
2516  if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
2517  {
2518  m = pool_elt_at_index (sm->static_mappings, value.value);
2519  return m->workers[0];
2520  }
2521  }
2522 
2523  proto = ip_proto_to_snat_proto (ip0->protocol);
2524  udp = ip4_next_header (ip0);
2525  port = udp->dst_port;
2526 
2527  if (PREDICT_FALSE (ip4_is_fragment (ip0)))
2528  {
2530  return vlib_get_thread_index ();
2531 
2532  if (PREDICT_TRUE (!ip4_is_first_fragment (ip0)))
2533  {
2534  nat_reass_ip4_t *reass;
2535 
2536  reass = nat_ip4_reass_find (ip0->src_address, ip0->dst_address,
2537  ip0->fragment_id, ip0->protocol);
2538 
2539  if (reass && (reass->thread_index != (u32) ~ 0))
2540  return reass->thread_index;
2541  else
2542  return vlib_get_thread_index ();
2543  }
2544  }
2545 
2546  /* unknown protocol */
2547  if (PREDICT_FALSE (proto == ~0))
2548  {
2549  /* use current thread */
2550  return vlib_get_thread_index ();
2551  }
2552 
2553  if (PREDICT_FALSE (ip0->protocol == IP_PROTOCOL_ICMP))
2554  {
2555  icmp46_header_t * icmp = (icmp46_header_t *) udp;
2556  icmp_echo_header_t *echo = (icmp_echo_header_t *)(icmp + 1);
2557  if (!icmp_is_error_message (icmp))
2558  port = echo->identifier;
2559  else
2560  {
2561  ip4_header_t *inner_ip = (ip4_header_t *)(echo + 1);
2562  proto = ip_proto_to_snat_proto (inner_ip->protocol);
2563  void *l4_header = ip4_next_header (inner_ip);
2564  switch (proto)
2565  {
2566  case SNAT_PROTOCOL_ICMP:
2567  icmp = (icmp46_header_t*)l4_header;
2568  echo = (icmp_echo_header_t *)(icmp + 1);
2569  port = echo->identifier;
2570  break;
2571  case SNAT_PROTOCOL_UDP:
2572  case SNAT_PROTOCOL_TCP:
2573  port = ((tcp_udp_header_t*)l4_header)->src_port;
2574  break;
2575  default:
2576  return vlib_get_thread_index ();
2577  }
2578  }
2579  }
2580 
2581  /* try static mappings with port */
2582  if (PREDICT_FALSE (pool_elts (sm->static_mappings)))
2583  {
2584  m_key.addr = ip0->dst_address;
2585  m_key.port = clib_net_to_host_u16 (port);
2586  m_key.protocol = proto;
2587  m_key.fib_index = rx_fib_index0;
2588  kv.key = m_key.as_u64;
2589  if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
2590  {
2591  m = pool_elt_at_index (sm->static_mappings, value.value);
2592  return m->workers[0];
2593  }
2594  }
2595 
2596  /* worker by outside port */
2597  next_worker_index = sm->first_worker_index;
2598  next_worker_index +=
2599  sm->workers[(clib_net_to_host_u16 (port) - 1024) / sm->port_per_thread];
2600  return next_worker_index;
2601 }
2602 
2603 static u32
2605 {
2606  snat_main_t *sm = &snat_main;
2607  clib_bihash_kv_8_8_t kv, value;
2608  u32 proto, next_worker_index = 0;
2609  udp_header_t *udp;
2610  u16 port;
2612  u32 hash;
2613 
2614  /* first try static mappings without port */
2616  {
2617  make_sm_kv (&kv, &ip->dst_address, 0, rx_fib_index, 0);
2618  if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
2619  {
2620  m = pool_elt_at_index (sm->static_mappings, value.value);
2621  return m->workers[0];
2622  }
2623  }
2624 
2625  proto = ip_proto_to_snat_proto (ip->protocol);
2626 
2627  /* unknown protocol */
2628  if (PREDICT_FALSE (proto == ~0))
2629  {
2630  /* use current thread */
2631  return vlib_get_thread_index ();
2632  }
2633 
2634  udp = ip4_next_header (ip);
2635  port = udp->dst_port;
2636 
2637  if (PREDICT_FALSE (ip->protocol == IP_PROTOCOL_ICMP))
2638  {
2639  icmp46_header_t * icmp = (icmp46_header_t *) udp;
2640  icmp_echo_header_t *echo = (icmp_echo_header_t *)(icmp + 1);
2641  if (!icmp_is_error_message (icmp))
2642  port = echo->identifier;
2643  else
2644  {
2645  ip4_header_t *inner_ip = (ip4_header_t *)(echo + 1);
2646  proto = ip_proto_to_snat_proto (inner_ip->protocol);
2647  void *l4_header = ip4_next_header (inner_ip);
2648  switch (proto)
2649  {
2650  case SNAT_PROTOCOL_ICMP:
2651  icmp = (icmp46_header_t*)l4_header;
2652  echo = (icmp_echo_header_t *)(icmp + 1);
2653  port = echo->identifier;
2654  break;
2655  case SNAT_PROTOCOL_UDP:
2656  case SNAT_PROTOCOL_TCP:
2657  port = ((tcp_udp_header_t*)l4_header)->src_port;
2658  break;
2659  default:
2660  return vlib_get_thread_index ();
2661  }
2662  }
2663  }
2664 
2665  /* try static mappings with port */
2666  if (PREDICT_FALSE (pool_elts (sm->static_mappings)))
2667  {
2668  make_sm_kv (&kv, &ip->dst_address, proto, rx_fib_index,
2669  clib_net_to_host_u16 (port));
2670  if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
2671  {
2672  m = pool_elt_at_index (sm->static_mappings, value.value);
2673  if (!vec_len(m->locals))
2674  return m->workers[0];
2675 
2676  hash = ip->src_address.as_u32 + (ip->src_address.as_u32 >> 8) +
2677  (ip->src_address.as_u32 >> 16) + (ip->src_address.as_u32 >>24);
2678 
2679  if (PREDICT_TRUE (is_pow2 (_vec_len (m->workers))))
2680  return m->workers[hash & (_vec_len (m->workers) - 1)];
2681  else
2682  return m->workers[hash % _vec_len (m->workers)];
2683  }
2684  }
2685 
2686  /* worker by outside port */
2687  next_worker_index = sm->first_worker_index;
2688  next_worker_index +=
2689  sm->workers[(clib_net_to_host_u16 (port) - 1024) / sm->port_per_thread];
2690 
2691  return next_worker_index;
2692 }
2693 
2694 static clib_error_t *
2696 {
2697  snat_main_t * sm = &snat_main;
2698  nat66_main_t * nm = &nat66_main;
2699  u32 translation_buckets = 1024;
2700  u32 translation_memory_size = 128<<20;
2701  u32 user_buckets = 128;
2702  u32 user_memory_size = 64<<20;
2703  u32 max_translations_per_user = 100;
2704  u32 outside_vrf_id = 0;
2705  u32 outside_ip6_vrf_id = 0;
2706  u32 inside_vrf_id = 0;
2707  u32 static_mapping_buckets = 1024;
2708  u32 static_mapping_memory_size = 64<<20;
2709  u32 nat64_bib_buckets = 1024;
2710  u32 nat64_bib_memory_size = 128 << 20;
2711  u32 nat64_st_buckets = 2048;
2712  u32 nat64_st_memory_size = 256 << 20;
2713  u8 static_mapping_only = 0;
2714  u8 static_mapping_connection_tracking = 0;
2716  dslite_main_t * dm = &dslite_main;
2717 
2718  sm->deterministic = 0;
2719  sm->out2in_dpo = 0;
2720  sm->endpoint_dependent = 0;
2721 
2722  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2723  {
2724  if (unformat (input, "translation hash buckets %d", &translation_buckets))
2725  ;
2726  else if (unformat (input, "translation hash memory %d",
2727  &translation_memory_size));
2728  else if (unformat (input, "user hash buckets %d", &user_buckets))
2729  ;
2730  else if (unformat (input, "user hash memory %d",
2731  &user_memory_size))
2732  ;
2733  else if (unformat (input, "max translations per user %d",
2734  &max_translations_per_user))
2735  ;
2736  else if (unformat (input, "outside VRF id %d",
2737  &outside_vrf_id))
2738  ;
2739  else if (unformat (input, "outside ip6 VRF id %d",
2740  &outside_ip6_vrf_id))
2741  ;
2742  else if (unformat (input, "inside VRF id %d",
2743  &inside_vrf_id))
2744  ;
2745  else if (unformat (input, "static mapping only"))
2746  {
2747  static_mapping_only = 1;
2748  if (unformat (input, "connection tracking"))
2749  static_mapping_connection_tracking = 1;
2750  }
2751  else if (unformat (input, "deterministic"))
2752  sm->deterministic = 1;
2753  else if (unformat (input, "nat64 bib hash buckets %d",
2754  &nat64_bib_buckets))
2755  ;
2756  else if (unformat (input, "nat64 bib hash memory %d",
2757  &nat64_bib_memory_size))
2758  ;
2759  else if (unformat (input, "nat64 st hash buckets %d", &nat64_st_buckets))
2760  ;
2761  else if (unformat (input, "nat64 st hash memory %d",
2762  &nat64_st_memory_size))
2763  ;
2764  else if (unformat (input, "out2in dpo"))
2765  sm->out2in_dpo = 1;
2766  else if (unformat (input, "dslite ce"))
2767  dslite_set_ce(dm, 1);
2768  else if (unformat (input, "endpoint-dependent"))
2769  sm->endpoint_dependent = 1;
2770  else
2771  return clib_error_return (0, "unknown input '%U'",
2772  format_unformat_error, input);
2773  }
2774 
2775  /* for show commands, etc. */
2776  sm->translation_buckets = translation_buckets;
2777  sm->translation_memory_size = translation_memory_size;
2778  /* do not exceed load factor 10 */
2779  sm->max_translations = 10 * translation_buckets;
2780  sm->user_buckets = user_buckets;
2781  sm->user_memory_size = user_memory_size;
2782  sm->max_translations_per_user = max_translations_per_user;
2783  sm->outside_vrf_id = outside_vrf_id;
2785  outside_vrf_id,
2787  nm->outside_vrf_id = outside_ip6_vrf_id;
2789  outside_ip6_vrf_id,
2791  sm->inside_vrf_id = inside_vrf_id;
2793  inside_vrf_id,
2795  sm->static_mapping_only = static_mapping_only;
2796  sm->static_mapping_connection_tracking = static_mapping_connection_tracking;
2797 
2798  nat64_set_hash(nat64_bib_buckets, nat64_bib_memory_size, nat64_st_buckets,
2799  nat64_st_memory_size);
2800 
2801  if (sm->deterministic)
2802  {
2804  sm->in2out_output_node_index = ~0;
2808  }
2809  else
2810  {
2811  if (sm->endpoint_dependent)
2812  {
2820  }
2821  else
2822  {
2825  sm->in2out_node_index = snat_in2out_node.index;
2827  sm->out2in_node_index = snat_out2in_node.index;
2830  }
2831  if (!static_mapping_only ||
2832  (static_mapping_only && static_mapping_connection_tracking))
2833  {
2834  vec_foreach (tsm, sm->per_thread_data)
2835  {
2836  if (sm->endpoint_dependent)
2837  {
2838  clib_bihash_init_16_8 (&tsm->in2out_ed, "in2out-ed",
2839  translation_buckets,
2840  translation_memory_size);
2841  clib_bihash_set_kvp_format_fn_16_8 (&tsm->in2out_ed,
2843 
2844  clib_bihash_init_16_8 (&tsm->out2in_ed, "out2in-ed",
2845  translation_buckets,
2846  translation_memory_size);
2847  clib_bihash_set_kvp_format_fn_16_8 (&tsm->out2in_ed,
2849  }
2850  else
2851  {
2852  clib_bihash_init_8_8 (&tsm->in2out, "in2out",
2853  translation_buckets,
2854  translation_memory_size);
2855  clib_bihash_set_kvp_format_fn_8_8 (&tsm->in2out,
2857 
2858  clib_bihash_init_8_8 (&tsm->out2in, "out2in",
2859  translation_buckets,
2860  translation_memory_size);
2861  clib_bihash_set_kvp_format_fn_8_8 (&tsm->out2in,
2863  }
2864 
2865  clib_bihash_init_8_8 (&tsm->user_hash, "users", user_buckets,
2866  user_memory_size);
2867  clib_bihash_set_kvp_format_fn_8_8 (&tsm->user_hash,
2868  format_user_kvp);
2869  }
2870 
2871  }
2872  else
2873  {
2876  }
2877  clib_bihash_init_8_8 (&sm->static_mapping_by_local,
2878  "static_mapping_by_local", static_mapping_buckets,
2879  static_mapping_memory_size);
2880  clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_local,
2882 
2883  clib_bihash_init_8_8 (&sm->static_mapping_by_external,
2884  "static_mapping_by_external", static_mapping_buckets,
2885  static_mapping_memory_size);
2886  clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_external,
2888  }
2889 
2890  return 0;
2891 }
2892 
2894 
2895 u8 * format_snat_session_state (u8 * s, va_list * args)
2896 {
2897  u32 i = va_arg (*args, u32);
2898  u8 *t = 0;
2899 
2900  switch (i)
2901  {
2902 #define _(v, N, str) case SNAT_SESSION_##N: t = (u8 *) str; break;
2904 #undef _
2905  default:
2906  t = format (t, "unknown");
2907  }
2908  s = format (s, "%s", t);
2909  return s;
2910 }
2911 
2912 u8 * format_snat_key (u8 * s, va_list * args)
2913 {
2914  snat_session_key_t * key = va_arg (*args, snat_session_key_t *);
2915 
2916  s = format (s, "%U proto %U port %d fib %d",
2917  format_ip4_address, &key->addr,
2919  clib_net_to_host_u16 (key->port), key->fib_index);
2920  return s;
2921 }
2922 
2923 u8 * format_snat_session (u8 * s, va_list * args)
2924 {
2926  snat_session_t * sess = va_arg (*args, snat_session_t *);
2927 
2928  if (snat_is_unk_proto_session (sess))
2929  {
2930  s = format (s, " i2o %U proto %u fib %u\n",
2931  format_ip4_address, &sess->in2out.addr,
2932  clib_net_to_host_u16 (sess->in2out.port),
2933  sess->in2out.fib_index);
2934  s = format (s, " o2i %U proto %u fib %u\n",
2935  format_ip4_address, &sess->out2in.addr,
2936  clib_net_to_host_u16 (sess->out2in.port),
2937  sess->out2in.fib_index);
2938  }
2939  else
2940  {
2941  s = format (s, " i2o %U\n", format_snat_key, &sess->in2out);
2942  s = format (s, " o2i %U\n", format_snat_key, &sess->out2in);
2943  }
2944  if (is_ed_session (sess) || is_fwd_bypass_session (sess))
2945  {
2946  if (is_twice_nat_session (sess))
2947  {
2948  s = format (s, " external host o2i %U:%d i2o %U:%d\n",
2949  format_ip4_address, &sess->ext_host_addr,
2950  clib_net_to_host_u16 (sess->ext_host_port),
2951  format_ip4_address, &sess->ext_host_nat_addr,
2952  clib_net_to_host_u16 (sess->ext_host_nat_port));
2953  }
2954  else
2955  {
2956  if (sess->ext_host_addr.as_u32)
2957  s = format (s, " external host %U:%u\n",
2958  format_ip4_address, &sess->ext_host_addr,
2959  clib_net_to_host_u16 (sess->ext_host_port));
2960  }
2961  }
2962  s = format (s, " index %llu\n", sess - sm->sessions);
2963  s = format (s, " last heard %.2f\n", sess->last_heard);
2964  s = format (s, " total pkts %d, total bytes %lld\n",
2965  sess->total_pkts, sess->total_bytes);
2966  if (snat_is_session_static (sess))
2967  s = format (s, " static translation\n");
2968  else
2969  s = format (s, " dynamic translation\n");
2970  if (is_fwd_bypass_session (sess))
2971  s = format (s, " forwarding-bypass\n");
2972  if (is_lb_session (sess))
2973  s = format (s, " load-balancing\n");
2974  if (is_twice_nat_session (sess))
2975  s = format (s, " twice-nat\n");
2976 
2977  return s;
2978 }
2979 
2980 u8 * format_snat_user (u8 * s, va_list * args)
2981 {
2983  snat_user_t * u = va_arg (*args, snat_user_t *);
2984  int verbose = va_arg (*args, int);
2985  dlist_elt_t * head, * elt;
2986  u32 elt_index, head_index;
2987  u32 session_index;
2988  snat_session_t * sess;
2989 
2990  s = format (s, "%U: %d dynamic translations, %d static translations\n",
2992 
2993  if (verbose == 0)
2994  return s;
2995 
2996  if (u->nsessions || u->nstaticsessions)
2997  {
2998  head_index = u->sessions_per_user_list_head_index;
2999  head = pool_elt_at_index (sm->list_pool, head_index);
3000 
3001  elt_index = head->next;
3002  elt = pool_elt_at_index (sm->list_pool, elt_index);
3003  session_index = elt->value;
3004 
3005  while (session_index != ~0)
3006  {
3007  sess = pool_elt_at_index (sm->sessions, session_index);
3008 
3009  s = format (s, " %U\n", format_snat_session, sm, sess);
3010 
3011  elt_index = elt->next;
3012  elt = pool_elt_at_index (sm->list_pool, elt_index);
3013  session_index = elt->value;
3014  }
3015  }
3016 
3017  return s;
3018 }
3019 
3020 u8 * format_snat_static_mapping (u8 * s, va_list * args)
3021 {
3022  snat_static_mapping_t *m = va_arg (*args, snat_static_mapping_t *);
3023  nat44_lb_addr_port_t *local;
3024 
3025  if (m->addr_only)
3026  s = format (s, "local %U external %U vrf %d %s %s",
3029  m->vrf_id,
3030  m->twice_nat == TWICE_NAT ? "twice-nat" :
3031  m->twice_nat == TWICE_NAT_SELF ? "self-twice-nat" : "",
3032  m->out2in_only ? "out2in-only" : "");
3033  else
3034  {
3035  if (vec_len (m->locals))
3036  {
3037  s = format (s, "%U vrf %d external %U:%d %s %s",
3039  m->vrf_id,
3041  m->twice_nat == TWICE_NAT ? "twice-nat" :
3042  m->twice_nat == TWICE_NAT_SELF ? "self-twice-nat" : "",
3043  m->out2in_only ? "out2in-only" : "");
3044  vec_foreach (local, m->locals)
3045  s = format (s, "\n local %U:%d probability %d\%",
3046  format_ip4_address, &local->addr, local->port,
3047  local->probability);
3048  }
3049  else
3050  s = format (s, "%U local %U:%d external %U:%d vrf %d %s %s",
3054  m->vrf_id,
3055  m->twice_nat == TWICE_NAT ? "twice-nat" :
3056  m->twice_nat == TWICE_NAT_SELF ? "self-twice-nat" : "",
3057  m->out2in_only ? "out2in-only" : "");
3058  }
3059  return s;
3060 }
3061 
3062 u8 * format_snat_static_map_to_resolve (u8 * s, va_list * args)
3063 {
3065  vnet_main_t *vnm = vnet_get_main();
3066 
3067  if (m->addr_only)
3068  s = format (s, "local %U external %U vrf %d",
3071  m->vrf_id);
3072  else
3073  s = format (s, "%U local %U:%d external %U:%d vrf %d",
3075  format_ip4_address, &m->l_addr, m->l_port,
3077  m->e_port, m->vrf_id);
3078 
3079  return s;
3080 }
3081 
3082 u8 * format_det_map_ses (u8 * s, va_list * args)
3083 {
3084  snat_det_map_t * det_map = va_arg (*args, snat_det_map_t *);
3085  ip4_address_t in_addr, out_addr;
3086  u32 in_offset, out_offset;
3087  snat_det_session_t * ses = va_arg (*args, snat_det_session_t *);
3088  u32 * i = va_arg (*args, u32 *);
3089 
3090  u32 user_index = *i / SNAT_DET_SES_PER_USER;
3091  in_addr.as_u32 = clib_host_to_net_u32 (
3092  clib_net_to_host_u32(det_map->in_addr.as_u32) + user_index);
3093  in_offset = clib_net_to_host_u32(in_addr.as_u32) -
3094  clib_net_to_host_u32(det_map->in_addr.as_u32);
3095  out_offset = in_offset / det_map->sharing_ratio;
3096  out_addr.as_u32 = clib_host_to_net_u32(
3097  clib_net_to_host_u32(det_map->out_addr.as_u32) + out_offset);
3098  s = format (s, "in %U:%d out %U:%d external host %U:%d state: %U expire: %d\n",
3099  format_ip4_address, &in_addr,
3100  clib_net_to_host_u16 (ses->in_port),
3101  format_ip4_address, &out_addr,
3102  clib_net_to_host_u16 (ses->out.out_port),
3104  clib_net_to_host_u16 (ses->out.ext_host_port),
3106  ses->expire);
3107 
3108  return s;
3109 }
3110 
3111 static void
3113  uword opaque,
3114  u32 sw_if_index,
3115  ip4_address_t * address,
3116  u32 address_length,
3117  u32 if_address_index,
3118  u32 is_delete)
3119 {
3120  snat_main_t *sm = &snat_main;
3123  snat_session_key_t m_key;
3124  clib_bihash_kv_8_8_t kv, value;
3125  int i, rv;
3126  ip4_address_t l_addr;
3127 
3128  for (i = 0; i < vec_len (sm->to_resolve); i++)
3129  {
3130  rp = sm->to_resolve + i;
3131  if (rp->addr_only == 0)
3132  continue;
3133  if (rp->sw_if_index == sw_if_index)
3134  goto match;
3135  }
3136 
3137  return;
3138 
3139 match:
3140  m_key.addr.as_u32 = address->as_u32;
3141  m_key.port = rp->addr_only ? 0 : rp->e_port;
3142  m_key.protocol = rp->addr_only ? 0 : rp->proto;
3143  m_key.fib_index = sm->outside_fib_index;
3144  kv.key = m_key.as_u64;
3145  if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
3146  m = 0;
3147  else
3148  m = pool_elt_at_index (sm->static_mappings, value.value);
3149 
3150  if (!is_delete)
3151  {
3152  /* Don't trip over lease renewal, static config */
3153  if (m)
3154  return;
3155  }
3156  else
3157  {
3158  if (!m)
3159  return;
3160  }
3161 
3162  /* Indetity mapping? */
3163  if (rp->l_addr.as_u32 == 0)
3164  l_addr.as_u32 = address[0].as_u32;
3165  else
3166  l_addr.as_u32 = rp->l_addr.as_u32;
3167  /* Add the static mapping */
3168  rv = snat_add_static_mapping (l_addr,
3169  address[0],
3170  rp->l_port,
3171  rp->e_port,
3172  rp->vrf_id,
3173  rp->addr_only,
3174  ~0 /* sw_if_index */,
3175  rp->proto,
3176  !is_delete,
3177  0, 0, rp->tag);
3178  if (rv)
3179  nat_log_notice ("snat_add_static_mapping returned %d", rv);
3180 }
3181 
3182 static void
3184  uword opaque,
3185  u32 sw_if_index,
3186  ip4_address_t * address,
3187  u32 address_length,
3188  u32 if_address_index,
3189  u32 is_delete)
3190 {
3191  snat_main_t *sm = &snat_main;
3193  ip4_address_t l_addr;
3194  int i, j;
3195  int rv;
3196  u8 twice_nat = 0;
3197  snat_address_t *addresses = sm->addresses;
3198 
3199  for (i = 0; i < vec_len(sm->auto_add_sw_if_indices); i++)
3200  {
3201  if (sw_if_index == sm->auto_add_sw_if_indices[i])
3202  goto match;
3203  }
3204 
3205  for (i = 0; i < vec_len(sm->auto_add_sw_if_indices_twice_nat); i++)
3206  {
3207  twice_nat = 1;
3208  addresses = sm->twice_nat_addresses;
3209  if (sw_if_index == sm->auto_add_sw_if_indices_twice_nat[i])
3210  goto match;
3211  }
3212 
3213  return;
3214 
3215 match:
3216  if (!is_delete)
3217  {
3218  /* Don't trip over lease renewal, static config */
3219  for (j = 0; j < vec_len(addresses); j++)
3220  if (addresses[j].addr.as_u32 == address->as_u32)
3221  return;
3222 
3223  (void) snat_add_address (sm, address, ~0, twice_nat);
3224  /* Scan static map resolution vector */
3225  for (j = 0; j < vec_len (sm->to_resolve); j++)
3226  {
3227  rp = sm->to_resolve + j;
3228  if (rp->addr_only)
3229  continue;
3230  /* On this interface? */
3231  if (rp->sw_if_index == sw_if_index)
3232  {
3233  /* Indetity mapping? */
3234  if (rp->l_addr.as_u32 == 0)
3235  l_addr.as_u32 = address[0].as_u32;
3236  else
3237  l_addr.as_u32 = rp->l_addr.as_u32;
3238  /* Add the static mapping */
3239  rv = snat_add_static_mapping (l_addr,
3240  address[0],
3241  rp->l_port,
3242  rp->e_port,
3243  rp->vrf_id,
3244  rp->addr_only,
3245  ~0 /* sw_if_index */,
3246  rp->proto,
3247  rp->is_add,
3248  0, 0, rp->tag);
3249  if (rv)
3250  nat_log_notice ("snat_add_static_mapping returned %d", rv);
3251  }
3252  }
3253  return;
3254  }
3255  else
3256  {
3257  (void) snat_del_address(sm, address[0], 1, twice_nat);
3258  return;
3259  }
3260 }
3261 
3262 
3263 int snat_add_interface_address (snat_main_t *sm, u32 sw_if_index, int is_del,
3264  u8 twice_nat)
3265 {
3266  ip4_main_t * ip4_main = sm->ip4_main;
3267  ip4_address_t * first_int_addr;
3269  u32 *indices_to_delete = 0;
3270  int i, j;
3271  u32 *auto_add_sw_if_indices =
3273 
3274  first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index,
3275  0 /* just want the address*/);
3276 
3277  for (i = 0; i < vec_len(auto_add_sw_if_indices); i++)
3278  {
3279  if (auto_add_sw_if_indices[i] == sw_if_index)
3280  {
3281  if (is_del)
3282  {
3283  /* if have address remove it */
3284  if (first_int_addr)
3285  (void) snat_del_address (sm, first_int_addr[0], 1, twice_nat);
3286  else
3287  {
3288  for (j = 0; j < vec_len (sm->to_resolve); j++)
3289  {
3290  rp = sm->to_resolve + j;
3291  if (rp->sw_if_index == sw_if_index)
3292  vec_add1 (indices_to_delete, j);
3293  }
3294  if (vec_len(indices_to_delete))
3295  {
3296  for (j = vec_len(indices_to_delete)-1; j >= 0; j--)
3297  vec_del1(sm->to_resolve, j);
3298  vec_free(indices_to_delete);
3299  }
3300  }
3301  if (twice_nat)
3303  else
3305  }
3306  else
3307  return VNET_API_ERROR_VALUE_EXIST;
3308 
3309  return 0;
3310  }
3311  }
3312 
3313  if (is_del)
3314  return VNET_API_ERROR_NO_SUCH_ENTRY;
3315 
3316  /* add to the auto-address list */
3317  if (twice_nat)
3318  vec_add1(sm->auto_add_sw_if_indices_twice_nat, sw_if_index);
3319  else
3320  vec_add1(sm->auto_add_sw_if_indices, sw_if_index);
3321 
3322  /* If the address is already bound - or static - add it now */
3323  if (first_int_addr)
3324  (void) snat_add_address (sm, first_int_addr, ~0, twice_nat);
3325 
3326  return 0;
3327 }
3328 
3329 int
3331  snat_protocol_t proto, u32 vrf_id, int is_in)
3332 {
3334  clib_bihash_kv_8_8_t kv, value;
3335  ip4_header_t ip;
3336  u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
3337  snat_session_key_t key;
3338  snat_session_t *s;
3339  clib_bihash_8_8_t *t;
3340 
3341  if (sm->endpoint_dependent)
3342  return VNET_API_ERROR_UNSUPPORTED;
3343 
3344  ip.dst_address.as_u32 = ip.src_address.as_u32 = addr->as_u32;
3345  if (sm->num_workers > 1)
3346  tsm =
3348  sm->worker_in2out_cb (&ip, fib_index));
3349  else
3350  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
3351 
3352  key.addr.as_u32 = addr->as_u32;
3353  key.port = clib_host_to_net_u16 (port);
3354  key.protocol = proto;
3355  key.fib_index = fib_index;
3356  kv.key = key.as_u64;
3357  t = is_in ? &tsm->in2out : &tsm->out2in;
3358  if (!clib_bihash_search_8_8 (t, &kv, &value))
3359  {
3360  if (pool_is_free_index (tsm->sessions, value.value))
3361  return VNET_API_ERROR_UNSPECIFIED;
3362 
3363  s = pool_elt_at_index (tsm->sessions, value.value);
3364  nat_free_session_data (sm, s, tsm - sm->per_thread_data);
3365  nat44_delete_session (sm, s, tsm - sm->per_thread_data);
3366  return 0;
3367  }
3368 
3369  return VNET_API_ERROR_NO_SUCH_ENTRY;
3370 }
3371 
3372 int
3374  ip4_address_t *eh_addr, u16 eh_port, u8 proto,
3375  u32 vrf_id, int is_in)
3376 {
3377  ip4_header_t ip;
3378  clib_bihash_16_8_t *t;
3379  nat_ed_ses_key_t key;
3380  clib_bihash_kv_16_8_t kv, value;
3381  u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
3382  snat_session_t *s;
3384 
3385  if (!sm->endpoint_dependent)
3386  return VNET_API_ERROR_FEATURE_DISABLED;
3387 
3388  ip.dst_address.as_u32 = ip.src_address.as_u32 = addr->as_u32;
3389  if (sm->num_workers > 1)
3390  tsm =
3392  sm->worker_in2out_cb (&ip, fib_index));
3393  else
3394  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
3395 
3396  t = is_in ? &tsm->in2out_ed : &tsm->out2in_ed;
3397  key.l_addr.as_u32 = addr->as_u32;
3398  key.r_addr.as_u32 = eh_addr->as_u32;
3399  key.l_port = clib_host_to_net_u16 (port);
3400  key.r_port = clib_host_to_net_u16 (eh_port);
3401  key.proto = proto;
3402  key.fib_index = clib_host_to_net_u32 (fib_index);
3403  kv.key[0] = key.as_u64[0];
3404  kv.key[1] = key.as_u64[1];
3405  if (clib_bihash_search_16_8 (t, &kv, &value))
3406  return VNET_API_ERROR_NO_SUCH_ENTRY;
3407 
3408  if (pool_is_free_index (tsm->sessions, value.value))
3409  return VNET_API_ERROR_UNSPECIFIED;
3410  s = pool_elt_at_index (tsm->sessions, value.value);
3411  nat_free_session_data (sm, s, tsm - sm->per_thread_data);
3412  nat44_delete_session (sm, s, tsm - sm->per_thread_data);
3413  return 0;
3414 }
3415 
3416 void
3417 nat_set_alloc_addr_and_port_mape (u16 psid, u16 psid_offset, u16 psid_length)
3418 {
3419  snat_main_t *sm = &snat_main;
3420 
3422  sm->psid = psid;
3423  sm->psid_offset = psid_offset;
3424  sm->psid_length = psid_length;
3425 }
3426 
3427 void
3429 {
3430  snat_main_t *sm = &snat_main;
3431 
3433 }
3434 
ip4_address_t external_addr
Definition: nat.h:239
u32 user_memory_size
Definition: nat.h:393
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:2980
#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
vmrglw vmrglh hi
format_function_t format_ip_protocol
Definition: format.h:45
#define nat_log_info(...)
Definition: nat.h:524
#define snat_is_session_static(s)
Check if SNAT session is created from static mapping.
Definition: nat.h:483
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:537
u8 * format_snat_protocol(u8 *s, va_list *args)
Definition: nat.c:2400
static void clib_dlist_init(dlist_elt_t *pool, u32 index)
Definition: dlist.h:36
u32 icmp_timeout
Definition: nat.h:404
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:2310
u32 fq_in2out_output_index
Definition: nat.h:368
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:513
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:225
#define NULL
Definition: clib.h:55
u32 index
Definition: node.h:273
snat_protocol_t proto
Definition: nat.h:247
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
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:327
u32 vlib_frame_queue_main_init(u32 node_index, u32 frame_queue_nelts)
Definition: threads.c:1773
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:520
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:2447
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:3373
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:348
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:3183
u32 num_snat_thread
Definition: nat.h:328
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:227
dlist_elt_t * list_pool
Definition: nat.h:290
#define snat_is_unk_proto_session(s)
Check if SNAT session for unknown protocol.
Definition: nat.h:489
u8 * format_snat_static_mapping(u8 *s, va_list *args)
Definition: nat.c:3020
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:572
format_function_t format_vnet_sw_if_index_name
unsigned char u8
Definition: types.h:56
u8 deterministic
Definition: nat.h:386
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:250
void nat66_init(void)
Definition: nat66.c:43
u32 user_buckets
Definition: nat.h:392
clib_bihash_8_8_t user_hash
Definition: nat.h:281
u16 identifier
Definition: nat.h:536
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:394
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:274
nat66_main_t nat66_main
Definition: nat66.c:23
u32 in2out_output_node_index
Definition: nat.h:373
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
Definition: ip4_fib.c:226
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:440
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:2434
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:2478
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:389
u8 * format_ed_session_kvp(u8 *s, va_list *args)
Definition: nat.c:2461
#define nat_log_err(...)
Definition: nat.h:518
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:2101
#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:507
void snat_ipfix_logging_init(vlib_main_t *vm)
Initialize NAT plugin IPFIX logging.
ip4_main_t * ip4_main
Definition: nat.h:415
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:238
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
u16 fp_len
The mask length.
Definition: fib_types.h:192
ip4_address_t local_addr
Definition: nat.h:238
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:3112
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:264
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:210
twice_nat_type_t twice_nat
Definition: nat.h:243
VNET_FEATURE_INIT(ip4_snat_in2out, static)
u32 max_translations
Definition: nat.h:391
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:358
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:461
void nat_free_session_data(snat_main_t *sm, snat_session_t *s, u32 thread_index)
Definition: nat.c:187
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:277
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
lo
vlib_main_t * vlib_main
Definition: nat.h:413
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:387
#define SNAT_UDP_TIMEOUT
Definition: nat.h:34
snat_static_mapping_t * static_mappings
Definition: nat.h:340
u32 inside_fib_index
Definition: nat.h:398
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:273
u32 udp_timeout
Definition: nat.h:401
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:373
u8 static_mapping_only
Definition: nat.h:384
#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:337
u8 psid_offset
Definition: nat.h:349
#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:3428
#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:522
api_main_t * api_main
Definition: nat.h:417
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:350
vnet_main_t * vnet_main
Definition: nat.h:414
u32 inside_vrf_id
Definition: nat.h:397
#define is_lb_session(s)
Check if NAT session is load-balancing.
Definition: nat.h:501
u32 fq_out2in_index
Definition: nat.h:369
snat_interface_t * output_feature_interfaces
Definition: nat.h:344
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:284
u32 random_seed
Definition: nat.h:364
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:153
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
static u32 nat44_ed_get_worker_out2in_cb(ip4_header_t *ip, u32 rx_fib_index)
Definition: nat.c:2604
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:2056
clib_bihash_8_8_t out2in
Definition: nat.h:273
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:395
void nat44_add_del_address_dpo(ip4_address_t addr, u8 is_add)
Definition: nat.c:2363
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:385
snat_get_worker_function_t * worker_in2out_cb
Definition: nat.h:325
#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:375
VLIB_PLUGIN_REGISTER()
int snat_interface_add_del_output_feature(u32 sw_if_index, u8 is_inside, int is_del)
Definition: nat.c:1790
static int ip4_is_first_fragment(ip4_header_t *i)
Definition: ip4_packet.h:217
u32 sharing_ratio
Definition: nat.h:217
ip4_address_t out_addr
Definition: nat.h:215
u16 psid
Definition: nat.h:351
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:396
u8 * format_session_kvp(u8 *s, va_list *args)
Definition: nat.c:2421
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:270
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:468
u32 tcp_transitory_timeout
Definition: nat.h:403
ip4_address_t r_addr
Definition: nat.h:66
u32 * auto_add_sw_if_indices
Definition: nat.h:357
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:2194
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:2218
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:3062
u32 num_workers
Definition: nat.h:322
Definition: nat.h:233
u32 first_worker_index
Definition: nat.h:323
snat_get_worker_function_t * worker_out2in_cb
Definition: nat.h:326
ip4_address_t l_addr
Definition: nat.h:259
snat_icmp_match_function_t * icmp_match_out2in_cb
Definition: nat.h:320
vlib_log_class_t log_class
Definition: nat.h:410
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:213
#define clib_bitmap_free(v)
Free a bitmap.
Definition: bitmap.h:92
u32 fq_in2out_index
Definition: nat.h:367
uword * thread_registrations_by_name
Definition: threads.h:297
u32 out2in_node_index
Definition: nat.h:374
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:3330
snat_address_t * twice_nat_addresses
Definition: nat.h:354
#define VNET_FEATURES(...)
Definition: feature.h:391
static clib_error_t * snat_init(vlib_main_t *vm)
Definition: nat.c:1959
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:2202
twice_nat_type_t
Definition: nat.h:231
#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:324
u64 uword
Definition: types.h:112
snat_main_per_thread_data_t * per_thread_data
Definition: nat.h:331
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:207
#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:347
void nat_dpo_create(dpo_proto_t dproto, u32 aftr_index, dpo_id_t *dpo)
Definition: nat_dpo.c:22
int snat_add_interface_address(snat_main_t *sm, u32 sw_if_index, int is_del, u8 twice_nat)
Definition: nat.c:3263
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:4293
u8 * format_snat_session(u8 *s, va_list *args)
Definition: nat.c:2923
#define hash_get_mem(h, key)
Definition: hash.h:269
u8 * format_det_map_ses(u8 *s, va_list *args)
Definition: nat.c:3082
u32 in2out_node_index
Definition: nat.h:372
#define SNAT_ICMP_TIMEOUT
Definition: nat.h:39
uword unformat_snat_protocol(unformat_input_t *input, va_list *args)
Definition: nat.c:2386
snat_static_map_resolve_t * to_resolve
Definition: nat.h:361
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:2571
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:2912
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:381
u32 translation_memory_size
Definition: nat.h:390
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:1906
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:495
clib_bihash_16_8_t in2out_ed
Definition: nat.h:278
vhost_vring_addr_t addr
Definition: vhost-user.h:83
u8 endpoint_dependent
Definition: nat.h:388
static clib_error_t * snat_config(vlib_main_t *vm, unformat_input_t *input)
Definition: nat.c:2695
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:3417
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:416
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:287
u8 * format_snat_session_state(u8 *s, va_list *args)
Definition: nat.c:2895
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:319
clib_bihash_8_8_t static_mapping_by_local
Definition: nat.h:334
static u32 snat_get_worker_out2in_cb(ip4_header_t *ip0, u32 rx_fib_index0)
Definition: nat.c:2497
u32 fib_index
Definition: nat.h:196
snat_interface_t * interfaces
Definition: nat.h:343
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:169
static u32 clib_dlist_remove_head(dlist_elt_t *pool, u32 head_index)
Definition: dlist.h:117
u32 tcp_established_timeout
Definition: nat.h:402
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128