FD.io VPP  v19.04.4-rc0-5-ge88582fac
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 <nat/nat_affinity.h>
32 #include <nat/nat_syslog.h>
33 #include <nat/nat_ha.h>
34 #include <vnet/fib/fib_table.h>
35 #include <vnet/fib/ip4_fib.h>
36 
37 #include <vpp/app/version.h>
38 
40 
41 /* *INDENT-OFF* */
42 
43 /* Hook up input features */
44 VNET_FEATURE_INIT (ip4_snat_in2out, static) = {
45  .arc_name = "ip4-unicast",
46  .node_name = "nat44-in2out",
47  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
48 };
49 VNET_FEATURE_INIT (ip4_snat_out2in, static) = {
50  .arc_name = "ip4-unicast",
51  .node_name = "nat44-out2in",
52  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
53  "ip4-dhcp-client-detect"),
54 };
55 VNET_FEATURE_INIT (ip4_nat_classify, static) = {
56  .arc_name = "ip4-unicast",
57  .node_name = "nat44-classify",
58  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
59 };
60 VNET_FEATURE_INIT (ip4_snat_det_in2out, static) = {
61  .arc_name = "ip4-unicast",
62  .node_name = "nat44-det-in2out",
63  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
64 };
65 VNET_FEATURE_INIT (ip4_snat_det_out2in, static) = {
66  .arc_name = "ip4-unicast",
67  .node_name = "nat44-det-out2in",
68  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
69  "ip4-dhcp-client-detect"),
70 };
71 VNET_FEATURE_INIT (ip4_nat_det_classify, static) = {
72  .arc_name = "ip4-unicast",
73  .node_name = "nat44-det-classify",
74  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
75 };
76 VNET_FEATURE_INIT (ip4_nat44_ed_in2out, static) = {
77  .arc_name = "ip4-unicast",
78  .node_name = "nat44-ed-in2out",
79  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
80 };
81 VNET_FEATURE_INIT (ip4_nat44_ed_out2in, static) = {
82  .arc_name = "ip4-unicast",
83  .node_name = "nat44-ed-out2in",
84  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
85  "ip4-dhcp-client-detect"),
86 };
87 VNET_FEATURE_INIT (ip4_nat44_ed_classify, static) = {
88  .arc_name = "ip4-unicast",
89  .node_name = "nat44-ed-classify",
90  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
91 };
92 VNET_FEATURE_INIT (ip4_snat_in2out_worker_handoff, static) = {
93  .arc_name = "ip4-unicast",
94  .node_name = "nat44-in2out-worker-handoff",
95  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
96 };
97 VNET_FEATURE_INIT (ip4_snat_out2in_worker_handoff, static) = {
98  .arc_name = "ip4-unicast",
99  .node_name = "nat44-out2in-worker-handoff",
100  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
101  "ip4-dhcp-client-detect"),
102 };
103 VNET_FEATURE_INIT (ip4_nat_handoff_classify, static) = {
104  .arc_name = "ip4-unicast",
105  .node_name = "nat44-handoff-classify",
106  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
107 };
108 VNET_FEATURE_INIT (ip4_snat_in2out_fast, static) = {
109  .arc_name = "ip4-unicast",
110  .node_name = "nat44-in2out-fast",
111  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
112 };
113 VNET_FEATURE_INIT (ip4_snat_out2in_fast, static) = {
114  .arc_name = "ip4-unicast",
115  .node_name = "nat44-out2in-fast",
116  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
117  "ip4-dhcp-client-detect"),
118 };
119 VNET_FEATURE_INIT (ip4_snat_hairpin_dst, static) = {
120  .arc_name = "ip4-unicast",
121  .node_name = "nat44-hairpin-dst",
122  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
123 };
124 VNET_FEATURE_INIT (ip4_nat44_ed_hairpin_dst, static) = {
125  .arc_name = "ip4-unicast",
126  .node_name = "nat44-ed-hairpin-dst",
127  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
128 };
129 
130 /* Hook up output features */
131 VNET_FEATURE_INIT (ip4_snat_in2out_output, static) = {
132  .arc_name = "ip4-output",
133  .node_name = "nat44-in2out-output",
134  .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
135 };
136 VNET_FEATURE_INIT (ip4_snat_in2out_output_worker_handoff, static) = {
137  .arc_name = "ip4-output",
138  .node_name = "nat44-in2out-output-worker-handoff",
139  .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
140 };
141 VNET_FEATURE_INIT (ip4_snat_hairpin_src, static) = {
142  .arc_name = "ip4-output",
143  .node_name = "nat44-hairpin-src",
144  .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
145 };
146 VNET_FEATURE_INIT (ip4_nat44_ed_in2out_output, static) = {
147  .arc_name = "ip4-output",
148  .node_name = "nat44-ed-in2out-output",
149  .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
150 };
151 VNET_FEATURE_INIT (ip4_nat44_ed_hairpin_src, static) = {
152  .arc_name = "ip4-output",
153  .node_name = "nat44-ed-hairpin-src",
154  .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
155 };
156 
157 /* Hook up ip4-local features */
158 VNET_FEATURE_INIT (ip4_nat_hairpinning, static) =
159 {
160  .arc_name = "ip4-local",
161  .node_name = "nat44-hairpinning",
162  .runs_before = VNET_FEATURES("ip4-local-end-of-arc"),
163 };
164 VNET_FEATURE_INIT (ip4_nat44_ed_hairpinning, static) =
165 {
166  .arc_name = "ip4-local",
167  .node_name = "nat44-ed-hairpinning",
168  .runs_before = VNET_FEATURES("ip4-local-end-of-arc"),
169 };
170 
171 
173  .version = VPP_BUILD_VER,
174  .description = "Network Address Translation (NAT)",
175 };
176 /* *INDENT-ON* */
177 
178 void
179 nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index,
180  u8 is_ha)
181 {
184  nat_ed_ses_key_t ed_key;
185  clib_bihash_kv_16_8_t ed_kv;
187  vec_elt_at_index (sm->per_thread_data, thread_index);
188 
189  if (is_fwd_bypass_session (s))
190  {
191  ed_key.l_addr = s->in2out.addr;
192  ed_key.r_addr = s->ext_host_addr;
193  ed_key.l_port = s->in2out.port;
194  ed_key.r_port = s->ext_host_port;
195  ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol);
196  ed_key.fib_index = 0;
197  ed_kv.key[0] = ed_key.as_u64[0];
198  ed_kv.key[1] = ed_key.as_u64[1];
199  if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0))
200  nat_log_warn ("in2out_ed key del failed");
201  return;
202  }
203 
204  /* session lookup tables */
205  if (is_ed_session (s))
206  {
207  if (is_affinity_sessions (s))
208  nat_affinity_unlock (s->ext_host_addr, s->out2in.addr,
209  s->in2out.protocol, s->out2in.port);
210  ed_key.l_addr = s->out2in.addr;
211  ed_key.r_addr = s->ext_host_addr;
212  ed_key.fib_index = s->out2in.fib_index;
214  {
215  ed_key.proto = s->in2out.port;
216  ed_key.r_port = 0;
217  ed_key.l_port = 0;
218  }
219  else
220  {
221  ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol);
222  ed_key.l_port = s->out2in.port;
223  ed_key.r_port = s->ext_host_port;
224  }
225  ed_kv.key[0] = ed_key.as_u64[0];
226  ed_kv.key[1] = ed_key.as_u64[1];
227  if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &ed_kv, 0))
228  nat_log_warn ("out2in_ed key del failed");
229  ed_key.l_addr = s->in2out.addr;
230  ed_key.fib_index = s->in2out.fib_index;
231  if (!snat_is_unk_proto_session (s))
232  ed_key.l_port = s->in2out.port;
233  if (is_twice_nat_session (s))
234  {
235  ed_key.r_addr = s->ext_host_nat_addr;
236  ed_key.r_port = s->ext_host_nat_port;
237  }
238  ed_kv.key[0] = ed_key.as_u64[0];
239  ed_kv.key[1] = ed_key.as_u64[1];
240  if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0))
241  nat_log_warn ("in2out_ed key del failed");
242 
243  if (!is_ha)
244  nat_syslog_nat44_sdel (s->user_index, s->in2out.fib_index,
245  &s->in2out.addr, s->in2out.port,
246  &s->ext_host_nat_addr, s->ext_host_nat_port,
247  &s->out2in.addr, s->out2in.port,
248  &s->ext_host_addr, s->ext_host_port,
249  s->in2out.protocol, is_twice_nat_session (s));
250  }
251  else
252  {
253  kv.key = s->in2out.as_u64;
254  if (clib_bihash_add_del_8_8 (&tsm->in2out, &kv, 0))
255  nat_log_warn ("in2out key del failed");
256  kv.key = s->out2in.as_u64;
257  if (clib_bihash_add_del_8_8 (&tsm->out2in, &kv, 0))
258  nat_log_warn ("out2in key del failed");
259 
260  if (!is_ha)
261  nat_syslog_nat44_apmdel (s->user_index, s->in2out.fib_index,
262  &s->in2out.addr, s->in2out.port,
263  &s->out2in.addr, s->out2in.port,
264  s->in2out.protocol);
265  }
266 
268  return;
269 
270  if (!is_ha)
271  {
272  /* log NAT event */
274  s->in2out.addr.as_u32,
275  s->out2in.addr.as_u32,
276  s->in2out.protocol,
277  s->in2out.port,
278  s->out2in.port,
279  s->in2out.fib_index);
280 
281  nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
282  s->ext_host_port, s->out2in.protocol, s->out2in.fib_index,
283  thread_index);
284  }
285 
286  /* Twice NAT address and port for external host */
287  if (is_twice_nat_session (s))
288  {
289  key.protocol = s->in2out.protocol;
290  key.port = s->ext_host_nat_port;
291  key.addr.as_u32 = s->ext_host_nat_addr.as_u32;
293  thread_index, &key);
294  }
295 
296  if (snat_is_session_static (s))
297  return;
298 
300  &s->out2in);
301 }
302 
303 snat_user_t *
305  u32 thread_index)
306 {
307  snat_user_t *u = 0;
308  snat_user_key_t user_key;
309  clib_bihash_kv_8_8_t kv, value;
310  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
311  dlist_elt_t *per_user_list_head_elt;
312 
313  user_key.addr.as_u32 = addr->as_u32;
314  user_key.fib_index = fib_index;
315  kv.key = user_key.as_u64;
316 
317  /* Ever heard of the "user" = src ip4 address before? */
318  if (clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
319  {
320  /* no, make a new one */
321  pool_get (tsm->users, u);
322  clib_memset (u, 0, sizeof (*u));
323  u->addr.as_u32 = addr->as_u32;
324  u->fib_index = fib_index;
325 
326  pool_get (tsm->list_pool, per_user_list_head_elt);
327 
328  u->sessions_per_user_list_head_index = per_user_list_head_elt -
329  tsm->list_pool;
330 
332 
333  kv.value = u - tsm->users;
334 
335  /* add user */
336  if (clib_bihash_add_del_8_8 (&tsm->user_hash, &kv, 1))
337  nat_log_warn ("user_hash keay add failed");
338 
339  vlib_set_simple_counter (&sm->total_users, thread_index, 0,
340  pool_elts (tsm->users));
341  }
342  else
343  {
344  u = pool_elt_at_index (tsm->users, value.value);
345  }
346 
347  return u;
348 }
349 
350 snat_session_t *
352  u32 thread_index, f64 now)
353 {
354  snat_session_t *s;
355  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
356  u32 oldest_per_user_translation_list_index, session_index;
357  dlist_elt_t *oldest_per_user_translation_list_elt;
358  dlist_elt_t *per_user_translation_list_elt;
359 
360  /* Over quota? Recycle the least recently used translation */
362  {
363  oldest_per_user_translation_list_index =
366 
367  ASSERT (oldest_per_user_translation_list_index != ~0);
368 
369  /* Add it back to the end of the LRU list */
372  oldest_per_user_translation_list_index);
373  /* Get the list element */
374  oldest_per_user_translation_list_elt =
376  oldest_per_user_translation_list_index);
377 
378  /* Get the session index from the list element */
379  session_index = oldest_per_user_translation_list_elt->value;
380 
381  /* Get the session */
382  s = pool_elt_at_index (tsm->sessions, session_index);
383  nat_free_session_data (sm, s, thread_index, 0);
384  if (snat_is_session_static (s))
385  u->nstaticsessions--;
386  else
387  u->nsessions--;
388  s->flags = 0;
389  s->total_bytes = 0;
390  s->total_pkts = 0;
391  s->state = 0;
392  s->ext_host_addr.as_u32 = 0;
393  s->ext_host_port = 0;
394  s->ext_host_nat_addr.as_u32 = 0;
395  s->ext_host_nat_port = 0;
396  }
397  else
398  {
399  pool_get (tsm->sessions, s);
400  clib_memset (s, 0, sizeof (*s));
401 
402  /* Create list elts */
403  pool_get (tsm->list_pool, per_user_translation_list_elt);
405  per_user_translation_list_elt - tsm->list_pool);
406 
407  per_user_translation_list_elt->value = s - tsm->sessions;
408  s->per_user_index = per_user_translation_list_elt - tsm->list_pool;
409  s->per_user_list_head_index = u->sessions_per_user_list_head_index;
410 
412  s->per_user_list_head_index,
413  per_user_translation_list_elt - tsm->list_pool);
414 
415  s->user_index = u - tsm->users;
416  vlib_set_simple_counter (&sm->total_sessions, thread_index, 0,
417  pool_elts (tsm->sessions));
418  }
419 
420  s->ha_last_refreshed = now;
421 
422  return s;
423 }
424 
425 snat_session_t *
427  f64 now)
428 {
429  snat_session_t *s;
430  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
431  dlist_elt_t *per_user_translation_list_elt, *oldest_elt;
432  u32 oldest_index;
433  u64 sess_timeout_time;
434 
435  if (PREDICT_FALSE (!(u->nsessions) && !(u->nstaticsessions)))
436  goto alloc_new;
437 
438  oldest_index =
441  oldest_elt = pool_elt_at_index (tsm->list_pool, oldest_index);
442  s = pool_elt_at_index (tsm->sessions, oldest_elt->value);
443  sess_timeout_time = s->last_heard + (f64) nat44_session_get_timeout (sm, s);
444  if (now >= sess_timeout_time)
445  {
447  u->sessions_per_user_list_head_index, oldest_index);
448  nat_free_session_data (sm, s, thread_index, 0);
449  if (snat_is_session_static (s))
450  u->nstaticsessions--;
451  else
452  u->nsessions--;
453  s->flags = 0;
454  s->total_bytes = 0;
455  s->total_pkts = 0;
456  s->state = 0;
457  s->ext_host_addr.as_u32 = 0;
458  s->ext_host_port = 0;
459  s->ext_host_nat_addr.as_u32 = 0;
460  s->ext_host_nat_port = 0;
461  }
462  else
463  {
465  u->sessions_per_user_list_head_index, oldest_index);
466  if ((u->nsessions + u->nstaticsessions) >=
468  {
469  nat_log_warn ("max translations per user %U", format_ip4_address,
470  &u->addr);
472  (thread_index, sm->max_translations_per_user, u->addr.as_u32);
473  return 0;
474  }
475  else
476  {
477  alloc_new:
478  pool_get (tsm->sessions, s);
479  clib_memset (s, 0, sizeof (*s));
480 
481  /* Create list elts */
482  pool_get (tsm->list_pool, per_user_translation_list_elt);
484  per_user_translation_list_elt - tsm->list_pool);
485 
486  per_user_translation_list_elt->value = s - tsm->sessions;
487  s->per_user_index = per_user_translation_list_elt - tsm->list_pool;
488  s->per_user_list_head_index = u->sessions_per_user_list_head_index;
489 
491  s->per_user_list_head_index,
492  per_user_translation_list_elt - tsm->list_pool);
493  }
494 
495  vlib_set_simple_counter (&sm->total_sessions, thread_index, 0,
496  pool_elts (tsm->sessions));
497  }
498 
499  s->ha_last_refreshed = now;
500 
501  return s;
502 }
503 
504 void
506  int is_add)
507 {
508  fib_prefix_t prefix = {
509  .fp_len = p_len,
510  .fp_proto = FIB_PROTOCOL_IP4,
511  .fp_addr = {
512  .ip4.as_u32 = addr->as_u32,
513  },
514  };
515  u32 fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
516 
517  if (is_add)
519  &prefix,
525  NULL,
526  sw_if_index,
528  else
529  fib_table_entry_delete (fib_index, &prefix, FIB_SOURCE_PLUGIN_LOW);
530 }
531 
532 int
534  u8 twice_nat)
535 {
536  snat_address_t *ap;
539 
540  if (twice_nat && !sm->endpoint_dependent)
541  return VNET_API_ERROR_FEATURE_DISABLED;
542 
543  /* Check if address already exists */
544  /* *INDENT-OFF* */
545  vec_foreach (ap, twice_nat ? sm->twice_nat_addresses : sm->addresses)
546  {
547  if (ap->addr.as_u32 == addr->as_u32)
548  return VNET_API_ERROR_VALUE_EXIST;
549  }
550  /* *INDENT-ON* */
551 
552  if (twice_nat)
553  vec_add2 (sm->twice_nat_addresses, ap, 1);
554  else
555  vec_add2 (sm->addresses, ap, 1);
556 
557  ap->addr = *addr;
558  if (vrf_id != ~0)
559  ap->fib_index =
562  else
563  ap->fib_index = ~0;
564 #define _(N, i, n, s) \
565  clib_bitmap_alloc (ap->busy_##n##_port_bitmap, 65535); \
566  ap->busy_##n##_ports = 0; \
567  ap->busy_##n##_ports_per_thread = 0;\
568  vec_validate_init_empty (ap->busy_##n##_ports_per_thread, tm->n_vlib_mains - 1, 0);
570 #undef _
571  if (twice_nat)
572  return 0;
573 
574  /* Add external address to FIB */
575  /* *INDENT-OFF* */
576  pool_foreach (i, sm->interfaces,
577  ({
578  if (nat_interface_is_inside(i) || sm->out2in_dpo)
579  continue;
580 
581  snat_add_del_addr_to_fib(addr, 32, i->sw_if_index, 1);
582  break;
583  }));
585  ({
586  if (nat_interface_is_inside(i) || sm->out2in_dpo)
587  continue;
588 
589  snat_add_del_addr_to_fib(addr, 32, i->sw_if_index, 1);
590  break;
591  }));
592  /* *INDENT-ON* */
593 
594  return 0;
595 }
596 
597 static int
599 {
601  /* *INDENT-OFF* */
603  ({
604  if (is_addr_only_static_mapping (m) ||
605  is_out2in_only_static_mapping (m) ||
606  is_identity_static_mapping (m))
607  continue;
608  if (m->external_addr.as_u32 == addr.as_u32)
609  return 1;
610  }));
611  /* *INDENT-ON* */
612 
613  return 0;
614 }
615 
616 void
618 {
619  u32 v;
620 
621  v = clib_net_to_host_u32 (a->as_u32) + 1;
622  a->as_u32 = clib_host_to_net_u32 (v);
623 }
624 
625 static void
627  ip4_address_t l_addr,
628  u16 l_port,
630  u16 e_port,
631  u32 vrf_id,
632  snat_protocol_t proto,
633  int addr_only, int is_add, u8 * tag,
634  int twice_nat, int out2in_only,
635  int identity_nat)
636 {
638 
639  vec_add2 (sm->to_resolve, rp, 1);
640  rp->l_addr.as_u32 = l_addr.as_u32;
641  rp->l_port = l_port;
642  rp->sw_if_index = sw_if_index;
643  rp->e_port = e_port;
644  rp->vrf_id = vrf_id;
645  rp->proto = proto;
646  rp->addr_only = addr_only;
647  rp->is_add = is_add;
648  rp->twice_nat = twice_nat;
649  rp->out2in_only = out2in_only;
650  rp->identity_nat = identity_nat;
651  rp->tag = vec_dup (tag);
652 }
653 
654 static u32
656 {
657  snat_main_t *sm = &snat_main;
658  u32 thread_idx = sm->num_workers;
659  if (sm->num_workers > 1)
660  {
661  thread_idx =
662  sm->first_worker_index +
663  sm->workers[(e_port - 1024) / sm->port_per_thread];
664  }
665  return thread_idx;
666 }
667 
668 int
670  u16 l_port, u16 e_port, u32 vrf_id, int addr_only,
672  twice_nat_type_t twice_nat, u8 out2in_only, u8 * tag,
673  u8 identity_nat)
674 {
675  snat_main_t *sm = &snat_main;
677  snat_session_key_t m_key;
678  clib_bihash_kv_8_8_t kv, value;
679  snat_address_t *a = 0;
680  u32 fib_index = ~0;
681  snat_interface_t *interface;
682  int i;
684  snat_user_key_t u_key;
685  snat_user_t *u;
686  dlist_elt_t *head, *elt;
687  u32 elt_index, head_index;
688  u32 ses_index;
689  u64 user_index;
690  snat_session_t *s;
691  snat_static_map_resolve_t *rp, *rp_match = 0;
692  nat44_lb_addr_port_t *local;
693  u32 find = ~0;
694 
695  if (!sm->endpoint_dependent)
696  {
697  if (twice_nat || out2in_only)
698  return VNET_API_ERROR_FEATURE_DISABLED;
699  }
700 
701  /* If the external address is a specific interface address */
702  if (sw_if_index != ~0)
703  {
704  ip4_address_t *first_int_addr;
705 
706  for (i = 0; i < vec_len (sm->to_resolve); i++)
707  {
708  rp = sm->to_resolve + i;
709  if (rp->sw_if_index != sw_if_index ||
710  rp->l_addr.as_u32 != l_addr.as_u32 ||
711  rp->vrf_id != vrf_id || rp->addr_only != addr_only)
712  continue;
713 
714  if (!addr_only)
715  {
716  if (rp->l_port != l_port || rp->e_port != e_port
717  || rp->proto != proto)
718  continue;
719  }
720 
721  rp_match = rp;
722  break;
723  }
724 
725  /* Might be already set... */
726  first_int_addr = ip4_interface_first_address
727  (sm->ip4_main, sw_if_index, 0 /* just want the address */ );
728 
729  if (is_add)
730  {
731  if (rp_match)
732  return VNET_API_ERROR_VALUE_EXIST;
733 
735  (sm, l_addr, l_port, sw_if_index, e_port, vrf_id, proto,
736  addr_only, is_add, tag, twice_nat, out2in_only, identity_nat);
737 
738  /* DHCP resolution required? */
739  if (first_int_addr == 0)
740  {
741  return 0;
742  }
743  else
744  {
745  e_addr.as_u32 = first_int_addr->as_u32;
746  /* Identity mapping? */
747  if (l_addr.as_u32 == 0)
748  l_addr.as_u32 = e_addr.as_u32;
749  }
750  }
751  else
752  {
753  if (!rp_match)
754  return VNET_API_ERROR_NO_SUCH_ENTRY;
755 
756  vec_del1 (sm->to_resolve, i);
757 
758  if (first_int_addr)
759  {
760  e_addr.as_u32 = first_int_addr->as_u32;
761  /* Identity mapping? */
762  if (l_addr.as_u32 == 0)
763  l_addr.as_u32 = e_addr.as_u32;
764  }
765  else
766  return 0;
767  }
768  }
769 
770  m_key.addr = e_addr;
771  m_key.port = addr_only ? 0 : e_port;
772  m_key.protocol = addr_only ? 0 : proto;
773  m_key.fib_index = 0;
774  kv.key = m_key.as_u64;
775  if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
776  m = 0;
777  else
778  m = pool_elt_at_index (sm->static_mappings, value.value);
779 
780  if (is_add)
781  {
782  if (m)
783  {
785  {
786  /* *INDENT-OFF* */
787  pool_foreach (local, m->locals,
788  ({
789  if (local->vrf_id == vrf_id)
790  return VNET_API_ERROR_VALUE_EXIST;
791  }));
792  /* *INDENT-ON* */
793  pool_get (m->locals, local);
794  local->vrf_id = vrf_id;
795  local->fib_index =
798  m_key.addr = m->local_addr;
799  m_key.port = m->local_port;
800  m_key.protocol = m->proto;
801  m_key.fib_index = local->fib_index;
802  kv.key = m_key.as_u64;
803  kv.value = m - sm->static_mappings;
804  clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1);
805  return 0;
806  }
807  else
808  return VNET_API_ERROR_VALUE_EXIST;
809  }
810 
811  if (twice_nat && addr_only)
812  return VNET_API_ERROR_UNSUPPORTED;
813 
814  /* Convert VRF id to FIB index */
815  if (vrf_id != ~0)
816  fib_index =
819  /* If not specified use inside VRF id from SNAT plugin startup config */
820  else
821  {
822  fib_index = sm->inside_fib_index;
823  vrf_id = sm->inside_vrf_id;
824  }
825 
826  if (!(out2in_only || identity_nat))
827  {
828  m_key.addr = l_addr;
829  m_key.port = addr_only ? 0 : l_port;
830  m_key.protocol = addr_only ? 0 : proto;
831  m_key.fib_index = fib_index;
832  kv.key = m_key.as_u64;
833  if (!clib_bihash_search_8_8
834  (&sm->static_mapping_by_local, &kv, &value))
835  return VNET_API_ERROR_VALUE_EXIST;
836  }
837 
838  /* Find external address in allocated addresses and reserve port for
839  address and port pair mapping when dynamic translations enabled */
840  if (!(addr_only || sm->static_mapping_only || out2in_only))
841  {
842  for (i = 0; i < vec_len (sm->addresses); i++)
843  {
844  if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
845  {
846  a = sm->addresses + i;
847  /* External port must be unused */
848  switch (proto)
849  {
850 #define _(N, j, n, s) \
851  case SNAT_PROTOCOL_##N: \
852  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, e_port)) \
853  return VNET_API_ERROR_INVALID_VALUE; \
854  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 1); \
855  if (e_port > 1024) \
856  { \
857  a->busy_##n##_ports++; \
858  a->busy_##n##_ports_per_thread[get_thread_idx_by_port(e_port)]++; \
859  } \
860  break;
862 #undef _
863  default:
864  nat_log_info ("unknown protocol");
865  return VNET_API_ERROR_INVALID_VALUE_2;
866  }
867  break;
868  }
869  }
870  /* External address must be allocated */
871  if (!a && (l_addr.as_u32 != e_addr.as_u32))
872  {
873  if (sw_if_index != ~0)
874  {
875  for (i = 0; i < vec_len (sm->to_resolve); i++)
876  {
877  rp = sm->to_resolve + i;
878  if (rp->addr_only)
879  continue;
880  if (rp->sw_if_index != sw_if_index &&
881  rp->l_addr.as_u32 != l_addr.as_u32 &&
882  rp->vrf_id != vrf_id && rp->l_port != l_port &&
883  rp->e_port != e_port && rp->proto != proto)
884  continue;
885 
886  vec_del1 (sm->to_resolve, i);
887  break;
888  }
889  }
890  return VNET_API_ERROR_NO_SUCH_ENTRY;
891  }
892  }
893 
894  pool_get (sm->static_mappings, m);
895  clib_memset (m, 0, sizeof (*m));
896  m->tag = vec_dup (tag);
897  m->local_addr = l_addr;
898  m->external_addr = e_addr;
899  m->twice_nat = twice_nat;
900  if (out2in_only)
902  if (addr_only)
904  if (identity_nat)
905  {
907  pool_get (m->locals, local);
908  local->vrf_id = vrf_id;
909  local->fib_index = fib_index;
910  }
911  else
912  {
913  m->vrf_id = vrf_id;
914  m->fib_index = fib_index;
915  }
916  if (!addr_only)
917  {
918  m->local_port = l_port;
919  m->external_port = e_port;
920  m->proto = proto;
921  }
922 
923  if (sm->num_workers > 1)
924  {
925  ip4_header_t ip = {
926  .src_address = m->local_addr,
927  };
928  vec_add1 (m->workers, sm->worker_in2out_cb (&ip, m->fib_index));
929  tsm = vec_elt_at_index (sm->per_thread_data, m->workers[0]);
930  }
931  else
933 
934  m_key.addr = m->local_addr;
935  m_key.port = m->local_port;
936  m_key.protocol = m->proto;
937  m_key.fib_index = fib_index;
938  kv.key = m_key.as_u64;
939  kv.value = m - sm->static_mappings;
940  if (!out2in_only)
941  clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1);
942 
943  m_key.addr = m->external_addr;
944  m_key.port = m->external_port;
945  m_key.fib_index = 0;
946  kv.key = m_key.as_u64;
947  kv.value = m - sm->static_mappings;
948  clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 1);
949 
950  /* Delete dynamic sessions matching local address (+ local port) */
951  if (!(sm->static_mapping_only))
952  {
953  u_key.addr = m->local_addr;
954  u_key.fib_index = m->fib_index;
955  kv.key = u_key.as_u64;
956  if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
957  {
958  user_index = value.value;
959  u = pool_elt_at_index (tsm->users, user_index);
960  if (u->nsessions)
961  {
962  head_index = u->sessions_per_user_list_head_index;
963  head = pool_elt_at_index (tsm->list_pool, head_index);
964  elt_index = head->next;
965  elt = pool_elt_at_index (tsm->list_pool, elt_index);
966  ses_index = elt->value;
967  while (ses_index != ~0)
968  {
969  s = pool_elt_at_index (tsm->sessions, ses_index);
970  elt = pool_elt_at_index (tsm->list_pool, elt->next);
971  ses_index = elt->value;
972 
973  if (snat_is_session_static (s))
974  continue;
975 
976  if (!addr_only
977  && (clib_net_to_host_u16 (s->in2out.port) !=
978  m->local_port))
979  continue;
980 
981  nat_free_session_data (sm, s,
982  tsm - sm->per_thread_data, 0);
983  nat44_delete_session (sm, s, tsm - sm->per_thread_data);
984 
985  if (!addr_only && !sm->endpoint_dependent)
986  break;
987  }
988  }
989  }
990  }
991  }
992  else
993  {
994  if (!m)
995  {
996  if (sw_if_index != ~0)
997  return 0;
998  else
999  return VNET_API_ERROR_NO_SUCH_ENTRY;
1000  }
1001 
1002  if (identity_nat)
1003  {
1004  if (vrf_id == ~0)
1005  vrf_id = sm->inside_vrf_id;
1006 
1007  /* *INDENT-OFF* */
1008  pool_foreach (local, m->locals,
1009  ({
1010  if (local->vrf_id == vrf_id)
1011  find = local - m->locals;
1012  }));
1013  /* *INDENT-ON* */
1014  if (find == ~0)
1015  return VNET_API_ERROR_NO_SUCH_ENTRY;
1016 
1017  local = pool_elt_at_index (m->locals, find);
1018  fib_index = local->fib_index;
1019  pool_put (m->locals, local);
1020  }
1021  else
1022  fib_index = m->fib_index;
1023 
1024  /* Free external address port */
1025  if (!(addr_only || sm->static_mapping_only || out2in_only))
1026  {
1027  for (i = 0; i < vec_len (sm->addresses); i++)
1028  {
1029  if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
1030  {
1031  a = sm->addresses + i;
1032  switch (proto)
1033  {
1034 #define _(N, j, n, s) \
1035  case SNAT_PROTOCOL_##N: \
1036  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 0); \
1037  if (e_port > 1024) \
1038  { \
1039  a->busy_##n##_ports--; \
1040  a->busy_##n##_ports_per_thread[get_thread_idx_by_port(e_port)]--; \
1041  } \
1042  break;
1044 #undef _
1045  default:
1046  nat_log_info ("unknown protocol");
1047  return VNET_API_ERROR_INVALID_VALUE_2;
1048  }
1049  break;
1050  }
1051  }
1052  }
1053 
1054  if (sm->num_workers > 1)
1055  tsm = vec_elt_at_index (sm->per_thread_data, m->workers[0]);
1056  else
1057  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1058 
1059  m_key.addr = m->local_addr;
1060  m_key.port = m->local_port;
1061  m_key.protocol = m->proto;
1062  m_key.fib_index = fib_index;
1063  kv.key = m_key.as_u64;
1064  if (!out2in_only)
1065  clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 0);
1066 
1067  /* Delete session(s) for static mapping if exist */
1068  if (!(sm->static_mapping_only) ||
1070  {
1071  u_key.addr = m->local_addr;
1072  u_key.fib_index = fib_index;
1073  kv.key = u_key.as_u64;
1074  if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
1075  {
1076  user_index = value.value;
1077  u = pool_elt_at_index (tsm->users, user_index);
1078  if (u->nstaticsessions)
1079  {
1080  head_index = u->sessions_per_user_list_head_index;
1081  head = pool_elt_at_index (tsm->list_pool, head_index);
1082  elt_index = head->next;
1083  elt = pool_elt_at_index (tsm->list_pool, elt_index);
1084  ses_index = elt->value;
1085  while (ses_index != ~0)
1086  {
1087  s = pool_elt_at_index (tsm->sessions, ses_index);
1088  elt = pool_elt_at_index (tsm->list_pool, elt->next);
1089  ses_index = elt->value;
1090 
1091  if (!addr_only)
1092  {
1093  if ((s->out2in.addr.as_u32 != e_addr.as_u32) ||
1094  (clib_net_to_host_u16 (s->out2in.port) !=
1095  e_port))
1096  continue;
1097  }
1098 
1099  if (is_lb_session (s))
1100  continue;
1101 
1102  if (!snat_is_session_static (s))
1103  continue;
1104 
1105  nat_free_session_data (sm, s,
1106  tsm - sm->per_thread_data, 0);
1107  nat44_delete_session (sm, s, tsm - sm->per_thread_data);
1108 
1109  if (!addr_only && !sm->endpoint_dependent)
1110  break;
1111  }
1112  }
1113  }
1114  }
1115 
1117  if (pool_elts (m->locals))
1118  return 0;
1119 
1120  m_key.addr = m->external_addr;
1121  m_key.port = m->external_port;
1122  m_key.fib_index = 0;
1123  kv.key = m_key.as_u64;
1124  clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 0);
1125 
1126  vec_free (m->tag);
1127  vec_free (m->workers);
1128  /* Delete static mapping from pool */
1129  pool_put (sm->static_mappings, m);
1130  }
1131 
1132  if (!addr_only || (l_addr.as_u32 == e_addr.as_u32))
1133  return 0;
1134 
1135  /* Add/delete external address to FIB */
1136  /* *INDENT-OFF* */
1137  pool_foreach (interface, sm->interfaces,
1138  ({
1139  if (nat_interface_is_inside(interface) || sm->out2in_dpo)
1140  continue;
1141 
1142  snat_add_del_addr_to_fib(&e_addr, 32, interface->sw_if_index, is_add);
1143  break;
1144  }));
1145  pool_foreach (interface, sm->output_feature_interfaces,
1146  ({
1147  if (nat_interface_is_inside(interface) || sm->out2in_dpo)
1148  continue;
1149 
1150  snat_add_del_addr_to_fib(&e_addr, 32, interface->sw_if_index, is_add);
1151  break;
1152  }));
1153  /* *INDENT-ON* */
1154 
1155  return 0;
1156 }
1157 
1158 int
1160  snat_protocol_t proto,
1161  nat44_lb_addr_port_t * locals, u8 is_add,
1162  twice_nat_type_t twice_nat, u8 out2in_only,
1163  u8 * tag, u32 affinity)
1164 {
1165  snat_main_t *sm = &snat_main;
1167  snat_session_key_t m_key;
1168  clib_bihash_kv_8_8_t kv, value;
1169  snat_address_t *a = 0;
1170  int i;
1171  nat44_lb_addr_port_t *local;
1172  u32 elt_index, head_index, ses_index;
1174  snat_user_key_t u_key;
1175  snat_user_t *u;
1176  snat_session_t *s;
1177  dlist_elt_t *head, *elt;
1178  uword *bitmap = 0;
1179 
1180  if (!sm->endpoint_dependent)
1181  return VNET_API_ERROR_FEATURE_DISABLED;
1182 
1183  m_key.addr = e_addr;
1184  m_key.port = e_port;
1185  m_key.protocol = proto;
1186  m_key.fib_index = 0;
1187  kv.key = m_key.as_u64;
1188  if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
1189  m = 0;
1190  else
1191  m = pool_elt_at_index (sm->static_mappings, value.value);
1192 
1193  if (is_add)
1194  {
1195  if (m)
1196  return VNET_API_ERROR_VALUE_EXIST;
1197 
1198  if (vec_len (locals) < 2)
1199  return VNET_API_ERROR_INVALID_VALUE;
1200 
1201  /* Find external address in allocated addresses and reserve port for
1202  address and port pair mapping when dynamic translations enabled */
1203  if (!(sm->static_mapping_only || out2in_only))
1204  {
1205  for (i = 0; i < vec_len (sm->addresses); i++)
1206  {
1207  if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
1208  {
1209  a = sm->addresses + i;
1210  /* External port must be unused */
1211  switch (proto)
1212  {
1213 #define _(N, j, n, s) \
1214  case SNAT_PROTOCOL_##N: \
1215  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, e_port)) \
1216  return VNET_API_ERROR_INVALID_VALUE; \
1217  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 1); \
1218  if (e_port > 1024) \
1219  { \
1220  a->busy_##n##_ports++; \
1221  a->busy_##n##_ports_per_thread[get_thread_idx_by_port(e_port)]++; \
1222  } \
1223  break;
1225 #undef _
1226  default:
1227  nat_log_info ("unknown protocol");
1228  return VNET_API_ERROR_INVALID_VALUE_2;
1229  }
1230  break;
1231  }
1232  }
1233  /* External address must be allocated */
1234  if (!a)
1235  return VNET_API_ERROR_NO_SUCH_ENTRY;
1236  }
1237 
1238  pool_get (sm->static_mappings, m);
1239  clib_memset (m, 0, sizeof (*m));
1240  m->tag = vec_dup (tag);
1241  m->external_addr = e_addr;
1242  m->external_port = e_port;
1243  m->proto = proto;
1244  m->twice_nat = twice_nat;
1246  if (out2in_only)
1248  m->affinity = affinity;
1249 
1250  if (affinity)
1253  else
1255 
1256  m_key.addr = m->external_addr;
1257  m_key.port = m->external_port;
1258  m_key.protocol = m->proto;
1259  m_key.fib_index = 0;
1260  kv.key = m_key.as_u64;
1261  kv.value = m - sm->static_mappings;
1262  if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 1))
1263  {
1264  nat_log_err ("static_mapping_by_external key add failed");
1265  return VNET_API_ERROR_UNSPECIFIED;
1266  }
1267 
1268  m_key.fib_index = m->fib_index;
1269  for (i = 0; i < vec_len (locals); i++)
1270  {
1271  locals[i].fib_index =
1273  locals[i].vrf_id,
1275  m_key.addr = locals[i].addr;
1276  m_key.fib_index = locals[i].fib_index;
1277  if (!out2in_only)
1278  {
1279  m_key.port = locals[i].port;
1280  kv.key = m_key.as_u64;
1281  kv.value = m - sm->static_mappings;
1282  clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1);
1283  }
1284  locals[i].prefix = (i == 0) ? locals[i].probability :
1285  (locals[i - 1].prefix + locals[i].probability);
1286  pool_get (m->locals, local);
1287  *local = locals[i];
1288  if (sm->num_workers > 1)
1289  {
1290  ip4_header_t ip = {
1291  .src_address = locals[i].addr,
1292  };
1293  bitmap =
1294  clib_bitmap_set (bitmap,
1295  sm->worker_in2out_cb (&ip, m->fib_index), 1);
1296  }
1297  }
1298 
1299  /* Assign workers */
1300  if (sm->num_workers > 1)
1301  {
1302  /* *INDENT-OFF* */
1303  clib_bitmap_foreach (i, bitmap,
1304  ({
1305  vec_add1(m->workers, i);
1306  }));
1307  /* *INDENT-ON* */
1308  }
1309  }
1310  else
1311  {
1312  if (!m)
1313  return VNET_API_ERROR_NO_SUCH_ENTRY;
1314 
1315  if (!is_lb_static_mapping (m))
1316  return VNET_API_ERROR_INVALID_VALUE;
1317 
1318  /* Free external address port */
1319  if (!(sm->static_mapping_only || out2in_only))
1320  {
1321  for (i = 0; i < vec_len (sm->addresses); i++)
1322  {
1323  if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
1324  {
1325  a = sm->addresses + i;
1326  switch (proto)
1327  {
1328 #define _(N, j, n, s) \
1329  case SNAT_PROTOCOL_##N: \
1330  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 0); \
1331  if (e_port > 1024) \
1332  { \
1333  a->busy_##n##_ports--; \
1334  a->busy_##n##_ports_per_thread[get_thread_idx_by_port(e_port)]--; \
1335  } \
1336  break;
1338 #undef _
1339  default:
1340  nat_log_info ("unknown protocol");
1341  return VNET_API_ERROR_INVALID_VALUE_2;
1342  }
1343  break;
1344  }
1345  }
1346  }
1347 
1348  m_key.addr = m->external_addr;
1349  m_key.port = m->external_port;
1350  m_key.protocol = m->proto;
1351  m_key.fib_index = 0;
1352  kv.key = m_key.as_u64;
1353  if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 0))
1354  {
1355  nat_log_err ("static_mapping_by_external key del failed");
1356  return VNET_API_ERROR_UNSPECIFIED;
1357  }
1358 
1359  /* *INDENT-OFF* */
1360  pool_foreach (local, m->locals,
1361  ({
1362  fib_table_unlock (local->fib_index, FIB_PROTOCOL_IP4,
1363  FIB_SOURCE_PLUGIN_LOW);
1364  m_key.addr = local->addr;
1365  if (!out2in_only)
1366  {
1367  m_key.port = local->port;
1368  m_key.fib_index = local->fib_index;
1369  kv.key = m_key.as_u64;
1370  if (clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 0))
1371  {
1372  nat_log_err ("static_mapping_by_local key del failed");
1373  return VNET_API_ERROR_UNSPECIFIED;
1374  }
1375  }
1376 
1377  if (sm->num_workers > 1)
1378  {
1379  ip4_header_t ip = {
1380  .src_address = local->addr,
1381  };
1382  tsm = vec_elt_at_index (sm->per_thread_data,
1383  sm->worker_in2out_cb (&ip, m->fib_index));
1384  }
1385  else
1386  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1387 
1388  /* Delete sessions */
1389  u_key.addr = local->addr;
1390  u_key.fib_index = local->fib_index;
1391  kv.key = u_key.as_u64;
1392  if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
1393  {
1394  u = pool_elt_at_index (tsm->users, value.value);
1395  if (u->nstaticsessions)
1396  {
1397  head_index = u->sessions_per_user_list_head_index;
1398  head = pool_elt_at_index (tsm->list_pool, head_index);
1399  elt_index = head->next;
1400  elt = pool_elt_at_index (tsm->list_pool, elt_index);
1401  ses_index = elt->value;
1402  while (ses_index != ~0)
1403  {
1404  s = pool_elt_at_index (tsm->sessions, ses_index);
1405  elt = pool_elt_at_index (tsm->list_pool, elt->next);
1406  ses_index = elt->value;
1407 
1408  if (!(is_lb_session (s)))
1409  continue;
1410 
1411  if ((s->in2out.addr.as_u32 != local->addr.as_u32) ||
1412  (clib_net_to_host_u16 (s->in2out.port) != local->port))
1413  continue;
1414 
1415  nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
1416  nat44_delete_session (sm, s, tsm - sm->per_thread_data);
1417  }
1418  }
1419  }
1420  }));
1421  /* *INDENT-ON* */
1422  if (m->affinity)
1423  nat_affinity_flush_service (m->affinity_per_service_list_head_index);
1424  pool_free (m->locals);
1425  vec_free (m->tag);
1426  vec_free (m->workers);
1427 
1428  pool_put (sm->static_mappings, m);
1429  }
1430 
1431  return 0;
1432 }
1433 
1434 int
1436  ip4_address_t l_addr, u16 l_port,
1437  snat_protocol_t proto, u32 vrf_id,
1438  u8 probability, u8 is_add)
1439 {
1440  snat_main_t *sm = &snat_main;
1441  snat_static_mapping_t *m = 0;
1442  snat_session_key_t m_key;
1443  clib_bihash_kv_8_8_t kv, value;
1444  nat44_lb_addr_port_t *local, *prev_local, *match_local = 0;
1446  snat_user_key_t u_key;
1447  snat_user_t *u;
1448  snat_session_t *s;
1449  dlist_elt_t *head, *elt;
1450  u32 elt_index, head_index, ses_index, *locals = 0;
1451  uword *bitmap = 0;
1452  int i;
1453 
1454  if (!sm->endpoint_dependent)
1455  return VNET_API_ERROR_FEATURE_DISABLED;
1456 
1457  m_key.addr = e_addr;
1458  m_key.port = e_port;
1459  m_key.protocol = proto;
1460  m_key.fib_index = 0;
1461  kv.key = m_key.as_u64;
1462  if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
1463  m = pool_elt_at_index (sm->static_mappings, value.value);
1464 
1465  if (!m)
1466  return VNET_API_ERROR_NO_SUCH_ENTRY;
1467 
1468  if (!is_lb_static_mapping (m))
1469  return VNET_API_ERROR_INVALID_VALUE;
1470 
1471  /* *INDENT-OFF* */
1472  pool_foreach (local, m->locals,
1473  ({
1474  if ((local->addr.as_u32 == l_addr.as_u32) && (local->port == l_port) &&
1475  (local->vrf_id == vrf_id))
1476  {
1477  match_local = local;
1478  break;
1479  }
1480  }));
1481  /* *INDENT-ON* */
1482 
1483  if (is_add)
1484  {
1485  if (match_local)
1486  return VNET_API_ERROR_VALUE_EXIST;
1487 
1488  pool_get (m->locals, local);
1489  clib_memset (local, 0, sizeof (*local));
1490  local->addr.as_u32 = l_addr.as_u32;
1491  local->port = l_port;
1492  local->probability = probability;
1493  local->vrf_id = vrf_id;
1494  local->fib_index =
1497 
1499  {
1500  m_key.addr = l_addr;
1501  m_key.port = l_port;
1502  m_key.fib_index = local->fib_index;
1503  kv.key = m_key.as_u64;
1504  kv.value = m - sm->static_mappings;
1505  if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1))
1506  nat_log_err ("static_mapping_by_local key add failed");
1507  }
1508  }
1509  else
1510  {
1511  if (!match_local)
1512  return VNET_API_ERROR_NO_SUCH_ENTRY;
1513 
1514  if (pool_elts (m->locals) < 3)
1515  return VNET_API_ERROR_UNSPECIFIED;
1516 
1517  fib_table_unlock (match_local->fib_index, FIB_PROTOCOL_IP4,
1519 
1521  {
1522  m_key.addr = l_addr;
1523  m_key.port = l_port;
1524  m_key.fib_index = match_local->fib_index;
1525  kv.key = m_key.as_u64;
1526  if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 0))
1527  nat_log_err ("static_mapping_by_local key del failed");
1528  }
1529 
1530  if (sm->num_workers > 1)
1531  {
1532  ip4_header_t ip = {
1533  .src_address = local->addr,
1534  };
1535  tsm = vec_elt_at_index (sm->per_thread_data,
1536  sm->worker_in2out_cb (&ip, m->fib_index));
1537  }
1538  else
1539  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1540 
1541  /* Delete sessions */
1542  u_key.addr = match_local->addr;
1543  u_key.fib_index = match_local->fib_index;
1544  kv.key = u_key.as_u64;
1545  if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
1546  {
1547  u = pool_elt_at_index (tsm->users, value.value);
1548  if (u->nstaticsessions)
1549  {
1550  head_index = u->sessions_per_user_list_head_index;
1551  head = pool_elt_at_index (tsm->list_pool, head_index);
1552  elt_index = head->next;
1553  elt = pool_elt_at_index (tsm->list_pool, elt_index);
1554  ses_index = elt->value;
1555  while (ses_index != ~0)
1556  {
1557  s = pool_elt_at_index (tsm->sessions, ses_index);
1558  elt = pool_elt_at_index (tsm->list_pool, elt->next);
1559  ses_index = elt->value;
1560 
1561  if (!(is_lb_session (s)))
1562  continue;
1563 
1564  if ((s->in2out.addr.as_u32 != match_local->addr.as_u32) ||
1565  (clib_net_to_host_u16 (s->in2out.port) !=
1566  match_local->port))
1567  continue;
1568 
1569  nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
1570  nat44_delete_session (sm, s, tsm - sm->per_thread_data);
1571  }
1572  }
1573  }
1574 
1575  pool_put (m->locals, match_local);
1576  }
1577 
1578  vec_free (m->workers);
1579 
1580  /* *INDENT-OFF* */
1581  pool_foreach (local, m->locals,
1582  ({
1583  vec_add1 (locals, local - m->locals);
1584  if (sm->num_workers > 1)
1585  {
1586  ip4_header_t ip;
1587  ip.src_address.as_u32 = local->addr.as_u32,
1588  bitmap = clib_bitmap_set (bitmap,
1589  sm->worker_in2out_cb (&ip, local->fib_index),
1590  1);
1591  }
1592  }));
1593  /* *INDENT-ON* */
1594 
1595  ASSERT (vec_len (locals) > 1);
1596 
1597  local = pool_elt_at_index (m->locals, locals[0]);
1598  local->prefix = local->probability;
1599  for (i = 1; i < vec_len (locals); i++)
1600  {
1601  local = pool_elt_at_index (m->locals, locals[i]);
1602  prev_local = pool_elt_at_index (m->locals, locals[i - 1]);
1603  local->prefix = local->probability + prev_local->prefix;
1604  }
1605 
1606  /* Assign workers */
1607  if (sm->num_workers > 1)
1608  {
1609  /* *INDENT-OFF* */
1610  clib_bitmap_foreach (i, bitmap, ({ vec_add1(m->workers, i); }));
1611  /* *INDENT-ON* */
1612  }
1613 
1614  return 0;
1615 }
1616 
1617 int
1619  u8 twice_nat)
1620 {
1621  snat_address_t *a = 0;
1622  snat_session_t *ses;
1623  u32 *ses_to_be_removed = 0, *ses_index;
1626  snat_interface_t *interface;
1627  int i;
1628  snat_address_t *addresses =
1629  twice_nat ? sm->twice_nat_addresses : sm->addresses;
1630 
1631  /* Find SNAT address */
1632  for (i = 0; i < vec_len (addresses); i++)
1633  {
1634  if (addresses[i].addr.as_u32 == addr.as_u32)
1635  {
1636  a = addresses + i;
1637  break;
1638  }
1639  }
1640  if (!a)
1641  return VNET_API_ERROR_NO_SUCH_ENTRY;
1642 
1643  if (delete_sm)
1644  {
1645  /* *INDENT-OFF* */
1646  pool_foreach (m, sm->static_mappings,
1647  ({
1648  if (m->external_addr.as_u32 == addr.as_u32)
1649  (void) snat_add_static_mapping (m->local_addr, m->external_addr,
1650  m->local_port, m->external_port,
1651  m->vrf_id, is_addr_only_static_mapping(m), ~0,
1652  m->proto, 0, m->twice_nat,
1653  is_out2in_only_static_mapping(m), m->tag, is_identity_static_mapping(m));
1654  }));
1655  /* *INDENT-ON* */
1656  }
1657  else
1658  {
1659  /* Check if address is used in some static mapping */
1661  {
1662  nat_log_notice ("address used in static mapping");
1663  return VNET_API_ERROR_UNSPECIFIED;
1664  }
1665  }
1666 
1667  if (a->fib_index != ~0)
1669 
1670  /* Delete sessions using address */
1671  if (a->busy_tcp_ports || a->busy_udp_ports || a->busy_icmp_ports)
1672  {
1673  /* *INDENT-OFF* */
1674  vec_foreach (tsm, sm->per_thread_data)
1675  {
1676  pool_foreach (ses, tsm->sessions, ({
1677  if (ses->out2in.addr.as_u32 == addr.as_u32)
1678  {
1679  nat_free_session_data (sm, ses, tsm - sm->per_thread_data, 0);
1680  vec_add1 (ses_to_be_removed, ses - tsm->sessions);
1681  }
1682  }));
1683 
1684  vec_foreach (ses_index, ses_to_be_removed)
1685  {
1686  ses = pool_elt_at_index (tsm->sessions, ses_index[0]);
1687  nat44_delete_session (sm, ses, tsm - sm->per_thread_data);
1688  }
1689 
1690  vec_free (ses_to_be_removed);
1691  }
1692  /* *INDENT-ON* */
1693  }
1694 
1695 #define _(N, i, n, s) \
1696  clib_bitmap_free (a->busy_##n##_port_bitmap); \
1697  vec_free (a->busy_##n##_ports_per_thread);
1699 #undef _
1700  if (twice_nat)
1701  {
1702  vec_del1 (sm->twice_nat_addresses, i);
1703  return 0;
1704  }
1705  else
1706  vec_del1 (sm->addresses, i);
1707 
1708  /* Delete external address from FIB */
1709  /* *INDENT-OFF* */
1710  pool_foreach (interface, sm->interfaces,
1711  ({
1712  if (nat_interface_is_inside(interface) || sm->out2in_dpo)
1713  continue;
1714 
1715  snat_add_del_addr_to_fib(&addr, 32, interface->sw_if_index, 0);
1716  break;
1717  }));
1718  pool_foreach (interface, sm->output_feature_interfaces,
1719  ({
1720  if (nat_interface_is_inside(interface) || sm->out2in_dpo)
1721  continue;
1722 
1723  snat_add_del_addr_to_fib(&addr, 32, interface->sw_if_index, 0);
1724  break;
1725  }));
1726  /* *INDENT-ON* */
1727 
1728  return 0;
1729 }
1730 
1731 int
1732 snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del)
1733 {
1734  snat_main_t *sm = &snat_main;
1736  const char *feature_name, *del_feature_name;
1737  snat_address_t *ap;
1739  snat_det_map_t *dm;
1740  nat_outside_fib_t *outside_fib;
1742  sw_if_index);
1743 
1744  if (sm->out2in_dpo && !is_inside)
1745  return VNET_API_ERROR_UNSUPPORTED;
1746 
1747  /* *INDENT-OFF* */
1749  ({
1750  if (i->sw_if_index == sw_if_index)
1751  return VNET_API_ERROR_VALUE_EXIST;
1752  }));
1753  /* *INDENT-ON* */
1754 
1756  feature_name = is_inside ? "nat44-in2out-fast" : "nat44-out2in-fast";
1757  else
1758  {
1759  if (sm->num_workers > 1 && !sm->deterministic)
1760  feature_name =
1761  is_inside ? "nat44-in2out-worker-handoff" :
1762  "nat44-out2in-worker-handoff";
1763  else if (sm->deterministic)
1764  feature_name = is_inside ? "nat44-det-in2out" : "nat44-det-out2in";
1765  else if (sm->endpoint_dependent)
1766  feature_name = is_inside ? "nat44-ed-in2out" : "nat44-ed-out2in";
1767  else
1768  feature_name = is_inside ? "nat44-in2out" : "nat44-out2in";
1769  }
1770 
1771  if (sm->fq_in2out_index == ~0 && !sm->deterministic && sm->num_workers > 1)
1773  NAT_FQ_NELTS);
1774 
1775  if (sm->fq_out2in_index == ~0 && !sm->deterministic && sm->num_workers > 1)
1777  NAT_FQ_NELTS);
1778 
1779  if (!is_inside)
1780  {
1781  /* *INDENT-OFF* */
1782  vec_foreach (outside_fib, sm->outside_fibs)
1783  {
1784  if (outside_fib->fib_index == fib_index)
1785  {
1786  if (is_del)
1787  {
1788  outside_fib->refcount--;
1789  if (!outside_fib->refcount)
1790  vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs);
1791  }
1792  else
1793  outside_fib->refcount++;
1794  goto feature_set;
1795  }
1796  }
1797  /* *INDENT-ON* */
1798  if (!is_del)
1799  {
1800  vec_add2 (sm->outside_fibs, outside_fib, 1);
1801  outside_fib->refcount = 1;
1802  outside_fib->fib_index = fib_index;
1803  }
1804  }
1805 feature_set:
1806  /* *INDENT-OFF* */
1807  pool_foreach (i, sm->interfaces,
1808  ({
1809  if (i->sw_if_index == sw_if_index)
1810  {
1811  if (is_del)
1812  {
1813  if (nat_interface_is_inside(i) && nat_interface_is_outside(i))
1814  {
1815  if (is_inside)
1816  i->flags &= ~NAT_INTERFACE_FLAG_IS_INSIDE;
1817  else
1818  i->flags &= ~NAT_INTERFACE_FLAG_IS_OUTSIDE;
1819 
1820  if (sm->num_workers > 1 && !sm->deterministic)
1821  {
1822  del_feature_name = "nat44-handoff-classify";
1823  feature_name = !is_inside ? "nat44-in2out-worker-handoff" :
1824  "nat44-out2in-worker-handoff";
1825  }
1826  else if (sm->deterministic)
1827  {
1828  del_feature_name = "nat44-det-classify";
1829  feature_name = !is_inside ? "nat44-det-in2out" :
1830  "nat44-det-out2in";
1831  }
1832  else if (sm->endpoint_dependent)
1833  {
1834  del_feature_name = "nat44-ed-classify";
1835  feature_name = !is_inside ? "nat44-ed-in2out" :
1836  "nat44-ed-out2in";
1837  }
1838  else
1839  {
1840  del_feature_name = "nat44-classify";
1841  feature_name = !is_inside ? "nat44-in2out" : "nat44-out2in";
1842  }
1843 
1844  vnet_feature_enable_disable ("ip4-unicast", del_feature_name,
1845  sw_if_index, 0, 0, 0);
1846  vnet_feature_enable_disable ("ip4-unicast", feature_name,
1847  sw_if_index, 1, 0, 0);
1848  if (!is_inside)
1849  {
1850  if (sm->endpoint_dependent)
1851  vnet_feature_enable_disable ("ip4-local",
1852  "nat44-ed-hairpinning",
1853  sw_if_index, 1, 0, 0);
1854  else if (!sm->deterministic)
1855  vnet_feature_enable_disable ("ip4-local",
1856  "nat44-hairpinning",
1857  sw_if_index, 1, 0, 0);
1858  }
1859  }
1860  else
1861  {
1862  vnet_feature_enable_disable ("ip4-unicast", feature_name,
1863  sw_if_index, 0, 0, 0);
1864  pool_put (sm->interfaces, i);
1865  if (is_inside)
1866  {
1867  if (sm->endpoint_dependent)
1868  vnet_feature_enable_disable ("ip4-local",
1869  "nat44-ed-hairpinning",
1870  sw_if_index, 0, 0, 0);
1871  else if (!sm->deterministic)
1872  vnet_feature_enable_disable ("ip4-local",
1873  "nat44-hairpinning",
1874  sw_if_index, 0, 0, 0);
1875  }
1876  }
1877  }
1878  else
1879  {
1880  if ((nat_interface_is_inside(i) && is_inside) ||
1881  (nat_interface_is_outside(i) && !is_inside))
1882  return 0;
1883 
1884  if (sm->num_workers > 1 && !sm->deterministic)
1885  {
1886  del_feature_name = !is_inside ? "nat44-in2out-worker-handoff" :
1887  "nat44-out2in-worker-handoff";
1888  feature_name = "nat44-handoff-classify";
1889  }
1890  else if (sm->deterministic)
1891  {
1892  del_feature_name = !is_inside ? "nat44-det-in2out" :
1893  "nat44-det-out2in";
1894  feature_name = "nat44-det-classify";
1895  }
1896  else if (sm->endpoint_dependent)
1897  {
1898  del_feature_name = !is_inside ? "nat44-ed-in2out" :
1899  "nat44-ed-out2in";
1900  feature_name = "nat44-ed-classify";
1901  }
1902  else
1903  {
1904  del_feature_name = !is_inside ? "nat44-in2out" : "nat44-out2in";
1905  feature_name = "nat44-classify";
1906  }
1907 
1908  vnet_feature_enable_disable ("ip4-unicast", del_feature_name,
1909  sw_if_index, 0, 0, 0);
1910  vnet_feature_enable_disable ("ip4-unicast", feature_name,
1911  sw_if_index, 1, 0, 0);
1912  if (!is_inside)
1913  {
1914  if (sm->endpoint_dependent)
1915  vnet_feature_enable_disable ("ip4-local", "nat44-ed-hairpinning",
1916  sw_if_index, 0, 0, 0);
1917  else if (!sm->deterministic)
1918  vnet_feature_enable_disable ("ip4-local", "nat44-hairpinning",
1919  sw_if_index, 0, 0, 0);
1920  }
1921  goto set_flags;
1922  }
1923 
1924  goto fib;
1925  }
1926  }));
1927  /* *INDENT-ON* */
1928 
1929  if (is_del)
1930  return VNET_API_ERROR_NO_SUCH_ENTRY;
1931 
1932  pool_get (sm->interfaces, i);
1933  i->sw_if_index = sw_if_index;
1934  i->flags = 0;
1935  vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, 1, 0,
1936  0);
1937 
1938  if (is_inside && !sm->out2in_dpo)
1939  {
1940  if (sm->endpoint_dependent)
1941  vnet_feature_enable_disable ("ip4-local", "nat44-ed-hairpinning",
1942  sw_if_index, 1, 0, 0);
1943  else if (!sm->deterministic)
1944  vnet_feature_enable_disable ("ip4-local", "nat44-hairpinning",
1945  sw_if_index, 1, 0, 0);
1946  }
1947 
1948 set_flags:
1949  if (is_inside)
1950  {
1951  i->flags |= NAT_INTERFACE_FLAG_IS_INSIDE;
1952  return 0;
1953  }
1954  else
1955  i->flags |= NAT_INTERFACE_FLAG_IS_OUTSIDE;
1956 
1957  /* Add/delete external addresses to FIB */
1958 fib:
1959  /* *INDENT-OFF* */
1960  vec_foreach (ap, sm->addresses)
1961  snat_add_del_addr_to_fib(&ap->addr, 32, sw_if_index, !is_del);
1962 
1963  pool_foreach (m, sm->static_mappings,
1964  ({
1965  if (!(is_addr_only_static_mapping(m)) || (m->local_addr.as_u32 == m->external_addr.as_u32))
1966  continue;
1967 
1968  snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
1969  }));
1970 
1971  pool_foreach (dm, sm->det_maps,
1972  ({
1973  snat_add_del_addr_to_fib(&dm->out_addr, dm->out_plen, sw_if_index, !is_del);
1974  }));
1975  /* *INDENT-ON* */
1976 
1977  return 0;
1978 }
1979 
1980 int
1982  u8 is_inside, int is_del)
1983 {
1984  snat_main_t *sm = &snat_main;
1986  snat_address_t *ap;
1988  nat_outside_fib_t *outside_fib;
1990  sw_if_index);
1991 
1992 
1993  if (sm->deterministic ||
1995  return VNET_API_ERROR_UNSUPPORTED;
1996 
1997  /* *INDENT-OFF* */
1998  pool_foreach (i, sm->interfaces,
1999  ({
2000  if (i->sw_if_index == sw_if_index)
2001  return VNET_API_ERROR_VALUE_EXIST;
2002  }));
2003  /* *INDENT-ON* */
2004 
2005  if (!is_inside)
2006  {
2007  /* *INDENT-OFF* */
2008  vec_foreach (outside_fib, sm->outside_fibs)
2009  {
2010  if (outside_fib->fib_index == fib_index)
2011  {
2012  if (is_del)
2013  {
2014  outside_fib->refcount--;
2015  if (!outside_fib->refcount)
2016  vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs);
2017  }
2018  else
2019  outside_fib->refcount++;
2020  goto feature_set;
2021  }
2022  }
2023  /* *INDENT-ON* */
2024  if (!is_del)
2025  {
2026  vec_add2 (sm->outside_fibs, outside_fib, 1);
2027  outside_fib->refcount = 1;
2028  outside_fib->fib_index = fib_index;
2029  }
2030  }
2031 
2032 feature_set:
2033  if (is_inside)
2034  {
2035  if (sm->endpoint_dependent)
2036  {
2037  vnet_feature_enable_disable ("ip4-unicast", "nat44-ed-hairpin-dst",
2038  sw_if_index, !is_del, 0, 0);
2039  vnet_feature_enable_disable ("ip4-output", "nat44-ed-hairpin-src",
2040  sw_if_index, !is_del, 0, 0);
2041  }
2042  else
2043  {
2044  vnet_feature_enable_disable ("ip4-unicast", "nat44-hairpin-dst",
2045  sw_if_index, !is_del, 0, 0);
2046  vnet_feature_enable_disable ("ip4-output", "nat44-hairpin-src",
2047  sw_if_index, !is_del, 0, 0);
2048  }
2049  goto fq;
2050  }
2051 
2052  if (sm->num_workers > 1)
2053  {
2054  vnet_feature_enable_disable ("ip4-unicast",
2055  "nat44-out2in-worker-handoff",
2056  sw_if_index, !is_del, 0, 0);
2057  vnet_feature_enable_disable ("ip4-output",
2058  "nat44-in2out-output-worker-handoff",
2059  sw_if_index, !is_del, 0, 0);
2060  }
2061  else
2062  {
2063  if (sm->endpoint_dependent)
2064  {
2065  vnet_feature_enable_disable ("ip4-unicast", "nat44-ed-out2in",
2066  sw_if_index, !is_del, 0, 0);
2067  vnet_feature_enable_disable ("ip4-output", "nat44-ed-in2out-output",
2068  sw_if_index, !is_del, 0, 0);
2069  }
2070  else
2071  {
2072  vnet_feature_enable_disable ("ip4-unicast", "nat44-out2in",
2073  sw_if_index, !is_del, 0, 0);
2074  vnet_feature_enable_disable ("ip4-output", "nat44-in2out-output",
2075  sw_if_index, !is_del, 0, 0);
2076  }
2077  }
2078 
2079 fq:
2080  if (sm->fq_in2out_output_index == ~0 && sm->num_workers > 1)
2083 
2084  if (sm->fq_out2in_index == ~0 && sm->num_workers > 1)
2085  sm->fq_out2in_index =
2087 
2088  /* *INDENT-OFF* */
2090  ({
2091  if (i->sw_if_index == sw_if_index)
2092  {
2093  if (is_del)
2094  pool_put (sm->output_feature_interfaces, i);
2095  else
2096  return VNET_API_ERROR_VALUE_EXIST;
2097 
2098  goto fib;
2099  }
2100  }));
2101  /* *INDENT-ON* */
2102 
2103  if (is_del)
2104  return VNET_API_ERROR_NO_SUCH_ENTRY;
2105 
2106  pool_get (sm->output_feature_interfaces, i);
2107  i->sw_if_index = sw_if_index;
2108  i->flags = 0;
2109  if (is_inside)
2110  i->flags |= NAT_INTERFACE_FLAG_IS_INSIDE;
2111  else
2112  i->flags |= NAT_INTERFACE_FLAG_IS_OUTSIDE;
2113 
2114  /* Add/delete external addresses to FIB */
2115 fib:
2116  if (is_inside)
2117  return 0;
2118 
2119  /* *INDENT-OFF* */
2120  vec_foreach (ap, sm->addresses)
2121  snat_add_del_addr_to_fib(&ap->addr, 32, sw_if_index, !is_del);
2122 
2123  pool_foreach (m, sm->static_mappings,
2124  ({
2125  if (!((is_addr_only_static_mapping(m))) || (m->local_addr.as_u32 == m->external_addr.as_u32))
2126  continue;
2127 
2128  snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
2129  }));
2130  /* *INDENT-ON* */
2131 
2132  return 0;
2133 }
2134 
2135 int
2137 {
2138  snat_main_t *sm = &snat_main;
2139  int i, j = 0;
2140 
2141  if (sm->num_workers < 2)
2142  return VNET_API_ERROR_FEATURE_DISABLED;
2143 
2144  if (clib_bitmap_last_set (bitmap) >= sm->num_workers)
2145  return VNET_API_ERROR_INVALID_WORKER;
2146 
2147  vec_free (sm->workers);
2148  /* *INDENT-OFF* */
2149  clib_bitmap_foreach (i, bitmap,
2150  ({
2151  vec_add1(sm->workers, i);
2153  j++;
2154  }));
2155  /* *INDENT-ON* */
2156 
2157  sm->port_per_thread = (0xffff - 1024) / _vec_len (sm->workers);
2158  sm->num_snat_thread = _vec_len (sm->workers);
2159 
2160  return 0;
2161 }
2162 
2163 static void
2165  u32 old_fib_index)
2166 {
2167  snat_main_t *sm = &snat_main;
2168  nat_outside_fib_t *outside_fib;
2170  u8 is_add = 1;
2171  u8 match = 0;
2172 
2173  if (new_fib_index == old_fib_index)
2174  return;
2175 
2176  if (!vec_len (sm->outside_fibs))
2177  return;
2178 
2179  /* *INDENT-OFF* */
2180  pool_foreach (i, sm->interfaces,
2181  ({
2182  if (i->sw_if_index == sw_if_index)
2183  {
2184  if (!(nat_interface_is_outside (i)))
2185  return;
2186  match = 1;
2187  }
2188  }));
2189  /* *INDENT-ON* */
2190 
2191  if (!match)
2192  return;
2193 
2194  vec_foreach (outside_fib, sm->outside_fibs)
2195  {
2196  if (outside_fib->fib_index == old_fib_index)
2197  {
2198  outside_fib->refcount--;
2199  if (!outside_fib->refcount)
2200  vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs);
2201  break;
2202  }
2203  }
2204 
2205  vec_foreach (outside_fib, sm->outside_fibs)
2206  {
2207  if (outside_fib->fib_index == new_fib_index)
2208  {
2209  outside_fib->refcount++;
2210  is_add = 0;
2211  break;
2212  }
2213  }
2214 
2215  if (is_add)
2216  {
2217  vec_add2 (sm->outside_fibs, outside_fib, 1);
2218  outside_fib->refcount = 1;
2219  outside_fib->fib_index = new_fib_index;
2220  }
2221 }
2222 
2223 static void
2225  uword opaque,
2226  u32 sw_if_index, u32 new_fib_index, u32 old_fib_index)
2227 {
2228  snat_update_outside_fib (sw_if_index, new_fib_index, old_fib_index);
2229 }
2230 
2231 static void
2233  uword opaque,
2234  u32 sw_if_index,
2237  u32 if_address_index, u32 is_delete);
2238 
2239 static void
2241  uword opaque,
2242  u32 sw_if_index,
2243  ip4_address_t * address,
2244  u32 address_length,
2245  u32 if_address_index, u32 is_delete);
2246 
2247 static int
2249  u32 fib_index,
2250  u32 thread_index,
2251  snat_session_key_t * k,
2252  u16 port_per_thread, u32 snat_thread_index);
2253 
2254 static clib_error_t *
2256 {
2257  snat_main_t *sm = &snat_main;
2258  clib_error_t *error = 0;
2259  ip4_main_t *im = &ip4_main;
2260  ip_lookup_main_t *lm = &im->lookup_main;
2261  uword *p;
2264  uword *bitmap = 0;
2265  u32 i;
2267  vlib_node_t *node;
2268 
2269  sm->vlib_main = vm;
2270  sm->vnet_main = vnet_get_main ();
2271  sm->ip4_main = im;
2272  sm->ip4_lookup_main = lm;
2273  sm->api_main = &api_main;
2274  sm->first_worker_index = 0;
2275  sm->num_workers = 0;
2276  sm->num_snat_thread = 1;
2277  sm->workers = 0;
2278  sm->port_per_thread = 0xffff - 1024;
2279  sm->fq_in2out_index = ~0;
2280  sm->fq_in2out_output_index = ~0;
2281  sm->fq_out2in_index = ~0;
2287  sm->addr_and_port_alloc_alg = NAT_ADDR_AND_PORT_ALLOC_ALG_DEFAULT;
2288  sm->forwarding_enabled = 0;
2289  sm->log_class = vlib_log_register_class ("nat", 0);
2290  sm->mss_clamping = 0;
2291 
2292  node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
2293  sm->error_node_index = node->index;
2294 
2295  node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out");
2296  sm->in2out_node_index = node->index;
2297  node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-output");
2298  sm->in2out_output_node_index = node->index;
2299  node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-fast");
2300  sm->in2out_fast_node_index = node->index;
2301  node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-slowpath");
2302  sm->in2out_slowpath_node_index = node->index;
2303  node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-output-slowpath");
2305  node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-reass");
2306  sm->in2out_reass_node_index = node->index;
2307 
2308  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-in2out");
2309  sm->ed_in2out_node_index = node->index;
2310  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-in2out-slowpath");
2312  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-in2out-reass");
2313  sm->ed_in2out_reass_node_index = node->index;
2314 
2315  node = vlib_get_node_by_name (vm, (u8 *) "nat44-out2in");
2316  sm->out2in_node_index = node->index;
2317  node = vlib_get_node_by_name (vm, (u8 *) "nat44-out2in-fast");
2318  sm->out2in_fast_node_index = node->index;
2319  node = vlib_get_node_by_name (vm, (u8 *) "nat44-out2in-reass");
2320  sm->out2in_reass_node_index = node->index;
2321 
2322  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-out2in");
2323  sm->ed_out2in_node_index = node->index;
2324  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-out2in-slowpath");
2326  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-out2in-reass");
2327  sm->ed_out2in_reass_node_index = node->index;
2328 
2329  node = vlib_get_node_by_name (vm, (u8 *) "nat44-det-in2out");
2330  sm->det_in2out_node_index = node->index;
2331  node = vlib_get_node_by_name (vm, (u8 *) "nat44-det-out2in");
2332  sm->det_out2in_node_index = node->index;
2333 
2334  node = vlib_get_node_by_name (vm, (u8 *) "nat44-hairpinning");
2335  sm->hairpinning_node_index = node->index;
2336  node = vlib_get_node_by_name (vm, (u8 *) "nat44-hairpin-dst");
2337  sm->hairpin_dst_node_index = node->index;
2338  node = vlib_get_node_by_name (vm, (u8 *) "nat44-hairpin-src");
2339  sm->hairpin_src_node_index = node->index;
2340  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-hairpinning");
2341  sm->ed_hairpinning_node_index = node->index;
2342  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-hairpin-dst");
2343  sm->ed_hairpin_dst_node_index = node->index;
2344  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-hairpin-src");
2345  sm->ed_hairpin_src_node_index = node->index;
2346 
2347  p = hash_get_mem (tm->thread_registrations_by_name, "workers");
2348  if (p)
2349  {
2350  tr = (vlib_thread_registration_t *) p[0];
2351  if (tr)
2352  {
2353  sm->num_workers = tr->count;
2354  sm->first_worker_index = tr->first_index;
2355  }
2356  }
2357 
2358  vec_validate (sm->per_thread_data, tm->n_vlib_mains - 1);
2359 
2360  /* Use all available workers by default */
2361  if (sm->num_workers > 1)
2362  {
2363  for (i = 0; i < sm->num_workers; i++)
2364  bitmap = clib_bitmap_set (bitmap, i, 1);
2365  snat_set_workers (bitmap);
2366  clib_bitmap_free (bitmap);
2367  }
2368  else
2369  {
2371  }
2372 
2373  error = snat_api_init (vm, sm);
2374  if (error)
2375  return error;
2376 
2377  /* Set up the interface address add/del callback */
2379  cb4.function_opaque = 0;
2380 
2382 
2384  cb4.function_opaque = 0;
2385 
2387 
2389 
2390  /* Init counters */
2391  sm->total_users.name = "total-users";
2392  sm->total_users.stat_segment_name = "/nat44/total-users";
2395  sm->total_sessions.name = "total-sessions";
2396  sm->total_sessions.stat_segment_name = "/nat44/total-sessions";
2399 
2400  /* Init IPFIX logging */
2402 
2403  /* Init NAT64 */
2404  error = nat64_init (vm);
2405  if (error)
2406  return error;
2407 
2408  dslite_init (vm);
2409 
2410  nat66_init (vm);
2411 
2412  ip4_table_bind_callback_t cbt4 = {
2414  };
2416 
2417  /* Init virtual fragmenentation reassembly */
2418  return nat_reass_init (vm);
2419 }
2420 
2422 
2423 void
2425  u32 thread_index, snat_session_key_t * k)
2426 {
2427  snat_address_t *a;
2428  u32 address_index;
2429  u16 port_host_byte_order = clib_net_to_host_u16 (k->port);
2430 
2431  for (address_index = 0; address_index < vec_len (addresses);
2432  address_index++)
2433  {
2434  if (addresses[address_index].addr.as_u32 == k->addr.as_u32)
2435  break;
2436  }
2437 
2438  ASSERT (address_index < vec_len (addresses));
2439 
2440  a = addresses + address_index;
2441 
2442  switch (k->protocol)
2443  {
2444 #define _(N, i, n, s) \
2445  case SNAT_PROTOCOL_##N: \
2446  ASSERT (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, \
2447  port_host_byte_order) == 1); \
2448  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, \
2449  port_host_byte_order, 0); \
2450  a->busy_##n##_ports--; \
2451  a->busy_##n##_ports_per_thread[thread_index]--; \
2452  break;
2454 #undef _
2455  default:
2456  nat_log_info ("unknown protocol");
2457  return;
2458  }
2459 }
2460 
2461 static int
2463  u32 thread_index, snat_session_key_t * k)
2464 {
2465  snat_address_t *a = 0;
2466  u32 address_index;
2467  u16 port_host_byte_order = clib_net_to_host_u16 (k->port);
2468 
2469  for (address_index = 0; address_index < vec_len (addresses);
2470  address_index++)
2471  {
2472  if (addresses[address_index].addr.as_u32 != k->addr.as_u32)
2473  continue;
2474 
2475  a = addresses + address_index;
2476  switch (k->protocol)
2477  {
2478 #define _(N, j, n, s) \
2479  case SNAT_PROTOCOL_##N: \
2480  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, port_host_byte_order)) \
2481  return VNET_API_ERROR_INSTANCE_IN_USE; \
2482  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, port_host_byte_order, 1); \
2483  a->busy_##n##_ports_per_thread[thread_index]++; \
2484  a->busy_##n##_ports++; \
2485  return 0;
2487 #undef _
2488  default:
2489  nat_log_info ("unknown protocol");
2490  return 1;
2491  }
2492  }
2493 
2494  return VNET_API_ERROR_NO_SUCH_ENTRY;
2495 }
2496 
2497 int
2499  snat_session_key_t match,
2500  snat_session_key_t * mapping,
2501  u8 by_external,
2502  u8 * is_addr_only,
2503  twice_nat_type_t * twice_nat,
2504  lb_nat_type_t * lb, ip4_address_t * ext_host_addr,
2505  u8 * is_identity_nat)
2506 {
2507  clib_bihash_kv_8_8_t kv, value;
2509  snat_session_key_t m_key;
2510  clib_bihash_8_8_t *mapping_hash = &sm->static_mapping_by_local;
2511  u32 rand, lo = 0, hi, mid, *tmp = 0, i;
2512  u8 backend_index;
2513  nat44_lb_addr_port_t *local;
2514 
2515  m_key.fib_index = match.fib_index;
2516  if (by_external)
2517  {
2518  mapping_hash = &sm->static_mapping_by_external;
2519  m_key.fib_index = 0;
2520  }
2521 
2522  m_key.addr = match.addr;
2523  m_key.port = clib_net_to_host_u16 (match.port);
2524  m_key.protocol = match.protocol;
2525 
2526  kv.key = m_key.as_u64;
2527 
2528  if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
2529  {
2530  /* Try address only mapping */
2531  m_key.port = 0;
2532  m_key.protocol = 0;
2533  kv.key = m_key.as_u64;
2534  if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
2535  return 1;
2536  }
2537 
2538  m = pool_elt_at_index (sm->static_mappings, value.value);
2539 
2540  if (by_external)
2541  {
2542  if (is_lb_static_mapping (m))
2543  {
2544  if (PREDICT_FALSE (lb != 0))
2545  *lb = m->affinity ? AFFINITY_LB_NAT : LB_NAT;
2546  if (m->affinity)
2547  {
2548  if (nat_affinity_find_and_lock (ext_host_addr[0], match.addr,
2549  match.protocol, match.port,
2550  &backend_index))
2551  goto get_local;
2552 
2553  local = pool_elt_at_index (m->locals, backend_index);
2554  mapping->addr = local->addr;
2555  mapping->port = clib_host_to_net_u16 (local->port);
2556  mapping->fib_index = local->fib_index;
2557  goto end;
2558  }
2559  get_local:
2560  /* *INDENT-OFF* */
2562  ({
2563  vec_add1 (tmp, i);
2564  }));
2565  /* *INDENT-ON* */
2566  hi = vec_len (tmp) - 1;
2567  local = pool_elt_at_index (m->locals, tmp[hi]);
2568  rand = 1 + (random_u32 (&sm->random_seed) % local->prefix);
2569  while (lo < hi)
2570  {
2571  mid = ((hi - lo) >> 1) + lo;
2572  local = pool_elt_at_index (m->locals, tmp[mid]);
2573  (rand > local->prefix) ? (lo = mid + 1) : (hi = mid);
2574  }
2575  local = pool_elt_at_index (m->locals, tmp[lo]);
2576  if (!(local->prefix >= rand))
2577  return 1;
2578  if (PREDICT_FALSE (sm->num_workers > 1))
2579  {
2580  ip4_header_t ip = {
2581  .src_address = local->addr,
2582  };
2583  if (sm->worker_in2out_cb (&ip, m->fib_index) !=
2585  goto get_local;
2586  }
2587  mapping->addr = local->addr;
2588  mapping->port = clib_host_to_net_u16 (local->port);
2589  mapping->fib_index = local->fib_index;
2590  if (m->affinity)
2591  {
2592  if (nat_affinity_create_and_lock (ext_host_addr[0], match.addr,
2593  match.protocol, match.port,
2594  tmp[lo], m->affinity,
2596  nat_log_info ("create affinity record failed");
2597  }
2598  vec_free (tmp);
2599  }
2600  else
2601  {
2602  if (PREDICT_FALSE (lb != 0))
2603  *lb = NO_LB_NAT;
2604  mapping->fib_index = m->fib_index;
2605  mapping->addr = m->local_addr;
2606  /* Address only mapping doesn't change port */
2607  mapping->port = is_addr_only_static_mapping (m) ? match.port
2608  : clib_host_to_net_u16 (m->local_port);
2609  }
2610  mapping->protocol = m->proto;
2611  }
2612  else
2613  {
2614  mapping->addr = m->external_addr;
2615  /* Address only mapping doesn't change port */
2616  mapping->port = is_addr_only_static_mapping (m) ? match.port
2617  : clib_host_to_net_u16 (m->external_port);
2618  mapping->fib_index = sm->outside_fib_index;
2619  }
2620 
2621 end:
2622  if (PREDICT_FALSE (is_addr_only != 0))
2623  *is_addr_only = is_addr_only_static_mapping (m);
2624 
2625  if (PREDICT_FALSE (twice_nat != 0))
2626  *twice_nat = m->twice_nat;
2627 
2628  if (PREDICT_FALSE (is_identity_nat != 0))
2629  *is_identity_nat = is_identity_static_mapping (m);
2630 
2631  return 0;
2632 }
2633 
2636 {
2637  snat_main_t *sm = &snat_main;
2638  return min + random_u32 (&sm->random_seed) /
2639  (random_u32_max () / (max - min + 1) + 1);
2640 }
2641 
2642 int
2644  u32 fib_index,
2645  u32 thread_index,
2646  snat_session_key_t * k,
2647  u16 port_per_thread,
2648  u32 snat_thread_index)
2649 {
2650  snat_main_t *sm = &snat_main;
2651 
2652  return sm->alloc_addr_and_port (addresses, fib_index, thread_index, k,
2653  port_per_thread, snat_thread_index);
2654 }
2655 
2656 static int
2658  u32 fib_index,
2659  u32 thread_index,
2660  snat_session_key_t * k,
2661  u16 port_per_thread, u32 snat_thread_index)
2662 {
2663  int i;
2664  snat_address_t *a, *ga = 0;
2665  u32 portnum;
2666 
2667  for (i = 0; i < vec_len (addresses); i++)
2668  {
2669  a = addresses + i;
2670  switch (k->protocol)
2671  {
2672 #define _(N, j, n, s) \
2673  case SNAT_PROTOCOL_##N: \
2674  if (a->busy_##n##_ports_per_thread[thread_index] < port_per_thread) \
2675  { \
2676  if (a->fib_index == fib_index) \
2677  { \
2678  while (1) \
2679  { \
2680  portnum = (port_per_thread * \
2681  snat_thread_index) + \
2682  snat_random_port(1, port_per_thread) + 1024; \
2683  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \
2684  continue; \
2685  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \
2686  a->busy_##n##_ports_per_thread[thread_index]++; \
2687  a->busy_##n##_ports++; \
2688  k->addr = a->addr; \
2689  k->port = clib_host_to_net_u16(portnum); \
2690  return 0; \
2691  } \
2692  } \
2693  else if (a->fib_index == ~0) \
2694  { \
2695  ga = a; \
2696  } \
2697  } \
2698  break;
2700 #undef _
2701  default:
2702  nat_log_info ("unknown protocol");
2703  return 1;
2704  }
2705 
2706  }
2707 
2708  if (ga)
2709  {
2710  a = ga;
2711  switch (k->protocol)
2712  {
2713 #define _(N, j, n, s) \
2714  case SNAT_PROTOCOL_##N: \
2715  while (1) \
2716  { \
2717  portnum = (port_per_thread * \
2718  snat_thread_index) + \
2719  snat_random_port(1, port_per_thread) + 1024; \
2720  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \
2721  continue; \
2722  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \
2723  a->busy_##n##_ports_per_thread[thread_index]++; \
2724  a->busy_##n##_ports++; \
2725  k->addr = a->addr; \
2726  k->port = clib_host_to_net_u16(portnum); \
2727  return 0; \
2728  }
2729  break;
2731 #undef _
2732  default:
2733  nat_log_info ("unknown protocol");
2734  return 1;
2735  }
2736  }
2737 
2738  /* Totally out of translations to use... */
2739  snat_ipfix_logging_addresses_exhausted (thread_index, 0);
2740  return 1;
2741 }
2742 
2743 static int
2745  u32 fib_index,
2746  u32 thread_index,
2747  snat_session_key_t * k,
2748  u16 port_per_thread, u32 snat_thread_index)
2749 {
2750  snat_main_t *sm = &snat_main;
2751  snat_address_t *a = addresses;
2752  u16 m, ports, portnum, A, j;
2753  m = 16 - (sm->psid_offset + sm->psid_length);
2754  ports = (1 << (16 - sm->psid_length)) - (1 << m);
2755 
2756  if (!vec_len (addresses))
2757  goto exhausted;
2758 
2759  switch (k->protocol)
2760  {
2761 #define _(N, i, n, s) \
2762  case SNAT_PROTOCOL_##N: \
2763  if (a->busy_##n##_ports < ports) \
2764  { \
2765  while (1) \
2766  { \
2767  A = snat_random_port(1, pow2_mask(sm->psid_offset)); \
2768  j = snat_random_port(0, pow2_mask(m)); \
2769  portnum = A | (sm->psid << sm->psid_offset) | (j << (16 - m)); \
2770  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \
2771  continue; \
2772  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \
2773  a->busy_##n##_ports++; \
2774  k->addr = a->addr; \
2775  k->port = clib_host_to_net_u16 (portnum); \
2776  return 0; \
2777  } \
2778  } \
2779  break;
2781 #undef _
2782  default:
2783  nat_log_info ("unknown protocol");
2784  return 1;
2785  }
2786 
2787 exhausted:
2788  /* Totally out of translations to use... */
2789  snat_ipfix_logging_addresses_exhausted (thread_index, 0);
2790  return 1;
2791 }
2792 
2793 static int
2795  u32 fib_index,
2796  u32 thread_index,
2797  snat_session_key_t * k,
2798  u16 port_per_thread, u32 snat_thread_index)
2799 {
2800  snat_main_t *sm = &snat_main;
2801  snat_address_t *a = addresses;
2802  u16 portnum, ports;
2803 
2804  ports = sm->end_port - sm->start_port + 1;
2805 
2806  if (!vec_len (addresses))
2807  goto exhausted;
2808 
2809  switch (k->protocol)
2810  {
2811 #define _(N, i, n, s) \
2812  case SNAT_PROTOCOL_##N: \
2813  if (a->busy_##n##_ports < ports) \
2814  { \
2815  while (1) \
2816  { \
2817  portnum = snat_random_port(sm->start_port, sm->end_port); \
2818  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \
2819  continue; \
2820  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \
2821  a->busy_##n##_ports++; \
2822  k->addr = a->addr; \
2823  k->port = clib_host_to_net_u16 (portnum); \
2824  return 0; \
2825  } \
2826  } \
2827  break;
2829 #undef _
2830  default:
2831  nat_log_info ("unknown protocol");
2832  return 1;
2833  }
2834 
2835 exhausted:
2836  /* Totally out of translations to use... */
2837  snat_ipfix_logging_addresses_exhausted (thread_index, 0);
2838  return 1;
2839 }
2840 
2841 void
2843 {
2844  dpo_id_t dpo_v4 = DPO_INVALID;
2845  fib_prefix_t pfx = {
2847  .fp_len = 32,
2848  .fp_addr.ip4.as_u32 = addr.as_u32,
2849  };
2850 
2851  if (is_add)
2852  {
2853  nat_dpo_create (DPO_PROTO_IP4, 0, &dpo_v4);
2855  FIB_ENTRY_FLAG_EXCLUSIVE, &dpo_v4);
2856  dpo_reset (&dpo_v4);
2857  }
2858  else
2859  {
2861  }
2862 }
2863 
2864 u8 *
2865 format_session_kvp (u8 * s, va_list * args)
2866 {
2867  clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
2869 
2870  k.as_u64 = v->key;
2871 
2872  s = format (s, "%U session-index %llu", format_snat_key, &k, v->value);
2873 
2874  return s;
2875 }
2876 
2877 u8 *
2878 format_static_mapping_kvp (u8 * s, va_list * args)
2879 {
2880  clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
2882 
2883  k.as_u64 = v->key;
2884 
2885  s = format (s, "%U static-mapping-index %llu",
2887 
2888  return s;
2889 }
2890 
2891 u8 *
2892 format_user_kvp (u8 * s, va_list * args)
2893 {
2894  clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
2895  snat_user_key_t k;
2896 
2897  k.as_u64 = v->key;
2898 
2899  s = format (s, "%U fib %d user-index %llu", format_ip4_address, &k.addr,
2900  k.fib_index, v->value);
2901 
2902  return s;
2903 }
2904 
2905 u8 *
2906 format_ed_session_kvp (u8 * s, va_list * args)
2907 {
2908  clib_bihash_kv_16_8_t *v = va_arg (*args, clib_bihash_kv_16_8_t *);
2909  nat_ed_ses_key_t k;
2910 
2911  k.as_u64[0] = v->key[0];
2912  k.as_u64[1] = v->key[1];
2913 
2914  s =
2915  format (s, "local %U:%d remote %U:%d proto %U fib %d session-index %llu",
2916  format_ip4_address, &k.l_addr, clib_net_to_host_u16 (k.l_port),
2917  format_ip4_address, &k.r_addr, clib_net_to_host_u16 (k.r_port),
2919 
2920  return s;
2921 }
2922 
2923 static u32
2925 {
2926  snat_main_t *sm = &snat_main;
2927  u32 next_worker_index = 0;
2928  u32 hash;
2929 
2930  next_worker_index = sm->first_worker_index;
2931  hash = ip0->src_address.as_u32 + (ip0->src_address.as_u32 >> 8) +
2932  (ip0->src_address.as_u32 >> 16) + (ip0->src_address.as_u32 >> 24);
2933 
2934  if (PREDICT_TRUE (is_pow2 (_vec_len (sm->workers))))
2935  next_worker_index += sm->workers[hash & (_vec_len (sm->workers) - 1)];
2936  else
2937  next_worker_index += sm->workers[hash % _vec_len (sm->workers)];
2938 
2939  return next_worker_index;
2940 }
2941 
2942 static u32
2944 {
2945  snat_main_t *sm = &snat_main;
2946  udp_header_t *udp;
2947  u16 port;
2948  snat_session_key_t m_key;
2949  clib_bihash_kv_8_8_t kv, value;
2951  u32 proto;
2952  u32 next_worker_index = 0;
2953 
2954  /* first try static mappings without port */
2956  {
2957  m_key.addr = ip0->dst_address;
2958  m_key.port = 0;
2959  m_key.protocol = 0;
2960  m_key.fib_index = rx_fib_index0;
2961  kv.key = m_key.as_u64;
2962  if (!clib_bihash_search_8_8
2963  (&sm->static_mapping_by_external, &kv, &value))
2964  {
2965  m = pool_elt_at_index (sm->static_mappings, value.value);
2966  return m->workers[0];
2967  }
2968  }
2969 
2970  proto = ip_proto_to_snat_proto (ip0->protocol);
2971  udp = ip4_next_header (ip0);
2972  port = udp->dst_port;
2973 
2974  if (PREDICT_FALSE (ip4_is_fragment (ip0)))
2975  {
2977  return vlib_get_thread_index ();
2978 
2979  nat_reass_ip4_t *reass;
2980  reass = nat_ip4_reass_find (ip0->src_address, ip0->dst_address,
2981  ip0->fragment_id, ip0->protocol);
2982 
2983  if (reass && (reass->thread_index != (u32) ~ 0))
2984  return reass->thread_index;
2985 
2986  if (ip4_is_first_fragment (ip0))
2987  {
2988  reass =
2990  ip0->fragment_id, ip0->protocol);
2991  if (!reass)
2992  goto no_reass;
2993 
2995  {
2996  m_key.addr = ip0->dst_address;
2997  m_key.port = clib_net_to_host_u16 (port);
2998  m_key.protocol = proto;
2999  m_key.fib_index = rx_fib_index0;
3000  kv.key = m_key.as_u64;
3001  if (!clib_bihash_search_8_8
3002  (&sm->static_mapping_by_external, &kv, &value))
3003  {
3004  m = pool_elt_at_index (sm->static_mappings, value.value);
3005  reass->thread_index = m->workers[0];
3006  return reass->thread_index;
3007  }
3008  }
3009  reass->thread_index = sm->first_worker_index;
3010  reass->thread_index +=
3011  sm->workers[(clib_net_to_host_u16 (port) - 1024) /
3012  sm->port_per_thread];
3013  return reass->thread_index;
3014  }
3015  else
3016  return vlib_get_thread_index ();
3017  }
3018 
3019 no_reass:
3020  /* unknown protocol */
3021  if (PREDICT_FALSE (proto == ~0))
3022  {
3023  /* use current thread */
3024  return vlib_get_thread_index ();
3025  }
3026 
3027  if (PREDICT_FALSE (ip0->protocol == IP_PROTOCOL_ICMP))
3028  {
3029  icmp46_header_t *icmp = (icmp46_header_t *) udp;
3030  icmp_echo_header_t *echo = (icmp_echo_header_t *) (icmp + 1);
3031  if (!icmp_is_error_message (icmp))
3032  port = echo->identifier;
3033  else
3034  {
3035  ip4_header_t *inner_ip = (ip4_header_t *) (echo + 1);
3036  proto = ip_proto_to_snat_proto (inner_ip->protocol);
3037  void *l4_header = ip4_next_header (inner_ip);
3038  switch (proto)
3039  {
3040  case SNAT_PROTOCOL_ICMP:
3041  icmp = (icmp46_header_t *) l4_header;
3042  echo = (icmp_echo_header_t *) (icmp + 1);
3043  port = echo->identifier;
3044  break;
3045  case SNAT_PROTOCOL_UDP:
3046  case SNAT_PROTOCOL_TCP:
3047  port = ((tcp_udp_header_t *) l4_header)->src_port;
3048  break;
3049  default:
3050  return vlib_get_thread_index ();
3051  }
3052  }
3053  }
3054 
3055  /* try static mappings with port */
3056  if (PREDICT_FALSE (pool_elts (sm->static_mappings)))
3057  {
3058  m_key.addr = ip0->dst_address;
3059  m_key.port = clib_net_to_host_u16 (port);
3060  m_key.protocol = proto;
3061  m_key.fib_index = rx_fib_index0;
3062  kv.key = m_key.as_u64;
3063  if (!clib_bihash_search_8_8
3064  (&sm->static_mapping_by_external, &kv, &value))
3065  {
3066  m = pool_elt_at_index (sm->static_mappings, value.value);
3067  return m->workers[0];
3068  }
3069  }
3070 
3071  /* worker by outside port */
3072  next_worker_index = sm->first_worker_index;
3073  next_worker_index +=
3074  sm->workers[(clib_net_to_host_u16 (port) - 1024) / sm->port_per_thread];
3075  return next_worker_index;
3076 }
3077 
3078 static u32
3080 {
3081  snat_main_t *sm = &snat_main;
3082  clib_bihash_kv_8_8_t kv, value;
3083  u32 proto, next_worker_index = 0;
3084  udp_header_t *udp;
3085  u16 port;
3087  u32 hash;
3088 
3089  /* first try static mappings without port */
3091  {
3092  make_sm_kv (&kv, &ip->dst_address, 0, rx_fib_index, 0);
3093  if (!clib_bihash_search_8_8
3094  (&sm->static_mapping_by_external, &kv, &value))
3095  {
3096  m = pool_elt_at_index (sm->static_mappings, value.value);
3097  return m->workers[0];
3098  }
3099  }
3100 
3101  proto = ip_proto_to_snat_proto (ip->protocol);
3102 
3103  /* unknown protocol */
3104  if (PREDICT_FALSE (proto == ~0))
3105  {
3106  /* use current thread */
3107  return vlib_get_thread_index ();
3108  }
3109 
3110  udp = ip4_next_header (ip);
3111  port = udp->dst_port;
3112 
3113  if (PREDICT_FALSE (ip->protocol == IP_PROTOCOL_ICMP))
3114  {
3115  icmp46_header_t *icmp = (icmp46_header_t *) udp;
3116  icmp_echo_header_t *echo = (icmp_echo_header_t *) (icmp + 1);
3117  if (!icmp_is_error_message (icmp))
3118  port = echo->identifier;
3119  else
3120  {
3121  ip4_header_t *inner_ip = (ip4_header_t *) (echo + 1);
3122  proto = ip_proto_to_snat_proto (inner_ip->protocol);
3123  void *l4_header = ip4_next_header (inner_ip);
3124  switch (proto)
3125  {
3126  case SNAT_PROTOCOL_ICMP:
3127  icmp = (icmp46_header_t *) l4_header;
3128  echo = (icmp_echo_header_t *) (icmp + 1);
3129  port = echo->identifier;
3130  break;
3131  case SNAT_PROTOCOL_UDP:
3132  case SNAT_PROTOCOL_TCP:
3133  port = ((tcp_udp_header_t *) l4_header)->src_port;
3134  break;
3135  default:
3136  return vlib_get_thread_index ();
3137  }
3138  }
3139  }
3140 
3141  /* try static mappings with port */
3142  if (PREDICT_FALSE (pool_elts (sm->static_mappings)))
3143  {
3144  make_sm_kv (&kv, &ip->dst_address, proto, rx_fib_index,
3145  clib_net_to_host_u16 (port));
3146  if (!clib_bihash_search_8_8
3147  (&sm->static_mapping_by_external, &kv, &value))
3148  {
3149  m = pool_elt_at_index (sm->static_mappings, value.value);
3150  if (!is_lb_static_mapping (m))
3151  return m->workers[0];
3152 
3153  hash = ip->src_address.as_u32 + (ip->src_address.as_u32 >> 8) +
3154  (ip->src_address.as_u32 >> 16) + (ip->src_address.as_u32 >> 24);
3155 
3156  if (PREDICT_TRUE (is_pow2 (_vec_len (m->workers))))
3157  return m->workers[hash & (_vec_len (m->workers) - 1)];
3158  else
3159  return m->workers[hash % _vec_len (m->workers)];
3160  }
3161  }
3162 
3163  /* worker by outside port */
3164  next_worker_index = sm->first_worker_index;
3165  next_worker_index +=
3166  sm->workers[(clib_net_to_host_u16 (port) - 1024) / sm->port_per_thread];
3167 
3168  return next_worker_index;
3169 }
3170 
3171 void
3172 nat_ha_sadd_cb (ip4_address_t * in_addr, u16 in_port,
3173  ip4_address_t * out_addr, u16 out_port,
3174  ip4_address_t * eh_addr, u16 eh_port,
3175  ip4_address_t * ehn_addr, u16 ehn_port, u8 proto,
3176  u32 fib_index, u16 flags, u32 thread_index)
3177 {
3178  snat_main_t *sm = &snat_main;
3180  snat_user_t *u;
3181  snat_session_t *s;
3183  f64 now = vlib_time_now (sm->vlib_main);
3184  nat_outside_fib_t *outside_fib;
3187  fib_prefix_t pfx = {
3189  .fp_len = 32,
3190  .fp_addr = {
3191  .ip4.as_u32 = eh_addr->as_u32,
3192  },
3193  };
3194 
3195  tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
3196 
3197  key.addr.as_u32 = out_addr->as_u32;
3198  key.port = out_port;
3199  key.protocol = proto;
3200 
3201  if (!(flags & SNAT_SESSION_FLAG_STATIC_MAPPING))
3202  {
3204  (sm->addresses, thread_index, &key))
3205  return;
3206  }
3207 
3208  u = nat_user_get_or_create (sm, in_addr, fib_index, thread_index);
3209  if (!u)
3210  return;
3211 
3212  s = nat_session_alloc_or_recycle (sm, u, thread_index, now);
3213  if (!s)
3214  return;
3215 
3216  s->last_heard = now;
3217  s->flags = flags;
3218  s->ext_host_addr.as_u32 = eh_addr->as_u32;
3219  s->ext_host_port = eh_port;
3221  switch (vec_len (sm->outside_fibs))
3222  {
3223  case 0:
3224  key.fib_index = sm->outside_fib_index;
3225  break;
3226  case 1:
3227  key.fib_index = sm->outside_fibs[0].fib_index;
3228  break;
3229  default:
3230  /* *INDENT-OFF* */
3231  vec_foreach (outside_fib, sm->outside_fibs)
3232  {
3233  fei = fib_table_lookup (outside_fib->fib_index, &pfx);
3234  if (FIB_NODE_INDEX_INVALID != fei)
3235  {
3236  if (fib_entry_get_resolving_interface (fei) != ~0)
3237  {
3238  key.fib_index = outside_fib->fib_index;
3239  break;
3240  }
3241  }
3242  }
3243  /* *INDENT-ON* */
3244  break;
3245  }
3246  s->out2in = key;
3247  kv.key = key.as_u64;
3248  kv.value = s - tsm->sessions;
3249  if (clib_bihash_add_del_8_8 (&tsm->out2in, &kv, 1))
3250  nat_log_warn ("out2in key add failed");
3251 
3252  key.addr.as_u32 = in_addr->as_u32;
3253  key.port = in_port;
3254  key.fib_index = fib_index;
3255  s->in2out = key;
3256  kv.key = key.as_u64;
3257  if (clib_bihash_add_del_8_8 (&tsm->in2out, &kv, 1))
3258  nat_log_warn ("in2out key add failed");
3259 }
3260 
3261 void
3262 nat_ha_sdel_cb (ip4_address_t * out_addr, u16 out_port,
3263  ip4_address_t * eh_addr, u16 eh_port, u8 proto, u32 fib_index,
3264  u32 ti)
3265 {
3266  snat_main_t *sm = &snat_main;
3268  clib_bihash_kv_8_8_t kv, value;
3269  u32 thread_index;
3270  snat_session_t *s;
3272 
3273  if (sm->num_workers > 1)
3274  thread_index =
3275  sm->first_worker_index +
3276  (sm->workers[(clib_net_to_host_u16 (out_port) -
3277  1024) / sm->port_per_thread]);
3278  else
3279  thread_index = sm->num_workers;
3280  tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
3281 
3282  key.addr.as_u32 = out_addr->as_u32;
3283  key.port = out_port;
3284  key.protocol = proto;
3285  key.fib_index = fib_index;
3286  kv.key = key.as_u64;
3287  if (clib_bihash_search_8_8 (&tsm->out2in, &kv, &value))
3288  return;
3289 
3290  s = pool_elt_at_index (tsm->sessions, value.value);
3291  nat_free_session_data (sm, s, thread_index, 1);
3292  nat44_delete_session (sm, s, thread_index);
3293 }
3294 
3295 void
3296 nat_ha_sref_cb (ip4_address_t * out_addr, u16 out_port,
3297  ip4_address_t * eh_addr, u16 eh_port, u8 proto, u32 fib_index,
3298  u32 total_pkts, u64 total_bytes, u32 thread_index)
3299 {
3300  snat_main_t *sm = &snat_main;
3302  clib_bihash_kv_8_8_t kv, value;
3303  snat_session_t *s;
3305 
3306  tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
3307 
3308  key.addr.as_u32 = out_addr->as_u32;
3309  key.port = out_port;
3310  key.protocol = proto;
3311  key.fib_index = fib_index;
3312  kv.key = key.as_u64;
3313  if (clib_bihash_search_8_8 (&tsm->out2in, &kv, &value))
3314  return;
3315 
3316  s = pool_elt_at_index (tsm->sessions, value.value);
3317  s->total_pkts = total_pkts;
3318  s->total_bytes = total_bytes;
3319 }
3320 
3321 void
3323  ip4_address_t * out_addr, u16 out_port,
3324  ip4_address_t * eh_addr, u16 eh_port,
3325  ip4_address_t * ehn_addr, u16 ehn_port, u8 proto,
3326  u32 fib_index, u16 flags, u32 thread_index)
3327 {
3328  snat_main_t *sm = &snat_main;
3330  snat_user_t *u;
3331  snat_session_t *s;
3333  f64 now = vlib_time_now (sm->vlib_main);
3334  nat_outside_fib_t *outside_fib;
3337  fib_prefix_t pfx = {
3339  .fp_len = 32,
3340  .fp_addr = {
3341  .ip4.as_u32 = eh_addr->as_u32,
3342  },
3343  };
3344 
3345  tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
3346 
3347  key.addr.as_u32 = out_addr->as_u32;
3348  key.port = out_port;
3349  key.protocol = proto;
3350 
3351  if (!(flags & SNAT_SESSION_FLAG_STATIC_MAPPING))
3352  {
3354  (sm->addresses, thread_index, &key))
3355  return;
3356  }
3357 
3358  key.addr.as_u32 = ehn_addr->as_u32;
3359  key.port = ehn_port;
3360  if (flags & SNAT_SESSION_FLAG_TWICE_NAT)
3361  {
3363  (sm->twice_nat_addresses, thread_index, &key))
3364  return;
3365  }
3366 
3367  u = nat_user_get_or_create (sm, in_addr, fib_index, thread_index);
3368  if (!u)
3369  return;
3370 
3371  s = nat_ed_session_alloc (sm, u, thread_index, now);
3372  if (!s)
3373  return;
3374 
3375  s->last_heard = now;
3376  s->flags = flags;
3377  s->ext_host_nat_addr.as_u32 = s->ext_host_addr.as_u32 = eh_addr->as_u32;
3378  s->ext_host_nat_port = s->ext_host_port = eh_port;
3379  if (is_twice_nat_session (s))
3380  {
3381  s->ext_host_nat_addr.as_u32 = ehn_addr->as_u32;
3382  s->ext_host_nat_port = ehn_port;
3383  }
3385  switch (vec_len (sm->outside_fibs))
3386  {
3387  case 0:
3388  key.fib_index = sm->outside_fib_index;
3389  break;
3390  case 1:
3391  key.fib_index = sm->outside_fibs[0].fib_index;
3392  break;
3393  default:
3394  /* *INDENT-OFF* */
3395  vec_foreach (outside_fib, sm->outside_fibs)
3396  {
3397  fei = fib_table_lookup (outside_fib->fib_index, &pfx);
3398  if (FIB_NODE_INDEX_INVALID != fei)
3399  {
3400  if (fib_entry_get_resolving_interface (fei) != ~0)
3401  {
3402  key.fib_index = outside_fib->fib_index;
3403  break;
3404  }
3405  }
3406  }
3407  /* *INDENT-ON* */
3408  break;
3409  }
3410  key.addr.as_u32 = out_addr->as_u32;
3411  key.port = out_port;
3412  s->out2in = key;
3413  kv.value = s - tsm->sessions;
3414 
3415  key.addr.as_u32 = in_addr->as_u32;
3416  key.port = in_port;
3417  key.fib_index = fib_index;
3418  s->in2out = key;
3419 
3420  make_ed_kv (&kv, in_addr, &s->ext_host_nat_addr,
3421  snat_proto_to_ip_proto (proto), fib_index, in_port,
3422  s->ext_host_nat_port);
3423  if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &kv, 1))
3424  nat_log_warn ("in2out key add failed");
3425 
3426  make_ed_kv (&kv, out_addr, eh_addr, snat_proto_to_ip_proto (proto),
3427  s->out2in.fib_index, out_port, eh_port);
3428  if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &kv, 1))
3429  nat_log_warn ("out2in key add failed");
3430 }
3431 
3432 void
3433 nat_ha_sdel_ed_cb (ip4_address_t * out_addr, u16 out_port,
3434  ip4_address_t * eh_addr, u16 eh_port, u8 proto,
3435  u32 fib_index, u32 ti)
3436 {
3437  snat_main_t *sm = &snat_main;
3439  clib_bihash_kv_16_8_t kv, value;
3440  u32 thread_index;
3441  snat_session_t *s;
3443 
3444  if (sm->num_workers > 1)
3445  thread_index =
3446  sm->first_worker_index +
3447  (sm->workers[(clib_net_to_host_u16 (out_port) -
3448  1024) / sm->port_per_thread]);
3449  else
3450  thread_index = sm->num_workers;
3451  tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
3452 
3453  key.l_addr.as_u32 = out_addr->as_u32;
3454  key.l_port = out_port;
3455  key.r_addr.as_u32 = eh_addr->as_u32;
3456  key.r_port = eh_port;
3457  key.proto = proto;
3458  key.fib_index = fib_index;
3459  kv.key[0] = key.as_u64[0];
3460  kv.key[1] = key.as_u64[1];
3461  if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
3462  return;
3463 
3464  s = pool_elt_at_index (tsm->sessions, value.value);
3465  nat_free_session_data (sm, s, thread_index, 1);
3466  nat44_delete_session (sm, s, thread_index);
3467 }
3468 
3469 void
3470 nat_ha_sref_ed_cb (ip4_address_t * out_addr, u16 out_port,
3471  ip4_address_t * eh_addr, u16 eh_port, u8 proto,
3472  u32 fib_index, u32 total_pkts, u64 total_bytes,
3473  u32 thread_index)
3474 {
3475  snat_main_t *sm = &snat_main;
3477  clib_bihash_kv_16_8_t kv, value;
3478  snat_session_t *s;
3480 
3481  tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
3482 
3483  key.l_addr.as_u32 = out_addr->as_u32;
3484  key.l_port = out_port;
3485  key.r_addr.as_u32 = eh_addr->as_u32;
3486  key.r_port = eh_port;
3487  key.proto = proto;
3488  key.fib_index = fib_index;
3489  kv.key[0] = key.as_u64[0];
3490  kv.key[1] = key.as_u64[1];
3491  if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
3492  return;
3493 
3494  s = pool_elt_at_index (tsm->sessions, value.value);
3495  s->total_pkts = total_pkts;
3496  s->total_bytes = total_bytes;
3497 }
3498 
3499 static clib_error_t *
3501 {
3502  snat_main_t *sm = &snat_main;
3503  nat66_main_t *nm = &nat66_main;
3504  u32 translation_buckets = 1024;
3505  u32 translation_memory_size = 128 << 20;
3506  u32 user_buckets = 128;
3507  u32 user_memory_size = 64 << 20;
3508  u32 max_translations_per_user = 100;
3509  u32 outside_vrf_id = 0;
3510  u32 outside_ip6_vrf_id = 0;
3511  u32 inside_vrf_id = 0;
3512  u32 static_mapping_buckets = 1024;
3513  u32 static_mapping_memory_size = 64 << 20;
3514  u32 nat64_bib_buckets = 1024;
3515  u32 nat64_bib_memory_size = 128 << 20;
3516  u32 nat64_st_buckets = 2048;
3517  u32 nat64_st_memory_size = 256 << 20;
3518  u8 static_mapping_only = 0;
3519  u8 static_mapping_connection_tracking = 0;
3521  dslite_main_t *dm = &dslite_main;
3522 
3523  sm->deterministic = 0;
3524  sm->out2in_dpo = 0;
3525  sm->endpoint_dependent = 0;
3526 
3527  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3528  {
3529  if (unformat
3530  (input, "translation hash buckets %d", &translation_buckets))
3531  ;
3532  else if (unformat (input, "translation hash memory %d",
3533  &translation_memory_size));
3534  else if (unformat (input, "user hash buckets %d", &user_buckets))
3535  ;
3536  else if (unformat (input, "user hash memory %d", &user_memory_size))
3537  ;
3538  else if (unformat (input, "max translations per user %d",
3539  &max_translations_per_user))
3540  ;
3541  else if (unformat (input, "outside VRF id %d", &outside_vrf_id))
3542  ;
3543  else if (unformat (input, "outside ip6 VRF id %d", &outside_ip6_vrf_id))
3544  ;
3545  else if (unformat (input, "inside VRF id %d", &inside_vrf_id))
3546  ;
3547  else if (unformat (input, "static mapping only"))
3548  {
3549  static_mapping_only = 1;
3550  if (unformat (input, "connection tracking"))
3551  static_mapping_connection_tracking = 1;
3552  }
3553  else if (unformat (input, "deterministic"))
3554  sm->deterministic = 1;
3555  else if (unformat (input, "nat64 bib hash buckets %d",
3556  &nat64_bib_buckets))
3557  ;
3558  else if (unformat (input, "nat64 bib hash memory %d",
3559  &nat64_bib_memory_size))
3560  ;
3561  else
3562  if (unformat (input, "nat64 st hash buckets %d", &nat64_st_buckets))
3563  ;
3564  else if (unformat (input, "nat64 st hash memory %d",
3565  &nat64_st_memory_size))
3566  ;
3567  else if (unformat (input, "out2in dpo"))
3568  sm->out2in_dpo = 1;
3569  else if (unformat (input, "dslite ce"))
3570  dslite_set_ce (dm, 1);
3571  else if (unformat (input, "endpoint-dependent"))
3572  sm->endpoint_dependent = 1;
3573  else
3574  return clib_error_return (0, "unknown input '%U'",
3575  format_unformat_error, input);
3576  }
3577 
3578  if (sm->deterministic && sm->endpoint_dependent)
3579  return clib_error_return (0,
3580  "deterministic and endpoint-dependent modes are mutually exclusive");
3581 
3582  if (static_mapping_only && (sm->deterministic || sm->endpoint_dependent))
3583  return clib_error_return (0,
3584  "static mapping only mode available only for simple nat");
3585 
3586  if (sm->out2in_dpo && (sm->deterministic || sm->endpoint_dependent))
3587  return clib_error_return (0,
3588  "out2in dpo mode available only for simple nat");
3589 
3590  /* for show commands, etc. */
3591  sm->translation_buckets = translation_buckets;
3592  sm->translation_memory_size = translation_memory_size;
3593  /* do not exceed load factor 10 */
3594  sm->max_translations = 10 * translation_buckets;
3595  sm->user_buckets = user_buckets;
3596  sm->user_memory_size = user_memory_size;
3597  sm->max_translations_per_user = max_translations_per_user;
3598  sm->outside_vrf_id = outside_vrf_id;
3600  outside_vrf_id,
3602  nm->outside_vrf_id = outside_ip6_vrf_id;
3604  outside_ip6_vrf_id,
3606  sm->inside_vrf_id = inside_vrf_id;
3608  inside_vrf_id,
3610  sm->static_mapping_only = static_mapping_only;
3611  sm->static_mapping_connection_tracking = static_mapping_connection_tracking;
3612 
3613  nat64_set_hash (nat64_bib_buckets, nat64_bib_memory_size, nat64_st_buckets,
3614  nat64_st_memory_size);
3615 
3616  if (sm->deterministic)
3617  {
3619  sm->in2out_output_node_index = ~0;
3623  }
3624  else
3625  {
3626  if (sm->endpoint_dependent)
3627  {
3635  nat_affinity_init (vm);
3638  }
3639  else
3640  {
3643  sm->in2out_node_index = snat_in2out_node.index;
3645  sm->out2in_node_index = snat_out2in_node.index;
3649  }
3650  if (!static_mapping_only ||
3651  (static_mapping_only && static_mapping_connection_tracking))
3652  {
3653  /* *INDENT-OFF* */
3654  vec_foreach (tsm, sm->per_thread_data)
3655  {
3656  if (sm->endpoint_dependent)
3657  {
3658  clib_bihash_init_16_8 (&tsm->in2out_ed, "in2out-ed",
3659  translation_buckets,
3660  translation_memory_size);
3661  clib_bihash_set_kvp_format_fn_16_8 (&tsm->in2out_ed,
3663 
3664  clib_bihash_init_16_8 (&tsm->out2in_ed, "out2in-ed",
3665  translation_buckets,
3666  translation_memory_size);
3667  clib_bihash_set_kvp_format_fn_16_8 (&tsm->out2in_ed,
3669  }
3670  else
3671  {
3672  clib_bihash_init_8_8 (&tsm->in2out, "in2out",
3673  translation_buckets,
3674  translation_memory_size);
3675  clib_bihash_set_kvp_format_fn_8_8 (&tsm->in2out,
3677 
3678  clib_bihash_init_8_8 (&tsm->out2in, "out2in",
3679  translation_buckets,
3680  translation_memory_size);
3681  clib_bihash_set_kvp_format_fn_8_8 (&tsm->out2in,
3683  }
3684 
3685  clib_bihash_init_8_8 (&tsm->user_hash, "users", user_buckets,
3686  user_memory_size);
3687  clib_bihash_set_kvp_format_fn_8_8 (&tsm->user_hash,
3688  format_user_kvp);
3689  }
3690  /* *INDENT-ON* */
3691 
3692  }
3693  else
3694  {
3697  }
3698  clib_bihash_init_8_8 (&sm->static_mapping_by_local,
3699  "static_mapping_by_local", static_mapping_buckets,
3700  static_mapping_memory_size);
3701  clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_local,
3703 
3704  clib_bihash_init_8_8 (&sm->static_mapping_by_external,
3705  "static_mapping_by_external",
3706  static_mapping_buckets,
3707  static_mapping_memory_size);
3708  clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_external,
3710  }
3711 
3712  return 0;
3713 }
3714 
3716 
3717 static void
3719  uword opaque,
3720  u32 sw_if_index,
3723  u32 if_address_index, u32 is_delete)
3724 {
3725  snat_main_t *sm = &snat_main;
3728  snat_session_key_t m_key;
3729  clib_bihash_kv_8_8_t kv, value;
3730  int i, rv;
3731  ip4_address_t l_addr;
3732 
3733  for (i = 0; i < vec_len (sm->to_resolve); i++)
3734  {
3735  rp = sm->to_resolve + i;
3736  if (rp->addr_only == 0)
3737  continue;
3738  if (rp->sw_if_index == sw_if_index)
3739  goto match;
3740  }
3741 
3742  return;
3743 
3744 match:
3745  m_key.addr.as_u32 = address->as_u32;
3746  m_key.port = rp->addr_only ? 0 : rp->e_port;
3747  m_key.protocol = rp->addr_only ? 0 : rp->proto;
3748  m_key.fib_index = sm->outside_fib_index;
3749  kv.key = m_key.as_u64;
3750  if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
3751  m = 0;
3752  else
3753  m = pool_elt_at_index (sm->static_mappings, value.value);
3754 
3755  if (!is_delete)
3756  {
3757  /* Don't trip over lease renewal, static config */
3758  if (m)
3759  return;
3760  }
3761  else
3762  {
3763  if (!m)
3764  return;
3765  }
3766 
3767  /* Indetity mapping? */
3768  if (rp->l_addr.as_u32 == 0)
3769  l_addr.as_u32 = address[0].as_u32;
3770  else
3771  l_addr.as_u32 = rp->l_addr.as_u32;
3772  /* Add the static mapping */
3773  rv = snat_add_static_mapping (l_addr,
3774  address[0],
3775  rp->l_port,
3776  rp->e_port,
3777  rp->vrf_id,
3778  rp->addr_only, ~0 /* sw_if_index */ ,
3779  rp->proto, !is_delete, rp->twice_nat,
3780  rp->out2in_only, rp->tag, rp->identity_nat);
3781  if (rv)
3782  nat_log_notice ("snat_add_static_mapping returned %d", rv);
3783 }
3784 
3785 static void
3787  uword opaque,
3788  u32 sw_if_index,
3791  u32 if_address_index, u32 is_delete)
3792 {
3793  snat_main_t *sm = &snat_main;
3795  ip4_address_t l_addr;
3796  int i, j;
3797  int rv;
3798  u8 twice_nat = 0;
3799  snat_address_t *addresses = sm->addresses;
3800 
3801  for (i = 0; i < vec_len (sm->auto_add_sw_if_indices); i++)
3802  {
3803  if (sw_if_index == sm->auto_add_sw_if_indices[i])
3804  goto match;
3805  }
3806 
3807  for (i = 0; i < vec_len (sm->auto_add_sw_if_indices_twice_nat); i++)
3808  {
3809  twice_nat = 1;
3810  addresses = sm->twice_nat_addresses;
3811  if (sw_if_index == sm->auto_add_sw_if_indices_twice_nat[i])
3812  goto match;
3813  }
3814 
3815  return;
3816 
3817 match:
3818  if (!is_delete)
3819  {
3820  /* Don't trip over lease renewal, static config */
3821  for (j = 0; j < vec_len (addresses); j++)
3822  if (addresses[j].addr.as_u32 == address->as_u32)
3823  return;
3824 
3825  (void) snat_add_address (sm, address, ~0, twice_nat);
3826  /* Scan static map resolution vector */
3827  for (j = 0; j < vec_len (sm->to_resolve); j++)
3828  {
3829  rp = sm->to_resolve + j;
3830  if (rp->addr_only)
3831  continue;
3832  /* On this interface? */
3833  if (rp->sw_if_index == sw_if_index)
3834  {
3835  /* Indetity mapping? */
3836  if (rp->l_addr.as_u32 == 0)
3837  l_addr.as_u32 = address[0].as_u32;
3838  else
3839  l_addr.as_u32 = rp->l_addr.as_u32;
3840  /* Add the static mapping */
3841  rv = snat_add_static_mapping (l_addr,
3842  address[0],
3843  rp->l_port,
3844  rp->e_port,
3845  rp->vrf_id,
3846  rp->addr_only,
3847  ~0 /* sw_if_index */ ,
3848  rp->proto,
3849  rp->is_add, rp->twice_nat,
3850  rp->out2in_only, rp->tag,
3851  rp->identity_nat);
3852  if (rv)
3853  nat_log_notice ("snat_add_static_mapping returned %d", rv);
3854  }
3855  }
3856  return;
3857  }
3858  else
3859  {
3860  (void) snat_del_address (sm, address[0], 1, twice_nat);
3861  return;
3862  }
3863 }
3864 
3865 
3866 int
3868  u8 twice_nat)
3869 {
3870  ip4_main_t *ip4_main = sm->ip4_main;
3871  ip4_address_t *first_int_addr;
3873  u32 *indices_to_delete = 0;
3874  int i, j;
3875  u32 *auto_add_sw_if_indices =
3876  twice_nat ? sm->
3877  auto_add_sw_if_indices_twice_nat : sm->auto_add_sw_if_indices;
3878 
3879  first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index, 0 /* just want the address */
3880  );
3881 
3882  for (i = 0; i < vec_len (auto_add_sw_if_indices); i++)
3883  {
3884  if (auto_add_sw_if_indices[i] == sw_if_index)
3885  {
3886  if (is_del)
3887  {
3888  /* if have address remove it */
3889  if (first_int_addr)
3890  (void) snat_del_address (sm, first_int_addr[0], 1, twice_nat);
3891  else
3892  {
3893  for (j = 0; j < vec_len (sm->to_resolve); j++)
3894  {
3895  rp = sm->to_resolve + j;
3896  if (rp->sw_if_index == sw_if_index)
3897  vec_add1 (indices_to_delete, j);
3898  }
3899  if (vec_len (indices_to_delete))
3900  {
3901  for (j = vec_len (indices_to_delete) - 1; j >= 0; j--)
3902  vec_del1 (sm->to_resolve, j);
3903  vec_free (indices_to_delete);
3904  }
3905  }
3906  if (twice_nat)
3908  else
3910  }
3911  else
3912  return VNET_API_ERROR_VALUE_EXIST;
3913 
3914  return 0;
3915  }
3916  }
3917 
3918  if (is_del)
3919  return VNET_API_ERROR_NO_SUCH_ENTRY;
3920 
3921  /* add to the auto-address list */
3922  if (twice_nat)
3923  vec_add1 (sm->auto_add_sw_if_indices_twice_nat, sw_if_index);
3924  else
3925  vec_add1 (sm->auto_add_sw_if_indices, sw_if_index);
3926 
3927  /* If the address is already bound - or static - add it now */
3928  if (first_int_addr)
3929  (void) snat_add_address (sm, first_int_addr, ~0, twice_nat);
3930 
3931  return 0;
3932 }
3933 
3934 int
3936  snat_protocol_t proto, u32 vrf_id, int is_in)
3937 {
3939  clib_bihash_kv_8_8_t kv, value;
3940  ip4_header_t ip;
3941  u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
3943  snat_session_t *s;
3944  clib_bihash_8_8_t *t;
3945 
3946  if (sm->endpoint_dependent)
3947  return VNET_API_ERROR_UNSUPPORTED;
3948 
3949  ip.dst_address.as_u32 = ip.src_address.as_u32 = addr->as_u32;
3950  if (sm->num_workers > 1)
3951  tsm =
3953  sm->worker_in2out_cb (&ip, fib_index));
3954  else
3955  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
3956 
3957  key.addr.as_u32 = addr->as_u32;
3958  key.port = clib_host_to_net_u16 (port);
3959  key.protocol = proto;
3960  key.fib_index = fib_index;
3961  kv.key = key.as_u64;
3962  t = is_in ? &tsm->in2out : &tsm->out2in;
3963  if (!clib_bihash_search_8_8 (t, &kv, &value))
3964  {
3965  if (pool_is_free_index (tsm->sessions, value.value))
3966  return VNET_API_ERROR_UNSPECIFIED;
3967 
3968  s = pool_elt_at_index (tsm->sessions, value.value);
3969  nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
3970  nat44_delete_session (sm, s, tsm - sm->per_thread_data);
3971  return 0;
3972  }
3973 
3974  return VNET_API_ERROR_NO_SUCH_ENTRY;
3975 }
3976 
3977 int
3979  ip4_address_t * eh_addr, u16 eh_port, u8 proto,
3980  u32 vrf_id, int is_in)
3981 {
3982  ip4_header_t ip;
3983  clib_bihash_16_8_t *t;
3985  clib_bihash_kv_16_8_t kv, value;
3986  u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
3987  snat_session_t *s;
3989 
3990  if (!sm->endpoint_dependent)
3991  return VNET_API_ERROR_FEATURE_DISABLED;
3992 
3993  ip.dst_address.as_u32 = ip.src_address.as_u32 = addr->as_u32;
3994  if (sm->num_workers > 1)
3995  tsm =
3997  sm->worker_in2out_cb (&ip, fib_index));
3998  else
3999  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
4000 
4001  t = is_in ? &tsm->in2out_ed : &tsm->out2in_ed;
4002  key.l_addr.as_u32 = addr->as_u32;
4003  key.r_addr.as_u32 = eh_addr->as_u32;
4004  key.l_port = clib_host_to_net_u16 (port);
4005  key.r_port = clib_host_to_net_u16 (eh_port);
4006  key.proto = proto;
4007  key.fib_index = fib_index;
4008  kv.key[0] = key.as_u64[0];
4009  kv.key[1] = key.as_u64[1];
4010  if (clib_bihash_search_16_8 (t, &kv, &value))
4011  return VNET_API_ERROR_NO_SUCH_ENTRY;
4012 
4013  if (pool_is_free_index (tsm->sessions, value.value))
4014  return VNET_API_ERROR_UNSPECIFIED;
4015  s = pool_elt_at_index (tsm->sessions, value.value);
4016  nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
4017  nat44_delete_session (sm, s, tsm - sm->per_thread_data);
4018  return 0;
4019 }
4020 
4021 void
4022 nat_set_alloc_addr_and_port_mape (u16 psid, u16 psid_offset, u16 psid_length)
4023 {
4024  snat_main_t *sm = &snat_main;
4025 
4026  sm->addr_and_port_alloc_alg = NAT_ADDR_AND_PORT_ALLOC_ALG_MAPE;
4028  sm->psid = psid;
4029  sm->psid_offset = psid_offset;
4030  sm->psid_length = psid_length;
4031 }
4032 
4033 void
4035 {
4036  snat_main_t *sm = &snat_main;
4037 
4038  sm->addr_and_port_alloc_alg = NAT_ADDR_AND_PORT_ALLOC_ALG_RANGE;
4040  sm->start_port = start_port;
4041  sm->end_port = end_port;
4042 }
4043 
4044 void
4046 {
4047  snat_main_t *sm = &snat_main;
4048 
4049  sm->addr_and_port_alloc_alg = NAT_ADDR_AND_PORT_ALLOC_ALG_DEFAULT;
4051 }
4052 
4053 /*
4054  * fd.io coding-style-patch-verification: ON
4055  *
4056  * Local Variables:
4057  * eval: (c-set-style "gnu")
4058  * End:
4059  */
ip4_address_t external_addr
Definition: nat.h:333
u32 user_memory_size
Definition: nat.h:544
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:227
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:439
clib_error_t * snat_api_init(vlib_main_t *vm, snat_main_t *sm)
Definition: nat_api.c:3499
void dslite_set_ce(dslite_main_t *dm, u8 set)
Definition: dslite.c:94
u32 sw_if_index
Definition: ipsec_gre.api:37
u32 next
Definition: dlist.h:30
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:212
static void snat_update_outside_fib(u32 sw_if_index, u32 new_fib_index, u32 old_fib_index)
Definition: nat.c:2164
nat_outside_fib_t * outside_fibs
Definition: nat.h:479
void snat_ipfix_logging_max_entries_per_user(u32 thread_index, u32 limit, u32 src_ip)
Generate maximum entries per user exceeded event.
vmrglw vmrglh hi
format_function_t format_ip_protocol
Definition: format.h:45
#define nat_log_info(...)
Definition: nat.h:724
#define snat_is_session_static(s)
Check if SNAT session is created from static mapping.
Definition: nat.h:631
typedef address
Definition: ip_types.api:30
u32 sessions_per_user_list_head_index
Definition: nat.h:239
vlib_node_registration_t nat44_ed_in2out_output_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_output_node)
Definition: in2out_ed.c:1700
u32 flags
Definition: vhost_user.h:115
ip4_table_bind_function_t * function
Definition: ip4.h:83
int nat_affinity_create_and_lock(ip4_address_t client_addr, ip4_address_t service_addr, u8 proto, u16 service_port, u8 backend_index, u32 sticky_time, u32 affinity_per_service_list_head_index)
Create affinity record and take reference counting lock.
Definition: nat_affinity.c:191
int snat_del_address(snat_main_t *sm, ip4_address_t addr, u8 delete_sm, u8 twice_nat)
Delete external address from NAT44 pool.
Definition: nat.c:1618
u32 hairpin_dst_node_index
Definition: nat.h:521
void dslite_init(vlib_main_t *vm)
Definition: dslite.c:22
ip4_add_del_interface_address_callback_t * add_del_interface_address_callbacks
Functions to call when interface address changes.
Definition: ip4.h:130
u32 ed_hairpinning_node_index
Definition: nat.h:523
a
Definition: bitmap.h:538
static void clib_dlist_init(dlist_elt_t *pool, u32 index)
Definition: dlist.h:36
u32 icmp_timeout
Definition: nat.h:555
ip4_address_t src_address
Definition: ip4_packet.h:170
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
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, int twice_nat, int out2in_only, int identity_nat)
Definition: nat.c:626
static u32 nat44_session_get_timeout(snat_main_t *sm, snat_session_t *s)
Definition: nat_inlines.h:274
u16 start_port
Definition: nat.h:475
u32 fq_in2out_output_index
Definition: nat.h:496
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...
u32 ed_out2in_node_index
Definition: nat.h:514
clib_error_t * nat_reass_init(vlib_main_t *vm)
Initialize NAT virtual fragmentation reassembly.
Definition: nat_reass.c:661
static int nat_alloc_addr_and_port_range(snat_address_t *addresses, u32 fib_index, u32 thread_index, snat_session_key_t *k, u16 port_per_thread, u32 snat_thread_index)
Definition: nat.c:2794
#define SNAT_TCP_ESTABLISHED_TIMEOUT
Definition: nat.h:36
#define PREDICT_TRUE(x)
Definition: clib.h:112
u32 nsessions
Definition: nat.h:240
#define is_ed_session(s)
Check if NAT session is endpoint dependent.
Definition: nat.h:661
static_always_inline u8 icmp_is_error_message(icmp46_header_t *icmp)
Definition: nat_inlines.h:54
unsigned long u64
Definition: types.h:89
ip4_address_t addr
Definition: nat.h:297
#define NULL
Definition: clib.h:58
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
u32 index
Definition: node.h:279
snat_protocol_t proto
Definition: nat.h:344
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:314
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:255
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:956
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:338
u16 port_per_thread
Definition: nat.h:445
u32 vlib_frame_queue_main_init(u32 node_index, u32 frame_queue_nelts)
Definition: threads.c:1762
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
void nat_free_session_data(snat_main_t *sm, snat_session_t *s, u32 thread_index, u8 is_ha)
Free NAT44 session data (lookup keys, external addrres port)
Definition: nat.c:179
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
u32 ed_in2out_reass_node_index
Definition: nat.h:510
#define nat_log_warn(...)
Definition: nat.h:720
u32 nstaticsessions
Definition: nat.h:241
void nat_ha_sref_ed_cb(ip4_address_t *out_addr, u16 out_port, ip4_address_t *eh_addr, u16 eh_port, u8 proto, u32 fib_index, u32 total_pkts, u64 total_bytes, u32 thread_index)
Definition: nat.c:3470
u32 ed_out2in_slowpath_node_index
Definition: nat.h:515
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:325
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:560
#define NAT_INTERFACE_FLAG_IS_OUTSIDE
Definition: nat.h:182
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:2892
void nat_syslog_nat44_sdel(u32 ssubix, u32 sfibix, ip4_address_t *isaddr, u16 isport, ip4_address_t *idaddr, u16 idport, ip4_address_t *xsaddr, u16 xsport, ip4_address_t *xdaddr, u16 xdport, snat_protocol_t proto, u8 is_twicenat)
Definition: nat_syslog.c:211
ip_lookup_main_t lookup_main
Definition: ip4.h:98
vlib_node_registration_t snat_det_out2in_node
(constructor) VLIB_REGISTER_NODE (snat_det_out2in_node)
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:293
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)
Delete NAT44 endpoint-dependent session.
Definition: nat.c:3978
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
u32 fib_index
Definition: nat.h:238
format_function_t format_snat_key
Definition: nat.h:619
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:505
nat_alloc_out_addr_and_port_function_t * alloc_addr_and_port
Definition: nat.h:467
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:3786
u32 num_snat_thread
Definition: nat.h:446
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:236
dlist_elt_t * list_pool
Definition: nat.h:402
#define snat_is_unk_proto_session(s)
Check if SNAT session for unknown protocol.
Definition: nat.h:637
vhost_vring_addr_t addr
Definition: vhost_user.h:121
u32 proto
Definition: nat.h:69
static int nat_alloc_addr_and_port_mape(snat_address_t *addresses, u32 fib_index, u32 thread_index, snat_session_key_t *k, u16 port_per_thread, u32 snat_thread_index)
Definition: nat.c:2744
static int nat_alloc_addr_and_port_default(snat_address_t *addresses, u32 fib_index, u32 thread_index, snat_session_key_t *k, u16 port_per_thread, u32 snat_thread_index)
Definition: nat.c:2657
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:577
unsigned char u8
Definition: types.h:56
u8 deterministic
Definition: nat.h:537
int snat_interface_add_del(u32 sw_if_index, u8 is_inside, int is_del)
Enable/disable NAT44 feature on the interface.
Definition: nat.c:1732
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_ed.c:504
u16 l_port
Definition: nat.h:70
nat44_lb_addr_port_t * locals
Definition: nat.h:352
u32 user_buckets
Definition: nat.h:543
double f64
Definition: types.h:142
clib_bihash_8_8_t user_hash
Definition: nat.h:393
static int ip4_is_fragment(const ip4_header_t *i)
Definition: ip4_packet.h:213
int nat44_add_del_lb_static_mapping(ip4_address_t e_addr, u16 e_port, snat_protocol_t proto, nat44_lb_addr_port_t *locals, u8 is_add, twice_nat_type_t twice_nat, u8 out2in_only, u8 *tag, u32 affinity)
Add/delete static mapping with load-balancing (multiple backends)
Definition: nat.c:1159
snat_session_t * nat_session_alloc_or_recycle(snat_main_t *sm, snat_user_t *u, u32 thread_index, f64 now)
Allocate new NAT session or recycle last used.
Definition: nat.c:351
#define NAT_STATIC_MAPPING_FLAG_OUT2IN_ONLY
Definition: nat.h:186
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:545
clib_bihash_8_8_t in2out
Definition: nat.h:386
nat66_main_t nat66_main
Definition: nat66.c:23
u32 in2out_reass_node_index
Definition: nat.h:507
void nat_ha_sadd_cb(ip4_address_t *in_addr, u16 in_port, ip4_address_t *out_addr, u16 out_port, ip4_address_t *eh_addr, u16 eh_port, ip4_address_t *ehn_addr, u16 ehn_port, u8 proto, u32 fib_index, u16 flags, u32 thread_index)
Definition: nat.c:3172
u32 in2out_output_node_index
Definition: nat.h:503
u32 ed_in2out_node_index
Definition: nat.h:508
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:75
#define static_always_inline
Definition: clib.h:99
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:493
u16 r_port
Definition: nat.h:71
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:163
vlib_node_registration_t snat_out2in_node
(constructor) VLIB_REGISTER_NODE (snat_out2in_node)
Definition: out2in.c:1341
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:2878
ip4_address_t dst_address
Definition: ip4_packet.h:170
void nat_ha_sadd_ed_cb(ip4_address_t *in_addr, u16 in_port, ip4_address_t *out_addr, u16 out_port, ip4_address_t *eh_addr, u16 eh_port, ip4_address_t *ehn_addr, u16 ehn_port, u8 proto, u32 fib_index, u16 flags, u32 thread_index)
Definition: nat.c:3322
u32 det_in2out_node_index
Definition: nat.h:517
static u32 snat_get_worker_in2out_cb(ip4_header_t *ip0, u32 rx_fib_index0)
Definition: nat.c:2924
int snat_add_address(snat_main_t *sm, ip4_address_t *addr, u32 vrf_id, u8 twice_nat)
Add external address to NAT44 pool.
Definition: nat.c:533
u32 translation_buckets
Definition: nat.h:540
u8 * format_ed_session_kvp(u8 *s, va_list *args)
Definition: nat.c:2906
#define nat_log_err(...)
Definition: nat.h:718
lb_nat_type_t
Definition: nat.h:318
ip4_address_t addr
Definition: nat.h:237
A high priority source a plugin can use.
Definition: fib_entry.h:62
#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:203
#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:655
void snat_ipfix_logging_init(vlib_main_t *vm)
Initialize NAT plugin IPFIX logging.
ip4_main_t * ip4_main
Definition: nat.h:574
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:241
void snat_ipfix_logging_addresses_exhausted(u32 thread_index, u32 pool_id)
Generate NAT addresses exhausted event.
unsigned int u32
Definition: types.h:88
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:1064
void nat_ha_sdel_ed_cb(ip4_address_t *out_addr, u16 out_port, ip4_address_t *eh_addr, u16 eh_port, u8 proto, u32 fib_index, u32 ti)
Definition: nat.c:3433
ip4_address_t local_addr
Definition: nat.h:331
fib_node_index_t fib_table_lookup(u32 fib_index, const fib_prefix_t *prefix)
Perfom a longest prefix match in the non-forwarding table.
Definition: fib_table.c:66
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:3718
void nat_affinity_unlock(ip4_address_t client_addr, ip4_address_t service_addr, u8 proto, u16 service_port)
Release a reference counting lock for affinity.
Definition: nat_affinity.c:242
u64 as_u64[2]
Definition: nat.h:73
int snat_static_mapping_match(snat_main_t *sm, snat_session_key_t match, snat_session_key_t *mapping, u8 by_external, u8 *is_addr_only, twice_nat_type_t *twice_nat, lb_nat_type_t *lb, ip4_address_t *ext_host_addr, u8 *is_identity_nat)
Match NAT44 static mapping.
Definition: nat.c:2498
snat_protocol_t proto
Definition: nat.h:372
void snat_free_outside_address_and_port(snat_address_t *addresses, u32 thread_index, snat_session_key_t *k)
Free outside address and port pair.
Definition: nat.c:2424
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...
static void nat44_delete_session(snat_main_t *sm, snat_session_t *ses, u32 thread_index)
Definition: nat_inlines.h:169
char * name
The counter collection&#39;s name.
Definition: counter.h:64
twice_nat_type_t twice_nat
Definition: nat.h:339
VNET_FEATURE_INIT(ip4_snat_in2out, static)
u32 max_translations
Definition: nat.h:542
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:486
Definition: fib_entry.h:280
void nat66_init(vlib_main_t *vm)
Definition: nat66.c:43
vlib_node_registration_t nat44_ed_out2in_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_out2in_node)
Definition: out2in_ed.c:1568
int snat_alloc_outside_address_and_port(snat_address_t *addresses, u32 fib_index, u32 thread_index, snat_session_key_t *k, u16 port_per_thread, u32 snat_thread_index)
Alloc outside address and port.
Definition: nat.c:2643
u32 fib_index
Definition: nat.h:69
snat_user_t * nat_user_get_or_create(snat_main_t *sm, ip4_address_t *addr, u32 fib_index, u32 thread_index)
Find or create NAT user.
Definition: nat.c:304
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:514
u32 fib_index
Definition: nat.h:260
void nat_dpo_module_init(void)
Definition: nat_dpo.c:68
nat_addr_and_port_alloc_alg_t addr_and_port_alloc_alg
Definition: nat.h:469
clib_bihash_16_8_t out2in_ed
Definition: nat.h:389
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:33
void nat_ha_sdel_cb(ip4_address_t *out_addr, u16 out_port, ip4_address_t *eh_addr, u16 eh_port, u8 proto, u32 fib_index, u32 ti)
Definition: nat.c:3262
u8 address_length
Definition: ip_types.api:37
lo
void nat_ha_sref_cb(ip4_address_t *out_addr, u16 out_port, ip4_address_t *eh_addr, u16 eh_port, u8 proto, u32 fib_index, u32 total_pkts, u64 total_bytes, u32 thread_index)
Definition: nat.c:3296
u16 mss_clamping
Definition: nat.h:558
vlib_main_t * vlib_main
Definition: nat.h:572
static void clib_dlist_addtail(dlist_elt_t *pool, u32 head_index, u32 new_index)
Definition: dlist.h:43
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
u16 protocol
Definition: nat.h:54
u8 out2in_dpo
Definition: nat.h:538
snat_session_t * nat_ed_session_alloc(snat_main_t *sm, snat_user_t *u, u32 thread_index, f64 now)
Allocate NAT endpoint-dependent session.
Definition: nat.c:426
#define SNAT_UDP_TIMEOUT
Definition: nat.h:34
snat_static_mapping_t * static_mappings
Definition: nat.h:458
u32 inside_fib_index
Definition: nat.h:549
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:286
u32 udp_timeout
Definition: nat.h:552
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:375
u8 static_mapping_only
Definition: nat.h:535
#define NAT_FQ_NELTS
Definition: nat.h:40
#define PREDICT_FALSE(x)
Definition: clib.h:111
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:172
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:804
u32 hairpin_src_node_index
Definition: nat.h:522
clib_bihash_8_8_t static_mapping_by_external
Definition: nat.h:455
u32 in2out_slowpath_output_node_index
Definition: nat.h:506
u8 psid_offset
Definition: nat.h:471
static void vlib_set_simple_counter(vlib_simple_counter_main_t *cm, u32 thread_index, u32 index, u64 value)
Set a simple counter.
Definition: counter.h:94
void nat_set_alloc_addr_and_port_default(void)
Set address and port assignment algorithm to default/standard.
Definition: nat.c:4045
#define nat_log_notice(...)
Definition: nat.h:722
api_main_t * api_main
Definition: nat.h:576
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:1237
u8 psid_length
Definition: nat.h:472
u32 refcount
Definition: nat.h:261
vnet_main_t * vnet_main
Definition: nat.h:573
u32 inside_vrf_id
Definition: nat.h:548
Definition: nat.h:323
#define is_lb_session(s)
Check if NAT session is load-balancing.
Definition: nat.h:649
u32 fq_out2in_index
Definition: nat.h:497
u32 fib_entry_get_resolving_interface(fib_node_index_t entry_index)
Definition: fib_entry.c:1461
snat_interface_t * output_feature_interfaces
Definition: nat.h:462
snat_main_t snat_main
Definition: nat.c:39
u32 ed_hairpin_src_node_index
Definition: nat.h:525
#define pool_free(p)
Free a pool.
Definition: pool.h:407
void snat_ipfix_logging_nat44_ses_delete(u32 thread_index, u32 src_ip, u32 nat_src_ip, snat_protocol_t snat_proto, u16 src_port, u16 nat_src_port, u32 vrf_id)
Generate NAT44 session delete event.
vlib_node_registration_t snat_det_in2out_node
(constructor) VLIB_REGISTER_NODE (snat_det_in2out_node)
u64 value
the value
Definition: bihash_8_8.h:34
snat_user_t * users
Definition: nat.h:396
#define is_affinity_sessions(s)
Check if NAT session has affinity record.
Definition: nat.h:667
u32 random_seed
Definition: nat.h:492
u32 ed_out2in_reass_node_index
Definition: nat.h:516
#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:3079
static u8 snat_proto_to_ip_proto(snat_protocol_t snat_proto)
Definition: nat_inlines.h:42
#define NAT_STATIC_MAPPING_FLAG_IDENTITY_NAT
Definition: nat.h:187
u32 nat_affinity_get_per_service_list_head_index(void)
Get new affinity per service list head index.
Definition: nat_affinity.c:81
static void clib_dlist_addhead(dlist_elt_t *pool, u32 head_index, u32 new_index)
Definition: dlist.h:71
clib_bihash_8_8_t out2in
Definition: nat.h:385
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:212
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:312
u32 outside_vrf_id
Definition: nat.h:546
void nat44_add_del_address_dpo(ip4_address_t addr, u8 is_add)
Add/delete external address to FIB DPO (out2in DPO mode)
Definition: nat.c:2842
vlib_node_registration_t snat_in2out_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_node)
Definition: in2out.c:1576
ip4_address_t l_addr
Definition: nat.h:67
u8 static_mapping_connection_tracking
Definition: nat.h:536
snat_get_worker_function_t * worker_in2out_cb
Definition: nat.h:443
u16 end_port
Definition: nat.h:476
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
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:73
deterministic NAT definitions
int nat_affinity_find_and_lock(ip4_address_t client_addr, ip4_address_t service_addr, u8 proto, u16 service_port, u8 *backend_index)
Find service backend index for client-IP and take a reference counting lock.
Definition: nat_affinity.c:127
u32 ed_in2out_slowpath_node_index
Definition: nat.h:509
u32 error_node_index
Definition: nat.h:500
VLIB_PLUGIN_REGISTER()
int snat_interface_add_del_output_feature(u32 sw_if_index, u8 is_inside, int is_del)
Enable/disable NAT44 output feature on the interface (postrouting NAT)
Definition: nat.c:1981
u16 psid
Definition: nat.h:473
dslite_main_t dslite_main
Definition: dslite.c:19
u32 outside_fib_index
Definition: nat.h:547
static void snat_ip4_table_bind(ip4_main_t *im, uword opaque, u32 sw_if_index, u32 new_fib_index, u32 old_fib_index)
Definition: nat.c:2224
u8 * format_session_kvp(u8 *s, va_list *args)
Definition: nat.c:2865
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:30
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:283
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:31
ip4_address_t addr
Definition: nat.h:52
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
u32 ed_hairpin_dst_node_index
Definition: nat.h:524
static void make_ed_kv(clib_bihash_kv_16_8_t *kv, ip4_address_t *l_addr, ip4_address_t *r_addr, u8 proto, u32 fib_index, u16 l_port, u16 r_port)
Definition: nat_inlines.h:321
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:458
u32 tcp_transitory_timeout
Definition: nat.h:554
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, u8 identity_nat)
Add/delete NAT44 static mapping.
Definition: nat.c:669
ip4_address_t r_addr
Definition: nat.h:68
u32 * auto_add_sw_if_indices
Definition: nat.h:485
u32 in2out_fast_node_index
Definition: nat.h:504
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
void vlib_validate_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
validate a simple counter
Definition: counter.c:91
static_always_inline u16 snat_random_port(u16 min, u16 max)
Definition: nat.c:2635
#define ASSERT(truth)
#define NAT_INTERFACE_FLAG_IS_INSIDE
Definition: nat.h:181
#define is_addr_only_static_mapping(sm)
Check if NAT static mapping is address only (1:1NAT).
Definition: nat.h:691
u32 num_workers
Definition: nat.h:440
u32 first_worker_index
Definition: nat.h:441
#define is_identity_static_mapping(sm)
Check if NAT static mapping is identity NAT.
Definition: nat.h:703
u32 det_out2in_node_index
Definition: nat.h:518
snat_get_worker_function_t * worker_out2in_cb
Definition: nat.h:444
u8 is_add
Definition: ipsec_gre.api:36
ip4_address_t l_addr
Definition: nat.h:367
clib_error_t * nat_affinity_init(vlib_main_t *vm)
Initialize NAT client-IP based affinity.
Definition: nat_affinity.c:47
u32 in2out_slowpath_node_index
Definition: nat.h:505
snat_icmp_match_function_t * icmp_match_out2in_cb
Definition: nat.h:437
vlib_log_class_t log_class
Definition: nat.h:569
IPv4 main type.
Definition: ip4.h:96
#define SNAT_SESSION_FLAG_TWICE_NAT
Definition: nat.h:174
u64 as_u64
Definition: nat.h:102
void nat_set_alloc_addr_and_port_range(u16 start_port, u16 end_port)
Set address and port assignment algorithm for port range.
Definition: nat.c:4034
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:1123
ip4_address_t addr
Definition: nat.h:99
#define clib_bitmap_free(v)
Free a bitmap.
Definition: bitmap.h:92
u32 fq_in2out_index
Definition: nat.h:495
static void vlib_zero_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Clear a simple counter Clears the set of per-thread u16 counters, and the u64 counter.
Definition: counter.h:139
uword * thread_registrations_by_name
Definition: threads.h:288
u32 out2in_node_index
Definition: nat.h:511
ip4_address_t addr
Definition: nat.h:246
vlib_node_registration_t nat44_ed_in2out_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_node)
Definition: in2out_ed.c:1673
int nat44_del_session(snat_main_t *sm, ip4_address_t *addr, u16 port, snat_protocol_t proto, u32 vrf_id, int is_in)
Delete NAT44 session.
Definition: nat.c:3935
snat_address_t * twice_nat_addresses
Definition: nat.h:482
#define VNET_FEATURES(...)
Definition: feature.h:435
#define A(x)
Definition: main.c:1017
void nat_syslog_nat44_apmdel(u32 ssubix, u32 sfibix, ip4_address_t *isaddr, u16 isport, ip4_address_t *xsaddr, u16 xsport, snat_protocol_t proto)
Definition: nat_syslog.c:118
static clib_error_t * snat_init(vlib_main_t *vm)
Definition: nat.c:2255
void nat_ha_sdel(ip4_address_t *out_addr, u16 out_port, ip4_address_t *eh_addr, u16 eh_port, u8 proto, u32 fib_index, u32 thread_index)
Create session delete HA event.
Definition: nat_ha.c:707
static uword is_pow2(uword x)
Definition: clib.h:235
u32 value
Definition: dlist.h:32
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:455
ip4_table_bind_callback_t * table_bind_callbacks
Functions to call when interface to table biding changes.
Definition: ip4.h:133
clib_error_t * nat64_init(vlib_main_t *vm)
Initialize NAT64.
Definition: nat64.c:229
u32 out2in_reass_node_index
Definition: nat.h:513
NAT64 global declarations.
#define is_lb_static_mapping(sm)
Check if NAT static mapping is load-balancing.
Definition: nat.h:709
void increment_v4_address(ip4_address_t *a)
Increment IPv4 address.
Definition: nat.c:617
Definition: nat.h:321
char * stat_segment_name
Name in stat segment directory.
Definition: counter.h:65
vlib_simple_counter_main_t total_users
Definition: nat.h:562
static int ip4_is_first_fragment(const ip4_header_t *i)
Definition: ip4_packet.h:220
static u32 ip_proto_to_snat_proto(u8 ip_proto)
The NAT inline functions.
Definition: nat_inlines.h:27
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:31
format_function_t format_static_mapping_key
Definition: nat.h:620
static void user_session_increment(snat_main_t *sm, snat_user_t *u, u8 is_static)
Definition: nat_inlines.h:135
twice_nat_type_t
Definition: nat.h:308
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u32 hairpinning_node_index
Definition: nat.h:520
u32 outside_fib_index
Definition: nat66.h:63
#define is_out2in_only_static_mapping(sm)
Check if NAT static mapping match only out2in direction.
Definition: nat.h:697
Definition: fib_entry.h:276
u32 * workers
Definition: nat.h:442
u64 uword
Definition: types.h:112
snat_main_per_thread_data_t * per_thread_data
Definition: nat.h:449
snat_protocol_t
Definition: nat.h:133
void nat_affinity_flush_service(u32 affinity_per_service_list_head_index)
Flush all service affinity data.
Definition: nat_affinity.c:97
typedef key
Definition: ipsec.api:244
NAT syslog logging.
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:195
u32 affinity_per_service_list_head_index
Definition: nat.h:354
u32 fib_index
Definition: nat.h:100
snat_address_t * addresses
Definition: nat.h:465
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:35
int snat_add_interface_address(snat_main_t *sm, u32 sw_if_index, int is_del, u8 twice_nat)
Add/delete NAT44 pool address from specific interfce.
Definition: nat.c:3867
u32 out2in_fast_node_index
Definition: nat.h:512
#define hash_get_mem(h, key)
Definition: hash.h:269
u32 in2out_node_index
Definition: nat.h:502
#define SNAT_ICMP_TIMEOUT
Definition: nat.h:37
snat_static_map_resolve_t * to_resolve
Definition: nat.h:489
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
#define SNAT_SESSION_FLAG_STATIC_MAPPING
Definition: nat.h:171
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:905
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
u32 outside_vrf_id
Definition: nat66.h:62
u8 forwarding_enabled
Definition: nat.h:532
static u32 get_thread_idx_by_port(u16 e_port)
Definition: nat.c:655
u32 translation_memory_size
Definition: nat.h:541
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:1609
int snat_set_workers(uword *bitmap)
Set NAT plugin workers.
Definition: nat.c:2136
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_ed.c:600
#define is_twice_nat_session(s)
Check if NAT session is twice NAT.
Definition: nat.h:643
clib_bihash_16_8_t in2out_ed
Definition: nat.h:390
u8 endpoint_dependent
Definition: nat.h:539
static clib_error_t * snat_config(vlib_main_t *vm, unformat_input_t *input)
Definition: nat.c:3500
#define pool_foreach_index(i, v, body)
Iterate pool by index.
Definition: pool.h:538
NAT plugin virtual fragmentation reassembly.
void nat_set_alloc_addr_and_port_mape(u16 psid, u16 psid_offset, u16 psid_length)
Set address and port assignment algorithm for MAP-E CE.
Definition: nat.c:4022
NAT66 global declarations.
NAT plugin client-IP based session affinity for load-balancing.
vlib_simple_counter_main_t total_sessions
Definition: nat.h:563
#define SNAT_TCP_TRANSITORY_TIMEOUT
Definition: nat.h:35
ip_lookup_main_t * ip4_lookup_main
Definition: nat.h:575
api_main_t api_main
Definition: api_shared.c:35
#define NAT_STATIC_MAPPING_FLAG_LB
Definition: nat.h:188
static int is_snat_address_used_in_static_mapping(snat_main_t *sm, ip4_address_t addr)
Definition: nat.c:598
#define NAT_STATIC_MAPPING_FLAG_ADDR_ONLY
Definition: nat.h:185
snat_session_t * sessions
Definition: nat.h:399
A low (below routing) priority source a plugin can use.
Definition: fib_entry.h:82
snat_icmp_match_function_t * icmp_match_in2out_cb
Definition: nat.h:436
clib_bihash_8_8_t static_mapping_by_local
Definition: nat.h:452
static u32 snat_get_worker_out2in_cb(ip4_header_t *ip0, u32 rx_fib_index0)
Definition: nat.c:2943
int nat44_lb_static_mapping_add_del_local(ip4_address_t e_addr, u16 e_port, ip4_address_t l_addr, u16 l_port, snat_protocol_t proto, u32 vrf_id, u8 probability, u8 is_add)
Definition: nat.c:1435
u32 fib_index
Definition: nat.h:247
snat_interface_t * interfaces
Definition: nat.h:461
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
NAT active-passive HA.
void nat_ha_init(vlib_main_t *vm, nat_ha_sadd_cb_t sadd_cb, nat_ha_sdel_cb_t sdel_cb, nat_ha_sref_cb_t sref_cb)
Initialize NAT HA.
Definition: nat_ha.c:306
u16 fib_index
Definition: nat.h:54
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:274
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
nat_reass_ip4_t * nat_ip4_reass_create(ip4_address_t src, ip4_address_t dst, u16 frag_id, u8 proto)
Create reassembly.
Definition: nat_reass.c:220
static u32 clib_dlist_remove_head(dlist_elt_t *pool, u32 head_index)
Definition: dlist.h:117
static int nat_set_outside_address_and_port(snat_address_t *addresses, u32 thread_index, snat_session_key_t *k)
Definition: nat.c:2462
u32 tcp_established_timeout
Definition: nat.h:553
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128