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