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