FD.io VPP  v19.08-27-gf4dcae4
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  /* *INDENT-ON* */
2203 
2204  if (!match)
2205  return;
2206 
2207  vec_foreach (outside_fib, sm->outside_fibs)
2208  {
2209  if (outside_fib->fib_index == old_fib_index)
2210  {
2211  outside_fib->refcount--;
2212  if (!outside_fib->refcount)
2213  vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs);
2214  break;
2215  }
2216  }
2217 
2218  vec_foreach (outside_fib, sm->outside_fibs)
2219  {
2220  if (outside_fib->fib_index == new_fib_index)
2221  {
2222  outside_fib->refcount++;
2223  is_add = 0;
2224  break;
2225  }
2226  }
2227 
2228  if (is_add)
2229  {
2230  vec_add2 (sm->outside_fibs, outside_fib, 1);
2231  outside_fib->refcount = 1;
2232  outside_fib->fib_index = new_fib_index;
2233  }
2234 }
2235 
2236 static void
2238  uword opaque,
2239  u32 sw_if_index, u32 new_fib_index, u32 old_fib_index)
2240 {
2241  snat_update_outside_fib (sw_if_index, new_fib_index, old_fib_index);
2242 }
2243 
2244 static void
2246  uword opaque,
2247  u32 sw_if_index,
2249  u32 address_length,
2250  u32 if_address_index, u32 is_delete);
2251 
2252 static void
2254  uword opaque,
2255  u32 sw_if_index,
2256  ip4_address_t * address,
2257  u32 address_length,
2258  u32 if_address_index, u32 is_delete);
2259 
2260 static int
2262  u32 fib_index,
2263  u32 thread_index,
2264  snat_session_key_t * k,
2265  u16 port_per_thread, u32 snat_thread_index);
2266 
2267 static clib_error_t *
2269 {
2270  snat_main_t *sm = &snat_main;
2271  clib_error_t *error = 0;
2272  ip4_main_t *im = &ip4_main;
2273  ip_lookup_main_t *lm = &im->lookup_main;
2274  uword *p;
2277  uword *bitmap = 0;
2278  u32 i;
2280  vlib_node_t *node;
2281 
2282  sm->vlib_main = vm;
2283  sm->vnet_main = vnet_get_main ();
2284  sm->ip4_main = im;
2285  sm->ip4_lookup_main = lm;
2286  sm->api_main = &api_main;
2287  sm->first_worker_index = 0;
2288  sm->num_workers = 0;
2289  sm->num_snat_thread = 1;
2290  sm->workers = 0;
2291  sm->port_per_thread = 0xffff - 1024;
2292  sm->fq_in2out_index = ~0;
2293  sm->fq_in2out_output_index = ~0;
2294  sm->fq_out2in_index = ~0;
2300  sm->addr_and_port_alloc_alg = NAT_ADDR_AND_PORT_ALLOC_ALG_DEFAULT;
2301  sm->forwarding_enabled = 0;
2302  sm->log_class = vlib_log_register_class ("nat", 0);
2303  sm->log_level = SNAT_LOG_ERROR;
2304  sm->mss_clamping = 0;
2305 
2306  node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
2307  sm->error_node_index = node->index;
2308 
2309  node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out");
2310  sm->in2out_node_index = node->index;
2311  node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-output");
2312  sm->in2out_output_node_index = node->index;
2313  node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-fast");
2314  sm->in2out_fast_node_index = node->index;
2315  node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-slowpath");
2316  sm->in2out_slowpath_node_index = node->index;
2317  node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-output-slowpath");
2319  node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-reass");
2320  sm->in2out_reass_node_index = node->index;
2321 
2322  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-in2out");
2323  sm->ed_in2out_node_index = node->index;
2324  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-in2out-slowpath");
2326  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-in2out-reass");
2327  sm->ed_in2out_reass_node_index = node->index;
2328 
2329  node = vlib_get_node_by_name (vm, (u8 *) "nat44-out2in");
2330  sm->out2in_node_index = node->index;
2331  node = vlib_get_node_by_name (vm, (u8 *) "nat44-out2in-fast");
2332  sm->out2in_fast_node_index = node->index;
2333  node = vlib_get_node_by_name (vm, (u8 *) "nat44-out2in-reass");
2334  sm->out2in_reass_node_index = node->index;
2335 
2336  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-out2in");
2337  sm->ed_out2in_node_index = node->index;
2338  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-out2in-slowpath");
2340  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-out2in-reass");
2341  sm->ed_out2in_reass_node_index = node->index;
2342 
2343  node = vlib_get_node_by_name (vm, (u8 *) "nat44-det-in2out");
2344  sm->det_in2out_node_index = node->index;
2345  node = vlib_get_node_by_name (vm, (u8 *) "nat44-det-out2in");
2346  sm->det_out2in_node_index = node->index;
2347 
2348  node = vlib_get_node_by_name (vm, (u8 *) "nat44-hairpinning");
2349  sm->hairpinning_node_index = node->index;
2350  node = vlib_get_node_by_name (vm, (u8 *) "nat44-hairpin-dst");
2351  sm->hairpin_dst_node_index = node->index;
2352  node = vlib_get_node_by_name (vm, (u8 *) "nat44-hairpin-src");
2353  sm->hairpin_src_node_index = node->index;
2354  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-hairpinning");
2355  sm->ed_hairpinning_node_index = node->index;
2356  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-hairpin-dst");
2357  sm->ed_hairpin_dst_node_index = node->index;
2358  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-hairpin-src");
2359  sm->ed_hairpin_src_node_index = node->index;
2360 
2361  p = hash_get_mem (tm->thread_registrations_by_name, "workers");
2362  if (p)
2363  {
2364  tr = (vlib_thread_registration_t *) p[0];
2365  if (tr)
2366  {
2367  sm->num_workers = tr->count;
2368  sm->first_worker_index = tr->first_index;
2369  }
2370  }
2371 
2372  vec_validate (sm->per_thread_data, tm->n_vlib_mains - 1);
2373 
2374  /* Use all available workers by default */
2375  if (sm->num_workers > 1)
2376  {
2377  for (i = 0; i < sm->num_workers; i++)
2378  bitmap = clib_bitmap_set (bitmap, i, 1);
2379  snat_set_workers (bitmap);
2380  clib_bitmap_free (bitmap);
2381  }
2382  else
2383  {
2385  }
2386 
2387  error = snat_api_init (vm, sm);
2388  if (error)
2389  return error;
2390 
2391  /* Set up the interface address add/del callback */
2393  cb4.function_opaque = 0;
2394 
2396 
2398  cb4.function_opaque = 0;
2399 
2401 
2403 
2404  /* Init counters */
2405  sm->total_users.name = "total-users";
2406  sm->total_users.stat_segment_name = "/nat44/total-users";
2409  sm->total_sessions.name = "total-sessions";
2410  sm->total_sessions.stat_segment_name = "/nat44/total-sessions";
2413 
2414  /* Init IPFIX logging */
2416 
2417  /* Init NAT64 */
2418  error = nat64_init (vm);
2419  if (error)
2420  return error;
2421 
2422  dslite_init (vm);
2423 
2424  nat66_init (vm);
2425 
2426  ip4_table_bind_callback_t cbt4 = {
2428  };
2430 
2431  /* Init virtual fragmenentation reassembly */
2432  return nat_reass_init (vm);
2433 }
2434 
2436 
2437 void
2439  u32 thread_index, snat_session_key_t * k)
2440 {
2441  snat_address_t *a;
2442  u32 address_index;
2443  u16 port_host_byte_order = clib_net_to_host_u16 (k->port);
2444 
2445  for (address_index = 0; address_index < vec_len (addresses);
2446  address_index++)
2447  {
2448  if (addresses[address_index].addr.as_u32 == k->addr.as_u32)
2449  break;
2450  }
2451 
2452  ASSERT (address_index < vec_len (addresses));
2453 
2454  a = addresses + address_index;
2455 
2456  switch (k->protocol)
2457  {
2458 #define _(N, i, n, s) \
2459  case SNAT_PROTOCOL_##N: \
2460  ASSERT (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, \
2461  port_host_byte_order) == 1); \
2462  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, \
2463  port_host_byte_order, 0); \
2464  a->busy_##n##_ports--; \
2465  a->busy_##n##_ports_per_thread[thread_index]--; \
2466  break;
2468 #undef _
2469  default:
2470  nat_elog_info ("unknown protocol");
2471  return;
2472  }
2473 }
2474 
2475 static int
2477  u32 thread_index, snat_session_key_t * k)
2478 {
2479  snat_address_t *a = 0;
2480  u32 address_index;
2481  u16 port_host_byte_order = clib_net_to_host_u16 (k->port);
2482 
2483  for (address_index = 0; address_index < vec_len (addresses);
2484  address_index++)
2485  {
2486  if (addresses[address_index].addr.as_u32 != k->addr.as_u32)
2487  continue;
2488 
2489  a = addresses + address_index;
2490  switch (k->protocol)
2491  {
2492 #define _(N, j, n, s) \
2493  case SNAT_PROTOCOL_##N: \
2494  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, port_host_byte_order)) \
2495  return VNET_API_ERROR_INSTANCE_IN_USE; \
2496  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, port_host_byte_order, 1); \
2497  a->busy_##n##_ports_per_thread[thread_index]++; \
2498  a->busy_##n##_ports++; \
2499  return 0;
2501 #undef _
2502  default:
2503  nat_elog_info ("unknown protocol");
2504  return 1;
2505  }
2506  }
2507 
2508  return VNET_API_ERROR_NO_SUCH_ENTRY;
2509 }
2510 
2511 int
2513  snat_session_key_t match,
2514  snat_session_key_t * mapping,
2515  u8 by_external,
2516  u8 * is_addr_only,
2517  twice_nat_type_t * twice_nat,
2518  lb_nat_type_t * lb, ip4_address_t * ext_host_addr,
2519  u8 * is_identity_nat)
2520 {
2523  snat_session_key_t m_key;
2524  clib_bihash_8_8_t *mapping_hash = &sm->static_mapping_by_local;
2525  u32 rand, lo = 0, hi, mid, *tmp = 0, i;
2526  u8 backend_index;
2527  nat44_lb_addr_port_t *local;
2528 
2529  m_key.fib_index = match.fib_index;
2530  if (by_external)
2531  {
2532  mapping_hash = &sm->static_mapping_by_external;
2533  m_key.fib_index = 0;
2534  }
2535 
2536  m_key.addr = match.addr;
2537  m_key.port = clib_net_to_host_u16 (match.port);
2538  m_key.protocol = match.protocol;
2539 
2540  kv.key = m_key.as_u64;
2541 
2542  if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
2543  {
2544  /* Try address only mapping */
2545  m_key.port = 0;
2546  m_key.protocol = 0;
2547  kv.key = m_key.as_u64;
2548  if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
2549  return 1;
2550  }
2551 
2552  m = pool_elt_at_index (sm->static_mappings, value.value);
2553 
2554  if (by_external)
2555  {
2556  if (is_lb_static_mapping (m))
2557  {
2558  if (PREDICT_FALSE (lb != 0))
2559  *lb = m->affinity ? AFFINITY_LB_NAT : LB_NAT;
2560  if (m->affinity && !nat_affinity_find_and_lock (ext_host_addr[0],
2561  match.addr,
2562  match.protocol,
2563  match.port,
2564  &backend_index))
2565  {
2566  local = pool_elt_at_index (m->locals, backend_index);
2567  mapping->addr = local->addr;
2568  mapping->port = clib_host_to_net_u16 (local->port);
2569  mapping->fib_index = local->fib_index;
2570  goto end;
2571  }
2572  // pick locals matching this worker
2573  if (PREDICT_FALSE (sm->num_workers > 1))
2574  {
2575  u32 thread_index = vlib_get_thread_index ();
2576  /* *INDENT-OFF* */
2578  ({
2579  local = pool_elt_at_index (m->locals, i);
2580 
2581  ip4_header_t ip = {
2582  .src_address = local->addr,
2583  };
2584 
2585  if (sm->worker_in2out_cb (&ip, m->fib_index, 0) ==
2586  thread_index)
2587  {
2588  vec_add1 (tmp, i);
2589  }
2590  }));
2591  /* *INDENT-ON* */
2592  ASSERT (vec_len (tmp) != 0);
2593  }
2594  else
2595  {
2596  /* *INDENT-OFF* */
2598  ({
2599  vec_add1 (tmp, i);
2600  }));
2601  /* *INDENT-ON* */
2602  }
2603  hi = vec_len (tmp) - 1;
2604  local = pool_elt_at_index (m->locals, tmp[hi]);
2605  rand = 1 + (random_u32 (&sm->random_seed) % local->prefix);
2606  while (lo < hi)
2607  {
2608  mid = ((hi - lo) >> 1) + lo;
2609  local = pool_elt_at_index (m->locals, tmp[mid]);
2610  (rand > local->prefix) ? (lo = mid + 1) : (hi = mid);
2611  }
2612  local = pool_elt_at_index (m->locals, tmp[lo]);
2613  if (!(local->prefix >= rand))
2614  return 1;
2615  mapping->addr = local->addr;
2616  mapping->port = clib_host_to_net_u16 (local->port);
2617  mapping->fib_index = local->fib_index;
2618  if (m->affinity)
2619  {
2620  if (nat_affinity_create_and_lock (ext_host_addr[0], match.addr,
2621  match.protocol, match.port,
2622  tmp[lo], m->affinity,
2624  nat_elog_info ("create affinity record failed");
2625  }
2626  vec_free (tmp);
2627  }
2628  else
2629  {
2630  if (PREDICT_FALSE (lb != 0))
2631  *lb = NO_LB_NAT;
2632  mapping->fib_index = m->fib_index;
2633  mapping->addr = m->local_addr;
2634  /* Address only mapping doesn't change port */
2635  mapping->port = is_addr_only_static_mapping (m) ? match.port
2636  : clib_host_to_net_u16 (m->local_port);
2637  }
2638  mapping->protocol = m->proto;
2639  }
2640  else
2641  {
2642  mapping->addr = m->external_addr;
2643  /* Address only mapping doesn't change port */
2644  mapping->port = is_addr_only_static_mapping (m) ? match.port
2645  : clib_host_to_net_u16 (m->external_port);
2646  mapping->fib_index = sm->outside_fib_index;
2647  }
2648 
2649 end:
2650  if (PREDICT_FALSE (is_addr_only != 0))
2651  *is_addr_only = is_addr_only_static_mapping (m);
2652 
2653  if (PREDICT_FALSE (twice_nat != 0))
2654  *twice_nat = m->twice_nat;
2655 
2656  if (PREDICT_FALSE (is_identity_nat != 0))
2657  *is_identity_nat = is_identity_static_mapping (m);
2658 
2659  return 0;
2660 }
2661 
2664 {
2665  snat_main_t *sm = &snat_main;
2666  return min + random_u32 (&sm->random_seed) /
2667  (random_u32_max () / (max - min + 1) + 1);
2668 }
2669 
2670 int
2672  u32 fib_index,
2673  u32 thread_index,
2674  snat_session_key_t * k,
2675  u16 port_per_thread,
2676  u32 snat_thread_index)
2677 {
2678  snat_main_t *sm = &snat_main;
2679 
2680  return sm->alloc_addr_and_port (addresses, fib_index, thread_index, k,
2681  port_per_thread, snat_thread_index);
2682 }
2683 
2684 static int
2686  u32 fib_index,
2687  u32 thread_index,
2688  snat_session_key_t * k,
2689  u16 port_per_thread, u32 snat_thread_index)
2690 {
2691  int i;
2692  snat_address_t *a, *ga = 0;
2693  u32 portnum;
2694 
2695  for (i = 0; i < vec_len (addresses); i++)
2696  {
2697  a = addresses + i;
2698  switch (k->protocol)
2699  {
2700 #define _(N, j, n, s) \
2701  case SNAT_PROTOCOL_##N: \
2702  if (a->busy_##n##_ports_per_thread[thread_index] < port_per_thread) \
2703  { \
2704  if (a->fib_index == fib_index) \
2705  { \
2706  while (1) \
2707  { \
2708  portnum = (port_per_thread * \
2709  snat_thread_index) + \
2710  snat_random_port(1, port_per_thread) + 1024; \
2711  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \
2712  continue; \
2713  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \
2714  a->busy_##n##_ports_per_thread[thread_index]++; \
2715  a->busy_##n##_ports++; \
2716  k->addr = a->addr; \
2717  k->port = clib_host_to_net_u16(portnum); \
2718  return 0; \
2719  } \
2720  } \
2721  else if (a->fib_index == ~0) \
2722  { \
2723  ga = a; \
2724  } \
2725  } \
2726  break;
2728 #undef _
2729  default:
2730  nat_elog_info ("unknown protocol");
2731  return 1;
2732  }
2733 
2734  }
2735 
2736  if (ga)
2737  {
2738  a = ga;
2739  switch (k->protocol)
2740  {
2741 #define _(N, j, n, s) \
2742  case SNAT_PROTOCOL_##N: \
2743  while (1) \
2744  { \
2745  portnum = (port_per_thread * \
2746  snat_thread_index) + \
2747  snat_random_port(1, port_per_thread) + 1024; \
2748  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \
2749  continue; \
2750  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \
2751  a->busy_##n##_ports_per_thread[thread_index]++; \
2752  a->busy_##n##_ports++; \
2753  k->addr = a->addr; \
2754  k->port = clib_host_to_net_u16(portnum); \
2755  return 0; \
2756  }
2757  break;
2759 #undef _
2760  default:
2761  nat_elog_info ("unknown protocol");
2762  return 1;
2763  }
2764  }
2765 
2766  /* Totally out of translations to use... */
2767  snat_ipfix_logging_addresses_exhausted (thread_index, 0);
2768  return 1;
2769 }
2770 
2771 static int
2773  u32 fib_index,
2774  u32 thread_index,
2775  snat_session_key_t * k,
2776  u16 port_per_thread, u32 snat_thread_index)
2777 {
2778  snat_main_t *sm = &snat_main;
2779  snat_address_t *a = addresses;
2780  u16 m, ports, portnum, A, j;
2781  m = 16 - (sm->psid_offset + sm->psid_length);
2782  ports = (1 << (16 - sm->psid_length)) - (1 << m);
2783 
2784  if (!vec_len (addresses))
2785  goto exhausted;
2786 
2787  switch (k->protocol)
2788  {
2789 #define _(N, i, n, s) \
2790  case SNAT_PROTOCOL_##N: \
2791  if (a->busy_##n##_ports < ports) \
2792  { \
2793  while (1) \
2794  { \
2795  A = snat_random_port(1, pow2_mask(sm->psid_offset)); \
2796  j = snat_random_port(0, pow2_mask(m)); \
2797  portnum = A | (sm->psid << sm->psid_offset) | (j << (16 - m)); \
2798  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \
2799  continue; \
2800  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \
2801  a->busy_##n##_ports++; \
2802  k->addr = a->addr; \
2803  k->port = clib_host_to_net_u16 (portnum); \
2804  return 0; \
2805  } \
2806  } \
2807  break;
2809 #undef _
2810  default:
2811  nat_elog_info ("unknown protocol");
2812  return 1;
2813  }
2814 
2815 exhausted:
2816  /* Totally out of translations to use... */
2817  snat_ipfix_logging_addresses_exhausted (thread_index, 0);
2818  return 1;
2819 }
2820 
2821 static int
2823  u32 fib_index,
2824  u32 thread_index,
2825  snat_session_key_t * k,
2826  u16 port_per_thread, u32 snat_thread_index)
2827 {
2828  snat_main_t *sm = &snat_main;
2829  snat_address_t *a = addresses;
2830  u16 portnum, ports;
2831 
2832  ports = sm->end_port - sm->start_port + 1;
2833 
2834  if (!vec_len (addresses))
2835  goto exhausted;
2836 
2837  switch (k->protocol)
2838  {
2839 #define _(N, i, n, s) \
2840  case SNAT_PROTOCOL_##N: \
2841  if (a->busy_##n##_ports < ports) \
2842  { \
2843  while (1) \
2844  { \
2845  portnum = snat_random_port(sm->start_port, sm->end_port); \
2846  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \
2847  continue; \
2848  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \
2849  a->busy_##n##_ports++; \
2850  k->addr = a->addr; \
2851  k->port = clib_host_to_net_u16 (portnum); \
2852  return 0; \
2853  } \
2854  } \
2855  break;
2857 #undef _
2858  default:
2859  nat_elog_info ("unknown protocol");
2860  return 1;
2861  }
2862 
2863 exhausted:
2864  /* Totally out of translations to use... */
2865  snat_ipfix_logging_addresses_exhausted (thread_index, 0);
2866  return 1;
2867 }
2868 
2869 void
2871 {
2872  dpo_id_t dpo_v4 = DPO_INVALID;
2873  fib_prefix_t pfx = {
2875  .fp_len = 32,
2876  .fp_addr.ip4.as_u32 = addr.as_u32,
2877  };
2878 
2879  if (is_add)
2880  {
2881  nat_dpo_create (DPO_PROTO_IP4, 0, &dpo_v4);
2883  FIB_ENTRY_FLAG_EXCLUSIVE, &dpo_v4);
2884  dpo_reset (&dpo_v4);
2885  }
2886  else
2887  {
2889  }
2890 }
2891 
2892 u8 *
2893 format_session_kvp (u8 * s, va_list * args)
2894 {
2895  clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
2897 
2898  k.as_u64 = v->key;
2899 
2900  s = format (s, "%U session-index %llu", format_snat_key, &k, v->value);
2901 
2902  return s;
2903 }
2904 
2905 u8 *
2906 format_static_mapping_kvp (u8 * s, va_list * args)
2907 {
2908  clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
2910 
2911  k.as_u64 = v->key;
2912 
2913  s = format (s, "%U static-mapping-index %llu",
2915 
2916  return s;
2917 }
2918 
2919 u8 *
2920 format_user_kvp (u8 * s, va_list * args)
2921 {
2922  clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
2923  snat_user_key_t k;
2924 
2925  k.as_u64 = v->key;
2926 
2927  s = format (s, "%U fib %d user-index %llu", format_ip4_address, &k.addr,
2928  k.fib_index, v->value);
2929 
2930  return s;
2931 }
2932 
2933 u8 *
2934 format_ed_session_kvp (u8 * s, va_list * args)
2935 {
2936  clib_bihash_kv_16_8_t *v = va_arg (*args, clib_bihash_kv_16_8_t *);
2937  nat_ed_ses_key_t k;
2938 
2939  k.as_u64[0] = v->key[0];
2940  k.as_u64[1] = v->key[1];
2941 
2942  s =
2943  format (s, "local %U:%d remote %U:%d proto %U fib %d session-index %llu",
2944  format_ip4_address, &k.l_addr, clib_net_to_host_u16 (k.l_port),
2945  format_ip4_address, &k.r_addr, clib_net_to_host_u16 (k.r_port),
2947 
2948  return s;
2949 }
2950 
2951 static u32
2953  u8 is_output)
2954 {
2955  snat_main_t *sm = &snat_main;
2956  u32 next_worker_index = 0;
2957  u32 hash;
2958 
2959  next_worker_index = sm->first_worker_index;
2960  hash = ip0->src_address.as_u32 + (ip0->src_address.as_u32 >> 8) +
2961  (ip0->src_address.as_u32 >> 16) + (ip0->src_address.as_u32 >> 24);
2962 
2963  if (PREDICT_TRUE (is_pow2 (_vec_len (sm->workers))))
2964  next_worker_index += sm->workers[hash & (_vec_len (sm->workers) - 1)];
2965  else
2966  next_worker_index += sm->workers[hash % _vec_len (sm->workers)];
2967 
2968  return next_worker_index;
2969 }
2970 
2971 static u32
2973  u8 is_output)
2974 {
2975  snat_main_t *sm = &snat_main;
2976  udp_header_t *udp;
2977  u16 port;
2978  snat_session_key_t m_key;
2981  u32 proto;
2982  u32 next_worker_index = 0;
2983 
2984  /* first try static mappings without port */
2986  {
2987  m_key.addr = ip0->dst_address;
2988  m_key.port = 0;
2989  m_key.protocol = 0;
2990  m_key.fib_index = rx_fib_index0;
2991  kv.key = m_key.as_u64;
2992  if (!clib_bihash_search_8_8
2993  (&sm->static_mapping_by_external, &kv, &value))
2994  {
2995  m = pool_elt_at_index (sm->static_mappings, value.value);
2996  return m->workers[0];
2997  }
2998  }
2999 
3000  proto = ip_proto_to_snat_proto (ip0->protocol);
3001  udp = ip4_next_header (ip0);
3002  port = udp->dst_port;
3003 
3004  if (PREDICT_FALSE (ip4_is_fragment (ip0)))
3005  {
3007  return vlib_get_thread_index ();
3008 
3009  nat_reass_ip4_t *reass;
3010  reass = nat_ip4_reass_find (ip0->src_address, ip0->dst_address,
3011  ip0->fragment_id, ip0->protocol);
3012 
3013  if (reass && (reass->thread_index != (u32) ~ 0))
3014  return reass->thread_index;
3015 
3016  if (ip4_is_first_fragment (ip0))
3017  {
3018  reass =
3020  ip0->fragment_id, ip0->protocol);
3021  if (!reass)
3022  goto no_reass;
3023 
3025  {
3026  m_key.addr = ip0->dst_address;
3027  m_key.port = clib_net_to_host_u16 (port);
3028  m_key.protocol = proto;
3029  m_key.fib_index = rx_fib_index0;
3030  kv.key = m_key.as_u64;
3031  if (!clib_bihash_search_8_8
3032  (&sm->static_mapping_by_external, &kv, &value))
3033  {
3034  m = pool_elt_at_index (sm->static_mappings, value.value);
3035  reass->thread_index = m->workers[0];
3036  return reass->thread_index;
3037  }
3038  }
3039  reass->thread_index = sm->first_worker_index;
3040  reass->thread_index +=
3041  sm->workers[(clib_net_to_host_u16 (port) - 1024) /
3042  sm->port_per_thread];
3043  return reass->thread_index;
3044  }
3045  else
3046  return vlib_get_thread_index ();
3047  }
3048 
3049 no_reass:
3050  /* unknown protocol */
3051  if (PREDICT_FALSE (proto == ~0))
3052  {
3053  /* use current thread */
3054  return vlib_get_thread_index ();
3055  }
3056 
3057  if (PREDICT_FALSE (ip0->protocol == IP_PROTOCOL_ICMP))
3058  {
3059  icmp46_header_t *icmp = (icmp46_header_t *) udp;
3060  icmp_echo_header_t *echo = (icmp_echo_header_t *) (icmp + 1);
3061  if (!icmp_is_error_message (icmp))
3062  port = echo->identifier;
3063  else
3064  {
3065  ip4_header_t *inner_ip = (ip4_header_t *) (echo + 1);
3066  proto = ip_proto_to_snat_proto (inner_ip->protocol);
3067  void *l4_header = ip4_next_header (inner_ip);
3068  switch (proto)
3069  {
3070  case SNAT_PROTOCOL_ICMP:
3071  icmp = (icmp46_header_t *) l4_header;
3072  echo = (icmp_echo_header_t *) (icmp + 1);
3073  port = echo->identifier;
3074  break;
3075  case SNAT_PROTOCOL_UDP:
3076  case SNAT_PROTOCOL_TCP:
3077  port = ((tcp_udp_header_t *) l4_header)->src_port;
3078  break;
3079  default:
3080  return vlib_get_thread_index ();
3081  }
3082  }
3083  }
3084 
3085  /* try static mappings with port */
3086  if (PREDICT_FALSE (pool_elts (sm->static_mappings)))
3087  {
3088  m_key.addr = ip0->dst_address;
3089  m_key.port = clib_net_to_host_u16 (port);
3090  m_key.protocol = proto;
3091  m_key.fib_index = rx_fib_index0;
3092  kv.key = m_key.as_u64;
3093  if (!clib_bihash_search_8_8
3094  (&sm->static_mapping_by_external, &kv, &value))
3095  {
3096  m = pool_elt_at_index (sm->static_mappings, value.value);
3097  return m->workers[0];
3098  }
3099  }
3100 
3101  /* worker by outside port */
3102  next_worker_index = sm->first_worker_index;
3103  next_worker_index +=
3104  sm->workers[(clib_net_to_host_u16 (port) - 1024) / sm->port_per_thread];
3105  return next_worker_index;
3106 }
3107 
3108 static u32
3110  u8 is_output)
3111 {
3112  snat_main_t *sm = &snat_main;
3113  u32 next_worker_index = sm->first_worker_index;
3114  u32 hash;
3115 
3116  clib_bihash_kv_16_8_t kv16, value16;
3118  udp_header_t *udp;
3119 
3120  if (PREDICT_FALSE (is_output))
3121  {
3122  u32 fib_index = sm->outside_fib_index;
3123  nat_outside_fib_t *outside_fib;
3125  fib_prefix_t pfx = {
3127  .fp_len = 32,
3128  .fp_addr = {
3129  .ip4.as_u32 = ip->dst_address.as_u32,
3130  }
3131  ,
3132  };
3133 
3134  udp = ip4_next_header (ip);
3135 
3136  switch (vec_len (sm->outside_fibs))
3137  {
3138  case 0:
3139  fib_index = sm->outside_fib_index;
3140  break;
3141  case 1:
3142  fib_index = sm->outside_fibs[0].fib_index;
3143  break;
3144  default:
3145  /* *INDENT-OFF* */
3146  vec_foreach (outside_fib, sm->outside_fibs)
3147  {
3148  fei = fib_table_lookup (outside_fib->fib_index, &pfx);
3149  if (FIB_NODE_INDEX_INVALID != fei)
3150  {
3151  if (fib_entry_get_resolving_interface (fei) != ~0)
3152  {
3153  fib_index = outside_fib->fib_index;
3154  break;
3155  }
3156  }
3157  }
3158  /* *INDENT-ON* */
3159  break;
3160  }
3161 
3162  make_ed_kv (&kv16, &ip->src_address, &ip->dst_address,
3163  ip->protocol, fib_index, udp->src_port, udp->dst_port);
3164 
3165  /* *INDENT-OFF* */
3166  vec_foreach (tsm, sm->per_thread_data)
3167  {
3168  if (PREDICT_TRUE (!clib_bihash_search_16_8 (&tsm->out2in_ed,
3169  &kv16, &value16)))
3170  {
3171  next_worker_index += tsm->thread_index;
3172 
3174  "HANDOFF IN2OUT-OUTPUT-FEATURE (session)",
3175  next_worker_index, fib_index,
3176  clib_net_to_host_u32 (ip->src_address.as_u32),
3177  clib_net_to_host_u32 (ip->dst_address.as_u32));
3178 
3179  return next_worker_index;
3180  }
3181  }
3182  /* *INDENT-ON* */
3183  }
3184 
3185  hash = ip->src_address.as_u32 + (ip->src_address.as_u32 >> 8) +
3186  (ip->src_address.as_u32 >> 16) + (ip->src_address.as_u32 >> 24);
3187 
3188  if (PREDICT_TRUE (is_pow2 (_vec_len (sm->workers))))
3189  next_worker_index += sm->workers[hash & (_vec_len (sm->workers) - 1)];
3190  else
3191  next_worker_index += sm->workers[hash % _vec_len (sm->workers)];
3192 
3193  if (PREDICT_TRUE (!is_output))
3194  {
3195  nat_elog_debug_handoff ("HANDOFF IN2OUT",
3196  next_worker_index, rx_fib_index,
3197  clib_net_to_host_u32 (ip->src_address.as_u32),
3198  clib_net_to_host_u32 (ip->dst_address.as_u32));
3199  }
3200  else
3201  {
3202  nat_elog_debug_handoff ("HANDOFF IN2OUT-OUTPUT-FEATURE",
3203  next_worker_index, rx_fib_index,
3204  clib_net_to_host_u32 (ip->src_address.as_u32),
3205  clib_net_to_host_u32 (ip->dst_address.as_u32));
3206  }
3207 
3208  return next_worker_index;
3209 }
3210 
3211 static u32
3213  u8 is_output)
3214 {
3215  snat_main_t *sm = &snat_main;
3217  clib_bihash_kv_16_8_t kv16, value16;
3219 
3220  u32 proto, next_worker_index = 0;
3221  udp_header_t *udp;
3222  u16 port;
3224  u32 hash;
3225 
3226  proto = ip_proto_to_snat_proto (ip->protocol);
3227 
3228  if (PREDICT_TRUE (proto == SNAT_PROTOCOL_UDP || proto == SNAT_PROTOCOL_TCP))
3229  {
3230  udp = ip4_next_header (ip);
3231 
3232  make_ed_kv (&kv16, &ip->dst_address, &ip->src_address,
3233  ip->protocol, rx_fib_index, udp->dst_port, udp->src_port);
3234 
3235  /* *INDENT-OFF* */
3236  vec_foreach (tsm, sm->per_thread_data)
3237  {
3238  if (PREDICT_TRUE (!clib_bihash_search_16_8 (&tsm->out2in_ed,
3239  &kv16, &value16)))
3240  {
3241  next_worker_index = sm->first_worker_index + tsm->thread_index;
3242  nat_elog_debug_handoff ("HANDOFF OUT2IN (session)",
3243  next_worker_index, rx_fib_index,
3244  clib_net_to_host_u32 (ip->src_address.as_u32),
3245  clib_net_to_host_u32 (ip->dst_address.as_u32));
3246  return next_worker_index;
3247  }
3248  }
3249  /* *INDENT-ON* */
3250  }
3251  else if (proto == SNAT_PROTOCOL_ICMP)
3252  {
3254 
3255  if (!get_icmp_o2i_ed_key (ip, &key))
3256  {
3257 
3258  key.fib_index = rx_fib_index;
3259  kv16.key[0] = key.as_u64[0];
3260  kv16.key[1] = key.as_u64[1];
3261 
3262  /* *INDENT-OFF* */
3263  vec_foreach (tsm, sm->per_thread_data)
3264  {
3265  if (PREDICT_TRUE (!clib_bihash_search_16_8 (&tsm->out2in_ed,
3266  &kv16, &value16)))
3267  {
3268  next_worker_index = sm->first_worker_index +
3269  tsm->thread_index;
3270  nat_elog_debug_handoff ("HANDOFF OUT2IN (session)",
3271  next_worker_index, rx_fib_index,
3272  clib_net_to_host_u32 (ip->src_address.as_u32),
3273  clib_net_to_host_u32 (ip->dst_address.as_u32));
3274  return next_worker_index;
3275  }
3276  }
3277  /* *INDENT-ON* */
3278  }
3279  }
3280 
3281  /* first try static mappings without port */
3283  {
3284  make_sm_kv (&kv, &ip->dst_address, 0, 0, 0);
3285  if (!clib_bihash_search_8_8
3286  (&sm->static_mapping_by_external, &kv, &value))
3287  {
3288  m = pool_elt_at_index (sm->static_mappings, value.value);
3289  next_worker_index = m->workers[0];
3290  goto done;
3291  }
3292  }
3293 
3294  /* unknown protocol */
3295  if (PREDICT_FALSE (proto == ~0))
3296  {
3297  /* use current thread */
3298  next_worker_index = vlib_get_thread_index ();
3299  goto done;
3300  }
3301 
3302  udp = ip4_next_header (ip);
3303  port = udp->dst_port;
3304 
3305  if (PREDICT_FALSE (ip->protocol == IP_PROTOCOL_ICMP))
3306  {
3307  icmp46_header_t *icmp = (icmp46_header_t *) udp;
3308  icmp_echo_header_t *echo = (icmp_echo_header_t *) (icmp + 1);
3309  if (!icmp_is_error_message (icmp))
3310  port = echo->identifier;
3311  else
3312  {
3313  ip4_header_t *inner_ip = (ip4_header_t *) (echo + 1);
3314  proto = ip_proto_to_snat_proto (inner_ip->protocol);
3315  void *l4_header = ip4_next_header (inner_ip);
3316  switch (proto)
3317  {
3318  case SNAT_PROTOCOL_ICMP:
3319  icmp = (icmp46_header_t *) l4_header;
3320  echo = (icmp_echo_header_t *) (icmp + 1);
3321  port = echo->identifier;
3322  break;
3323  case SNAT_PROTOCOL_UDP:
3324  case SNAT_PROTOCOL_TCP:
3325  port = ((tcp_udp_header_t *) l4_header)->src_port;
3326  break;
3327  default:
3328  next_worker_index = vlib_get_thread_index ();
3329  goto done;
3330  }
3331  }
3332  }
3333 
3334  /* try static mappings with port */
3335  if (PREDICT_FALSE (pool_elts (sm->static_mappings)))
3336  {
3337  make_sm_kv (&kv, &ip->dst_address, proto, 0,
3338  clib_net_to_host_u16 (port));
3339  if (!clib_bihash_search_8_8
3340  (&sm->static_mapping_by_external, &kv, &value))
3341  {
3342  m = pool_elt_at_index (sm->static_mappings, value.value);
3343  if (!is_lb_static_mapping (m))
3344  {
3345  next_worker_index = m->workers[0];
3346  goto done;
3347  }
3348 
3349  hash = ip->src_address.as_u32 + (ip->src_address.as_u32 >> 8) +
3350  (ip->src_address.as_u32 >> 16) + (ip->src_address.as_u32 >> 24);
3351 
3352  if (PREDICT_TRUE (is_pow2 (_vec_len (m->workers))))
3353  next_worker_index =
3354  m->workers[hash & (_vec_len (m->workers) - 1)];
3355  else
3356  next_worker_index = m->workers[hash % _vec_len (m->workers)];
3357  goto done;
3358  }
3359  }
3360 
3361  /* worker by outside port */
3362  next_worker_index = sm->first_worker_index;
3363  next_worker_index +=
3364  sm->workers[(clib_net_to_host_u16 (port) - 1024) / sm->port_per_thread];
3365 
3366 done:
3367  nat_elog_debug_handoff ("HANDOFF OUT2IN", next_worker_index, rx_fib_index,
3368  clib_net_to_host_u32 (ip->src_address.as_u32),
3369  clib_net_to_host_u32 (ip->dst_address.as_u32));
3370  return next_worker_index;
3371 }
3372 
3373 void
3374 nat_ha_sadd_cb (ip4_address_t * in_addr, u16 in_port,
3375  ip4_address_t * out_addr, u16 out_port,
3376  ip4_address_t * eh_addr, u16 eh_port,
3377  ip4_address_t * ehn_addr, u16 ehn_port, u8 proto,
3378  u32 fib_index, u16 flags, u32 thread_index)
3379 {
3380  snat_main_t *sm = &snat_main;
3382  snat_user_t *u;
3383  snat_session_t *s;
3385  f64 now = vlib_time_now (sm->vlib_main);
3386  nat_outside_fib_t *outside_fib;
3389  fib_prefix_t pfx = {
3391  .fp_len = 32,
3392  .fp_addr = {
3393  .ip4.as_u32 = eh_addr->as_u32,
3394  },
3395  };
3396 
3397  tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
3398 
3399  key.addr.as_u32 = out_addr->as_u32;
3400  key.port = out_port;
3401  key.protocol = proto;
3402 
3403  if (!(flags & SNAT_SESSION_FLAG_STATIC_MAPPING))
3404  {
3406  (sm->addresses, thread_index, &key))
3407  return;
3408  }
3409 
3410  u = nat_user_get_or_create (sm, in_addr, fib_index, thread_index);
3411  if (!u)
3412  return;
3413 
3414  s = nat_session_alloc_or_recycle (sm, u, thread_index, now);
3415  if (!s)
3416  return;
3417 
3418  s->last_heard = now;
3419  s->flags = flags;
3420  s->ext_host_addr.as_u32 = eh_addr->as_u32;
3421  s->ext_host_port = eh_port;
3423  switch (vec_len (sm->outside_fibs))
3424  {
3425  case 0:
3426  key.fib_index = sm->outside_fib_index;
3427  break;
3428  case 1:
3429  key.fib_index = sm->outside_fibs[0].fib_index;
3430  break;
3431  default:
3432  /* *INDENT-OFF* */
3433  vec_foreach (outside_fib, sm->outside_fibs)
3434  {
3435  fei = fib_table_lookup (outside_fib->fib_index, &pfx);
3436  if (FIB_NODE_INDEX_INVALID != fei)
3437  {
3438  if (fib_entry_get_resolving_interface (fei) != ~0)
3439  {
3440  key.fib_index = outside_fib->fib_index;
3441  break;
3442  }
3443  }
3444  }
3445  /* *INDENT-ON* */
3446  break;
3447  }
3448  s->out2in = key;
3449  kv.key = key.as_u64;
3450  kv.value = s - tsm->sessions;
3451  if (clib_bihash_add_del_8_8 (&tsm->out2in, &kv, 1))
3452  nat_elog_warn ("out2in key add failed");
3453 
3454  key.addr.as_u32 = in_addr->as_u32;
3455  key.port = in_port;
3456  key.fib_index = fib_index;
3457  s->in2out = key;
3458  kv.key = key.as_u64;
3459  if (clib_bihash_add_del_8_8 (&tsm->in2out, &kv, 1))
3460  nat_elog_warn ("in2out key add failed");
3461 }
3462 
3463 void
3464 nat_ha_sdel_cb (ip4_address_t * out_addr, u16 out_port,
3465  ip4_address_t * eh_addr, u16 eh_port, u8 proto, u32 fib_index,
3466  u32 ti)
3467 {
3468  snat_main_t *sm = &snat_main;
3471  u32 thread_index;
3472  snat_session_t *s;
3474 
3475  if (sm->num_workers > 1)
3476  thread_index =
3477  sm->first_worker_index +
3478  (sm->workers[(clib_net_to_host_u16 (out_port) -
3479  1024) / sm->port_per_thread]);
3480  else
3481  thread_index = sm->num_workers;
3482  tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
3483 
3484  key.addr.as_u32 = out_addr->as_u32;
3485  key.port = out_port;
3486  key.protocol = proto;
3487  key.fib_index = fib_index;
3488  kv.key = key.as_u64;
3489  if (clib_bihash_search_8_8 (&tsm->out2in, &kv, &value))
3490  return;
3491 
3492  s = pool_elt_at_index (tsm->sessions, value.value);
3493  nat_free_session_data (sm, s, thread_index, 1);
3494  nat44_delete_session (sm, s, thread_index);
3495 }
3496 
3497 void
3498 nat_ha_sref_cb (ip4_address_t * out_addr, u16 out_port,
3499  ip4_address_t * eh_addr, u16 eh_port, u8 proto, u32 fib_index,
3500  u32 total_pkts, u64 total_bytes, u32 thread_index)
3501 {
3502  snat_main_t *sm = &snat_main;
3505  snat_session_t *s;
3507 
3508  tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
3509 
3510  key.addr.as_u32 = out_addr->as_u32;
3511  key.port = out_port;
3512  key.protocol = proto;
3513  key.fib_index = fib_index;
3514  kv.key = key.as_u64;
3515  if (clib_bihash_search_8_8 (&tsm->out2in, &kv, &value))
3516  return;
3517 
3518  s = pool_elt_at_index (tsm->sessions, value.value);
3519  s->total_pkts = total_pkts;
3520  s->total_bytes = total_bytes;
3521 }
3522 
3523 void
3525  ip4_address_t * out_addr, u16 out_port,
3526  ip4_address_t * eh_addr, u16 eh_port,
3527  ip4_address_t * ehn_addr, u16 ehn_port, u8 proto,
3528  u32 fib_index, u16 flags, u32 thread_index)
3529 {
3530  snat_main_t *sm = &snat_main;
3532  snat_user_t *u;
3533  snat_session_t *s;
3535  f64 now = vlib_time_now (sm->vlib_main);
3536  nat_outside_fib_t *outside_fib;
3539  fib_prefix_t pfx = {
3541  .fp_len = 32,
3542  .fp_addr = {
3543  .ip4.as_u32 = eh_addr->as_u32,
3544  },
3545  };
3546 
3547  tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
3548 
3549  key.addr.as_u32 = out_addr->as_u32;
3550  key.port = out_port;
3551  key.protocol = proto;
3552 
3553  if (!(flags & SNAT_SESSION_FLAG_STATIC_MAPPING))
3554  {
3556  (sm->addresses, thread_index, &key))
3557  return;
3558  }
3559 
3560  key.addr.as_u32 = ehn_addr->as_u32;
3561  key.port = ehn_port;
3562  if (flags & SNAT_SESSION_FLAG_TWICE_NAT)
3563  {
3565  (sm->twice_nat_addresses, thread_index, &key))
3566  return;
3567  }
3568 
3569  u = nat_user_get_or_create (sm, in_addr, fib_index, thread_index);
3570  if (!u)
3571  return;
3572 
3573  s = nat_ed_session_alloc (sm, u, thread_index, now);
3574  if (!s)
3575  return;
3576 
3577  s->last_heard = now;
3578  s->flags = flags;
3579  s->ext_host_nat_addr.as_u32 = s->ext_host_addr.as_u32 = eh_addr->as_u32;
3580  s->ext_host_nat_port = s->ext_host_port = eh_port;
3581  if (is_twice_nat_session (s))
3582  {
3583  s->ext_host_nat_addr.as_u32 = ehn_addr->as_u32;
3584  s->ext_host_nat_port = ehn_port;
3585  }
3587  switch (vec_len (sm->outside_fibs))
3588  {
3589  case 0:
3590  key.fib_index = sm->outside_fib_index;
3591  break;
3592  case 1:
3593  key.fib_index = sm->outside_fibs[0].fib_index;
3594  break;
3595  default:
3596  /* *INDENT-OFF* */
3597  vec_foreach (outside_fib, sm->outside_fibs)
3598  {
3599  fei = fib_table_lookup (outside_fib->fib_index, &pfx);
3600  if (FIB_NODE_INDEX_INVALID != fei)
3601  {
3602  if (fib_entry_get_resolving_interface (fei) != ~0)
3603  {
3604  key.fib_index = outside_fib->fib_index;
3605  break;
3606  }
3607  }
3608  }
3609  /* *INDENT-ON* */
3610  break;
3611  }
3612  key.addr.as_u32 = out_addr->as_u32;
3613  key.port = out_port;
3614  s->out2in = key;
3615  kv.value = s - tsm->sessions;
3616 
3617  key.addr.as_u32 = in_addr->as_u32;
3618  key.port = in_port;
3619  key.fib_index = fib_index;
3620  s->in2out = key;
3621 
3622  make_ed_kv (&kv, in_addr, &s->ext_host_nat_addr,
3623  snat_proto_to_ip_proto (proto), fib_index, in_port,
3624  s->ext_host_nat_port);
3625  if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &kv, 1))
3626  nat_elog_warn ("in2out key add failed");
3627 
3628  make_ed_kv (&kv, out_addr, eh_addr, snat_proto_to_ip_proto (proto),
3629  s->out2in.fib_index, out_port, eh_port);
3630  if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &kv, 1))
3631  nat_elog_warn ("out2in key add failed");
3632 }
3633 
3634 void
3635 nat_ha_sdel_ed_cb (ip4_address_t * out_addr, u16 out_port,
3636  ip4_address_t * eh_addr, u16 eh_port, u8 proto,
3637  u32 fib_index, u32 ti)
3638 {
3639  snat_main_t *sm = &snat_main;
3642  u32 thread_index;
3643  snat_session_t *s;
3645 
3646  if (sm->num_workers > 1)
3647  thread_index =
3648  sm->first_worker_index +
3649  (sm->workers[(clib_net_to_host_u16 (out_port) -
3650  1024) / sm->port_per_thread]);
3651  else
3652  thread_index = sm->num_workers;
3653  tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
3654 
3655  key.l_addr.as_u32 = out_addr->as_u32;
3656  key.l_port = out_port;
3657  key.r_addr.as_u32 = eh_addr->as_u32;
3658  key.r_port = eh_port;
3659  key.proto = proto;
3660  key.fib_index = fib_index;
3661  kv.key[0] = key.as_u64[0];
3662  kv.key[1] = key.as_u64[1];
3663  if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
3664  return;
3665 
3666  s = pool_elt_at_index (tsm->sessions, value.value);
3667  nat_free_session_data (sm, s, thread_index, 1);
3668  nat44_delete_session (sm, s, thread_index);
3669 }
3670 
3671 void
3672 nat_ha_sref_ed_cb (ip4_address_t * out_addr, u16 out_port,
3673  ip4_address_t * eh_addr, u16 eh_port, u8 proto,
3674  u32 fib_index, u32 total_pkts, u64 total_bytes,
3675  u32 thread_index)
3676 {
3677  snat_main_t *sm = &snat_main;
3680  snat_session_t *s;
3682 
3683  tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
3684 
3685  key.l_addr.as_u32 = out_addr->as_u32;
3686  key.l_port = out_port;
3687  key.r_addr.as_u32 = eh_addr->as_u32;
3688  key.r_port = eh_port;
3689  key.proto = proto;
3690  key.fib_index = fib_index;
3691  kv.key[0] = key.as_u64[0];
3692  kv.key[1] = key.as_u64[1];
3693  if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
3694  return;
3695 
3696  s = pool_elt_at_index (tsm->sessions, value.value);
3697  s->total_pkts = total_pkts;
3698  s->total_bytes = total_bytes;
3699 }
3700 
3701 static clib_error_t *
3703 {
3704  snat_main_t *sm = &snat_main;
3705  nat66_main_t *nm = &nat66_main;
3706  u32 translation_buckets = 1024;
3707  u32 translation_memory_size = 128 << 20;
3708  u32 user_buckets = 128;
3709  u32 user_memory_size = 64 << 20;
3710  u32 max_translations_per_user = 100;
3711  u32 outside_vrf_id = 0;
3712  u32 outside_ip6_vrf_id = 0;
3713  u32 inside_vrf_id = 0;
3714  u32 static_mapping_buckets = 1024;
3715  u32 static_mapping_memory_size = 64 << 20;
3716  u32 nat64_bib_buckets = 1024;
3717  u32 nat64_bib_memory_size = 128 << 20;
3718  u32 nat64_st_buckets = 2048;
3719  u32 nat64_st_memory_size = 256 << 20;
3720  u8 static_mapping_only = 0;
3721  u8 static_mapping_connection_tracking = 0;
3723  dslite_main_t *dm = &dslite_main;
3724 
3725  sm->deterministic = 0;
3726  sm->out2in_dpo = 0;
3727  sm->endpoint_dependent = 0;
3728 
3729  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3730  {
3731  if (unformat
3732  (input, "translation hash buckets %d", &translation_buckets))
3733  ;
3734  else if (unformat (input, "translation hash memory %d",
3735  &translation_memory_size));
3736  else if (unformat (input, "user hash buckets %d", &user_buckets))
3737  ;
3738  else if (unformat (input, "user hash memory %d", &user_memory_size))
3739  ;
3740  else if (unformat (input, "max translations per user %d",
3741  &max_translations_per_user))
3742  ;
3743  else if (unformat (input, "outside VRF id %d", &outside_vrf_id))
3744  ;
3745  else if (unformat (input, "outside ip6 VRF id %d", &outside_ip6_vrf_id))
3746  ;
3747  else if (unformat (input, "inside VRF id %d", &inside_vrf_id))
3748  ;
3749  else if (unformat (input, "static mapping only"))
3750  {
3751  static_mapping_only = 1;
3752  if (unformat (input, "connection tracking"))
3753  static_mapping_connection_tracking = 1;
3754  }
3755  else if (unformat (input, "deterministic"))
3756  sm->deterministic = 1;
3757  else if (unformat (input, "nat64 bib hash buckets %d",
3758  &nat64_bib_buckets))
3759  ;
3760  else if (unformat (input, "nat64 bib hash memory %d",
3761  &nat64_bib_memory_size))
3762  ;
3763  else
3764  if (unformat (input, "nat64 st hash buckets %d", &nat64_st_buckets))
3765  ;
3766  else if (unformat (input, "nat64 st hash memory %d",
3767  &nat64_st_memory_size))
3768  ;
3769  else if (unformat (input, "out2in dpo"))
3770  sm->out2in_dpo = 1;
3771  else if (unformat (input, "dslite ce"))
3772  dslite_set_ce (dm, 1);
3773  else if (unformat (input, "endpoint-dependent"))
3774  sm->endpoint_dependent = 1;
3775  else
3776  return clib_error_return (0, "unknown input '%U'",
3777  format_unformat_error, input);
3778  }
3779 
3780  if (sm->deterministic && sm->endpoint_dependent)
3781  return clib_error_return (0,
3782  "deterministic and endpoint-dependent modes are mutually exclusive");
3783 
3784  if (static_mapping_only && (sm->deterministic || sm->endpoint_dependent))
3785  return clib_error_return (0,
3786  "static mapping only mode available only for simple nat");
3787 
3788  if (sm->out2in_dpo && (sm->deterministic || sm->endpoint_dependent))
3789  return clib_error_return (0,
3790  "out2in dpo mode available only for simple nat");
3791 
3792  /* for show commands, etc. */
3793  sm->translation_buckets = translation_buckets;
3794  sm->translation_memory_size = translation_memory_size;
3795  /* do not exceed load factor 10 */
3796  sm->max_translations = 10 * translation_buckets;
3797  sm->user_buckets = user_buckets;
3798  sm->user_memory_size = user_memory_size;
3799  sm->max_translations_per_user = max_translations_per_user;
3800  sm->outside_vrf_id = outside_vrf_id;
3802  outside_vrf_id,
3804  nm->outside_vrf_id = outside_ip6_vrf_id;
3806  outside_ip6_vrf_id,
3808  sm->inside_vrf_id = inside_vrf_id;
3810  inside_vrf_id,
3812  sm->static_mapping_only = static_mapping_only;
3813  sm->static_mapping_connection_tracking = static_mapping_connection_tracking;
3814 
3815  nat64_set_hash (nat64_bib_buckets, nat64_bib_memory_size, nat64_st_buckets,
3816  nat64_st_memory_size);
3817 
3818  if (sm->deterministic)
3819  {
3821  sm->in2out_output_node_index = ~0;
3825  }
3826  else
3827  {
3828  if (sm->endpoint_dependent)
3829  {
3837  nat_affinity_init (vm);
3840  }
3841  else
3842  {
3845  sm->in2out_node_index = snat_in2out_node.index;
3847  sm->out2in_node_index = snat_out2in_node.index;
3851  }
3852  if (!static_mapping_only ||
3853  (static_mapping_only && static_mapping_connection_tracking))
3854  {
3855  /* *INDENT-OFF* */
3856  vec_foreach (tsm, sm->per_thread_data)
3857  {
3858  if (sm->endpoint_dependent)
3859  {
3860  clib_bihash_init_16_8 (&tsm->in2out_ed, "in2out-ed",
3861  translation_buckets,
3862  translation_memory_size);
3863  clib_bihash_set_kvp_format_fn_16_8 (&tsm->in2out_ed,
3865 
3866  clib_bihash_init_16_8 (&tsm->out2in_ed, "out2in-ed",
3867  translation_buckets,
3868  translation_memory_size);
3869  clib_bihash_set_kvp_format_fn_16_8 (&tsm->out2in_ed,
3871  }
3872  else
3873  {
3874  clib_bihash_init_8_8 (&tsm->in2out, "in2out",
3875  translation_buckets,
3876  translation_memory_size);
3877  clib_bihash_set_kvp_format_fn_8_8 (&tsm->in2out,
3879 
3880  clib_bihash_init_8_8 (&tsm->out2in, "out2in",
3881  translation_buckets,
3882  translation_memory_size);
3883  clib_bihash_set_kvp_format_fn_8_8 (&tsm->out2in,
3885  }
3886 
3887  clib_bihash_init_8_8 (&tsm->user_hash, "users", user_buckets,
3888  user_memory_size);
3889  clib_bihash_set_kvp_format_fn_8_8 (&tsm->user_hash,
3890  format_user_kvp);
3891  }
3892  /* *INDENT-ON* */
3893 
3894  }
3895  else
3896  {
3899  }
3900  clib_bihash_init_8_8 (&sm->static_mapping_by_local,
3901  "static_mapping_by_local", static_mapping_buckets,
3902  static_mapping_memory_size);
3903  clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_local,
3905 
3906  clib_bihash_init_8_8 (&sm->static_mapping_by_external,
3907  "static_mapping_by_external",
3908  static_mapping_buckets,
3909  static_mapping_memory_size);
3910  clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_external,
3912  }
3913 
3914  return 0;
3915 }
3916 
3918 
3919 static void
3921  uword opaque,
3922  u32 sw_if_index,
3924  u32 address_length,
3925  u32 if_address_index, u32 is_delete)
3926 {
3927  snat_main_t *sm = &snat_main;
3930  snat_session_key_t m_key;
3932  int i, rv;
3933  ip4_address_t l_addr;
3934 
3935  for (i = 0; i < vec_len (sm->to_resolve); i++)
3936  {
3937  rp = sm->to_resolve + i;
3938  if (rp->addr_only == 0)
3939  continue;
3940  if (rp->sw_if_index == sw_if_index)
3941  goto match;
3942  }
3943 
3944  return;
3945 
3946 match:
3947  m_key.addr.as_u32 = address->as_u32;
3948  m_key.port = rp->addr_only ? 0 : rp->e_port;
3949  m_key.protocol = rp->addr_only ? 0 : rp->proto;
3950  m_key.fib_index = sm->outside_fib_index;
3951  kv.key = m_key.as_u64;
3952  if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
3953  m = 0;
3954  else
3955  m = pool_elt_at_index (sm->static_mappings, value.value);
3956 
3957  if (!is_delete)
3958  {
3959  /* Don't trip over lease renewal, static config */
3960  if (m)
3961  return;
3962  }
3963  else
3964  {
3965  if (!m)
3966  return;
3967  }
3968 
3969  /* Indetity mapping? */
3970  if (rp->l_addr.as_u32 == 0)
3971  l_addr.as_u32 = address[0].as_u32;
3972  else
3973  l_addr.as_u32 = rp->l_addr.as_u32;
3974  /* Add the static mapping */
3975  rv = snat_add_static_mapping (l_addr,
3976  address[0],
3977  rp->l_port,
3978  rp->e_port,
3979  rp->vrf_id,
3980  rp->addr_only, ~0 /* sw_if_index */ ,
3981  rp->proto, !is_delete, rp->twice_nat,
3982  rp->out2in_only, rp->tag, rp->identity_nat);
3983  if (rv)
3984  nat_elog_notice_X1 ("snat_add_static_mapping returned %d", "i4", rv);
3985 }
3986 
3987 static void
3989  uword opaque,
3990  u32 sw_if_index,
3992  u32 address_length,
3993  u32 if_address_index, u32 is_delete)
3994 {
3995  snat_main_t *sm = &snat_main;
3997  ip4_address_t l_addr;
3998  int i, j;
3999  int rv;
4000  u8 twice_nat = 0;
4001  snat_address_t *addresses = sm->addresses;
4002 
4003  for (i = 0; i < vec_len (sm->auto_add_sw_if_indices); i++)
4004  {
4005  if (sw_if_index == sm->auto_add_sw_if_indices[i])
4006  goto match;
4007  }
4008 
4009  for (i = 0; i < vec_len (sm->auto_add_sw_if_indices_twice_nat); i++)
4010  {
4011  twice_nat = 1;
4012  addresses = sm->twice_nat_addresses;
4013  if (sw_if_index == sm->auto_add_sw_if_indices_twice_nat[i])
4014  goto match;
4015  }
4016 
4017  return;
4018 
4019 match:
4020  if (!is_delete)
4021  {
4022  /* Don't trip over lease renewal, static config */
4023  for (j = 0; j < vec_len (addresses); j++)
4024  if (addresses[j].addr.as_u32 == address->as_u32)
4025  return;
4026 
4027  (void) snat_add_address (sm, address, ~0, twice_nat);
4028  /* Scan static map resolution vector */
4029  for (j = 0; j < vec_len (sm->to_resolve); j++)
4030  {
4031  rp = sm->to_resolve + j;
4032  if (rp->addr_only)
4033  continue;
4034  /* On this interface? */
4035  if (rp->sw_if_index == sw_if_index)
4036  {
4037  /* Indetity mapping? */
4038  if (rp->l_addr.as_u32 == 0)
4039  l_addr.as_u32 = address[0].as_u32;
4040  else
4041  l_addr.as_u32 = rp->l_addr.as_u32;
4042  /* Add the static mapping */
4043  rv = snat_add_static_mapping (l_addr,
4044  address[0],
4045  rp->l_port,
4046  rp->e_port,
4047  rp->vrf_id,
4048  rp->addr_only,
4049  ~0 /* sw_if_index */ ,
4050  rp->proto,
4051  rp->is_add, rp->twice_nat,
4052  rp->out2in_only, rp->tag,
4053  rp->identity_nat);
4054  if (rv)
4055  nat_elog_notice_X1 ("snat_add_static_mapping returned %d",
4056  "i4", rv);
4057  }
4058  }
4059  return;
4060  }
4061  else
4062  {
4063  (void) snat_del_address (sm, address[0], 1, twice_nat);
4064  return;
4065  }
4066 }
4067 
4068 
4069 int
4071  u8 twice_nat)
4072 {
4073  ip4_main_t *ip4_main = sm->ip4_main;
4074  ip4_address_t *first_int_addr;
4076  u32 *indices_to_delete = 0;
4077  int i, j;
4078  u32 *auto_add_sw_if_indices =
4079  twice_nat ? sm->
4080  auto_add_sw_if_indices_twice_nat : sm->auto_add_sw_if_indices;
4081 
4082  first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index, 0 /* just want the address */
4083  );
4084 
4085  for (i = 0; i < vec_len (auto_add_sw_if_indices); i++)
4086  {
4087  if (auto_add_sw_if_indices[i] == sw_if_index)
4088  {
4089  if (is_del)
4090  {
4091  /* if have address remove it */
4092  if (first_int_addr)
4093  (void) snat_del_address (sm, first_int_addr[0], 1, twice_nat);
4094  else
4095  {
4096  for (j = 0; j < vec_len (sm->to_resolve); j++)
4097  {
4098  rp = sm->to_resolve + j;
4099  if (rp->sw_if_index == sw_if_index)
4100  vec_add1 (indices_to_delete, j);
4101  }
4102  if (vec_len (indices_to_delete))
4103  {
4104  for (j = vec_len (indices_to_delete) - 1; j >= 0; j--)
4105  vec_del1 (sm->to_resolve, j);
4106  vec_free (indices_to_delete);
4107  }
4108  }
4109  if (twice_nat)
4111  else
4113  }
4114  else
4115  return VNET_API_ERROR_VALUE_EXIST;
4116 
4117  return 0;
4118  }
4119  }
4120 
4121  if (is_del)
4122  return VNET_API_ERROR_NO_SUCH_ENTRY;
4123 
4124  /* add to the auto-address list */
4125  if (twice_nat)
4126  vec_add1 (sm->auto_add_sw_if_indices_twice_nat, sw_if_index);
4127  else
4128  vec_add1 (sm->auto_add_sw_if_indices, sw_if_index);
4129 
4130  /* If the address is already bound - or static - add it now */
4131  if (first_int_addr)
4132  (void) snat_add_address (sm, first_int_addr, ~0, twice_nat);
4133 
4134  return 0;
4135 }
4136 
4137 int
4139  snat_protocol_t proto, u32 vrf_id, int is_in)
4140 {
4143  ip4_header_t ip;
4144  u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
4146  snat_session_t *s;
4147  clib_bihash_8_8_t *t;
4148 
4149  if (sm->endpoint_dependent)
4150  return VNET_API_ERROR_UNSUPPORTED;
4151 
4152  ip.dst_address.as_u32 = ip.src_address.as_u32 = addr->as_u32;
4153  if (sm->num_workers > 1)
4154  tsm =
4156  sm->worker_in2out_cb (&ip, fib_index, 0));
4157  else
4158  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
4159 
4160  key.addr.as_u32 = addr->as_u32;
4161  key.port = clib_host_to_net_u16 (port);
4162  key.protocol = proto;
4163  key.fib_index = fib_index;
4164  kv.key = key.as_u64;
4165  t = is_in ? &tsm->in2out : &tsm->out2in;
4166  if (!clib_bihash_search_8_8 (t, &kv, &value))
4167  {
4168  if (pool_is_free_index (tsm->sessions, value.value))
4169  return VNET_API_ERROR_UNSPECIFIED;
4170 
4171  s = pool_elt_at_index (tsm->sessions, value.value);
4172  nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
4173  nat44_delete_session (sm, s, tsm - sm->per_thread_data);
4174  return 0;
4175  }
4176 
4177  return VNET_API_ERROR_NO_SUCH_ENTRY;
4178 }
4179 
4180 int
4182  ip4_address_t * eh_addr, u16 eh_port, u8 proto,
4183  u32 vrf_id, int is_in)
4184 {
4185  ip4_header_t ip;
4186  clib_bihash_16_8_t *t;
4189  u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
4190  snat_session_t *s;
4192 
4193  if (!sm->endpoint_dependent)
4194  return VNET_API_ERROR_FEATURE_DISABLED;
4195 
4196  ip.dst_address.as_u32 = ip.src_address.as_u32 = addr->as_u32;
4197  if (sm->num_workers > 1)
4198  tsm =
4200  sm->worker_in2out_cb (&ip, fib_index, 0));
4201  else
4202  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
4203 
4204  t = is_in ? &tsm->in2out_ed : &tsm->out2in_ed;
4205  key.l_addr.as_u32 = addr->as_u32;
4206  key.r_addr.as_u32 = eh_addr->as_u32;
4207  key.l_port = clib_host_to_net_u16 (port);
4208  key.r_port = clib_host_to_net_u16 (eh_port);
4209  key.proto = proto;
4210  key.fib_index = fib_index;
4211  kv.key[0] = key.as_u64[0];
4212  kv.key[1] = key.as_u64[1];
4213  if (clib_bihash_search_16_8 (t, &kv, &value))
4214  return VNET_API_ERROR_NO_SUCH_ENTRY;
4215 
4216  if (pool_is_free_index (tsm->sessions, value.value))
4217  return VNET_API_ERROR_UNSPECIFIED;
4218  s = pool_elt_at_index (tsm->sessions, value.value);
4219  nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
4220  nat44_delete_session (sm, s, tsm - sm->per_thread_data);
4221  return 0;
4222 }
4223 
4224 void
4225 nat_set_alloc_addr_and_port_mape (u16 psid, u16 psid_offset, u16 psid_length)
4226 {
4227  snat_main_t *sm = &snat_main;
4228 
4229  sm->addr_and_port_alloc_alg = NAT_ADDR_AND_PORT_ALLOC_ALG_MAPE;
4231  sm->psid = psid;
4232  sm->psid_offset = psid_offset;
4233  sm->psid_length = psid_length;
4234 }
4235 
4236 void
4238 {
4239  snat_main_t *sm = &snat_main;
4240 
4241  sm->addr_and_port_alloc_alg = NAT_ADDR_AND_PORT_ALLOC_ALG_RANGE;
4243  sm->start_port = start_port;
4244  sm->end_port = end_port;
4245 }
4246 
4247 void
4249 {
4250  snat_main_t *sm = &snat_main;
4251 
4252  sm->addr_and_port_alloc_alg = NAT_ADDR_AND_PORT_ALLOC_ALG_DEFAULT;
4254 }
4255 
4256 /*
4257  * fd.io coding-style-patch-verification: ON
4258  *
4259  * Local Variables:
4260  * eval: (c-set-style "gnu")
4261  * End:
4262  */
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:1622
#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:268
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:2822
#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
u32 index
Definition: node.h:279
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:258
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:967
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:332
u16 port_per_thread
Definition: nat.h:521
u32 vlib_frame_queue_main_init(u32 node_index, u32 frame_queue_nelts)
Definition: threads.c:1766
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:3672
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:2920
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
clib_memset(h->entries, 0, sizeof(h->entries[0])*entries)
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:4181
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:3988
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:2772
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:2685
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:2972
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:783
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:3374
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:397
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:1341
void fib_table_entry_special_remove(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source)
Remove a &#39;special&#39; entry from the FIB.
Definition: fib_table.c:407
u8 * format_static_mapping_kvp(u8 *s, va_list *args)
Definition: nat.c:2906
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:3524
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:2934
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.
Aggregrate type for a prefix.
Definition: fib_types.h:203
#define clib_error_return(e, args...)
Definition: error.h:99
#define is_fwd_bypass_session(s)
Check if NAT session is forwarding bypass.
Definition: nat.h:733
static u32 snat_get_worker_in2out_cb(ip4_header_t *ip0, u32 rx_fib_index0, u8 is_output)
Definition: nat.c:2952
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:1075
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:3635
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:3920
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:2512
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:2438
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:1528
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:2671
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:3464
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:3498
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:4248
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:1248
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:1448
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:312
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:2870
vlib_node_registration_t snat_in2out_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_node)
Definition: in2out.c:1576
ip4_address_t l_addr
Definition: nat.h: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:864
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:2237
u8 * format_session_kvp(u8 *s, va_list *args)
Definition: nat.c:2893
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:315
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:1268
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:2663
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:4237
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:1134
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:1595
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:4138
snat_address_t * twice_nat_addresses
Definition: nat.h:558
#define VNET_FEATURES(...)
Definition: feature.h:435
#define A(x)
Definition: main.c:1020
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:2268
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:3212
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:245
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:4070
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:921
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:1609
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:3702
static u32 nat44_ed_get_worker_in2out_cb(ip4_header_t *ip, u32 rx_fib_index, u8 is_output)
Definition: nat.c:3109
#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:4225
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:274
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:2476
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