FD.io VPP  v20.05-21-gb1500e9ff
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/nat_inlines.h>
29 #include <nat/nat44/inlines.h>
30 #include <nat/nat_affinity.h>
31 #include <nat/nat_syslog.h>
32 #include <nat/nat_ha.h>
33 #include <vnet/fib/fib_table.h>
34 #include <vnet/fib/ip4_fib.h>
36 #include <vppinfra/bihash_16_8.h>
37 #include <nat/nat44/ed_inlines.h>
38 
39 #include <vpp/app/version.h>
40 
42 
45 
46 /* *INDENT-OFF* */
47 /* Hook up input features */
48 VNET_FEATURE_INIT (nat_pre_in2out, static) = {
49  .arc_name = "ip4-unicast",
50  .node_name = "nat-pre-in2out",
51  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
52  "ip4-sv-reassembly-feature"),
53 };
54 VNET_FEATURE_INIT (nat_pre_out2in, static) = {
55  .arc_name = "ip4-unicast",
56  .node_name = "nat-pre-out2in",
57  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
58  "ip4-dhcp-client-detect",
59  "ip4-sv-reassembly-feature"),
60 };
61 VNET_FEATURE_INIT (snat_in2out_worker_handoff, static) = {
62  .arc_name = "ip4-unicast",
63  .node_name = "nat44-in2out-worker-handoff",
64  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
65 };
66 VNET_FEATURE_INIT (snat_out2in_worker_handoff, static) = {
67  .arc_name = "ip4-unicast",
68  .node_name = "nat44-out2in-worker-handoff",
69  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
70  "ip4-dhcp-client-detect"),
71 };
72 VNET_FEATURE_INIT (ip4_snat_in2out, static) = {
73  .arc_name = "ip4-unicast",
74  .node_name = "nat44-in2out",
75  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"),
76 };
77 VNET_FEATURE_INIT (ip4_snat_out2in, static) = {
78  .arc_name = "ip4-unicast",
79  .node_name = "nat44-out2in",
80  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature",
81  "ip4-dhcp-client-detect"),
82 };
83 VNET_FEATURE_INIT (ip4_nat_classify, static) = {
84  .arc_name = "ip4-unicast",
85  .node_name = "nat44-classify",
86  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"),
87 };
88 VNET_FEATURE_INIT (ip4_snat_det_in2out, static) = {
89  .arc_name = "ip4-unicast",
90  .node_name = "nat44-det-in2out",
91  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"),
92 };
93 VNET_FEATURE_INIT (ip4_snat_det_out2in, static) = {
94  .arc_name = "ip4-unicast",
95  .node_name = "nat44-det-out2in",
96  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature",
97  "ip4-dhcp-client-detect"),
98 };
99 VNET_FEATURE_INIT (ip4_nat_det_classify, static) = {
100  .arc_name = "ip4-unicast",
101  .node_name = "nat44-det-classify",
102  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"),
103 };
104 VNET_FEATURE_INIT (ip4_nat44_ed_in2out, static) = {
105  .arc_name = "ip4-unicast",
106  .node_name = "nat44-ed-in2out",
107  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"),
108 };
109 VNET_FEATURE_INIT (ip4_nat44_ed_out2in, static) = {
110  .arc_name = "ip4-unicast",
111  .node_name = "nat44-ed-out2in",
112  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature",
113  "ip4-dhcp-client-detect"),
114 };
115 VNET_FEATURE_INIT (ip4_nat44_ed_classify, static) = {
116  .arc_name = "ip4-unicast",
117  .node_name = "nat44-ed-classify",
118  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"),
119 };
120 VNET_FEATURE_INIT (ip4_nat_handoff_classify, static) = {
121  .arc_name = "ip4-unicast",
122  .node_name = "nat44-handoff-classify",
123  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"),
124 };
125 VNET_FEATURE_INIT (ip4_snat_in2out_fast, static) = {
126  .arc_name = "ip4-unicast",
127  .node_name = "nat44-in2out-fast",
128  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"),
129 };
130 VNET_FEATURE_INIT (ip4_snat_out2in_fast, static) = {
131  .arc_name = "ip4-unicast",
132  .node_name = "nat44-out2in-fast",
133  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature",
134  "ip4-dhcp-client-detect"),
135 };
136 VNET_FEATURE_INIT (ip4_snat_hairpin_dst, static) = {
137  .arc_name = "ip4-unicast",
138  .node_name = "nat44-hairpin-dst",
139  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"),
140 };
141 VNET_FEATURE_INIT (ip4_nat44_ed_hairpin_dst, static) = {
142  .arc_name = "ip4-unicast",
143  .node_name = "nat44-ed-hairpin-dst",
144  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"),
145 };
146 
147 /* Hook up output features */
148 VNET_FEATURE_INIT (ip4_snat_in2out_output, static) = {
149  .arc_name = "ip4-output",
150  .node_name = "nat44-in2out-output",
151  .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa","ip4-sv-reassembly-output-feature"),
152 };
153 VNET_FEATURE_INIT (ip4_snat_in2out_output_worker_handoff, static) = {
154  .arc_name = "ip4-output",
155  .node_name = "nat44-in2out-output-worker-handoff",
156  .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa","ip4-sv-reassembly-output-feature"),
157 };
158 VNET_FEATURE_INIT (ip4_snat_hairpin_src, static) = {
159  .arc_name = "ip4-output",
160  .node_name = "nat44-hairpin-src",
161  .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa","ip4-sv-reassembly-output-feature"),
162 };
163 VNET_FEATURE_INIT (ip4_nat44_ed_in2out_output, static) = {
164  .arc_name = "ip4-output",
165  .node_name = "nat44-ed-in2out-output",
166  .runs_after = VNET_FEATURES ("ip4-sv-reassembly-output-feature"),
167  .runs_before = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
168 };
169 VNET_FEATURE_INIT (ip4_nat44_ed_hairpin_src, static) = {
170  .arc_name = "ip4-output",
171  .node_name = "nat44-ed-hairpin-src",
172  .runs_after = VNET_FEATURES ("ip4-sv-reassembly-output-feature"),
173  .runs_before = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
174 };
175 
176 /* Hook up ip4-local features */
177 VNET_FEATURE_INIT (ip4_nat_hairpinning, static) =
178 {
179  .arc_name = "ip4-local",
180  .node_name = "nat44-hairpinning",
181  .runs_before = VNET_FEATURES("ip4-local-end-of-arc"),
182 };
183 VNET_FEATURE_INIT (ip4_nat44_ed_hairpinning, static) =
184 {
185  .arc_name = "ip4-local",
186  .node_name = "nat44-ed-hairpinning",
187  .runs_before = VNET_FEATURES("ip4-local-end-of-arc"),
188 };
189 
190 
192  .version = VPP_BUILD_VER,
193  .description = "Network Address Translation (NAT)",
194 };
195 /* *INDENT-ON* */
196 
197 void
198 nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index,
199  u8 is_ha)
200 {
203  u8 proto;
204  u16 r_port, l_port;
205  ip4_address_t *l_addr, *r_addr;
206  u32 fib_index = 0;
207  clib_bihash_kv_16_8_t ed_kv;
209  vec_elt_at_index (sm->per_thread_data, thread_index);
210 
211  if (is_fwd_bypass_session (s))
212  {
214  {
215  make_ed_kv (&s->in2out.addr, &s->ext_host_addr, s->in2out.port, 0,
216  0, 0, ~0ULL, &ed_kv);
217  }
218  else
219  {
220  l_port = s->in2out.port;
221  r_port = s->ext_host_port;
222  l_addr = &s->in2out.addr;
223  r_addr = &s->ext_host_addr;
224  proto = nat_proto_to_ip_proto (s->in2out.protocol);
225  make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL,
226  &ed_kv);
227  }
228  if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0))
229  nat_elog_warn ("in2out_ed key del failed");
230  return;
231  }
232 
233  /* session lookup tables */
234  if (is_ed_session (s))
235  {
236  if (is_affinity_sessions (s))
237  nat_affinity_unlock (s->ext_host_addr, s->out2in.addr,
238  s->in2out.protocol, s->out2in.port);
239  l_addr = &s->out2in.addr;
240  r_addr = &s->ext_host_addr;
241  fib_index = s->out2in.fib_index;
243  {
244  proto = s->in2out.port;
245  r_port = 0;
246  l_port = 0;
247  }
248  else
249  {
250  proto = nat_proto_to_ip_proto (s->in2out.protocol);
251  l_port = s->out2in.port;
252  r_port = s->ext_host_port;
253  }
254  make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL,
255  &ed_kv);
256  if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &ed_kv, 0))
257  nat_elog_warn ("out2in_ed key del failed");
258  l_addr = &s->in2out.addr;
259  fib_index = s->in2out.fib_index;
260  if (!snat_is_unk_proto_session (s))
261  l_port = s->in2out.port;
262  if (is_twice_nat_session (s))
263  {
264  r_addr = &s->ext_host_nat_addr;
265  r_port = s->ext_host_nat_port;
266  }
267  make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL,
268  &ed_kv);
269  if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0))
270  nat_elog_warn ("in2out_ed key del failed");
271 
272  if (!is_ha)
273  nat_syslog_nat44_sdel (s->user_index, s->in2out.fib_index,
274  &s->in2out.addr, s->in2out.port,
275  &s->ext_host_nat_addr, s->ext_host_nat_port,
276  &s->out2in.addr, s->out2in.port,
277  &s->ext_host_addr, s->ext_host_port,
278  s->in2out.protocol, is_twice_nat_session (s));
279  }
280  else
281  {
282  kv.key = s->in2out.as_u64;
283  if (clib_bihash_add_del_8_8 (&tsm->in2out, &kv, 0))
284  nat_elog_warn ("in2out key del failed");
285  kv.key = s->out2in.as_u64;
286  if (clib_bihash_add_del_8_8 (&tsm->out2in, &kv, 0))
287  nat_elog_warn ("out2in key del failed");
288 
289  if (!is_ha)
290  nat_syslog_nat44_apmdel (s->user_index, s->in2out.fib_index,
291  &s->in2out.addr, s->in2out.port,
292  &s->out2in.addr, s->out2in.port,
293  s->in2out.protocol);
294  }
295 
297  return;
298 
299  if (!is_ha)
300  {
301  /* log NAT event */
303  s->in2out.addr.as_u32,
304  s->out2in.addr.as_u32,
305  s->in2out.protocol,
306  s->in2out.port,
307  s->out2in.port,
308  s->in2out.fib_index);
309 
310  nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
311  s->ext_host_port, s->out2in.protocol, s->out2in.fib_index,
312  thread_index);
313  }
314 
315  /* Twice NAT address and port for external host */
316  if (is_twice_nat_session (s))
317  {
318  key.protocol = s->in2out.protocol;
319  key.port = s->ext_host_nat_port;
320  key.addr.as_u32 = s->ext_host_nat_addr.as_u32;
322  thread_index, &key);
323  }
324 
325  if (snat_is_session_static (s))
326  return;
327 
329  &s->out2in);
330 }
331 
332 int
334 {
335  snat_main_t *sm = &snat_main;
336  u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
338 
339  if (len <= fib_index)
340  {
341  vec_validate (sm->max_translations_per_fib, fib_index + 1);
342 
343  for (; len < vec_len (sm->max_translations_per_fib); len++)
345  }
346 
347  sm->max_translations_per_fib[fib_index] = session_limit;
348  return 0;
349 }
350 
351 void
352 nat44_free_session_data (snat_main_t * sm, snat_session_t * s,
353  u32 thread_index, u8 is_ha)
354 {
356  u8 proto;
357  u16 r_port, l_port;
358  ip4_address_t *l_addr, *r_addr;
359  u32 fib_index;
360  clib_bihash_kv_16_8_t ed_kv;
362  vec_elt_at_index (sm->per_thread_data, thread_index);
363 
364  if (is_fwd_bypass_session (s))
365  {
367  {
368  proto = s->in2out.port;
369  r_port = 0;
370  l_port = 0;
371  }
372  else
373  {
374  proto = nat_proto_to_ip_proto (s->in2out.protocol);
375  l_port = s->in2out.port;
376  r_port = s->ext_host_port;
377  }
378 
379  l_addr = &s->in2out.addr;
380  r_addr = &s->ext_host_addr;
381  fib_index = 0;
382  make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL,
383  &ed_kv);
384 
385  if (PREDICT_FALSE
386  (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0)))
387  nat_elog_warn ("in2out_ed key del failed");
388  return;
389  }
390 
391  /* session lookup tables */
392  if (is_affinity_sessions (s))
393  nat_affinity_unlock (s->ext_host_addr, s->out2in.addr,
394  s->in2out.protocol, s->out2in.port);
395  l_addr = &s->out2in.addr;
396  r_addr = &s->ext_host_addr;
397  fib_index = s->out2in.fib_index;
399  {
400  proto = s->in2out.port;
401  r_port = 0;
402  l_port = 0;
403  }
404  else
405  {
406  proto = nat_proto_to_ip_proto (s->in2out.protocol);
407  l_port = s->out2in.port;
408  r_port = s->ext_host_port;
409  }
410  make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL,
411  &ed_kv);
412 
413  if (PREDICT_FALSE (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &ed_kv, 0)))
414  nat_elog_warn ("out2in_ed key del failed");
415 
416  l_addr = &s->in2out.addr;
417  fib_index = s->in2out.fib_index;
418 
419  if (!snat_is_unk_proto_session (s))
420  l_port = s->in2out.port;
421 
422  if (is_twice_nat_session (s))
423  {
424  r_addr = &s->ext_host_nat_addr;
425  r_port = s->ext_host_nat_port;
426  }
427  make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL,
428  &ed_kv);
429 
430  if (PREDICT_FALSE (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0)))
431  nat_elog_warn ("in2out_ed key del failed");
432 
433  if (!is_ha)
434  {
435  nat_syslog_nat44_sdel (s->user_index, s->in2out.fib_index,
436  &s->in2out.addr, s->in2out.port,
437  &s->ext_host_nat_addr, s->ext_host_nat_port,
438  &s->out2in.addr, s->out2in.port,
439  &s->ext_host_addr, s->ext_host_port,
440  s->in2out.protocol, is_twice_nat_session (s));
441  }
442 
444  return;
445 
446  // is this correct ?
447  if (!is_ha)
448  {
450  s->in2out.addr.as_u32,
451  s->out2in.addr.as_u32,
452  s->in2out.protocol,
453  s->in2out.port,
454  s->out2in.port,
455  s->in2out.fib_index);
456  nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
457  s->ext_host_port, s->out2in.protocol, s->out2in.fib_index,
458  thread_index);
459  }
460 
461  /* Twice NAT address and port for external host */
462  if (is_twice_nat_session (s))
463  {
464  key.protocol = s->in2out.protocol;
465  key.port = s->ext_host_nat_port;
466  key.addr.as_u32 = s->ext_host_nat_addr.as_u32;
468  thread_index, &key);
469  }
470 
471  if (snat_is_session_static (s))
472  return;
473 
474  // should be called for every dynamic session
476  &s->out2in);
477 }
478 
479 
480 snat_user_t *
482  u32 thread_index)
483 {
484  snat_user_t *u = 0;
485  snat_user_key_t user_key;
487  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
488  dlist_elt_t *per_user_list_head_elt;
489 
490  user_key.addr.as_u32 = addr->as_u32;
491  user_key.fib_index = fib_index;
492  kv.key = user_key.as_u64;
493 
494  /* Ever heard of the "user" = src ip4 address before? */
495  if (clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
496  {
497  /* no, make a new one */
498  pool_get (tsm->users, u);
499  clib_memset (u, 0, sizeof (*u));
500 
501  u->addr.as_u32 = addr->as_u32;
502  u->fib_index = fib_index;
503 
504  pool_get (tsm->list_pool, per_user_list_head_elt);
505 
506  u->sessions_per_user_list_head_index = per_user_list_head_elt -
507  tsm->list_pool;
508 
510 
511  kv.value = u - tsm->users;
512 
513  /* add user */
514  if (clib_bihash_add_del_8_8 (&tsm->user_hash, &kv, 1))
515  {
516  nat_elog_warn ("user_hash key add failed");
517  nat44_delete_user_with_no_session (sm, u, thread_index);
518  return NULL;
519  }
520 
521  vlib_set_simple_counter (&sm->total_users, thread_index, 0,
522  pool_elts (tsm->users));
523  }
524  else
525  {
526  u = pool_elt_at_index (tsm->users, value.value);
527  }
528 
529  return u;
530 }
531 
532 snat_session_t *
534  u32 thread_index, f64 now)
535 {
536  snat_session_t *s;
537  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
538  u32 oldest_per_user_translation_list_index, session_index;
539  dlist_elt_t *oldest_per_user_translation_list_elt;
540  dlist_elt_t *per_user_translation_list_elt;
541 
542  /* Over quota? Recycle the least recently used translation */
544  {
545  oldest_per_user_translation_list_index =
548 
549  ASSERT (oldest_per_user_translation_list_index != ~0);
550 
551  /* Add it back to the end of the LRU list */
554  oldest_per_user_translation_list_index);
555  /* Get the list element */
556  oldest_per_user_translation_list_elt =
558  oldest_per_user_translation_list_index);
559 
560  /* Get the session index from the list element */
561  session_index = oldest_per_user_translation_list_elt->value;
562 
563  /* Get the session */
564  s = pool_elt_at_index (tsm->sessions, session_index);
565  nat_free_session_data (sm, s, thread_index, 0);
566  if (snat_is_session_static (s))
567  u->nstaticsessions--;
568  else
569  u->nsessions--;
570  s->flags = 0;
571  s->total_bytes = 0;
572  s->total_pkts = 0;
573  s->state = 0;
574  s->ext_host_addr.as_u32 = 0;
575  s->ext_host_port = 0;
576  s->ext_host_nat_addr.as_u32 = 0;
577  s->ext_host_nat_port = 0;
578  }
579  else
580  {
581  pool_get (tsm->sessions, s);
582  clib_memset (s, 0, sizeof (*s));
583 
584  /* Create list elts */
585  pool_get (tsm->list_pool, per_user_translation_list_elt);
587  per_user_translation_list_elt - tsm->list_pool);
588 
589  per_user_translation_list_elt->value = s - tsm->sessions;
590  s->per_user_index = per_user_translation_list_elt - tsm->list_pool;
591  s->per_user_list_head_index = u->sessions_per_user_list_head_index;
592 
594  s->per_user_list_head_index,
595  per_user_translation_list_elt - tsm->list_pool);
596 
597  s->user_index = u - tsm->users;
598  vlib_set_simple_counter (&sm->total_sessions, thread_index, 0,
599  pool_elts (tsm->sessions));
600  }
601 
602  s->ha_last_refreshed = now;
603 
604  return s;
605 }
606 
607 void
609  int is_add)
610 {
611  fib_prefix_t prefix = {
612  .fp_len = p_len,
613  .fp_proto = FIB_PROTOCOL_IP4,
614  .fp_addr = {
615  .ip4.as_u32 = addr->as_u32,
616  },
617  };
618  u32 fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
619 
620  if (is_add)
622  &prefix,
623  nat_fib_src_low,
628  NULL,
629  sw_if_index,
630  ~0, 1, NULL, FIB_ROUTE_PATH_FLAG_NONE);
631  else
632  fib_table_entry_delete (fib_index, &prefix, nat_fib_src_low);
633 }
634 
635 int
637  u8 twice_nat)
638 {
639  snat_address_t *ap;
642 
643  if (twice_nat && !sm->endpoint_dependent)
644  return VNET_API_ERROR_FEATURE_DISABLED;
645 
646  /* Check if address already exists */
647  /* *INDENT-OFF* */
648  vec_foreach (ap, twice_nat ? sm->twice_nat_addresses : sm->addresses)
649  {
650  if (ap->addr.as_u32 == addr->as_u32)
651  return VNET_API_ERROR_VALUE_EXIST;
652  }
653  /* *INDENT-ON* */
654 
655  if (twice_nat)
656  vec_add2 (sm->twice_nat_addresses, ap, 1);
657  else
658  vec_add2 (sm->addresses, ap, 1);
659 
660  ap->addr = *addr;
661  if (vrf_id != ~0)
662  ap->fib_index =
664  nat_fib_src_low);
665  else
666  ap->fib_index = ~0;
667 #define _(N, i, n, s) \
668  clib_memset(ap->busy_##n##_port_refcounts, 0, sizeof(ap->busy_##n##_port_refcounts));\
669  ap->busy_##n##_ports = 0; \
670  ap->busy_##n##_ports_per_thread = 0;\
671  vec_validate_init_empty (ap->busy_##n##_ports_per_thread, tm->n_vlib_mains - 1, 0);
673 #undef _
674  if (twice_nat)
675  return 0;
676 
677  /* Add external address to FIB */
678  /* *INDENT-OFF* */
679  pool_foreach (i, sm->interfaces,
680  ({
681  if (nat_interface_is_inside(i) || sm->out2in_dpo)
682  continue;
683 
684  snat_add_del_addr_to_fib(addr, 32, i->sw_if_index, 1);
685  break;
686  }));
688  ({
689  if (nat_interface_is_inside(i) || sm->out2in_dpo)
690  continue;
691 
692  snat_add_del_addr_to_fib(addr, 32, i->sw_if_index, 1);
693  break;
694  }));
695  /* *INDENT-ON* */
696 
697  return 0;
698 }
699 
700 static int
702 {
704  /* *INDENT-OFF* */
706  ({
707  if (is_addr_only_static_mapping (m) ||
708  is_out2in_only_static_mapping (m) ||
709  is_identity_static_mapping (m))
710  continue;
711  if (m->external_addr.as_u32 == addr.as_u32)
712  return 1;
713  }));
714  /* *INDENT-ON* */
715 
716  return 0;
717 }
718 
719 static void
721  ip4_address_t l_addr,
722  u16 l_port,
724  u16 e_port,
725  u32 vrf_id,
727  int addr_only, int is_add, u8 * tag,
728  int twice_nat, int out2in_only,
729  int identity_nat)
730 {
732 
733  vec_add2 (sm->to_resolve, rp, 1);
734  rp->l_addr.as_u32 = l_addr.as_u32;
735  rp->l_port = l_port;
736  rp->sw_if_index = sw_if_index;
737  rp->e_port = e_port;
738  rp->vrf_id = vrf_id;
739  rp->proto = proto;
740  rp->addr_only = addr_only;
741  rp->is_add = is_add;
742  rp->twice_nat = twice_nat;
743  rp->out2in_only = out2in_only;
744  rp->identity_nat = identity_nat;
745  rp->tag = vec_dup (tag);
746 }
747 
748 static u32
750 {
751  snat_main_t *sm = &snat_main;
752  u32 thread_idx = sm->num_workers;
753  if (sm->num_workers > 1)
754  {
755  thread_idx =
756  sm->first_worker_index +
757  sm->workers[(e_port - 1024) / sm->port_per_thread];
758  }
759  return thread_idx;
760 }
761 
762 void
765  snat_user_key_t u_key, int addr_only,
766  ip4_address_t e_addr, u16 e_port)
767 {
769  kv.key = u_key.as_u64;
770  u64 user_index;
771  dlist_elt_t *head, *elt;
772  snat_user_t *u;
773  snat_session_t *s;
774  u32 elt_index, head_index, ses_index;
775  if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
776  {
777  user_index = value.value;
778  u = pool_elt_at_index (tsm->users, user_index);
779  if (u->nstaticsessions)
780  {
781  head_index = u->sessions_per_user_list_head_index;
782  head = pool_elt_at_index (tsm->list_pool, head_index);
783  elt_index = head->next;
784  elt = pool_elt_at_index (tsm->list_pool, elt_index);
785  ses_index = elt->value;
786  while (ses_index != ~0)
787  {
788  s = pool_elt_at_index (tsm->sessions, ses_index);
789  elt = pool_elt_at_index (tsm->list_pool, elt->next);
790  ses_index = elt->value;
791 
792  if (!addr_only)
793  {
794  if ((s->out2in.addr.as_u32 != e_addr.as_u32) ||
795  (clib_net_to_host_u16 (s->out2in.port) != e_port))
796  continue;
797  }
798 
799  if (is_lb_session (s))
800  continue;
801 
802  if (!snat_is_session_static (s))
803  continue;
804 
805  nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
806  nat44_delete_session (sm, s, tsm - sm->per_thread_data);
807 
808  if (!addr_only)
809  break;
810  }
811  }
812  }
813 }
814 
815 void
818  ip4_address_t l_addr,
819  u16 l_port,
820  u8 protocol,
821  u32 fib_index, int addr_only,
822  ip4_address_t e_addr, u16 e_port)
823 {
824  snat_session_t *s;
825  u32 *indexes_to_free = NULL;
826  /* *INDENT-OFF* */
827  pool_foreach (s, tsm->sessions, {
828  if (s->in2out.fib_index != fib_index ||
829  s->in2out.addr.as_u32 != l_addr.as_u32)
830  {
831  continue;
832  }
833  if (!addr_only)
834  {
835  if ((s->out2in.addr.as_u32 != e_addr.as_u32) ||
836  (clib_net_to_host_u16 (s->out2in.port) != e_port) ||
837  clib_net_to_host_u16 (s->in2out.port) != l_port ||
838  s->in2out.protocol != protocol)
839  continue;
840  }
841 
842  if (is_lb_session (s))
843  continue;
844  if (!snat_is_session_static (s))
845  continue;
846  nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
847  vec_add1 (indexes_to_free, s - tsm->sessions);
848  if (!addr_only)
849  break;
850  });
851  /* *INDENT-ON* */
852  u32 *ses_index;
853  vec_foreach (ses_index, indexes_to_free)
854  {
855  s = pool_elt_at_index (tsm->sessions, *ses_index);
856  nat_ed_session_delete (sm, s, tsm - sm->per_thread_data, 1);
857  }
858  vec_free (indexes_to_free);
859 }
860 
861 int
863  u16 l_port, u16 e_port, u32 vrf_id, int addr_only,
864  u32 sw_if_index, nat_protocol_t proto, int is_add,
865  twice_nat_type_t twice_nat, u8 out2in_only, u8 * tag,
866  u8 identity_nat)
867 {
868  snat_main_t *sm = &snat_main;
870  snat_session_key_t m_key;
872  snat_address_t *a = 0;
873  u32 fib_index = ~0;
874  snat_interface_t *interface;
875  int i;
877  snat_user_key_t u_key;
878  snat_user_t *u;
879  dlist_elt_t *head, *elt;
880  u32 elt_index, head_index;
881  u32 ses_index;
882  u64 user_index;
883  snat_session_t *s;
884  snat_static_map_resolve_t *rp, *rp_match = 0;
885  nat44_lb_addr_port_t *local;
886  u32 find = ~0;
887 
888  if (!sm->endpoint_dependent)
889  {
890  if (twice_nat || out2in_only)
891  return VNET_API_ERROR_FEATURE_DISABLED;
892  }
893 
894  /* If the external address is a specific interface address */
895  if (sw_if_index != ~0)
896  {
897  ip4_address_t *first_int_addr;
898 
899  for (i = 0; i < vec_len (sm->to_resolve); i++)
900  {
901  rp = sm->to_resolve + i;
902  if (rp->sw_if_index != sw_if_index ||
903  rp->l_addr.as_u32 != l_addr.as_u32 ||
904  rp->vrf_id != vrf_id || rp->addr_only != addr_only)
905  continue;
906 
907  if (!addr_only)
908  {
909  if ((rp->l_port != l_port && rp->e_port != e_port)
910  || rp->proto != proto)
911  continue;
912  }
913 
914  rp_match = rp;
915  break;
916  }
917 
918  /* Might be already set... */
919  first_int_addr = ip4_interface_first_address
920  (sm->ip4_main, sw_if_index, 0 /* just want the address */ );
921 
922  if (is_add)
923  {
924  if (rp_match)
925  return VNET_API_ERROR_VALUE_EXIST;
926 
928  (sm, l_addr, l_port, sw_if_index, e_port, vrf_id, proto,
929  addr_only, is_add, tag, twice_nat, out2in_only, identity_nat);
930 
931  /* DHCP resolution required? */
932  if (first_int_addr == 0)
933  {
934  return 0;
935  }
936  else
937  {
938  e_addr.as_u32 = first_int_addr->as_u32;
939  /* Identity mapping? */
940  if (l_addr.as_u32 == 0)
941  l_addr.as_u32 = e_addr.as_u32;
942  }
943  }
944  else
945  {
946  if (!rp_match)
947  return VNET_API_ERROR_NO_SUCH_ENTRY;
948 
949  vec_del1 (sm->to_resolve, i);
950 
951  if (first_int_addr)
952  {
953  e_addr.as_u32 = first_int_addr->as_u32;
954  /* Identity mapping? */
955  if (l_addr.as_u32 == 0)
956  l_addr.as_u32 = e_addr.as_u32;
957  }
958  else
959  return 0;
960  }
961  }
962 
963  m_key.addr = e_addr;
964  m_key.port = addr_only ? 0 : e_port;
965  m_key.protocol = addr_only ? 0 : proto;
966  m_key.fib_index = 0;
967  kv.key = m_key.as_u64;
968  if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
969  m = 0;
970  else
971  m = pool_elt_at_index (sm->static_mappings, value.value);
972 
973  if (is_add)
974  {
975  if (m)
976  {
978  {
979  /* *INDENT-OFF* */
980  pool_foreach (local, m->locals,
981  ({
982  if (local->vrf_id == vrf_id)
983  return VNET_API_ERROR_VALUE_EXIST;
984  }));
985  /* *INDENT-ON* */
986  pool_get (m->locals, local);
987  local->vrf_id = vrf_id;
988  local->fib_index =
991  m_key.addr = m->local_addr;
992  m_key.port = m->local_port;
993  m_key.protocol = m->proto;
994  m_key.fib_index = local->fib_index;
995  kv.key = m_key.as_u64;
996  kv.value = m - sm->static_mappings;
997  clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1);
998  return 0;
999  }
1000  else
1001  return VNET_API_ERROR_VALUE_EXIST;
1002  }
1003 
1004  if (twice_nat && addr_only)
1005  return VNET_API_ERROR_UNSUPPORTED;
1006 
1007  /* Convert VRF id to FIB index */
1008  if (vrf_id != ~0)
1009  fib_index =
1011  nat_fib_src_low);
1012  /* If not specified use inside VRF id from SNAT plugin startup config */
1013  else
1014  {
1015  fib_index = sm->inside_fib_index;
1016  vrf_id = sm->inside_vrf_id;
1018  }
1019 
1020  if (!(out2in_only || identity_nat))
1021  {
1022  m_key.addr = l_addr;
1023  m_key.port = addr_only ? 0 : l_port;
1024  m_key.protocol = addr_only ? 0 : proto;
1025  m_key.fib_index = fib_index;
1026  kv.key = m_key.as_u64;
1027  if (!clib_bihash_search_8_8
1028  (&sm->static_mapping_by_local, &kv, &value))
1029  return VNET_API_ERROR_VALUE_EXIST;
1030  }
1031 
1032  /* Find external address in allocated addresses and reserve port for
1033  address and port pair mapping when dynamic translations enabled */
1034  if (!(addr_only || sm->static_mapping_only || out2in_only))
1035  {
1036  for (i = 0; i < vec_len (sm->addresses); i++)
1037  {
1038  if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
1039  {
1040  a = sm->addresses + i;
1041  /* External port must be unused */
1042  switch (proto)
1043  {
1044 #define _(N, j, n, s) \
1045  case NAT_PROTOCOL_##N: \
1046  if (a->busy_##n##_port_refcounts[e_port]) \
1047  return VNET_API_ERROR_INVALID_VALUE; \
1048  ++a->busy_##n##_port_refcounts[e_port]; \
1049  if (e_port > 1024) \
1050  { \
1051  a->busy_##n##_ports++; \
1052  a->busy_##n##_ports_per_thread[get_thread_idx_by_port(e_port)]++; \
1053  } \
1054  break;
1056 #undef _
1057  default:
1058  nat_elog_info ("unknown protocol");
1059  return VNET_API_ERROR_INVALID_VALUE_2;
1060  }
1061  break;
1062  }
1063  }
1064  /* External address must be allocated */
1065  if (!a && (l_addr.as_u32 != e_addr.as_u32))
1066  {
1067  if (sw_if_index != ~0)
1068  {
1069  for (i = 0; i < vec_len (sm->to_resolve); i++)
1070  {
1071  rp = sm->to_resolve + i;
1072  if (rp->addr_only)
1073  continue;
1074  if (rp->sw_if_index != sw_if_index &&
1075  rp->l_addr.as_u32 != l_addr.as_u32 &&
1076  rp->vrf_id != vrf_id && rp->l_port != l_port &&
1077  rp->e_port != e_port && rp->proto != proto)
1078  continue;
1079 
1080  vec_del1 (sm->to_resolve, i);
1081  break;
1082  }
1083  }
1084  return VNET_API_ERROR_NO_SUCH_ENTRY;
1085  }
1086  }
1087 
1088  pool_get (sm->static_mappings, m);
1089  clib_memset (m, 0, sizeof (*m));
1090  m->tag = vec_dup (tag);
1091  m->local_addr = l_addr;
1092  m->external_addr = e_addr;
1093  m->twice_nat = twice_nat;
1094  if (out2in_only)
1096  if (addr_only)
1098  if (identity_nat)
1099  {
1101  pool_get (m->locals, local);
1102  local->vrf_id = vrf_id;
1103  local->fib_index = fib_index;
1104  }
1105  else
1106  {
1107  m->vrf_id = vrf_id;
1108  m->fib_index = fib_index;
1109  }
1110  if (!addr_only)
1111  {
1112  m->local_port = l_port;
1113  m->external_port = e_port;
1114  m->proto = proto;
1115  }
1116 
1117  if (sm->num_workers > 1)
1118  {
1119  ip4_header_t ip = {
1120  .src_address = m->local_addr,
1121  };
1122  vec_add1 (m->workers, sm->worker_in2out_cb (&ip, m->fib_index, 0));
1123  tsm = vec_elt_at_index (sm->per_thread_data, m->workers[0]);
1124  }
1125  else
1126  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1127 
1128  m_key.addr = m->local_addr;
1129  m_key.port = m->local_port;
1130  m_key.protocol = m->proto;
1131  m_key.fib_index = fib_index;
1132  kv.key = m_key.as_u64;
1133  kv.value = m - sm->static_mappings;
1134  if (!out2in_only)
1135  clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1);
1136 
1137  m_key.addr = m->external_addr;
1138  m_key.port = m->external_port;
1139  m_key.fib_index = 0;
1140  kv.key = m_key.as_u64;
1141  kv.value = m - sm->static_mappings;
1142  clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 1);
1143 
1144  /* Delete dynamic sessions matching local address (+ local port) */
1145  if (!(sm->static_mapping_only))
1146  {
1147  u_key.addr = m->local_addr;
1148  u_key.fib_index = m->fib_index;
1149  kv.key = u_key.as_u64;
1150  if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
1151  {
1152  user_index = value.value;
1153  u = pool_elt_at_index (tsm->users, user_index);
1154  if (u->nsessions)
1155  {
1156  head_index = u->sessions_per_user_list_head_index;
1157  head = pool_elt_at_index (tsm->list_pool, head_index);
1158  elt_index = head->next;
1159  elt = pool_elt_at_index (tsm->list_pool, elt_index);
1160  ses_index = elt->value;
1161  while (ses_index != ~0)
1162  {
1163  s = pool_elt_at_index (tsm->sessions, ses_index);
1164  elt = pool_elt_at_index (tsm->list_pool, elt->next);
1165  ses_index = elt->value;
1166 
1167  if (snat_is_session_static (s))
1168  continue;
1169 
1170  if (!addr_only
1171  && (clib_net_to_host_u16 (s->in2out.port) !=
1172  m->local_port))
1173  continue;
1174 
1175  nat_free_session_data (sm, s,
1176  tsm - sm->per_thread_data, 0);
1177  nat44_delete_session (sm, s, tsm - sm->per_thread_data);
1178 
1179  if (!addr_only && !sm->endpoint_dependent)
1180  break;
1181  }
1182  }
1183  }
1184  }
1185  }
1186  else
1187  {
1188  if (!m)
1189  {
1190  if (sw_if_index != ~0)
1191  return 0;
1192  else
1193  return VNET_API_ERROR_NO_SUCH_ENTRY;
1194  }
1195 
1196  if (identity_nat)
1197  {
1198  if (vrf_id == ~0)
1199  vrf_id = sm->inside_vrf_id;
1200 
1201  /* *INDENT-OFF* */
1202  pool_foreach (local, m->locals,
1203  ({
1204  if (local->vrf_id == vrf_id)
1205  find = local - m->locals;
1206  }));
1207  /* *INDENT-ON* */
1208  if (find == ~0)
1209  return VNET_API_ERROR_NO_SUCH_ENTRY;
1210 
1211  local = pool_elt_at_index (m->locals, find);
1212  fib_index = local->fib_index;
1213  pool_put (m->locals, local);
1214  }
1215  else
1216  fib_index = m->fib_index;
1217 
1218  /* Free external address port */
1219  if (!(addr_only || sm->static_mapping_only || out2in_only))
1220  {
1221  for (i = 0; i < vec_len (sm->addresses); i++)
1222  {
1223  if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
1224  {
1225  a = sm->addresses + i;
1226  switch (proto)
1227  {
1228 #define _(N, j, n, s) \
1229  case NAT_PROTOCOL_##N: \
1230  --a->busy_##n##_port_refcounts[e_port]; \
1231  if (e_port > 1024) \
1232  { \
1233  a->busy_##n##_ports--; \
1234  a->busy_##n##_ports_per_thread[get_thread_idx_by_port(e_port)]--; \
1235  } \
1236  break;
1238 #undef _
1239  default:
1240  nat_elog_info ("unknown protocol");
1241  return VNET_API_ERROR_INVALID_VALUE_2;
1242  }
1243  break;
1244  }
1245  }
1246  }
1247 
1248  if (sm->num_workers > 1)
1249  tsm = vec_elt_at_index (sm->per_thread_data, m->workers[0]);
1250  else
1251  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1252 
1253  m_key.addr = m->local_addr;
1254  m_key.port = m->local_port;
1255  m_key.protocol = m->proto;
1256  m_key.fib_index = fib_index;
1257  kv.key = m_key.as_u64;
1258  if (!out2in_only)
1259  clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 0);
1260 
1261  /* Delete session(s) for static mapping if exist */
1262  if (!(sm->static_mapping_only) ||
1264  {
1265  if (sm->endpoint_dependent)
1266  {
1268  m->local_port, m->proto,
1269  fib_index, addr_only,
1270  e_addr, e_port);
1271  }
1272  else
1273  {
1274  u_key.addr = m->local_addr;
1275  u_key.fib_index = fib_index;
1276  kv.key = u_key.as_u64;
1277  snat_static_mapping_del_sessions (sm, tsm, u_key, addr_only,
1278  e_addr, e_port);
1279  }
1280  }
1281 
1283  if (pool_elts (m->locals))
1284  return 0;
1285 
1286  m_key.addr = m->external_addr;
1287  m_key.port = m->external_port;
1288  m_key.fib_index = 0;
1289  kv.key = m_key.as_u64;
1290  clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 0);
1291 
1292  vec_free (m->tag);
1293  vec_free (m->workers);
1294  /* Delete static mapping from pool */
1295  pool_put (sm->static_mappings, m);
1296  }
1297 
1298  if (!addr_only || (l_addr.as_u32 == e_addr.as_u32))
1299  return 0;
1300 
1301  /* Add/delete external address to FIB */
1302  /* *INDENT-OFF* */
1303  pool_foreach (interface, sm->interfaces,
1304  ({
1305  if (nat_interface_is_inside(interface) || sm->out2in_dpo)
1306  continue;
1307 
1308  snat_add_del_addr_to_fib(&e_addr, 32, interface->sw_if_index, is_add);
1309  break;
1310  }));
1311  pool_foreach (interface, sm->output_feature_interfaces,
1312  ({
1313  if (nat_interface_is_inside(interface) || sm->out2in_dpo)
1314  continue;
1315 
1316  snat_add_del_addr_to_fib(&e_addr, 32, interface->sw_if_index, is_add);
1317  break;
1318  }));
1319  /* *INDENT-ON* */
1320 
1321  return 0;
1322 }
1323 
1324 int
1327  nat44_lb_addr_port_t * locals, u8 is_add,
1328  twice_nat_type_t twice_nat, u8 out2in_only,
1329  u8 * tag, u32 affinity)
1330 {
1331  snat_main_t *sm = &snat_main;
1333  snat_session_key_t m_key;
1335  snat_address_t *a = 0;
1336  int i;
1337  nat44_lb_addr_port_t *local;
1339  snat_session_t *s;
1340  uword *bitmap = 0;
1341 
1342  if (!sm->endpoint_dependent)
1343  return VNET_API_ERROR_FEATURE_DISABLED;
1344 
1345  m_key.addr = e_addr;
1346  m_key.port = e_port;
1347  m_key.protocol = proto;
1348  m_key.fib_index = 0;
1349  kv.key = m_key.as_u64;
1350  if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
1351  m = 0;
1352  else
1353  m = pool_elt_at_index (sm->static_mappings, value.value);
1354 
1355  if (is_add)
1356  {
1357  if (m)
1358  return VNET_API_ERROR_VALUE_EXIST;
1359 
1360  if (vec_len (locals) < 2)
1361  return VNET_API_ERROR_INVALID_VALUE;
1362 
1363  /* Find external address in allocated addresses and reserve port for
1364  address and port pair mapping when dynamic translations enabled */
1365  if (!(sm->static_mapping_only || out2in_only))
1366  {
1367  for (i = 0; i < vec_len (sm->addresses); i++)
1368  {
1369  if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
1370  {
1371  a = sm->addresses + i;
1372  /* External port must be unused */
1373  switch (proto)
1374  {
1375 #define _(N, j, n, s) \
1376  case NAT_PROTOCOL_##N: \
1377  if (a->busy_##n##_port_refcounts[e_port]) \
1378  return VNET_API_ERROR_INVALID_VALUE; \
1379  ++a->busy_##n##_port_refcounts[e_port]; \
1380  if (e_port > 1024) \
1381  { \
1382  a->busy_##n##_ports++; \
1383  a->busy_##n##_ports_per_thread[get_thread_idx_by_port(e_port)]++; \
1384  } \
1385  break;
1387 #undef _
1388  default:
1389  nat_elog_info ("unknown protocol");
1390  return VNET_API_ERROR_INVALID_VALUE_2;
1391  }
1392  break;
1393  }
1394  }
1395  /* External address must be allocated */
1396  if (!a)
1397  return VNET_API_ERROR_NO_SUCH_ENTRY;
1398  }
1399 
1400  pool_get (sm->static_mappings, m);
1401  clib_memset (m, 0, sizeof (*m));
1402  m->tag = vec_dup (tag);
1403  m->external_addr = e_addr;
1404  m->external_port = e_port;
1405  m->proto = proto;
1406  m->twice_nat = twice_nat;
1408  if (out2in_only)
1410  m->affinity = affinity;
1411 
1412  if (affinity)
1415  else
1417 
1418  m_key.addr = m->external_addr;
1419  m_key.port = m->external_port;
1420  m_key.protocol = m->proto;
1421  m_key.fib_index = 0;
1422  kv.key = m_key.as_u64;
1423  kv.value = m - sm->static_mappings;
1424  if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 1))
1425  {
1426  nat_elog_err ("static_mapping_by_external key add failed");
1427  return VNET_API_ERROR_UNSPECIFIED;
1428  }
1429 
1430  m_key.fib_index = m->fib_index;
1431  for (i = 0; i < vec_len (locals); i++)
1432  {
1433  locals[i].fib_index =
1435  locals[i].vrf_id,
1436  nat_fib_src_low);
1437  m_key.addr = locals[i].addr;
1438  m_key.fib_index = locals[i].fib_index;
1439  if (!out2in_only)
1440  {
1441  m_key.port = locals[i].port;
1442  kv.key = m_key.as_u64;
1443  kv.value = m - sm->static_mappings;
1444  clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1);
1445  }
1446  locals[i].prefix = (i == 0) ? locals[i].probability :
1447  (locals[i - 1].prefix + locals[i].probability);
1448  pool_get (m->locals, local);
1449  *local = locals[i];
1450  if (sm->num_workers > 1)
1451  {
1452  ip4_header_t ip = {
1453  .src_address = locals[i].addr,
1454  };
1455  bitmap =
1456  clib_bitmap_set (bitmap,
1457  sm->worker_in2out_cb (&ip, m->fib_index, 0),
1458  1);
1459  }
1460  }
1461 
1462  /* Assign workers */
1463  if (sm->num_workers > 1)
1464  {
1465  /* *INDENT-OFF* */
1466  clib_bitmap_foreach (i, bitmap,
1467  ({
1468  vec_add1(m->workers, i);
1469  }));
1470  /* *INDENT-ON* */
1471  }
1472  }
1473  else
1474  {
1475  if (!m)
1476  return VNET_API_ERROR_NO_SUCH_ENTRY;
1477 
1478  if (!is_lb_static_mapping (m))
1479  return VNET_API_ERROR_INVALID_VALUE;
1480 
1481  /* Free external address port */
1482  if (!(sm->static_mapping_only || out2in_only))
1483  {
1484  for (i = 0; i < vec_len (sm->addresses); i++)
1485  {
1486  if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
1487  {
1488  a = sm->addresses + i;
1489  switch (proto)
1490  {
1491 #define _(N, j, n, s) \
1492  case NAT_PROTOCOL_##N: \
1493  --a->busy_##n##_port_refcounts[e_port]; \
1494  if (e_port > 1024) \
1495  { \
1496  a->busy_##n##_ports--; \
1497  a->busy_##n##_ports_per_thread[get_thread_idx_by_port(e_port)]--; \
1498  } \
1499  break;
1501 #undef _
1502  default:
1503  nat_elog_info ("unknown protocol");
1504  return VNET_API_ERROR_INVALID_VALUE_2;
1505  }
1506  break;
1507  }
1508  }
1509  }
1510 
1511  m_key.addr = m->external_addr;
1512  m_key.port = m->external_port;
1513  m_key.protocol = m->proto;
1514  m_key.fib_index = 0;
1515  kv.key = m_key.as_u64;
1516  if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 0))
1517  {
1518  nat_elog_err ("static_mapping_by_external key del failed");
1519  return VNET_API_ERROR_UNSPECIFIED;
1520  }
1521 
1522  /* *INDENT-OFF* */
1523  pool_foreach (local, m->locals,
1524  ({
1525  fib_table_unlock (local->fib_index, FIB_PROTOCOL_IP4,
1526  nat_fib_src_low);
1527  m_key.addr = local->addr;
1528  if (!out2in_only)
1529  {
1530  m_key.port = local->port;
1531  m_key.fib_index = local->fib_index;
1532  kv.key = m_key.as_u64;
1533  if (clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 0))
1534  {
1535  nat_elog_err ("static_mapping_by_local key del failed");
1536  return VNET_API_ERROR_UNSPECIFIED;
1537  }
1538  }
1539 
1540  if (sm->num_workers > 1)
1541  {
1542  ip4_header_t ip = {
1543  .src_address = local->addr,
1544  };
1545  tsm = vec_elt_at_index (sm->per_thread_data,
1546  sm->worker_in2out_cb (&ip, m->fib_index, 0));
1547  }
1548  else
1549  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1550 
1551  /* Delete sessions */
1552  pool_foreach (s, tsm->sessions, {
1553  if (!(is_lb_session (s)))
1554  continue;
1555 
1556  if ((s->in2out.addr.as_u32 != local->addr.as_u32) ||
1557  (clib_net_to_host_u16 (s->in2out.port) != local->port))
1558  continue;
1559 
1560  nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
1561  nat_ed_session_delete (sm, s, tsm - sm->per_thread_data, 1);
1562  });
1563  }));
1564  /* *INDENT-ON* */
1565  if (m->affinity)
1566  nat_affinity_flush_service (m->affinity_per_service_list_head_index);
1567  pool_free (m->locals);
1568  vec_free (m->tag);
1569  vec_free (m->workers);
1570 
1571  pool_put (sm->static_mappings, m);
1572  }
1573 
1574  return 0;
1575 }
1576 
1577 int
1579  ip4_address_t l_addr, u16 l_port,
1581  u8 probability, u8 is_add)
1582 {
1583  snat_main_t *sm = &snat_main;
1584  snat_static_mapping_t *m = 0;
1585  snat_session_key_t m_key;
1587  nat44_lb_addr_port_t *local, *prev_local, *match_local = 0;
1589  snat_session_t *s;
1590  u32 *locals = 0;
1591  uword *bitmap = 0;
1592  int i;
1593 
1594  if (!sm->endpoint_dependent)
1595  return VNET_API_ERROR_FEATURE_DISABLED;
1596 
1597  m_key.addr = e_addr;
1598  m_key.port = e_port;
1599  m_key.protocol = proto;
1600  m_key.fib_index = 0;
1601  kv.key = m_key.as_u64;
1602  if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
1603  m = pool_elt_at_index (sm->static_mappings, value.value);
1604 
1605  if (!m)
1606  return VNET_API_ERROR_NO_SUCH_ENTRY;
1607 
1608  if (!is_lb_static_mapping (m))
1609  return VNET_API_ERROR_INVALID_VALUE;
1610 
1611  /* *INDENT-OFF* */
1612  pool_foreach (local, m->locals,
1613  ({
1614  if ((local->addr.as_u32 == l_addr.as_u32) && (local->port == l_port) &&
1615  (local->vrf_id == vrf_id))
1616  {
1617  match_local = local;
1618  break;
1619  }
1620  }));
1621  /* *INDENT-ON* */
1622 
1623  if (is_add)
1624  {
1625  if (match_local)
1626  return VNET_API_ERROR_VALUE_EXIST;
1627 
1628  pool_get (m->locals, local);
1629  clib_memset (local, 0, sizeof (*local));
1630  local->addr.as_u32 = l_addr.as_u32;
1631  local->port = l_port;
1632  local->probability = probability;
1633  local->vrf_id = vrf_id;
1634  local->fib_index =
1636  nat_fib_src_low);
1637 
1639  {
1640  m_key.addr = l_addr;
1641  m_key.port = l_port;
1642  m_key.fib_index = local->fib_index;
1643  kv.key = m_key.as_u64;
1644  kv.value = m - sm->static_mappings;
1645  if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1))
1646  nat_elog_err ("static_mapping_by_local key add failed");
1647  }
1648  }
1649  else
1650  {
1651  if (!match_local)
1652  return VNET_API_ERROR_NO_SUCH_ENTRY;
1653 
1654  if (pool_elts (m->locals) < 3)
1655  return VNET_API_ERROR_UNSPECIFIED;
1656 
1657  fib_table_unlock (match_local->fib_index, FIB_PROTOCOL_IP4,
1658  nat_fib_src_low);
1659 
1661  {
1662  m_key.addr = l_addr;
1663  m_key.port = l_port;
1664  m_key.fib_index = match_local->fib_index;
1665  kv.key = m_key.as_u64;
1666  if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 0))
1667  nat_elog_err ("static_mapping_by_local key del failed");
1668  }
1669 
1670  if (sm->num_workers > 1)
1671  {
1672  ip4_header_t ip = {
1673  .src_address = local->addr,
1674  };
1675  tsm = vec_elt_at_index (sm->per_thread_data,
1676  sm->worker_in2out_cb (&ip, m->fib_index,
1677  0));
1678  }
1679  else
1680  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1681 
1682  /* Delete sessions */
1683  /* *INDENT-OFF* */
1684  pool_foreach (s, tsm->sessions, {
1685  if (!(is_lb_session (s)))
1686  continue;
1687 
1688  if ((s->in2out.addr.as_u32 != match_local->addr.as_u32) ||
1689  (clib_net_to_host_u16 (s->in2out.port) != match_local->port))
1690  continue;
1691 
1692  nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
1693  nat_ed_session_delete (sm, s, tsm - sm->per_thread_data, 1);
1694  });
1695  /* *INDENT-ON* */
1696 
1697  pool_put (m->locals, match_local);
1698  }
1699 
1700  vec_free (m->workers);
1701 
1702  /* *INDENT-OFF* */
1703  pool_foreach (local, m->locals,
1704  ({
1705  vec_add1 (locals, local - m->locals);
1706  if (sm->num_workers > 1)
1707  {
1708  ip4_header_t ip;
1709  ip.src_address.as_u32 = local->addr.as_u32,
1710  bitmap = clib_bitmap_set (bitmap,
1711  sm->worker_in2out_cb (&ip, local->fib_index, 0),
1712  1);
1713  }
1714  }));
1715  /* *INDENT-ON* */
1716 
1717  ASSERT (vec_len (locals) > 1);
1718 
1719  local = pool_elt_at_index (m->locals, locals[0]);
1720  local->prefix = local->probability;
1721  for (i = 1; i < vec_len (locals); i++)
1722  {
1723  local = pool_elt_at_index (m->locals, locals[i]);
1724  prev_local = pool_elt_at_index (m->locals, locals[i - 1]);
1725  local->prefix = local->probability + prev_local->prefix;
1726  }
1727 
1728  /* Assign workers */
1729  if (sm->num_workers > 1)
1730  {
1731  /* *INDENT-OFF* */
1732  clib_bitmap_foreach (i, bitmap, ({ vec_add1(m->workers, i); }));
1733  /* *INDENT-ON* */
1734  }
1735 
1736  return 0;
1737 }
1738 
1739 int
1741  u8 twice_nat)
1742 {
1743  snat_address_t *a = 0;
1744  snat_session_t *ses;
1745  u32 *ses_to_be_removed = 0, *ses_index;
1748  snat_interface_t *interface;
1749  int i;
1750  snat_address_t *addresses =
1751  twice_nat ? sm->twice_nat_addresses : sm->addresses;
1752 
1753  /* Find SNAT address */
1754  for (i = 0; i < vec_len (addresses); i++)
1755  {
1756  if (addresses[i].addr.as_u32 == addr.as_u32)
1757  {
1758  a = addresses + i;
1759  break;
1760  }
1761  }
1762  if (!a)
1763  return VNET_API_ERROR_NO_SUCH_ENTRY;
1764 
1765  if (delete_sm)
1766  {
1767  /* *INDENT-OFF* */
1768  pool_foreach (m, sm->static_mappings,
1769  ({
1770  if (m->external_addr.as_u32 == addr.as_u32)
1771  (void) snat_add_static_mapping (m->local_addr, m->external_addr,
1772  m->local_port, m->external_port,
1773  m->vrf_id, is_addr_only_static_mapping(m), ~0,
1774  m->proto, 0, m->twice_nat,
1775  is_out2in_only_static_mapping(m), m->tag, is_identity_static_mapping(m));
1776  }));
1777  /* *INDENT-ON* */
1778  }
1779  else
1780  {
1781  /* Check if address is used in some static mapping */
1783  {
1784  nat_elog_notice ("address used in static mapping");
1785  return VNET_API_ERROR_UNSPECIFIED;
1786  }
1787  }
1788 
1789  if (a->fib_index != ~0)
1791 
1792  /* Delete sessions using address */
1793  if (a->busy_tcp_ports || a->busy_udp_ports || a->busy_icmp_ports)
1794  {
1795  /* *INDENT-OFF* */
1796  vec_foreach (tsm, sm->per_thread_data)
1797  {
1798  pool_foreach (ses, tsm->sessions, ({
1799  if (ses->out2in.addr.as_u32 == addr.as_u32)
1800  {
1801  nat_free_session_data (sm, ses, tsm - sm->per_thread_data, 0);
1802  vec_add1 (ses_to_be_removed, ses - tsm->sessions);
1803  }
1804  }));
1805 
1806  if (sm->endpoint_dependent){
1807  vec_foreach (ses_index, ses_to_be_removed)
1808  {
1809  ses = pool_elt_at_index (tsm->sessions, ses_index[0]);
1810  nat_ed_session_delete (sm, ses, tsm - sm->per_thread_data, 1);
1811  }
1812  }else{
1813  vec_foreach (ses_index, ses_to_be_removed)
1814  {
1815  ses = pool_elt_at_index (tsm->sessions, ses_index[0]);
1816  nat44_delete_session (sm, ses, tsm - sm->per_thread_data);
1817  }
1818  }
1819 
1820  vec_free (ses_to_be_removed);
1821  }
1822  /* *INDENT-ON* */
1823  }
1824 
1825 #define _(N, i, n, s) \
1826  vec_free (a->busy_##n##_ports_per_thread);
1828 #undef _
1829  if (twice_nat)
1830  {
1831  vec_del1 (sm->twice_nat_addresses, i);
1832  return 0;
1833  }
1834  else
1835  vec_del1 (sm->addresses, i);
1836 
1837  /* Delete external address from FIB */
1838  /* *INDENT-OFF* */
1839  pool_foreach (interface, sm->interfaces,
1840  ({
1841  if (nat_interface_is_inside(interface) || sm->out2in_dpo)
1842  continue;
1843 
1844  snat_add_del_addr_to_fib(&addr, 32, interface->sw_if_index, 0);
1845  break;
1846  }));
1847  pool_foreach (interface, sm->output_feature_interfaces,
1848  ({
1849  if (nat_interface_is_inside(interface) || sm->out2in_dpo)
1850  continue;
1851 
1852  snat_add_del_addr_to_fib(&addr, 32, interface->sw_if_index, 0);
1853  break;
1854  }));
1855  /* *INDENT-ON* */
1856 
1857  return 0;
1858 }
1859 
1860 int
1861 snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del)
1862 {
1863  snat_main_t *sm = &snat_main;
1865  const char *feature_name, *del_feature_name;
1866  snat_address_t *ap;
1868  snat_det_map_t *dm;
1869  nat_outside_fib_t *outside_fib;
1871  sw_if_index);
1872 
1873  if (sm->out2in_dpo && !is_inside)
1874  return VNET_API_ERROR_UNSUPPORTED;
1875 
1876  /* *INDENT-OFF* */
1878  ({
1879  if (i->sw_if_index == sw_if_index)
1880  return VNET_API_ERROR_VALUE_EXIST;
1881  }));
1882  /* *INDENT-ON* */
1883 
1885  feature_name = is_inside ? "nat44-in2out-fast" : "nat44-out2in-fast";
1886  else
1887  {
1888  if (sm->num_workers > 1 && !sm->deterministic)
1889  feature_name =
1890  is_inside ? "nat44-in2out-worker-handoff" :
1891  "nat44-out2in-worker-handoff";
1892  else if (sm->deterministic)
1893  feature_name = is_inside ? "nat44-det-in2out" : "nat44-det-out2in";
1894  else if (sm->endpoint_dependent)
1895  {
1896  feature_name = is_inside ? "nat-pre-in2out" : "nat-pre-out2in";
1897  }
1898  else
1899  feature_name = is_inside ? "nat44-in2out" : "nat44-out2in";
1900  }
1901 
1902  if (sm->fq_in2out_index == ~0 && !sm->deterministic && sm->num_workers > 1)
1903  sm->fq_in2out_index =
1905 
1906  if (sm->fq_out2in_index == ~0 && !sm->deterministic && sm->num_workers > 1)
1907  sm->fq_out2in_index =
1909 
1910  if (!is_inside)
1911  {
1912  /* *INDENT-OFF* */
1913  vec_foreach (outside_fib, sm->outside_fibs)
1914  {
1915  if (outside_fib->fib_index == fib_index)
1916  {
1917  if (is_del)
1918  {
1919  outside_fib->refcount--;
1920  if (!outside_fib->refcount)
1921  vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs);
1922  }
1923  else
1924  outside_fib->refcount++;
1925  goto feature_set;
1926  }
1927  }
1928  /* *INDENT-ON* */
1929  if (!is_del)
1930  {
1931  vec_add2 (sm->outside_fibs, outside_fib, 1);
1932  outside_fib->refcount = 1;
1933  outside_fib->fib_index = fib_index;
1934  }
1935  }
1936 feature_set:
1937  /* *INDENT-OFF* */
1938  pool_foreach (i, sm->interfaces,
1939  ({
1940  if (i->sw_if_index == sw_if_index)
1941  {
1942  if (is_del)
1943  {
1944  if (nat_interface_is_inside(i) && nat_interface_is_outside(i))
1945  {
1946  if (is_inside)
1947  i->flags &= ~NAT_INTERFACE_FLAG_IS_INSIDE;
1948  else
1949  i->flags &= ~NAT_INTERFACE_FLAG_IS_OUTSIDE;
1950 
1951  if (sm->num_workers > 1 && !sm->deterministic)
1952  {
1953  del_feature_name = "nat44-handoff-classify";
1954  feature_name = !is_inside ? "nat44-in2out-worker-handoff" :
1955  "nat44-out2in-worker-handoff";
1956  }
1957  else if (sm->deterministic)
1958  {
1959  del_feature_name = "nat44-det-classify";
1960  feature_name = !is_inside ? "nat44-det-in2out" :
1961  "nat44-det-out2in";
1962  }
1963  else if (sm->endpoint_dependent)
1964  {
1965  del_feature_name = "nat44-ed-classify";
1966  feature_name = !is_inside ? "nat-pre-in2out" :
1967  "nat-pre-out2in";
1968  }
1969  else
1970  {
1971  del_feature_name = "nat44-classify";
1972  feature_name = !is_inside ? "nat44-in2out" : "nat44-out2in";
1973  }
1974 
1975  int rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 0);
1976  if (rv)
1977  return rv;
1978  vnet_feature_enable_disable ("ip4-unicast", del_feature_name,
1979  sw_if_index, 0, 0, 0);
1980  vnet_feature_enable_disable ("ip4-unicast", feature_name,
1981  sw_if_index, 1, 0, 0);
1982  if (!is_inside)
1983  {
1984  if (sm->endpoint_dependent)
1985  vnet_feature_enable_disable ("ip4-local",
1986  "nat44-ed-hairpinning",
1987  sw_if_index, 1, 0, 0);
1988  else if (!sm->deterministic)
1989  vnet_feature_enable_disable ("ip4-local",
1990  "nat44-hairpinning",
1991  sw_if_index, 1, 0, 0);
1992  }
1993  }
1994  else
1995  {
1996  int rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 0);
1997  if (rv)
1998  return rv;
1999  vnet_feature_enable_disable ("ip4-unicast", feature_name,
2000  sw_if_index, 0, 0, 0);
2001  pool_put (sm->interfaces, i);
2002  if (is_inside)
2003  {
2004  if (sm->endpoint_dependent)
2005  vnet_feature_enable_disable ("ip4-local",
2006  "nat44-ed-hairpinning",
2007  sw_if_index, 0, 0, 0);
2008  else if (!sm->deterministic)
2009  vnet_feature_enable_disable ("ip4-local",
2010  "nat44-hairpinning",
2011  sw_if_index, 0, 0, 0);
2012  }
2013  }
2014  }
2015  else
2016  {
2017  if ((nat_interface_is_inside(i) && is_inside) ||
2018  (nat_interface_is_outside(i) && !is_inside))
2019  return 0;
2020 
2021  if (sm->num_workers > 1 && !sm->deterministic)
2022  {
2023  del_feature_name = !is_inside ? "nat44-in2out-worker-handoff" :
2024  "nat44-out2in-worker-handoff";
2025  feature_name = "nat44-handoff-classify";
2026  }
2027  else if (sm->deterministic)
2028  {
2029  del_feature_name = !is_inside ? "nat44-det-in2out" :
2030  "nat44-det-out2in";
2031  feature_name = "nat44-det-classify";
2032  }
2033  else if (sm->endpoint_dependent)
2034  {
2035  del_feature_name = !is_inside ? "nat-pre-in2out" :
2036  "nat-pre-out2in";
2037 
2038  feature_name = "nat44-ed-classify";
2039  }
2040  else
2041  {
2042  del_feature_name = !is_inside ? "nat44-in2out" : "nat44-out2in";
2043  feature_name = "nat44-classify";
2044  }
2045 
2046  int rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 1);
2047  if (rv)
2048  return rv;
2049  vnet_feature_enable_disable ("ip4-unicast", del_feature_name,
2050  sw_if_index, 0, 0, 0);
2051  vnet_feature_enable_disable ("ip4-unicast", feature_name,
2052  sw_if_index, 1, 0, 0);
2053  if (!is_inside)
2054  {
2055  if (sm->endpoint_dependent)
2056  vnet_feature_enable_disable ("ip4-local", "nat44-ed-hairpinning",
2057  sw_if_index, 0, 0, 0);
2058  else if (!sm->deterministic)
2059  vnet_feature_enable_disable ("ip4-local", "nat44-hairpinning",
2060  sw_if_index, 0, 0, 0);
2061  }
2062  goto set_flags;
2063  }
2064 
2065  goto fib;
2066  }
2067  }));
2068  /* *INDENT-ON* */
2069 
2070  if (is_del)
2071  return VNET_API_ERROR_NO_SUCH_ENTRY;
2072 
2073  pool_get (sm->interfaces, i);
2074  i->sw_if_index = sw_if_index;
2075  i->flags = 0;
2076  vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, 1, 0,
2077  0);
2078 
2080  if (rv)
2081  return rv;
2082 
2083  if (is_inside && !sm->out2in_dpo)
2084  {
2085  if (sm->endpoint_dependent)
2086  vnet_feature_enable_disable ("ip4-local", "nat44-ed-hairpinning",
2087  sw_if_index, 1, 0, 0);
2088  else if (!sm->deterministic)
2089  vnet_feature_enable_disable ("ip4-local", "nat44-hairpinning",
2090  sw_if_index, 1, 0, 0);
2091  }
2092 
2093 set_flags:
2094  if (is_inside)
2095  {
2096  i->flags |= NAT_INTERFACE_FLAG_IS_INSIDE;
2097  return 0;
2098  }
2099  else
2100  i->flags |= NAT_INTERFACE_FLAG_IS_OUTSIDE;
2101 
2102  /* Add/delete external addresses to FIB */
2103 fib:
2104  /* *INDENT-OFF* */
2105  vec_foreach (ap, sm->addresses)
2106  snat_add_del_addr_to_fib(&ap->addr, 32, sw_if_index, !is_del);
2107 
2108  pool_foreach (m, sm->static_mappings,
2109  ({
2110  if (!(is_addr_only_static_mapping(m)) || (m->local_addr.as_u32 == m->external_addr.as_u32))
2111  continue;
2112 
2113  snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
2114  }));
2115 
2116  pool_foreach (dm, sm->det_maps,
2117  ({
2118  snat_add_del_addr_to_fib(&dm->out_addr, dm->out_plen, sw_if_index, !is_del);
2119  }));
2120  /* *INDENT-ON* */
2121 
2122  return 0;
2123 }
2124 
2125 int
2127  u8 is_inside, int is_del)
2128 {
2129  snat_main_t *sm = &snat_main;
2131  snat_address_t *ap;
2133  nat_outside_fib_t *outside_fib;
2135  sw_if_index);
2136 
2137 
2138  if (sm->deterministic ||
2140  return VNET_API_ERROR_UNSUPPORTED;
2141 
2142  /* *INDENT-OFF* */
2143  pool_foreach (i, sm->interfaces,
2144  ({
2145  if (i->sw_if_index == sw_if_index)
2146  return VNET_API_ERROR_VALUE_EXIST;
2147  }));
2148  /* *INDENT-ON* */
2149 
2150  if (!is_inside)
2151  {
2152  /* *INDENT-OFF* */
2153  vec_foreach (outside_fib, sm->outside_fibs)
2154  {
2155  if (outside_fib->fib_index == fib_index)
2156  {
2157  if (is_del)
2158  {
2159  outside_fib->refcount--;
2160  if (!outside_fib->refcount)
2161  vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs);
2162  }
2163  else
2164  outside_fib->refcount++;
2165  goto feature_set;
2166  }
2167  }
2168  /* *INDENT-ON* */
2169  if (!is_del)
2170  {
2171  vec_add2 (sm->outside_fibs, outside_fib, 1);
2172  outside_fib->refcount = 1;
2173  outside_fib->fib_index = fib_index;
2174  }
2175  }
2176 
2177 feature_set:
2178  if (is_inside)
2179  {
2180  if (sm->endpoint_dependent)
2181  {
2182  int rv =
2183  ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, !is_del);
2184  if (rv)
2185  return rv;
2186  rv =
2188  !is_del);
2189  if (rv)
2190  return rv;
2191  vnet_feature_enable_disable ("ip4-unicast", "nat44-ed-hairpin-dst",
2192  sw_if_index, !is_del, 0, 0);
2193  vnet_feature_enable_disable ("ip4-output", "nat44-ed-hairpin-src",
2194  sw_if_index, !is_del, 0, 0);
2195  }
2196  else
2197  {
2198  int rv =
2199  ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, !is_del);
2200  if (rv)
2201  return rv;
2202  rv =
2204  !is_del);
2205  if (rv)
2206  return rv;
2207  vnet_feature_enable_disable ("ip4-unicast", "nat44-hairpin-dst",
2208  sw_if_index, !is_del, 0, 0);
2209  vnet_feature_enable_disable ("ip4-output", "nat44-hairpin-src",
2210  sw_if_index, !is_del, 0, 0);
2211  }
2212  goto fq;
2213  }
2214 
2215  if (sm->num_workers > 1)
2216  {
2217  int rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, !is_del);
2218  if (rv)
2219  return rv;
2220  rv =
2221  ip4_sv_reass_output_enable_disable_with_refcnt (sw_if_index, !is_del);
2222  if (rv)
2223  return rv;
2224  vnet_feature_enable_disable ("ip4-unicast",
2225  "nat44-out2in-worker-handoff",
2226  sw_if_index, !is_del, 0, 0);
2227  vnet_feature_enable_disable ("ip4-output",
2228  "nat44-in2out-output-worker-handoff",
2229  sw_if_index, !is_del, 0, 0);
2230  }
2231  else
2232  {
2233  if (sm->endpoint_dependent)
2234  {
2235  int rv =
2236  ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, !is_del);
2237  if (rv)
2238  return rv;
2239  rv =
2241  !is_del);
2242  if (rv)
2243  return rv;
2244  vnet_feature_enable_disable ("ip4-unicast", "nat-pre-out2in",
2245  sw_if_index, !is_del, 0, 0);
2246  vnet_feature_enable_disable ("ip4-output", "nat44-ed-in2out-output",
2247  sw_if_index, !is_del, 0, 0);
2248  }
2249  else
2250  {
2251  int rv =
2252  ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, !is_del);
2253  if (rv)
2254  return rv;
2255  rv =
2257  !is_del);
2258  if (rv)
2259  return rv;
2260  vnet_feature_enable_disable ("ip4-unicast", "nat44-out2in",
2261  sw_if_index, !is_del, 0, 0);
2262  vnet_feature_enable_disable ("ip4-output", "nat44-in2out-output",
2263  sw_if_index, !is_del, 0, 0);
2264  }
2265  }
2266 
2267 fq:
2268  if (sm->fq_in2out_output_index == ~0 && sm->num_workers > 1)
2271 
2272  if (sm->fq_out2in_index == ~0 && sm->num_workers > 1)
2273  sm->fq_out2in_index =
2275 
2276  /* *INDENT-OFF* */
2278  ({
2279  if (i->sw_if_index == sw_if_index)
2280  {
2281  if (is_del)
2282  pool_put (sm->output_feature_interfaces, i);
2283  else
2284  return VNET_API_ERROR_VALUE_EXIST;
2285 
2286  goto fib;
2287  }
2288  }));
2289  /* *INDENT-ON* */
2290 
2291  if (is_del)
2292  return VNET_API_ERROR_NO_SUCH_ENTRY;
2293 
2294  pool_get (sm->output_feature_interfaces, i);
2295  i->sw_if_index = sw_if_index;
2296  i->flags = 0;
2297  if (is_inside)
2298  i->flags |= NAT_INTERFACE_FLAG_IS_INSIDE;
2299  else
2300  i->flags |= NAT_INTERFACE_FLAG_IS_OUTSIDE;
2301 
2302  /* Add/delete external addresses to FIB */
2303 fib:
2304  if (is_inside)
2305  return 0;
2306 
2307  /* *INDENT-OFF* */
2308  vec_foreach (ap, sm->addresses)
2309  snat_add_del_addr_to_fib(&ap->addr, 32, sw_if_index, !is_del);
2310 
2311  pool_foreach (m, sm->static_mappings,
2312  ({
2313  if (!((is_addr_only_static_mapping(m))) || (m->local_addr.as_u32 == m->external_addr.as_u32))
2314  continue;
2315 
2316  snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
2317  }));
2318  /* *INDENT-ON* */
2319 
2320  return 0;
2321 }
2322 
2323 int
2325 {
2326  snat_main_t *sm = &snat_main;
2327  int i, j = 0;
2328 
2329  if (sm->num_workers < 2)
2330  return VNET_API_ERROR_FEATURE_DISABLED;
2331 
2332  if (clib_bitmap_last_set (bitmap) >= sm->num_workers)
2333  return VNET_API_ERROR_INVALID_WORKER;
2334 
2335  vec_free (sm->workers);
2336  /* *INDENT-OFF* */
2337  clib_bitmap_foreach (i, bitmap,
2338  ({
2339  vec_add1(sm->workers, i);
2342  j++;
2343  }));
2344  /* *INDENT-ON* */
2345 
2346  sm->port_per_thread = (0xffff - 1024) / _vec_len (sm->workers);
2347  sm->num_snat_thread = _vec_len (sm->workers);
2348 
2349  return 0;
2350 }
2351 
2352 static void
2354  u32 old_fib_index)
2355 {
2356  snat_main_t *sm = &snat_main;
2357  nat_outside_fib_t *outside_fib;
2359  u8 is_add = 1;
2360  u8 match = 0;
2361 
2362  if (new_fib_index == old_fib_index)
2363  return;
2364 
2365  if (!vec_len (sm->outside_fibs))
2366  return;
2367 
2368  /* *INDENT-OFF* */
2369  pool_foreach (i, sm->interfaces,
2370  ({
2371  if (i->sw_if_index == sw_if_index)
2372  {
2373  if (!(nat_interface_is_outside (i)))
2374  return;
2375  match = 1;
2376  }
2377  }));
2378 
2379  pool_foreach (i, sm->output_feature_interfaces,
2380  ({
2381  if (i->sw_if_index == sw_if_index)
2382  {
2383  if (!(nat_interface_is_outside (i)))
2384  return;
2385  match = 1;
2386  }
2387  }));
2388  /* *INDENT-ON* */
2389 
2390  if (!match)
2391  return;
2392 
2393  vec_foreach (outside_fib, sm->outside_fibs)
2394  {
2395  if (outside_fib->fib_index == old_fib_index)
2396  {
2397  outside_fib->refcount--;
2398  if (!outside_fib->refcount)
2399  vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs);
2400  break;
2401  }
2402  }
2403 
2404  vec_foreach (outside_fib, sm->outside_fibs)
2405  {
2406  if (outside_fib->fib_index == new_fib_index)
2407  {
2408  outside_fib->refcount++;
2409  is_add = 0;
2410  break;
2411  }
2412  }
2413 
2414  if (is_add)
2415  {
2416  vec_add2 (sm->outside_fibs, outside_fib, 1);
2417  outside_fib->refcount = 1;
2418  outside_fib->fib_index = new_fib_index;
2419  }
2420 }
2421 
2422 static void
2424  uword opaque,
2425  u32 sw_if_index, u32 new_fib_index, u32 old_fib_index)
2426 {
2427  snat_update_outside_fib (sw_if_index, new_fib_index, old_fib_index);
2428 }
2429 
2430 static void
2432  uword opaque,
2433  u32 sw_if_index,
2435  u32 address_length,
2436  u32 if_address_index, u32 is_delete);
2437 
2438 static void
2440  uword opaque,
2441  u32 sw_if_index,
2442  ip4_address_t * address,
2443  u32 address_length,
2444  u32 if_address_index, u32 is_delete);
2445 
2446 static int
2448  u32 fib_index,
2449  u32 thread_index,
2450  snat_session_key_t * k,
2451  u16 port_per_thread, u32 snat_thread_index);
2452 
2453 void
2455 {
2456  ip4_address_t l_addr;
2457  l_addr.as_u8[0] = 1;
2458  l_addr.as_u8[1] = 1;
2459  l_addr.as_u8[2] = 1;
2460  l_addr.as_u8[3] = 1;
2461  ip4_address_t r_addr;
2462  r_addr.as_u8[0] = 2;
2463  r_addr.as_u8[1] = 2;
2464  r_addr.as_u8[2] = 2;
2465  r_addr.as_u8[3] = 2;
2466  u16 l_port = 40001;
2467  u16 r_port = 40301;
2468  u8 proto = 9;
2469  u32 fib_index = 9000001;
2470  u64 value = ~0ULL;
2472  make_ed_kv (&l_addr, &r_addr, proto, fib_index, l_port, r_port, value, &kv);
2473  ip4_address_t l_addr2;
2474  ip4_address_t r_addr2;
2475  clib_memset (&l_addr2, 0, sizeof (l_addr2));
2476  clib_memset (&r_addr2, 0, sizeof (r_addr2));
2477  u16 l_port2 = 0;
2478  u16 r_port2 = 0;
2479  u8 proto2 = 0;
2480  u32 fib_index2 = 0;
2481  split_ed_kv (&kv, &l_addr2, &r_addr2, &proto2, &fib_index2, &l_port2,
2482  &r_port2);
2483  u64 value2 = kv.value;
2484  ASSERT (l_addr.as_u32 == l_addr2.as_u32);
2485  ASSERT (r_addr.as_u32 == r_addr2.as_u32);
2486  ASSERT (l_port == l_port2);
2487  ASSERT (r_port == r_port2);
2488  ASSERT (proto == proto2);
2489  ASSERT (fib_index == fib_index2);
2490  ASSERT (value == value2);
2491 }
2492 
2493 static clib_error_t *
2495 {
2496  snat_main_t *sm = &snat_main;
2497  clib_error_t *error = 0;
2498  ip4_main_t *im = &ip4_main;
2499  ip_lookup_main_t *lm = &im->lookup_main;
2500  uword *p;
2503  uword *bitmap = 0;
2504  u32 i;
2506  vlib_node_t *node;
2507 
2508  sm->vnet_main = vnet_get_main ();
2509  sm->ip4_main = im;
2510  sm->ip4_lookup_main = lm;
2511  sm->api_main = vlibapi_get_main ();
2512  sm->first_worker_index = 0;
2513  sm->num_workers = 0;
2514  sm->num_snat_thread = 1;
2515  sm->workers = 0;
2516  sm->port_per_thread = 0xffff - 1024;
2517  sm->fq_in2out_index = ~0;
2518  sm->fq_in2out_output_index = ~0;
2519  sm->fq_out2in_index = ~0;
2520 
2522  sm->addr_and_port_alloc_alg = NAT_ADDR_AND_PORT_ALLOC_ALG_DEFAULT;
2523  sm->forwarding_enabled = 0;
2524  sm->log_class = vlib_log_register_class ("nat", 0);
2525  sm->log_level = SNAT_LOG_ERROR;
2526  sm->mss_clamping = 0;
2527 
2528  node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
2529  sm->error_node_index = node->index;
2530 
2531  node = vlib_get_node_by_name (vm, (u8 *) "nat-pre-in2out");
2532  sm->pre_in2out_node_index = node->index;
2533  node = vlib_get_node_by_name (vm, (u8 *) "nat-pre-out2in");
2534  sm->pre_out2in_node_index = node->index;
2535 
2536  node = vlib_get_node_by_name (vm, (u8 *) "nat-pre-in2out");
2537  sm->pre_in2out_node_index = node->index;
2538 
2539  node = vlib_get_node_by_name (vm, (u8 *) "nat-pre-out2in");
2540  sm->pre_out2in_node_index = node->index;
2541 
2542  node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out");
2543  sm->in2out_node_index = node->index;
2544  node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-output");
2545  sm->in2out_output_node_index = node->index;
2546  node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-fast");
2547  sm->in2out_fast_node_index = node->index;
2548  node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-slowpath");
2549  sm->in2out_slowpath_node_index = node->index;
2550  node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-output-slowpath");
2552 
2553  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-in2out");
2554  sm->ed_in2out_node_index = node->index;
2555  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-in2out-slowpath");
2557 
2558  node = vlib_get_node_by_name (vm, (u8 *) "nat44-out2in");
2559  sm->out2in_node_index = node->index;
2560  node = vlib_get_node_by_name (vm, (u8 *) "nat44-out2in-fast");
2561  sm->out2in_fast_node_index = node->index;
2562 
2563  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-out2in");
2564  sm->ed_out2in_node_index = node->index;
2565  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-out2in-slowpath");
2567 
2568  node = vlib_get_node_by_name (vm, (u8 *) "nat44-det-in2out");
2569  sm->det_in2out_node_index = node->index;
2570  node = vlib_get_node_by_name (vm, (u8 *) "nat44-det-out2in");
2571  sm->det_out2in_node_index = node->index;
2572 
2573  node = vlib_get_node_by_name (vm, (u8 *) "nat44-hairpinning");
2574  sm->hairpinning_node_index = node->index;
2575  node = vlib_get_node_by_name (vm, (u8 *) "nat44-hairpin-dst");
2576  sm->hairpin_dst_node_index = node->index;
2577  node = vlib_get_node_by_name (vm, (u8 *) "nat44-hairpin-src");
2578  sm->hairpin_src_node_index = node->index;
2579  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-hairpinning");
2580  sm->ed_hairpinning_node_index = node->index;
2581  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-hairpin-dst");
2582  sm->ed_hairpin_dst_node_index = node->index;
2583  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-hairpin-src");
2584  sm->ed_hairpin_src_node_index = node->index;
2585 
2586  p = hash_get_mem (tm->thread_registrations_by_name, "workers");
2587  if (p)
2588  {
2589  tr = (vlib_thread_registration_t *) p[0];
2590  if (tr)
2591  {
2592  sm->num_workers = tr->count;
2593  sm->first_worker_index = tr->first_index;
2594  }
2595  }
2596 
2597  vec_validate (sm->per_thread_data, tm->n_vlib_mains - 1);
2598 
2599  /* Use all available workers by default */
2600  if (sm->num_workers > 1)
2601  {
2602  for (i = 0; i < sm->num_workers; i++)
2603  bitmap = clib_bitmap_set (bitmap, i, 1);
2604  // sets thread indexes for workes
2605  snat_set_workers (bitmap);
2606  clib_bitmap_free (bitmap);
2607  }
2608  else
2609  {
2611  }
2612 
2613  error = snat_api_init (vm, sm);
2614  if (error)
2615  return error;
2616 
2617  /* Set up the interface address add/del callback */
2619  cb4.function_opaque = 0;
2620 
2622 
2624  cb4.function_opaque = 0;
2625 
2627 
2629 
2630  /* Init counters */
2631  sm->total_users.name = "total-users";
2632  sm->total_users.stat_segment_name = "/nat44/total-users";
2635  sm->total_sessions.name = "total-sessions";
2636  sm->total_sessions.stat_segment_name = "/nat44/total-sessions";
2639 
2640  /* Init IPFIX logging */
2642 
2643  /* Init NAT64 */
2644  error = nat64_init (vm);
2645  if (error)
2646  return error;
2647 
2648  nat66_init (vm);
2649 
2650  ip4_table_bind_callback_t cbt4 = {
2652  };
2654 
2655  nat_fib_src_hi = fib_source_allocate ("nat-hi",
2658  nat_fib_src_low = fib_source_allocate ("nat-low",
2661 
2662  test_ed_make_split ();
2663  return error;
2664 }
2665 
2667 
2668 void
2670  u32 thread_index, snat_session_key_t * k)
2671 {
2672  snat_address_t *a;
2673  u32 address_index;
2674  u16 port_host_byte_order = clib_net_to_host_u16 (k->port);
2675 
2676  for (address_index = 0; address_index < vec_len (addresses);
2677  address_index++)
2678  {
2679  if (addresses[address_index].addr.as_u32 == k->addr.as_u32)
2680  break;
2681  }
2682 
2683  ASSERT (address_index < vec_len (addresses));
2684 
2685  a = addresses + address_index;
2686 
2687  switch (k->protocol)
2688  {
2689 #define _(N, i, n, s) \
2690  case NAT_PROTOCOL_##N: \
2691  ASSERT (a->busy_##n##_port_refcounts[port_host_byte_order] >= 1); \
2692  --a->busy_##n##_port_refcounts[port_host_byte_order]; \
2693  a->busy_##n##_ports--; \
2694  a->busy_##n##_ports_per_thread[thread_index]--; \
2695  break;
2697 #undef _
2698  default:
2699  nat_elog_info ("unknown protocol");
2700  return;
2701  }
2702 }
2703 
2704 static int
2706  u32 thread_index, snat_session_key_t * k)
2707 {
2708  snat_address_t *a = 0;
2709  u32 address_index;
2710  u16 port_host_byte_order = clib_net_to_host_u16 (k->port);
2711 
2712  for (address_index = 0; address_index < vec_len (addresses);
2713  address_index++)
2714  {
2715  if (addresses[address_index].addr.as_u32 != k->addr.as_u32)
2716  continue;
2717 
2718  a = addresses + address_index;
2719  switch (k->protocol)
2720  {
2721 #define _(N, j, n, s) \
2722  case NAT_PROTOCOL_##N: \
2723  if (a->busy_##n##_port_refcounts[port_host_byte_order]) \
2724  return VNET_API_ERROR_INSTANCE_IN_USE; \
2725  ++a->busy_##n##_port_refcounts[port_host_byte_order]; \
2726  a->busy_##n##_ports_per_thread[thread_index]++; \
2727  a->busy_##n##_ports++; \
2728  return 0;
2730 #undef _
2731  default:
2732  nat_elog_info ("unknown protocol");
2733  return 1;
2734  }
2735  }
2736 
2737  return VNET_API_ERROR_NO_SUCH_ENTRY;
2738 }
2739 
2740 int
2742  snat_session_key_t match,
2743  snat_session_key_t * mapping,
2744  u8 by_external,
2745  u8 * is_addr_only,
2746  twice_nat_type_t * twice_nat,
2747  lb_nat_type_t * lb, ip4_address_t * ext_host_addr,
2748  u8 * is_identity_nat)
2749 {
2752  snat_session_key_t m_key;
2753  clib_bihash_8_8_t *mapping_hash = &sm->static_mapping_by_local;
2754  u32 rand, lo = 0, hi, mid, *tmp = 0, i;
2755  u8 backend_index;
2756  nat44_lb_addr_port_t *local;
2757 
2758  m_key.fib_index = match.fib_index;
2759  if (by_external)
2760  {
2761  mapping_hash = &sm->static_mapping_by_external;
2762  m_key.fib_index = 0;
2763  }
2764 
2765  m_key.addr = match.addr;
2766  m_key.port = clib_net_to_host_u16 (match.port);
2767  m_key.protocol = match.protocol;
2768 
2769  kv.key = m_key.as_u64;
2770 
2771  if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
2772  {
2773  /* Try address only mapping */
2774  m_key.port = 0;
2775  m_key.protocol = 0;
2776  kv.key = m_key.as_u64;
2777  if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
2778  return 1;
2779  }
2780 
2781  m = pool_elt_at_index (sm->static_mappings, value.value);
2782 
2783  if (by_external)
2784  {
2785  if (is_lb_static_mapping (m))
2786  {
2787  if (PREDICT_FALSE (lb != 0))
2788  *lb = m->affinity ? AFFINITY_LB_NAT : LB_NAT;
2789  if (m->affinity && !nat_affinity_find_and_lock (ext_host_addr[0],
2790  match.addr,
2791  match.protocol,
2792  match.port,
2793  &backend_index))
2794  {
2795  local = pool_elt_at_index (m->locals, backend_index);
2796  mapping->addr = local->addr;
2797  mapping->port = clib_host_to_net_u16 (local->port);
2798  mapping->fib_index = local->fib_index;
2799  goto end;
2800  }
2801  // pick locals matching this worker
2802  if (PREDICT_FALSE (sm->num_workers > 1))
2803  {
2804  u32 thread_index = vlib_get_thread_index ();
2805  /* *INDENT-OFF* */
2807  ({
2808  local = pool_elt_at_index (m->locals, i);
2809 
2810  ip4_header_t ip = {
2811  .src_address = local->addr,
2812  };
2813 
2814  if (sm->worker_in2out_cb (&ip, m->fib_index, 0) ==
2815  thread_index)
2816  {
2817  vec_add1 (tmp, i);
2818  }
2819  }));
2820  /* *INDENT-ON* */
2821  ASSERT (vec_len (tmp) != 0);
2822  }
2823  else
2824  {
2825  /* *INDENT-OFF* */
2827  ({
2828  vec_add1 (tmp, i);
2829  }));
2830  /* *INDENT-ON* */
2831  }
2832  hi = vec_len (tmp) - 1;
2833  local = pool_elt_at_index (m->locals, tmp[hi]);
2834  rand = 1 + (random_u32 (&sm->random_seed) % local->prefix);
2835  while (lo < hi)
2836  {
2837  mid = ((hi - lo) >> 1) + lo;
2838  local = pool_elt_at_index (m->locals, tmp[mid]);
2839  (rand > local->prefix) ? (lo = mid + 1) : (hi = mid);
2840  }
2841  local = pool_elt_at_index (m->locals, tmp[lo]);
2842  if (!(local->prefix >= rand))
2843  return 1;
2844  mapping->addr = local->addr;
2845  mapping->port = clib_host_to_net_u16 (local->port);
2846  mapping->fib_index = local->fib_index;
2847  if (m->affinity)
2848  {
2849  if (nat_affinity_create_and_lock (ext_host_addr[0], match.addr,
2850  match.protocol, match.port,
2851  tmp[lo], m->affinity,
2853  nat_elog_info ("create affinity record failed");
2854  }
2855  vec_free (tmp);
2856  }
2857  else
2858  {
2859  if (PREDICT_FALSE (lb != 0))
2860  *lb = NO_LB_NAT;
2861  mapping->fib_index = m->fib_index;
2862  mapping->addr = m->local_addr;
2863  /* Address only mapping doesn't change port */
2864  mapping->port = is_addr_only_static_mapping (m) ? match.port
2865  : clib_host_to_net_u16 (m->local_port);
2866  }
2867  mapping->protocol = m->proto;
2868  }
2869  else
2870  {
2871  mapping->addr = m->external_addr;
2872  /* Address only mapping doesn't change port */
2873  mapping->port = is_addr_only_static_mapping (m) ? match.port
2874  : clib_host_to_net_u16 (m->external_port);
2875  mapping->fib_index = sm->outside_fib_index;
2876  }
2877 
2878 end:
2879  if (PREDICT_FALSE (is_addr_only != 0))
2880  *is_addr_only = is_addr_only_static_mapping (m);
2881 
2882  if (PREDICT_FALSE (twice_nat != 0))
2883  *twice_nat = m->twice_nat;
2884 
2885  if (PREDICT_FALSE (is_identity_nat != 0))
2886  *is_identity_nat = is_identity_static_mapping (m);
2887 
2888  return 0;
2889 }
2890 
2893 {
2894  snat_main_t *sm = &snat_main;
2895  return min + random_u32 (&sm->random_seed) /
2896  (random_u32_max () / (max - min + 1) + 1);
2897 }
2898 
2899 int
2901  u32 fib_index,
2902  u32 thread_index,
2903  snat_session_key_t * k,
2904  u16 port_per_thread,
2905  u32 snat_thread_index)
2906 {
2907  snat_main_t *sm = &snat_main;
2908 
2909  return sm->alloc_addr_and_port (addresses, fib_index, thread_index, k,
2910  port_per_thread, snat_thread_index);
2911 }
2912 
2913 static int
2915  u32 fib_index,
2916  u32 thread_index,
2917  snat_session_key_t * k,
2918  u16 port_per_thread, u32 snat_thread_index)
2919 {
2920  int i;
2921  snat_address_t *a, *ga = 0;
2922  u32 portnum;
2923 
2924  for (i = 0; i < vec_len (addresses); i++)
2925  {
2926  a = addresses + i;
2927  switch (k->protocol)
2928  {
2929 #define _(N, j, n, s) \
2930  case NAT_PROTOCOL_##N: \
2931  if (a->busy_##n##_ports_per_thread[thread_index] < port_per_thread) \
2932  { \
2933  if (a->fib_index == fib_index) \
2934  { \
2935  while (1) \
2936  { \
2937  portnum = (port_per_thread * \
2938  snat_thread_index) + \
2939  snat_random_port(1, port_per_thread) + 1024; \
2940  if (a->busy_##n##_port_refcounts[portnum]) \
2941  continue; \
2942  --a->busy_##n##_port_refcounts[portnum]; \
2943  a->busy_##n##_ports_per_thread[thread_index]++; \
2944  a->busy_##n##_ports++; \
2945  k->addr = a->addr; \
2946  k->port = clib_host_to_net_u16(portnum); \
2947  return 0; \
2948  } \
2949  } \
2950  else if (a->fib_index == ~0) \
2951  { \
2952  ga = a; \
2953  } \
2954  } \
2955  break;
2957 #undef _
2958  default:
2959  nat_elog_info ("unknown protocol");
2960  return 1;
2961  }
2962 
2963  }
2964 
2965  if (ga)
2966  {
2967  a = ga;
2968  switch (k->protocol)
2969  {
2970 #define _(N, j, n, s) \
2971  case NAT_PROTOCOL_##N: \
2972  while (1) \
2973  { \
2974  portnum = (port_per_thread * \
2975  snat_thread_index) + \
2976  snat_random_port(1, port_per_thread) + 1024; \
2977  if (a->busy_##n##_port_refcounts[portnum]) \
2978  continue; \
2979  ++a->busy_##n##_port_refcounts[portnum]; \
2980  a->busy_##n##_ports_per_thread[thread_index]++; \
2981  a->busy_##n##_ports++; \
2982  k->addr = a->addr; \
2983  k->port = clib_host_to_net_u16(portnum); \
2984  return 0; \
2985  }
2986  break;
2988 #undef _
2989  default:
2990  nat_elog_info ("unknown protocol");
2991  return 1;
2992  }
2993  }
2994 
2995  /* Totally out of translations to use... */
2996  snat_ipfix_logging_addresses_exhausted (thread_index, 0);
2997  return 1;
2998 }
2999 
3000 static int
3002  u32 fib_index,
3003  u32 thread_index,
3004  snat_session_key_t * k,
3005  u16 port_per_thread, u32 snat_thread_index)
3006 {
3007  snat_main_t *sm = &snat_main;
3008  snat_address_t *a = addresses;
3009  u16 m, ports, portnum, A, j;
3010  m = 16 - (sm->psid_offset + sm->psid_length);
3011  ports = (1 << (16 - sm->psid_length)) - (1 << m);
3012 
3013  if (!vec_len (addresses))
3014  goto exhausted;
3015 
3016  switch (k->protocol)
3017  {
3018 #define _(N, i, n, s) \
3019  case NAT_PROTOCOL_##N: \
3020  if (a->busy_##n##_ports < ports) \
3021  { \
3022  while (1) \
3023  { \
3024  A = snat_random_port(1, pow2_mask(sm->psid_offset)); \
3025  j = snat_random_port(0, pow2_mask(m)); \
3026  portnum = A | (sm->psid << sm->psid_offset) | (j << (16 - m)); \
3027  if (a->busy_##n##_port_refcounts[portnum]) \
3028  continue; \
3029  ++a->busy_##n##_port_refcounts[portnum]; \
3030  a->busy_##n##_ports++; \
3031  k->addr = a->addr; \
3032  k->port = clib_host_to_net_u16 (portnum); \
3033  return 0; \
3034  } \
3035  } \
3036  break;
3038 #undef _
3039  default:
3040  nat_elog_info ("unknown protocol");
3041  return 1;
3042  }
3043 
3044 exhausted:
3045  /* Totally out of translations to use... */
3046  snat_ipfix_logging_addresses_exhausted (thread_index, 0);
3047  return 1;
3048 }
3049 
3050 static int
3052  u32 fib_index,
3053  u32 thread_index,
3054  snat_session_key_t * k,
3055  u16 port_per_thread, u32 snat_thread_index)
3056 {
3057  snat_main_t *sm = &snat_main;
3058  snat_address_t *a = addresses;
3059  u16 portnum, ports;
3060 
3061  ports = sm->end_port - sm->start_port + 1;
3062 
3063  if (!vec_len (addresses))
3064  goto exhausted;
3065 
3066  switch (k->protocol)
3067  {
3068 #define _(N, i, n, s) \
3069  case NAT_PROTOCOL_##N: \
3070  if (a->busy_##n##_ports < ports) \
3071  { \
3072  while (1) \
3073  { \
3074  portnum = snat_random_port(sm->start_port, sm->end_port); \
3075  if (a->busy_##n##_port_refcounts[portnum]) \
3076  continue; \
3077  ++a->busy_##n##_port_refcounts[portnum]; \
3078  a->busy_##n##_ports++; \
3079  k->addr = a->addr; \
3080  k->port = clib_host_to_net_u16 (portnum); \
3081  return 0; \
3082  } \
3083  } \
3084  break;
3086 #undef _
3087  default:
3088  nat_elog_info ("unknown protocol");
3089  return 1;
3090  }
3091 
3092 exhausted:
3093  /* Totally out of translations to use... */
3094  snat_ipfix_logging_addresses_exhausted (thread_index, 0);
3095  return 1;
3096 }
3097 
3098 void
3100 {
3101  dpo_id_t dpo_v4 = DPO_INVALID;
3102  fib_prefix_t pfx = {
3104  .fp_len = 32,
3105  .fp_addr.ip4.as_u32 = addr.as_u32,
3106  };
3107 
3108  if (is_add)
3109  {
3110  nat_dpo_create (DPO_PROTO_IP4, 0, &dpo_v4);
3112  FIB_ENTRY_FLAG_EXCLUSIVE, &dpo_v4);
3113  dpo_reset (&dpo_v4);
3114  }
3115  else
3116  {
3118  }
3119 }
3120 
3121 u8 *
3122 format_session_kvp (u8 * s, va_list * args)
3123 {
3124  clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
3126 
3127  k.as_u64 = v->key;
3128 
3129  s = format (s, "%U session-index %llu", format_snat_key, &k, v->value);
3130 
3131  return s;
3132 }
3133 
3134 u8 *
3135 format_static_mapping_kvp (u8 * s, va_list * args)
3136 {
3137  clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
3139 
3140  k.as_u64 = v->key;
3141 
3142  s = format (s, "%U static-mapping-index %llu",
3144 
3145  return s;
3146 }
3147 
3148 u8 *
3149 format_user_kvp (u8 * s, va_list * args)
3150 {
3151  clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
3152  snat_user_key_t k;
3153 
3154  k.as_u64 = v->key;
3155 
3156  s = format (s, "%U fib %d user-index %llu", format_ip4_address, &k.addr,
3157  k.fib_index, v->value);
3158 
3159  return s;
3160 }
3161 
3162 u8 *
3163 format_ed_session_kvp (u8 * s, va_list * args)
3164 {
3165  clib_bihash_kv_16_8_t *v = va_arg (*args, clib_bihash_kv_16_8_t *);
3166 
3167  u8 proto;
3168  u16 r_port, l_port;
3169  ip4_address_t l_addr, r_addr;
3170  u32 fib_index;
3171 
3172  split_ed_kv (v, &l_addr, &r_addr, &proto, &fib_index, &l_port, &r_port);
3173  s =
3174  format (s, "local %U:%d remote %U:%d proto %U fib %d session-index %llu",
3175  format_ip4_address, &l_addr, clib_net_to_host_u16 (l_port),
3176  format_ip4_address, &r_addr, clib_net_to_host_u16 (r_port),
3177  format_ip_protocol, proto, fib_index, v->value);
3178 
3179  return s;
3180 }
3181 
3182 static u32
3184  u8 is_output)
3185 {
3186  snat_main_t *sm = &snat_main;
3187  u32 next_worker_index = 0;
3188  u32 hash;
3189 
3190  next_worker_index = sm->first_worker_index;
3191  hash = ip0->src_address.as_u32 + (ip0->src_address.as_u32 >> 8) +
3192  (ip0->src_address.as_u32 >> 16) + (ip0->src_address.as_u32 >> 24);
3193 
3194  if (PREDICT_TRUE (is_pow2 (_vec_len (sm->workers))))
3195  next_worker_index += sm->workers[hash & (_vec_len (sm->workers) - 1)];
3196  else
3197  next_worker_index += sm->workers[hash % _vec_len (sm->workers)];
3198 
3199  return next_worker_index;
3200 }
3201 
3202 static u32
3204  u32 rx_fib_index0, u8 is_output)
3205 {
3206  snat_main_t *sm = &snat_main;
3207  udp_header_t *udp;
3208  u16 port;
3209  snat_session_key_t m_key;
3212  u32 proto;
3213  u32 next_worker_index = 0;
3214 
3215  /* first try static mappings without port */
3217  {
3218  m_key.addr = ip0->dst_address;
3219  m_key.port = 0;
3220  m_key.protocol = 0;
3221  m_key.fib_index = rx_fib_index0;
3222  kv.key = m_key.as_u64;
3223  if (!clib_bihash_search_8_8
3224  (&sm->static_mapping_by_external, &kv, &value))
3225  {
3226  m = pool_elt_at_index (sm->static_mappings, value.value);
3227  return m->workers[0];
3228  }
3229  }
3230 
3231  proto = ip_proto_to_nat_proto (ip0->protocol);
3232  udp = ip4_next_header (ip0);
3233  port = udp->dst_port;
3234 
3235  /* unknown protocol */
3236  if (PREDICT_FALSE (proto == NAT_PROTOCOL_OTHER))
3237  {
3238  /* use current thread */
3239  return vlib_get_thread_index ();
3240  }
3241 
3242  if (PREDICT_FALSE (ip0->protocol == IP_PROTOCOL_ICMP))
3243  {
3244  icmp46_header_t *icmp = (icmp46_header_t *) udp;
3245  icmp_echo_header_t *echo = (icmp_echo_header_t *) (icmp + 1);
3247  (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags))
3248  port = vnet_buffer (b)->ip.reass.l4_src_port;
3249  else
3250  {
3251  /* if error message, then it's not fragmented and we can access it */
3252  ip4_header_t *inner_ip = (ip4_header_t *) (echo + 1);
3253  proto = ip_proto_to_nat_proto (inner_ip->protocol);
3254  void *l4_header = ip4_next_header (inner_ip);
3255  switch (proto)
3256  {
3257  case NAT_PROTOCOL_ICMP:
3258  icmp = (icmp46_header_t *) l4_header;
3259  echo = (icmp_echo_header_t *) (icmp + 1);
3260  port = echo->identifier;
3261  break;
3262  case NAT_PROTOCOL_UDP:
3263  case NAT_PROTOCOL_TCP:
3264  port = ((tcp_udp_header_t *) l4_header)->src_port;
3265  break;
3266  default:
3267  return vlib_get_thread_index ();
3268  }
3269  }
3270  }
3271 
3272  /* try static mappings with port */
3274  {
3275  m_key.addr = ip0->dst_address;
3276  m_key.port = clib_net_to_host_u16 (port);
3277  m_key.protocol = proto;
3278  m_key.fib_index = rx_fib_index0;
3279  kv.key = m_key.as_u64;
3280  if (!clib_bihash_search_8_8
3281  (&sm->static_mapping_by_external, &kv, &value))
3282  {
3283  m = pool_elt_at_index (sm->static_mappings, value.value);
3284  return m->workers[0];
3285  }
3286  }
3287 
3288  /* worker by outside port */
3289  next_worker_index = sm->first_worker_index;
3290  next_worker_index +=
3291  sm->workers[(clib_net_to_host_u16 (port) - 1024) / sm->port_per_thread];
3292  return next_worker_index;
3293 }
3294 
3295 static u32
3297  u8 is_output)
3298 {
3299  snat_main_t *sm = &snat_main;
3300  u32 next_worker_index = sm->first_worker_index;
3301  u32 hash;
3302 
3303  clib_bihash_kv_16_8_t kv16, value16;
3305  udp_header_t *udp;
3306 
3307  if (PREDICT_FALSE (is_output))
3308  {
3309  u32 fib_index = sm->outside_fib_index;
3310  nat_outside_fib_t *outside_fib;
3312  fib_prefix_t pfx = {
3314  .fp_len = 32,
3315  .fp_addr = {
3316  .ip4.as_u32 = ip->dst_address.as_u32,
3317  }
3318  ,
3319  };
3320 
3321  udp = ip4_next_header (ip);
3322 
3323  switch (vec_len (sm->outside_fibs))
3324  {
3325  case 0:
3326  fib_index = sm->outside_fib_index;
3327  break;
3328  case 1:
3329  fib_index = sm->outside_fibs[0].fib_index;
3330  break;
3331  default:
3332  /* *INDENT-OFF* */
3333  vec_foreach (outside_fib, sm->outside_fibs)
3334  {
3335  fei = fib_table_lookup (outside_fib->fib_index, &pfx);
3336  if (FIB_NODE_INDEX_INVALID != fei)
3337  {
3338  if (fib_entry_get_resolving_interface (fei) != ~0)
3339  {
3340  fib_index = outside_fib->fib_index;
3341  break;
3342  }
3343  }
3344  }
3345  /* *INDENT-ON* */
3346  break;
3347  }
3348 
3349  make_ed_kv (&ip->src_address, &ip->dst_address,
3350  ip->protocol, fib_index, udp->src_port, udp->dst_port,
3351  ~0ULL, &kv16);
3352 
3353  /* *INDENT-OFF* */
3354  vec_foreach (tsm, sm->per_thread_data)
3355  {
3356  if (PREDICT_TRUE (!clib_bihash_search_16_8 (&tsm->out2in_ed,
3357  &kv16, &value16)))
3358  {
3359  next_worker_index += tsm->thread_index;
3360 
3362  "HANDOFF IN2OUT-OUTPUT-FEATURE (session)",
3363  next_worker_index, fib_index,
3364  clib_net_to_host_u32 (ip->src_address.as_u32),
3365  clib_net_to_host_u32 (ip->dst_address.as_u32));
3366 
3367  return next_worker_index;
3368  }
3369  }
3370  /* *INDENT-ON* */
3371  }
3372 
3373  hash = ip->src_address.as_u32 + (ip->src_address.as_u32 >> 8) +
3374  (ip->src_address.as_u32 >> 16) + (ip->src_address.as_u32 >> 24);
3375 
3376  if (PREDICT_TRUE (is_pow2 (_vec_len (sm->workers))))
3377  next_worker_index += sm->workers[hash & (_vec_len (sm->workers) - 1)];
3378  else
3379  next_worker_index += sm->workers[hash % _vec_len (sm->workers)];
3380 
3381  if (PREDICT_TRUE (!is_output))
3382  {
3383  nat_elog_debug_handoff ("HANDOFF IN2OUT",
3384  next_worker_index, rx_fib_index,
3385  clib_net_to_host_u32 (ip->src_address.as_u32),
3386  clib_net_to_host_u32 (ip->dst_address.as_u32));
3387  }
3388  else
3389  {
3390  nat_elog_debug_handoff ("HANDOFF IN2OUT-OUTPUT-FEATURE",
3391  next_worker_index, rx_fib_index,
3392  clib_net_to_host_u32 (ip->src_address.as_u32),
3393  clib_net_to_host_u32 (ip->dst_address.as_u32));
3394  }
3395 
3396  return next_worker_index;
3397 }
3398 
3399 static u32
3401  u32 rx_fib_index, u8 is_output)
3402 {
3403  snat_main_t *sm = &snat_main;
3405  clib_bihash_kv_16_8_t kv16, value16;
3407 
3408  u32 proto, next_worker_index = 0;
3409  udp_header_t *udp;
3410  u16 port;
3412  u32 hash;
3413 
3414  proto = ip_proto_to_nat_proto (ip->protocol);
3415 
3416  if (PREDICT_TRUE (proto == NAT_PROTOCOL_UDP || proto == NAT_PROTOCOL_TCP))
3417  {
3418  udp = ip4_next_header (ip);
3419 
3420  make_ed_kv (&ip->dst_address, &ip->src_address,
3421  ip->protocol, rx_fib_index, udp->dst_port, udp->src_port,
3422  ~0ULL, &kv16);
3423 
3424  /* *INDENT-OFF* */
3425  vec_foreach (tsm, sm->per_thread_data)
3426  {
3427  if (PREDICT_TRUE (!clib_bihash_search_16_8 (&tsm->out2in_ed,
3428  &kv16, &value16)))
3429  {
3430  next_worker_index = sm->first_worker_index + tsm->thread_index;
3431  nat_elog_debug_handoff ("HANDOFF OUT2IN (session)",
3432  next_worker_index, rx_fib_index,
3433  clib_net_to_host_u32 (ip->src_address.as_u32),
3434  clib_net_to_host_u32 (ip->dst_address.as_u32));
3435  return next_worker_index;
3436  }
3437  }
3438  /* *INDENT-ON* */
3439  }
3440  else if (proto == NAT_PROTOCOL_ICMP)
3441  {
3442  if (!get_icmp_o2i_ed_key (b, ip, rx_fib_index, ~0ULL, 0, 0, 0, &kv16))
3443  {
3444  /* *INDENT-OFF* */
3445  vec_foreach (tsm, sm->per_thread_data)
3446  {
3447  if (PREDICT_TRUE (!clib_bihash_search_16_8 (&tsm->out2in_ed,
3448  &kv16, &value16)))
3449  {
3450  next_worker_index = sm->first_worker_index +
3451  tsm->thread_index;
3452  nat_elog_debug_handoff ("HANDOFF OUT2IN (session)",
3453  next_worker_index, rx_fib_index,
3454  clib_net_to_host_u32 (ip->src_address.as_u32),
3455  clib_net_to_host_u32 (ip->dst_address.as_u32));
3456  return next_worker_index;
3457  }
3458  }
3459  /* *INDENT-ON* */
3460  }
3461  }
3462 
3463  /* first try static mappings without port */
3465  {
3466  make_sm_kv (&kv, &ip->dst_address, 0, 0, 0);
3467  if (!clib_bihash_search_8_8
3468  (&sm->static_mapping_by_external, &kv, &value))
3469  {
3470  m = pool_elt_at_index (sm->static_mappings, value.value);
3471  next_worker_index = m->workers[0];
3472  goto done;
3473  }
3474  }
3475 
3476  /* unknown protocol */
3477  if (PREDICT_FALSE (proto == NAT_PROTOCOL_OTHER))
3478  {
3479  /* use current thread */
3480  next_worker_index = vlib_get_thread_index ();
3481  goto done;
3482  }
3483 
3484  udp = ip4_next_header (ip);
3485  port = udp->dst_port;
3486 
3487  if (PREDICT_FALSE (ip->protocol == IP_PROTOCOL_ICMP))
3488  {
3489  icmp46_header_t *icmp = (icmp46_header_t *) udp;
3490  icmp_echo_header_t *echo = (icmp_echo_header_t *) (icmp + 1);
3492  (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags))
3493  port = vnet_buffer (b)->ip.reass.l4_src_port;
3494  else
3495  {
3496  /* if error message, then it's not fragmented and we can access it */
3497  ip4_header_t *inner_ip = (ip4_header_t *) (echo + 1);
3498  proto = ip_proto_to_nat_proto (inner_ip->protocol);
3499  void *l4_header = ip4_next_header (inner_ip);
3500  switch (proto)
3501  {
3502  case NAT_PROTOCOL_ICMP:
3503  icmp = (icmp46_header_t *) l4_header;
3504  echo = (icmp_echo_header_t *) (icmp + 1);
3505  port = echo->identifier;
3506  break;
3507  case NAT_PROTOCOL_UDP:
3508  case NAT_PROTOCOL_TCP:
3509  port = ((tcp_udp_header_t *) l4_header)->src_port;
3510  break;
3511  default:
3512  next_worker_index = vlib_get_thread_index ();
3513  goto done;
3514  }
3515  }
3516  }
3517 
3518  /* try static mappings with port */
3520  {
3521  make_sm_kv (&kv, &ip->dst_address, proto, 0,
3522  clib_net_to_host_u16 (port));
3523  if (!clib_bihash_search_8_8
3524  (&sm->static_mapping_by_external, &kv, &value))
3525  {
3526  m = pool_elt_at_index (sm->static_mappings, value.value);
3527  if (!is_lb_static_mapping (m))
3528  {
3529  next_worker_index = m->workers[0];
3530  goto done;
3531  }
3532 
3533  hash = ip->src_address.as_u32 + (ip->src_address.as_u32 >> 8) +
3534  (ip->src_address.as_u32 >> 16) + (ip->src_address.as_u32 >> 24);
3535 
3536  if (PREDICT_TRUE (is_pow2 (_vec_len (m->workers))))
3537  next_worker_index =
3538  m->workers[hash & (_vec_len (m->workers) - 1)];
3539  else
3540  next_worker_index = m->workers[hash % _vec_len (m->workers)];
3541  goto done;
3542  }
3543  }
3544 
3545  /* worker by outside port */
3546  next_worker_index = sm->first_worker_index;
3547  next_worker_index +=
3548  sm->workers[(clib_net_to_host_u16 (port) - 1024) / sm->port_per_thread];
3549 
3550 done:
3551  nat_elog_debug_handoff ("HANDOFF OUT2IN", next_worker_index, rx_fib_index,
3552  clib_net_to_host_u32 (ip->src_address.as_u32),
3553  clib_net_to_host_u32 (ip->dst_address.as_u32));
3554  return next_worker_index;
3555 }
3556 
3557 void
3558 nat_ha_sadd_cb (ip4_address_t * in_addr, u16 in_port,
3559  ip4_address_t * out_addr, u16 out_port,
3560  ip4_address_t * eh_addr, u16 eh_port,
3561  ip4_address_t * ehn_addr, u16 ehn_port, u8 proto,
3562  u32 fib_index, u16 flags, u32 thread_index)
3563 {
3564  snat_main_t *sm = &snat_main;
3565  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
3567  snat_user_t *u;
3568  snat_session_t *s;
3571  f64 now = vlib_time_now (vm);
3572  nat_outside_fib_t *outside_fib;
3574  fib_prefix_t pfx = {
3576  .fp_len = 32,
3577  .fp_addr = {
3578  .ip4.as_u32 = eh_addr->as_u32,
3579  },
3580  };
3581 
3582  key.addr.as_u32 = out_addr->as_u32;
3583  key.port = out_port;
3584  key.protocol = proto;
3585 
3586  if (!(flags & SNAT_SESSION_FLAG_STATIC_MAPPING))
3587  {
3589  (sm->addresses, thread_index, &key))
3590  return;
3591  }
3592 
3593  u = nat_user_get_or_create (sm, in_addr, fib_index, thread_index);
3594  if (!u)
3595  return;
3596 
3597  s = nat_session_alloc_or_recycle (sm, u, thread_index, now);
3598  if (!s)
3599  return;
3600 
3601  if (sm->endpoint_dependent)
3602  {
3603  nat_ed_lru_insert (tsm, s, now, proto);
3604  }
3605 
3606  s->last_heard = now;
3607  s->flags = flags;
3608  s->ext_host_addr.as_u32 = eh_addr->as_u32;
3609  s->ext_host_port = eh_port;
3611  switch (vec_len (sm->outside_fibs))
3612  {
3613  case 0:
3614  key.fib_index = sm->outside_fib_index;
3615  break;
3616  case 1:
3617  key.fib_index = sm->outside_fibs[0].fib_index;
3618  break;
3619  default:
3620  /* *INDENT-OFF* */
3621  vec_foreach (outside_fib, sm->outside_fibs)
3622  {
3623  fei = fib_table_lookup (outside_fib->fib_index, &pfx);
3624  if (FIB_NODE_INDEX_INVALID != fei)
3625  {
3626  if (fib_entry_get_resolving_interface (fei) != ~0)
3627  {
3628  key.fib_index = outside_fib->fib_index;
3629  break;
3630  }
3631  }
3632  }
3633  /* *INDENT-ON* */
3634  break;
3635  }
3636  s->out2in = key;
3637  kv.key = key.as_u64;
3638  kv.value = s - tsm->sessions;
3639  if (clib_bihash_add_del_8_8 (&tsm->out2in, &kv, 1))
3640  nat_elog_warn ("out2in key add failed");
3641 
3642  key.addr.as_u32 = in_addr->as_u32;
3643  key.port = in_port;
3644  key.fib_index = fib_index;
3645  s->in2out = key;
3646  kv.key = key.as_u64;
3647  if (clib_bihash_add_del_8_8 (&tsm->in2out, &kv, 1))
3648  nat_elog_warn ("in2out key add failed");
3649 }
3650 
3651 void
3652 nat_ha_sdel_cb (ip4_address_t * out_addr, u16 out_port,
3653  ip4_address_t * eh_addr, u16 eh_port, u8 proto, u32 fib_index,
3654  u32 ti)
3655 {
3656  snat_main_t *sm = &snat_main;
3659  u32 thread_index;
3660  snat_session_t *s;
3662 
3663  if (sm->num_workers > 1)
3664  thread_index =
3665  sm->first_worker_index +
3666  (sm->workers[(clib_net_to_host_u16 (out_port) -
3667  1024) / sm->port_per_thread]);
3668  else
3669  thread_index = sm->num_workers;
3670  tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
3671 
3672  key.addr.as_u32 = out_addr->as_u32;
3673  key.port = out_port;
3674  key.protocol = proto;
3675  key.fib_index = fib_index;
3676  kv.key = key.as_u64;
3677  if (clib_bihash_search_8_8 (&tsm->out2in, &kv, &value))
3678  return;
3679 
3680  s = pool_elt_at_index (tsm->sessions, value.value);
3681  nat_free_session_data (sm, s, thread_index, 1);
3682  nat44_delete_session (sm, s, thread_index);
3683 }
3684 
3685 void
3686 nat_ha_sref_cb (ip4_address_t * out_addr, u16 out_port,
3687  ip4_address_t * eh_addr, u16 eh_port, u8 proto, u32 fib_index,
3688  u32 total_pkts, u64 total_bytes, u32 thread_index)
3689 {
3690  snat_main_t *sm = &snat_main;
3693  snat_session_t *s;
3695 
3696  tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
3697 
3698  key.addr.as_u32 = out_addr->as_u32;
3699  key.port = out_port;
3700  key.protocol = proto;
3701  key.fib_index = fib_index;
3702  kv.key = key.as_u64;
3703  if (clib_bihash_search_8_8 (&tsm->out2in, &kv, &value))
3704  return;
3705 
3706  s = pool_elt_at_index (tsm->sessions, value.value);
3707  s->total_pkts = total_pkts;
3708  s->total_bytes = total_bytes;
3709 }
3710 
3711 void
3713  ip4_address_t * out_addr, u16 out_port,
3714  ip4_address_t * eh_addr, u16 eh_port,
3715  ip4_address_t * ehn_addr, u16 ehn_port, u8 proto,
3716  u32 fib_index, u16 flags, u32 thread_index)
3717 {
3718  snat_main_t *sm = &snat_main;
3719  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
3721  snat_session_t *s;
3724  f64 now = vlib_time_now (vm);
3725  nat_outside_fib_t *outside_fib;
3727  fib_prefix_t pfx = {
3729  .fp_len = 32,
3730  .fp_addr = {
3731  .ip4.as_u32 = eh_addr->as_u32,
3732  },
3733  };
3734 
3735  key.addr.as_u32 = out_addr->as_u32;
3736  key.port = out_port;
3737  key.protocol = proto;
3738 
3739  if (!(flags & SNAT_SESSION_FLAG_STATIC_MAPPING))
3740  {
3742  (sm->addresses, thread_index, &key))
3743  return;
3744  }
3745 
3746  key.addr.as_u32 = ehn_addr->as_u32;
3747  key.port = ehn_port;
3748  if (flags & SNAT_SESSION_FLAG_TWICE_NAT)
3749  {
3751  (sm->twice_nat_addresses, thread_index, &key))
3752  return;
3753  }
3754 
3755  s = nat_ed_session_alloc (sm, thread_index, now, proto);
3756  if (!s)
3757  return;
3758 
3759  s->last_heard = now;
3760  s->flags = flags;
3761  s->ext_host_nat_addr.as_u32 = s->ext_host_addr.as_u32 = eh_addr->as_u32;
3762  s->ext_host_nat_port = s->ext_host_port = eh_port;
3763  if (is_twice_nat_session (s))
3764  {
3765  s->ext_host_nat_addr.as_u32 = ehn_addr->as_u32;
3766  s->ext_host_nat_port = ehn_port;
3767  }
3768  switch (vec_len (sm->outside_fibs))
3769  {
3770  case 0:
3771  key.fib_index = sm->outside_fib_index;
3772  break;
3773  case 1:
3774  key.fib_index = sm->outside_fibs[0].fib_index;
3775  break;
3776  default:
3777  /* *INDENT-OFF* */
3778  vec_foreach (outside_fib, sm->outside_fibs)
3779  {
3780  fei = fib_table_lookup (outside_fib->fib_index, &pfx);
3781  if (FIB_NODE_INDEX_INVALID != fei)
3782  {
3783  if (fib_entry_get_resolving_interface (fei) != ~0)
3784  {
3785  key.fib_index = outside_fib->fib_index;
3786  break;
3787  }
3788  }
3789  }
3790  /* *INDENT-ON* */
3791  break;
3792  }
3793  key.addr.as_u32 = out_addr->as_u32;
3794  key.port = out_port;
3795  s->out2in = key;
3796  kv.value = s - tsm->sessions;
3797 
3798  key.addr.as_u32 = in_addr->as_u32;
3799  key.port = in_port;
3800  key.fib_index = fib_index;
3801  s->in2out = key;
3802 
3803  make_ed_kv (in_addr, &s->ext_host_nat_addr,
3804  nat_proto_to_ip_proto (proto), fib_index, in_port,
3805  s->ext_host_nat_port, s - tsm->sessions, &kv);
3806  if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &kv, 1))
3807  nat_elog_warn ("in2out key add failed");
3808 
3809  make_ed_kv (out_addr, eh_addr, nat_proto_to_ip_proto (proto),
3810  s->out2in.fib_index, out_port, eh_port, s - tsm->sessions, &kv);
3811  if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &kv, 1))
3812  nat_elog_warn ("out2in key add failed");
3813 }
3814 
3815 void
3816 nat_ha_sdel_ed_cb (ip4_address_t * out_addr, u16 out_port,
3817  ip4_address_t * eh_addr, u16 eh_port, u8 proto,
3818  u32 fib_index, u32 ti)
3819 {
3820  snat_main_t *sm = &snat_main;
3822  u32 thread_index;
3823  snat_session_t *s;
3825 
3826  if (sm->num_workers > 1)
3827  thread_index =
3828  sm->first_worker_index +
3829  (sm->workers[(clib_net_to_host_u16 (out_port) -
3830  1024) / sm->port_per_thread]);
3831  else
3832  thread_index = sm->num_workers;
3833  tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
3834 
3835  make_ed_kv (out_addr, eh_addr, proto, fib_index, out_port, eh_port, ~0ULL,
3836  &kv);
3837  if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
3838  return;
3839 
3840  s = pool_elt_at_index (tsm->sessions, value.value);
3841  nat_free_session_data (sm, s, thread_index, 1);
3842  nat44_delete_session (sm, s, thread_index);
3843 }
3844 
3845 void
3846 nat_ha_sref_ed_cb (ip4_address_t * out_addr, u16 out_port,
3847  ip4_address_t * eh_addr, u16 eh_port, u8 proto,
3848  u32 fib_index, u32 total_pkts, u64 total_bytes,
3849  u32 thread_index)
3850 {
3851  snat_main_t *sm = &snat_main;
3853  snat_session_t *s;
3855 
3856  tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
3857 
3858  make_ed_kv (out_addr, eh_addr, proto, fib_index, out_port, eh_port, ~0ULL,
3859  &kv);
3860  if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
3861  return;
3862 
3863  s = pool_elt_at_index (tsm->sessions, value.value);
3864  s->total_pkts = total_pkts;
3865  s->total_bytes = total_bytes;
3866 }
3867 
3868 void
3870 {
3871  snat_main_t *sm = &snat_main;
3872 
3873  pool_alloc (tsm->sessions, sm->max_translations);
3874  pool_alloc (tsm->lru_pool, sm->max_translations);
3875 
3876  dlist_elt_t *head;
3877 
3878  pool_get (tsm->lru_pool, head);
3879  tsm->tcp_trans_lru_head_index = head - tsm->lru_pool;
3881 
3882  pool_get (tsm->lru_pool, head);
3883  tsm->tcp_estab_lru_head_index = head - tsm->lru_pool;
3885 
3886  pool_get (tsm->lru_pool, head);
3887  tsm->udp_lru_head_index = head - tsm->lru_pool;
3889 
3890  pool_get (tsm->lru_pool, head);
3891  tsm->icmp_lru_head_index = head - tsm->lru_pool;
3893 
3894  pool_get (tsm->lru_pool, head);
3895  tsm->unk_proto_lru_head_index = head - tsm->lru_pool;
3897 
3898  if (sm->endpoint_dependent)
3899  {
3900  clib_bihash_init_16_8 (&tsm->in2out_ed, "in2out-ed",
3901  sm->translation_buckets,
3903  clib_bihash_set_kvp_format_fn_16_8 (&tsm->in2out_ed,
3905  clib_bihash_init_16_8 (&tsm->out2in_ed, "out2in-ed",
3906  sm->translation_buckets,
3908  clib_bihash_set_kvp_format_fn_16_8 (&tsm->out2in_ed,
3910  }
3911  else
3912  {
3913  clib_bihash_init_8_8 (&tsm->in2out, "in2out",
3914  sm->translation_buckets,
3916  clib_bihash_set_kvp_format_fn_8_8 (&tsm->in2out, format_session_kvp);
3917  clib_bihash_init_8_8 (&tsm->out2in, "out2in",
3918  sm->translation_buckets,
3920  clib_bihash_set_kvp_format_fn_8_8 (&tsm->out2in, format_session_kvp);
3921  }
3922 
3923  // TODO: resolve static mappings (put only to !ED)
3925  clib_bihash_init_8_8 (&tsm->user_hash, "users", sm->user_buckets,
3926  sm->user_memory_size);
3927  clib_bihash_set_kvp_format_fn_8_8 (&tsm->user_hash, format_user_kvp);
3928 }
3929 
3930 void
3932 {
3933  snat_main_t *sm = &snat_main;
3934 
3935  pool_free (tsm->sessions);
3936  pool_free (tsm->lru_pool);
3937 
3938  if (sm->endpoint_dependent)
3939  {
3940  clib_bihash_free_16_8 (&tsm->in2out_ed);
3941  clib_bihash_free_16_8 (&tsm->out2in_ed);
3942  }
3943  else
3944  {
3945  clib_bihash_free_8_8 (&tsm->in2out);
3946  clib_bihash_free_8_8 (&tsm->out2in);
3947  }
3948 
3949  // TODO: resolve static mappings (put only to !ED)
3950  pool_free (tsm->users);
3951  pool_free (tsm->list_pool);
3952  clib_bihash_free_8_8 (&tsm->user_hash);
3953 }
3954 
3955 static clib_error_t *
3957 {
3958  snat_main_t *sm = &snat_main;
3959  nat66_main_t *nm = &nat66_main;
3961 
3962  u32 static_mapping_buckets = 1024;
3963  uword static_mapping_memory_size = 64 << 20;
3964 
3965  u32 nat64_bib_buckets = 1024;
3966  u32 nat64_bib_memory_size = 128 << 20;
3967 
3968  u32 nat64_st_buckets = 2048;
3969  uword nat64_st_memory_size = 256 << 20;
3970 
3971  u32 user_buckets = 128;
3972  uword user_memory_size = 64 << 20;
3973  u32 translation_buckets = 1024;
3974  uword translation_memory_size = 128 << 20;
3975 
3976  u32 max_translations_per_user = ~0;
3977 
3978  u32 outside_vrf_id = 0;
3979  u32 outside_ip6_vrf_id = 0;
3980  u32 inside_vrf_id = 0;
3981  u8 static_mapping_only = 0;
3982  u8 static_mapping_connection_tracking = 0;
3983 
3984  // configurable timeouts
3985  u32 udp_timeout = SNAT_UDP_TIMEOUT;
3986  u32 icmp_timeout = SNAT_ICMP_TIMEOUT;
3987  u32 tcp_transitory_timeout = SNAT_TCP_TRANSITORY_TIMEOUT;
3988  u32 tcp_established_timeout = SNAT_TCP_ESTABLISHED_TIMEOUT;
3989 
3990  sm->deterministic = 0;
3991  sm->out2in_dpo = 0;
3992  sm->endpoint_dependent = 0;
3993 
3994  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3995  {
3996  if (unformat
3997  (input, "translation hash buckets %d", &translation_buckets))
3998  ;
3999  else if (unformat (input, "udp timeout %d", &udp_timeout))
4000  ;
4001  else if (unformat (input, "icmp timeout %d", &icmp_timeout))
4002  ;
4003  else if (unformat (input, "tcp transitory timeout %d",
4004  &tcp_transitory_timeout));
4005  else if (unformat (input, "tcp established timeout %d",
4006  &tcp_established_timeout));
4007  else if (unformat (input, "translation hash memory %d",
4008  &translation_memory_size));
4009  else if (unformat (input, "user hash buckets %d", &user_buckets))
4010  ;
4011  else if (unformat (input, "user hash memory %d", &user_memory_size))
4012  ;
4013  else if (unformat (input, "max translations per user %d",
4014  &max_translations_per_user))
4015  ;
4016  else if (unformat (input, "outside VRF id %d", &outside_vrf_id))
4017  ;
4018  else if (unformat (input, "outside ip6 VRF id %d", &outside_ip6_vrf_id))
4019  ;
4020  else if (unformat (input, "inside VRF id %d", &inside_vrf_id))
4021  ;
4022  else if (unformat (input, "static mapping only"))
4023  {
4024  static_mapping_only = 1;
4025  if (unformat (input, "connection tracking"))
4026  static_mapping_connection_tracking = 1;
4027  }
4028  else if (unformat (input, "deterministic"))
4029  sm->deterministic = 1;
4030  else if (unformat (input, "nat64 bib hash buckets %d",
4031  &nat64_bib_buckets))
4032  ;
4033  else if (unformat (input, "nat64 bib hash memory %d",
4034  &nat64_bib_memory_size))
4035  ;
4036  else
4037  if (unformat (input, "nat64 st hash buckets %d", &nat64_st_buckets))
4038  ;
4039  else if (unformat (input, "nat64 st hash memory %d",
4040  &nat64_st_memory_size))
4041  ;
4042  else if (unformat (input, "out2in dpo"))
4043  sm->out2in_dpo = 1;
4044  //else if (unformat (input, "dslite ce"))
4045  //dslite_set_ce (dm, 1);
4046  else if (unformat (input, "endpoint-dependent"))
4047  sm->endpoint_dependent = 1;
4048  else
4049  return clib_error_return (0, "unknown input '%U'",
4050  format_unformat_error, input);
4051  }
4052 
4053  if (sm->deterministic && sm->endpoint_dependent)
4054  return clib_error_return (0,
4055  "deterministic and endpoint-dependent modes are mutually exclusive");
4056 
4057  if (static_mapping_only && (sm->deterministic || sm->endpoint_dependent))
4058  return clib_error_return (0,
4059  "static mapping only mode available only for simple nat");
4060 
4061  if (sm->out2in_dpo && (sm->deterministic || sm->endpoint_dependent))
4062  return clib_error_return (0,
4063  "out2in dpo mode available only for simple nat");
4064 
4065  /* optionally configurable timeouts for testing purposes */
4066  sm->udp_timeout = udp_timeout;
4067  sm->tcp_transitory_timeout = tcp_transitory_timeout;
4068  sm->tcp_established_timeout = tcp_established_timeout;
4069  sm->icmp_timeout = icmp_timeout;
4070 
4071  sm->user_buckets = user_buckets;
4072  sm->user_memory_size = user_memory_size;
4073 
4074  sm->translation_buckets = translation_buckets;
4075  sm->translation_memory_size = translation_memory_size;
4076  /* do not exceed load factor 10 */
4077  sm->max_translations = 10 * translation_buckets;
4079 
4080  sm->max_translations_per_user = max_translations_per_user == ~0 ?
4081  sm->max_translations : max_translations_per_user;
4082 
4083  sm->outside_vrf_id = outside_vrf_id;
4085  outside_vrf_id,
4086  nat_fib_src_hi);
4087  nm->outside_vrf_id = outside_ip6_vrf_id;
4089  outside_ip6_vrf_id,
4090  nat_fib_src_hi);
4091  sm->inside_vrf_id = inside_vrf_id;
4093  inside_vrf_id,
4094  nat_fib_src_hi);
4095  sm->static_mapping_only = static_mapping_only;
4096  sm->static_mapping_connection_tracking = static_mapping_connection_tracking;
4097 
4098  nat64_set_hash (nat64_bib_buckets, nat64_bib_memory_size, nat64_st_buckets,
4099  nat64_st_memory_size);
4100 
4101  if (sm->deterministic)
4102  {
4104  sm->in2out_output_node_index = ~0;
4108  }
4109  else
4110  {
4111  if (sm->endpoint_dependent)
4112  {
4115 
4119 
4122  nat_affinity_init (vm);
4125  }
4126  else
4127  {
4130 
4131  sm->in2out_node_index = snat_in2out_node.index;
4133  sm->out2in_node_index = snat_out2in_node.index;
4134 
4138  }
4139  if (!static_mapping_only ||
4140  (static_mapping_only && static_mapping_connection_tracking))
4141  {
4142  /* *INDENT-OFF* */
4143  vec_foreach (tsm, sm->per_thread_data)
4144  {
4145  nat44_db_init (tsm);
4146  }
4147  /* *INDENT-ON* */
4148  }
4149  else
4150  {
4153  }
4154  clib_bihash_init_8_8 (&sm->static_mapping_by_local,
4155  "static_mapping_by_local", static_mapping_buckets,
4156  static_mapping_memory_size);
4157  clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_local,
4159 
4160  clib_bihash_init_8_8 (&sm->static_mapping_by_external,
4161  "static_mapping_by_external",
4162  static_mapping_buckets,
4163  static_mapping_memory_size);
4164  clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_external,
4166  }
4167 
4168  return 0;
4169 }
4170 
4172 
4173 static void
4175  uword opaque,
4176  u32 sw_if_index,
4178  u32 address_length,
4179  u32 if_address_index, u32 is_delete)
4180 {
4181  snat_main_t *sm = &snat_main;
4184  snat_session_key_t m_key;
4186  int i, rv;
4187  ip4_address_t l_addr;
4188 
4189  for (i = 0; i < vec_len (sm->to_resolve); i++)
4190  {
4191  rp = sm->to_resolve + i;
4192  if (rp->addr_only == 0)
4193  continue;
4194  if (rp->sw_if_index == sw_if_index)
4195  goto match;
4196  }
4197 
4198  return;
4199 
4200 match:
4201  m_key.addr.as_u32 = address->as_u32;
4202  m_key.port = rp->addr_only ? 0 : rp->e_port;
4203  m_key.protocol = rp->addr_only ? 0 : rp->proto;
4204  m_key.fib_index = sm->outside_fib_index;
4205  kv.key = m_key.as_u64;
4206  if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
4207  m = 0;
4208  else
4209  m = pool_elt_at_index (sm->static_mappings, value.value);
4210 
4211  if (!is_delete)
4212  {
4213  /* Don't trip over lease renewal, static config */
4214  if (m)
4215  return;
4216  }
4217  else
4218  {
4219  if (!m)
4220  return;
4221  }
4222 
4223  /* Indetity mapping? */
4224  if (rp->l_addr.as_u32 == 0)
4225  l_addr.as_u32 = address[0].as_u32;
4226  else
4227  l_addr.as_u32 = rp->l_addr.as_u32;
4228  /* Add the static mapping */
4229  rv = snat_add_static_mapping (l_addr,
4230  address[0],
4231  rp->l_port,
4232  rp->e_port,
4233  rp->vrf_id,
4234  rp->addr_only, ~0 /* sw_if_index */ ,
4235  rp->proto, !is_delete, rp->twice_nat,
4236  rp->out2in_only, rp->tag, rp->identity_nat);
4237  if (rv)
4238  nat_elog_notice_X1 ("snat_add_static_mapping returned %d", "i4", rv);
4239 }
4240 
4241 static void
4243  uword opaque,
4244  u32 sw_if_index,
4246  u32 address_length,
4247  u32 if_address_index, u32 is_delete)
4248 {
4249  snat_main_t *sm = &snat_main;
4251  ip4_address_t l_addr;
4252  int i, j;
4253  int rv;
4254  u8 twice_nat = 0;
4255  snat_address_t *addresses = sm->addresses;
4256 
4257  for (i = 0; i < vec_len (sm->auto_add_sw_if_indices); i++)
4258  {
4259  if (sw_if_index == sm->auto_add_sw_if_indices[i])
4260  goto match;
4261  }
4262 
4263  for (i = 0; i < vec_len (sm->auto_add_sw_if_indices_twice_nat); i++)
4264  {
4265  twice_nat = 1;
4266  addresses = sm->twice_nat_addresses;
4267  if (sw_if_index == sm->auto_add_sw_if_indices_twice_nat[i])
4268  goto match;
4269  }
4270 
4271  return;
4272 
4273 match:
4274  if (!is_delete)
4275  {
4276  /* Don't trip over lease renewal, static config */
4277  for (j = 0; j < vec_len (addresses); j++)
4278  if (addresses[j].addr.as_u32 == address->as_u32)
4279  return;
4280 
4281  (void) snat_add_address (sm, address, ~0, twice_nat);
4282  /* Scan static map resolution vector */
4283  for (j = 0; j < vec_len (sm->to_resolve); j++)
4284  {
4285  rp = sm->to_resolve + j;
4286  if (rp->addr_only)
4287  continue;
4288  /* On this interface? */
4289  if (rp->sw_if_index == sw_if_index)
4290  {
4291  /* Indetity mapping? */
4292  if (rp->l_addr.as_u32 == 0)
4293  l_addr.as_u32 = address[0].as_u32;
4294  else
4295  l_addr.as_u32 = rp->l_addr.as_u32;
4296  /* Add the static mapping */
4297  rv = snat_add_static_mapping (l_addr,
4298  address[0],
4299  rp->l_port,
4300  rp->e_port,
4301  rp->vrf_id,
4302  rp->addr_only,
4303  ~0 /* sw_if_index */ ,
4304  rp->proto,
4305  rp->is_add, rp->twice_nat,
4306  rp->out2in_only, rp->tag,
4307  rp->identity_nat);
4308  if (rv)
4309  nat_elog_notice_X1 ("snat_add_static_mapping returned %d",
4310  "i4", rv);
4311  }
4312  }
4313  return;
4314  }
4315  else
4316  {
4317  (void) snat_del_address (sm, address[0], 1, twice_nat);
4318  return;
4319  }
4320 }
4321 
4322 
4323 int
4325  u8 twice_nat)
4326 {
4327  ip4_main_t *ip4_main = sm->ip4_main;
4328  ip4_address_t *first_int_addr;
4330  u32 *indices_to_delete = 0;
4331  int i, j;
4332  u32 *auto_add_sw_if_indices =
4333  twice_nat ? sm->
4334  auto_add_sw_if_indices_twice_nat : sm->auto_add_sw_if_indices;
4335 
4336  first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index, 0 /* just want the address */
4337  );
4338 
4339  for (i = 0; i < vec_len (auto_add_sw_if_indices); i++)
4340  {
4341  if (auto_add_sw_if_indices[i] == sw_if_index)
4342  {
4343  if (is_del)
4344  {
4345  /* if have address remove it */
4346  if (first_int_addr)
4347  (void) snat_del_address (sm, first_int_addr[0], 1, twice_nat);
4348  else
4349  {
4350  for (j = 0; j < vec_len (sm->to_resolve); j++)
4351  {
4352  rp = sm->to_resolve + j;
4353  if (rp->sw_if_index == sw_if_index)
4354  vec_add1 (indices_to_delete, j);
4355  }
4356  if (vec_len (indices_to_delete))
4357  {
4358  for (j = vec_len (indices_to_delete) - 1; j >= 0; j--)
4359  vec_del1 (sm->to_resolve, j);
4360  vec_free (indices_to_delete);
4361  }
4362  }
4363  if (twice_nat)
4365  else
4367  }
4368  else
4369  return VNET_API_ERROR_VALUE_EXIST;
4370 
4371  return 0;
4372  }
4373  }
4374 
4375  if (is_del)
4376  return VNET_API_ERROR_NO_SUCH_ENTRY;
4377 
4378  /* add to the auto-address list */
4379  if (twice_nat)
4380  vec_add1 (sm->auto_add_sw_if_indices_twice_nat, sw_if_index);
4381  else
4382  vec_add1 (sm->auto_add_sw_if_indices, sw_if_index);
4383 
4384  /* If the address is already bound - or static - add it now */
4385  if (first_int_addr)
4386  (void) snat_add_address (sm, first_int_addr, ~0, twice_nat);
4387 
4388  return 0;
4389 }
4390 
4391 int
4393  nat_protocol_t proto, u32 vrf_id, int is_in)
4394 {
4397  ip4_header_t ip;
4398  u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
4400  snat_session_t *s;
4401  clib_bihash_8_8_t *t;
4402 
4403  if (sm->endpoint_dependent)
4404  return VNET_API_ERROR_UNSUPPORTED;
4405 
4406  ip.dst_address.as_u32 = ip.src_address.as_u32 = addr->as_u32;
4407  if (sm->num_workers > 1)
4408  tsm =
4410  sm->worker_in2out_cb (&ip, fib_index, 0));
4411  else
4412  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
4413 
4414  key.addr.as_u32 = addr->as_u32;
4415  key.port = clib_host_to_net_u16 (port);
4416  key.protocol = proto;
4417  key.fib_index = fib_index;
4418  kv.key = key.as_u64;
4419  t = is_in ? &tsm->in2out : &tsm->out2in;
4420  if (!clib_bihash_search_8_8 (t, &kv, &value))
4421  {
4422  if (pool_is_free_index (tsm->sessions, value.value))
4423  return VNET_API_ERROR_UNSPECIFIED;
4424 
4425  s = pool_elt_at_index (tsm->sessions, value.value);
4426  nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
4427  nat44_delete_session (sm, s, tsm - sm->per_thread_data);
4428  return 0;
4429  }
4430 
4431  return VNET_API_ERROR_NO_SUCH_ENTRY;
4432 }
4433 
4434 int
4436  ip4_address_t * eh_addr, u16 eh_port, u8 proto,
4437  u32 vrf_id, int is_in)
4438 {
4439  ip4_header_t ip;
4440  clib_bihash_16_8_t *t;
4442  u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
4443  snat_session_t *s;
4445 
4446  if (!sm->endpoint_dependent)
4447  return VNET_API_ERROR_FEATURE_DISABLED;
4448 
4449  ip.dst_address.as_u32 = ip.src_address.as_u32 = addr->as_u32;
4450  if (sm->num_workers > 1)
4451  tsm =
4453  sm->worker_in2out_cb (&ip, fib_index, 0));
4454  else
4455  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
4456 
4457  t = is_in ? &tsm->in2out_ed : &tsm->out2in_ed;
4458  make_ed_kv (addr, eh_addr, proto, fib_index, clib_host_to_net_u16 (port),
4459  clib_host_to_net_u16 (eh_port), ~0ULL, &kv);
4460  if (clib_bihash_search_16_8 (t, &kv, &value))
4461  {
4462  return VNET_API_ERROR_NO_SUCH_ENTRY;
4463  }
4464 
4465  if (pool_is_free_index (tsm->sessions, value.value))
4466  return VNET_API_ERROR_UNSPECIFIED;
4467  s = pool_elt_at_index (tsm->sessions, value.value);
4468  nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
4469  nat_ed_session_delete (sm, s, tsm - sm->per_thread_data, 1);
4470  return 0;
4471 }
4472 
4473 void
4474 nat_set_alloc_addr_and_port_mape (u16 psid, u16 psid_offset, u16 psid_length)
4475 {
4476  snat_main_t *sm = &snat_main;
4477 
4478  sm->addr_and_port_alloc_alg = NAT_ADDR_AND_PORT_ALLOC_ALG_MAPE;
4480  sm->psid = psid;
4481  sm->psid_offset = psid_offset;
4482  sm->psid_length = psid_length;
4483 }
4484 
4485 void
4487 {
4488  snat_main_t *sm = &snat_main;
4489 
4490  sm->addr_and_port_alloc_alg = NAT_ADDR_AND_PORT_ALLOC_ALG_RANGE;
4492  sm->start_port = start_port;
4493  sm->end_port = end_port;
4494 }
4495 
4496 void
4498 {
4499  snat_main_t *sm = &snat_main;
4500 
4501  sm->addr_and_port_alloc_alg = NAT_ADDR_AND_PORT_ALLOC_ALG_DEFAULT;
4503 }
4504 
4507  vlib_frame_t * frame)
4508 {
4509  return 0;
4510 }
4511 
4512 /* *INDENT-OFF* */
4514  .name = "nat-default",
4515  .vector_size = sizeof (u32),
4516  .format_trace = 0,
4518  .n_errors = 0,
4519  .n_next_nodes = NAT_N_NEXT,
4520  .next_nodes = {
4521  [NAT_NEXT_DROP] = "error-drop",
4522  [NAT_NEXT_ICMP_ERROR] = "ip4-icmp-error",
4523  //[NAT_NEXT_IN2OUT_PRE] = "nat-pre-in2out",
4524  //[NAT_NEXT_OUT2IN_PRE] = "nat-pre-out2in",
4525  [NAT_NEXT_IN2OUT_ED_FAST_PATH] = "nat44-ed-in2out",
4526  [NAT_NEXT_IN2OUT_ED_SLOW_PATH] = "nat44-ed-in2out-slowpath",
4527  [NAT_NEXT_IN2OUT_ED_OUTPUT_SLOW_PATH] = "nat44-ed-in2out-output-slowpath",
4528  [NAT_NEXT_OUT2IN_ED_FAST_PATH] = "nat44-ed-out2in",
4529  [NAT_NEXT_OUT2IN_ED_SLOW_PATH] = "nat44-ed-out2in-slowpath",
4530  [NAT_NEXT_IN2OUT_CLASSIFY] = "nat44-in2out-worker-handoff",
4531  [NAT_NEXT_OUT2IN_CLASSIFY] = "nat44-out2in-worker-handoff",
4532  },
4533 };
4534 /* *INDENT-ON* */
4535 
4536 /*
4537  * fd.io coding-style-patch-verification: ON
4538  *
4539  * Local Variables:
4540  * eval: (c-set-style "gnu")
4541  * End:
4542  */
ip4_address_t external_addr
Definition: nat.h:401
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:209
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:507
clib_error_t * snat_api_init(vlib_main_t *vm, snat_main_t *sm)
Definition: nat_api.c:3275
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:2353
nat_outside_fib_t * outside_fibs
Definition: nat.h:566
enum fib_source_t_ fib_source_t
The different sources that can create a route.
uword translation_memory_size
Definition: nat.h:634
u32 * max_translations_per_fib
Definition: nat.h:636
format_function_t format_ip_protocol
Definition: format.h:45
dlist_elt_t * lru_pool
Definition: nat.h:473
#define snat_is_session_static(s)
Check if SNAT session is created from static mapping.
Definition: nat.h:728
u32 sessions_per_user_list_head_index
Definition: nat.h:307
void nat44_db_init(snat_main_per_thread_data_t *tsm)
Initialize NAT44 data.
Definition: nat.c:3869
vlib_node_registration_t nat_default_node
(constructor) VLIB_REGISTER_NODE (nat_default_node)
Definition: nat.c:4513
vlib_node_registration_t nat44_ed_in2out_output_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_output_node)
Definition: in2out_ed.c:1535
#define nat_elog_debug_handoff(_str, _tid, _fib, _src, _dst)
Definition: nat.h:886
ip4_table_bind_function_t * function
Definition: ip4.h:93
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:1740
u32 hairpin_dst_node_index
Definition: nat.h:613
void test_ed_make_split()
Definition: nat.c:2454
ip4_add_del_interface_address_callback_t * add_del_interface_address_callbacks
Functions to call when interface address changes.
Definition: ip4.h:140
u32 ed_hairpinning_node_index
Definition: nat.h:615
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:652
int ip4_sv_reass_enable_disable_with_refcnt(u32 sw_if_index, int is_enable)
ip4_address_t src_address
Definition: ip4_packet.h:170
int nat44_del_session(snat_main_t *sm, ip4_address_t *addr, u16 port, nat_protocol_t proto, u32 vrf_id, int is_in)
Delete NAT44 session.
Definition: nat.c:4392
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
#define nat_elog_info(nat_elog_str)
Definition: nat.h:994
u16 start_port
Definition: nat.h:562
u32 fq_in2out_output_index
Definition: nat.h:583
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:607
#define nat_elog_notice(nat_elog_str)
Definition: nat.h:986
#define pool_alloc(P, N)
Allocate N more free elements to pool (unspecified alignment).
Definition: pool.h:361
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:3051
#define SNAT_TCP_ESTABLISHED_TIMEOUT
Definition: nat.h:42
#define PREDICT_TRUE(x)
Definition: clib.h:119
u32 nsessions
Definition: nat.h:308
#define is_ed_session(s)
Check if NAT session is endpoint dependent.
Definition: nat.h:758
unsigned long u64
Definition: types.h:89
ip4_address_t addr
Definition: nat.h:365
static u32 nat44_ed_get_worker_out2in_cb(vlib_buffer_t *b, ip4_header_t *ip, u32 rx_fib_index, u8 is_output)
Definition: nat.c:3400
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
u32 index
Definition: node.h:282
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:281
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:291
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:989
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:489
u16 port_per_thread
Definition: nat.h:532
u32 vlib_frame_queue_main_init(u32 node_index, u32 frame_queue_nelts)
Definition: threads.c:1854
#define thread_idx
Definition: tls_async.c:40
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 address port)
Definition: nat.c:198
add paths without path extensions
Definition: fib_source.h:205
int ip4_sv_reass_output_enable_disable_with_refcnt(u32 sw_if_index, int is_enable)
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:590
u32 nstaticsessions
Definition: nat.h:309
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:3846
u32 ed_out2in_slowpath_node_index
Definition: nat.h:608
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:326
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:628
#define NAT_INTERFACE_FLAG_IS_OUTSIDE
Definition: nat.h:243
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:3149
nat_protocol_t proto
Definition: nat.h:412
ip_lookup_main_t lookup_main
Definition: ip4.h:108
void snat_static_mapping_del_sessions(snat_main_t *sm, snat_main_per_thread_data_t *tsm, snat_user_key_t u_key, int addr_only, ip4_address_t e_addr, u16 e_port)
Definition: nat.c:763
#define nat_elog_warn(nat_elog_str)
Definition: nat.h:988
vlib_node_registration_t snat_det_out2in_node
(constructor) VLIB_REGISTER_NODE (snat_det_out2in_node)
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:4435
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
u32 fib_index
Definition: nat.h:306
format_function_t format_snat_key
Definition: nat.h:717
nat_protocol_t
Definition: lib.h:41
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:608
#define VLIB_NODE_FN(node)
Definition: node.h:202
static void nat_ed_session_delete(snat_main_t *sm, snat_session_t *ses, u32 thread_index, int lru_delete)
Definition: ed_inlines.h:55
vl_api_prefix_t prefix
Definition: ip.api:144
nat_alloc_out_addr_and_port_function_t * alloc_addr_and_port
Definition: nat.h:554
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:4242
u32 num_snat_thread
Definition: nat.h:533
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:252
dlist_elt_t * list_pool
Definition: nat.h:470
#define snat_is_unk_proto_session(s)
Check if SNAT session for unknown protocol.
Definition: nat.h:734
void nat44_db_free(snat_main_per_thread_data_t *tsm)
Free NAT44 data.
Definition: nat.c:3931
vhost_vring_addr_t addr
Definition: vhost_user.h:254
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:3001
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:2914
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:581
unsigned char u8
Definition: types.h:56
u8 deterministic
Definition: nat.h:629
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:1861
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:430
VNET_FEATURE_INIT(nat_pre_in2out, static)
nat44_lb_addr_port_t * locals
Definition: nat.h:420
u32 user_buckets
Definition: nat.h:638
double f64
Definition: types.h:142
clib_bihash_8_8_t user_hash
Definition: nat.h:461
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:533
#define NAT_STATIC_MAPPING_FLAG_OUT2IN_ONLY
Definition: nat.h:247
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:805
u32 max_translations_per_user
Definition: nat.h:640
clib_bihash_8_8_t in2out
Definition: nat.h:454
Definition: nat.h:62
nat66_main_t nat66_main
Definition: nat66.c:24
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:3558
u32 in2out_output_node_index
Definition: nat.h:599
vl_api_ip_proto_t protocol
Definition: lb_types.api:71
u32 ed_in2out_node_index
Definition: nat.h:603
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
Definition: ip4_fib.c:230
format_function_t format_ip4_address
Definition: format.h:73
snat_get_worker_out2in_function_t * worker_out2in_cb
Definition: nat.h:531
#define static_always_inline
Definition: clib.h:106
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:513
static nat_protocol_t ip_proto_to_nat_proto(u8 ip_proto)
Common NAT inline functions.
Definition: inlines.h:22
vl_api_interface_index_t sw_if_index
Definition: gre.api:53
#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:1386
void nat_syslog_nat44_apmdel(u32 ssubix, u32 sfibix, ip4_address_t *isaddr, u16 isport, ip4_address_t *xsaddr, u16 xsport, nat_protocol_t proto)
Definition: nat_syslog.c:116
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:424
u8 * format_static_mapping_kvp(u8 *s, va_list *args)
Definition: nat.c:3135
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:3712
u32 det_in2out_node_index
Definition: nat.h:609
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:636
u32 translation_buckets
Definition: nat.h:633
u8 * format_ed_session_kvp(u8 *s, va_list *args)
Definition: nat.c:3163
lb_nat_type_t
Definition: nat.h:386
ip4_address_t addr
Definition: nat.h:305
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Aggregate type for a prefix.
Definition: fib_types.h:203
u8 probability
Definition: nat.api:855
static_always_inline u8 icmp_type_is_error_message(u8 icmp_type)
Definition: inlines.h:53
#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:752
static u32 snat_get_worker_in2out_cb(ip4_header_t *ip0, u32 rx_fib_index0, u8 is_output)
Definition: nat.c:3183
static void split_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:458
void snat_ipfix_logging_init(vlib_main_t *vm)
Initialize NAT plugin IPFIX logging.
ip4_main_t * ip4_main
Definition: nat.h:672
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:1097
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:3816
ip4_address_t local_addr
Definition: nat.h:399
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:68
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:4174
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
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:2741
fib_source_t fib_source_allocate(const char *name, fib_source_priority_t prio, fib_source_behaviour_t bh)
Definition: fib_source.c:118
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:2669
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:249
char * name
The counter collection&#39;s name.
Definition: counter.h:64
vl_api_fib_path_type_t type
Definition: fib_types.api:123
int nat44_set_session_limit(u32 session_limit, u32 vrf_id)
Set NAT44 session limit (session limit, vrf id)
Definition: nat.c:333
twice_nat_type_t twice_nat
Definition: nat.h:407
static u32 snat_get_worker_out2in_cb(vlib_buffer_t *b, ip4_header_t *ip0, u32 rx_fib_index0, u8 is_output)
Definition: nat.c:3203
u32 max_translations
Definition: nat.h:635
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:573
Definition: fib_entry.h:117
void nat66_init(vlib_main_t *vm)
Definition: nat66.c:46
vlib_node_registration_t nat44_ed_out2in_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_out2in_node)
Definition: out2in_ed.c:1263
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:2900
uword user_memory_size
Definition: nat.h:639
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:481
Definition: fib_entry.h:116
#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:534
u32 fib_index
Definition: nat.h:328
void nat_dpo_module_init(void)
Definition: nat_dpo.c:68
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
nat_addr_and_port_alloc_alg_t addr_and_port_alloc_alg
Definition: nat.h:556
#define FIB_SOURCE_PRIORITY_HI
Some priority values that plugins might use when they are not to concerned where in the list they&#39;ll ...
Definition: fib_source.h:273
clib_bihash_16_8_t out2in_ed
Definition: nat.h:457
static uword clib_bitmap_last_set(uword *ai)
Return the higest numbered set bit in a bitmap.
Definition: bitmap.h:423
vl_api_ip_proto_t proto
Definition: acl_types.api:50
u64 key
the key
Definition: bihash_8_8.h:41
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:3652
lo
IPv4 shallow virtual reassembly.
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:3686
u16 mss_clamping
Definition: nat.h:655
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
u32 pre_in2out_node_index
Definition: nat.h:596
u16 protocol
Definition: nat.h:80
u8 out2in_dpo
Definition: nat.h:630
#define SNAT_UDP_TIMEOUT
Definition: nat.h:40
snat_static_mapping_t * static_mappings
Definition: nat.h:545
u32 inside_fib_index
Definition: nat.h:645
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:302
u32 udp_timeout
Definition: nat.h:649
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:427
u8 static_mapping_only
Definition: nat.h:627
#define NAT_FQ_NELTS
Definition: nat.h:46
#define PREDICT_FALSE(x)
Definition: clib.h:118
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:182
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:873
u32 hairpin_src_node_index
Definition: nat.h:614
clib_bihash_8_8_t static_mapping_by_external
Definition: nat.h:542
u32 in2out_slowpath_output_node_index
Definition: nat.h:602
u8 psid_offset
Definition: nat.h:558
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
static_always_inline int nat_ed_lru_insert(snat_main_per_thread_data_t *tsm, snat_session_t *s, f64 now, u8 proto)
Definition: ed_inlines.h:27
void nat_set_alloc_addr_and_port_default(void)
Set address and port assignment algorithm to default/standard.
Definition: nat.c:4497
api_main_t * api_main
Definition: nat.h:674
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:1291
static_always_inline snat_session_t * nat_ed_session_alloc(snat_main_t *sm, u32 thread_index, f64 now, u8 proto)
Definition: ed_inlines.h:126
vlib_main_t * vm
Definition: in2out_ed.c:1599
u8 psid_length
Definition: nat.h:559
u32 refcount
Definition: nat.h:329
vnet_main_t * vnet_main
Definition: nat.h:671
u32 inside_vrf_id
Definition: nat.h:644
Definition: nat.h:391
#define is_lb_session(s)
Check if NAT session is load-balancing.
Definition: nat.h:746
u8 log_level
Definition: nat.h:668
u32 fq_out2in_index
Definition: nat.h:584
u8 len
Definition: ip_types.api:92
u32 fib_entry_get_resolving_interface(fib_node_index_t entry_index)
Definition: fib_entry.c:1458
snat_interface_t * output_feature_interfaces
Definition: nat.h:549
void snat_ed_static_mapping_del_sessions(snat_main_t *sm, snat_main_per_thread_data_t *tsm, ip4_address_t l_addr, u16 l_port, u8 protocol, u32 fib_index, int addr_only, ip4_address_t e_addr, u16 e_port)
Definition: nat.c:816
snat_main_t snat_main
Definition: nat.c:41
u32 pre_out2in_node_index
Definition: nat.h:595
u32 ed_hairpin_src_node_index
Definition: nat.h:617
#define pool_free(p)
Free a pool.
Definition: pool.h:427
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:42
snat_user_t * users
Definition: nat.h:464
void nat64_set_hash(u32 bib_buckets, uword bib_memory_size, u32 st_buckets, uword st_memory_size)
Set NAT64 hash tables configuration.
Definition: nat64.c:259
static void nat44_delete_user_with_no_session(snat_main_t *sm, snat_user_t *u, u32 thread_index)
Definition: nat_inlines.h:227
#define is_affinity_sessions(s)
Check if NAT session has affinity record.
Definition: nat.h:764
u32 random_seed
Definition: nat.h:579
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
u32 flags
Definition: vhost_user.h:248
#define NAT_STATIC_MAPPING_FLAG_IDENTITY_NAT
Definition: nat.h:248
u32 nat_affinity_get_per_service_list_head_index(void)
Get new affinity per service list head index.
Definition: nat_affinity.c:81
clib_bihash_8_8_t out2in
Definition: nat.h:453
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:218
fib_source_t nat_fib_src_low
Definition: nat.c:44
u32 outside_vrf_id
Definition: nat.h:642
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:3099
vlib_node_registration_t snat_in2out_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_node)
Definition: in2out.c:1650
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
u8 static_mapping_connection_tracking
Definition: nat.h:628
u16 end_port
Definition: nat.h:563
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
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:886
ip4_add_del_interface_address_function_t * function
Definition: ip4.h:74
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:604
u32 error_node_index
Definition: nat.h:587
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:2126
#define nat_elog_notice_X1(nat_elog_fmt_str, nat_elog_fmt_arg, nat_elog_val1)
Definition: nat.h:997
u16 psid
Definition: nat.h:560
u32 outside_fib_index
Definition: nat.h:643
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:2423
u8 * format_session_kvp(u8 *s, va_list *args)
Definition: nat.c:3122
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:299
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:39
ip4_address_t addr
Definition: nat.h:78
u32 ed_hairpin_dst_node_index
Definition: nat.h:616
fib_source_t nat_fib_src_hi
Definition: nat.c:43
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:457
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1599
u32 tcp_transitory_timeout
Definition: nat.h:650
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:1310
u32 * auto_add_sw_if_indices
Definition: nat.h:572
u32 in2out_fast_node_index
Definition: nat.h:600
void nat44_free_session_data(snat_main_t *sm, snat_session_t *s, u32 thread_index, u8 is_ha)
Free NAT44 ED session data (lookup keys, external address port)
Definition: nat.c:352
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:324
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:2892
void nat_syslog_nat44_sdel(u32 ssubix, u32 sfibix, ip4_address_t *isaddr, u16 isport, ip4_address_t *idaddr, u16 idport, ip4_address_t *xsaddr, u16 xsport, ip4_address_t *xdaddr, u16 xdport, nat_protocol_t proto, u8 is_twicenat)
Definition: nat_syslog.c:209
u8 value
Definition: qos.api:54
#define ASSERT(truth)
#define NAT_INTERFACE_FLAG_IS_INSIDE
Definition: nat.h:242
#define is_addr_only_static_mapping(sm)
Check if NAT static mapping is address only (1:1NAT).
Definition: nat.h:788
u32 num_workers
Definition: nat.h:527
manual_print typedef address
Definition: ip_types.api:85
u32 first_worker_index
Definition: nat.h:528
#define is_identity_static_mapping(sm)
Check if NAT static mapping is identity NAT.
Definition: nat.h:800
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, nat_protocol_t proto, int addr_only, int is_add, u8 *tag, int twice_nat, int out2in_only, int identity_nat)
Definition: nat.c:720
u32 det_out2in_node_index
Definition: nat.h:610
ip4_address_t l_addr
Definition: nat.h:435
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:601
snat_icmp_match_function_t * icmp_match_out2in_cb
Definition: nat.h:524
vlib_log_class_t log_class
Definition: nat.h:666
IPv4 main type.
Definition: ip4.h:106
#define SNAT_SESSION_FLAG_TWICE_NAT
Definition: nat.h:235
u64 as_u64
Definition: nat.h:111
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:4486
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:1156
ip4_address_t addr
Definition: nat.h:108
#define clib_bitmap_free(v)
Free a bitmap.
Definition: bitmap.h:92
u32 fq_in2out_index
Definition: nat.h:582
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:294
u32 out2in_node_index
Definition: nat.h:605
void snat_ipfix_logging_nat44_ses_delete(u32 thread_index, u32 src_ip, u32 nat_src_ip, nat_protocol_t nat_proto, u16 src_port, u16 nat_src_port, u32 vrf_id)
Generate NAT44 session delete event.
ip4_address_t addr
Definition: nat.h:314
vlib_node_registration_t nat44_ed_in2out_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_node)
Definition: in2out_ed.c:1515
#define FIB_SOURCE_PRIORITY_LOW
Definition: fib_source.h:274
snat_address_t * twice_nat_addresses
Definition: nat.h:569
#define VNET_FEATURES(...)
Definition: feature.h:470
#define A(x)
Definition: main.c:1048
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
vl_api_ip4_address_t hi
Definition: arp.api:37
static clib_error_t * snat_init(vlib_main_t *vm)
Definition: nat.c:2494
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:250
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:461
ip4_table_bind_callback_t * table_bind_callbacks
Functions to call when interface to table biding changes.
Definition: ip4.h:147
clib_error_t * nat64_init(vlib_main_t *vm)
Initialize NAT64.
Definition: nat64.c:201
typedef key
Definition: ipsec_types.api:85
NAT64 global declarations.
#define is_lb_static_mapping(sm)
Check if NAT static mapping is load-balancing.
Definition: nat.h:806
Definition: nat.h:389
char * stat_segment_name
Name in stat segment directory.
Definition: counter.h:65
vlib_simple_counter_main_t total_users
Definition: nat.h:659
#define nat_elog_err(nat_elog_str)
Definition: nat.h:990
vl_api_address_t ip
Definition: l2.api:501
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:31
format_function_t format_static_mapping_key
Definition: nat.h:718
int nat44_lb_static_mapping_add_del_local(ip4_address_t e_addr, u16 e_port, ip4_address_t l_addr, u16 l_port, nat_protocol_t proto, u32 vrf_id, u8 probability, u8 is_add)
Definition: nat.c:1578
static void user_session_increment(snat_main_t *sm, snat_user_t *u, u8 is_static)
Definition: nat_inlines.h:215
twice_nat_type_t
Definition: nat.h:376
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u32 hairpinning_node_index
Definition: nat.h:612
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:794
static_always_inline u8 nat_proto_to_ip_proto(nat_protocol_t nat_proto)
Definition: inlines.h:35
Definition: fib_entry.h:113
VLIB buffer representation.
Definition: buffer.h:102
u32 * workers
Definition: nat.h:529
u64 uword
Definition: types.h:112
snat_main_per_thread_data_t * per_thread_data
Definition: nat.h:536
void nat_affinity_flush_service(u32 affinity_per_service_list_head_index)
Flush all service affinity data.
Definition: nat_affinity.c:97
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:422
u32 fib_index
Definition: nat.h:109
snat_address_t * addresses
Definition: nat.h:552
u16 port
Definition: lb_types.api:72
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 interface.
Definition: nat.c:4324
u32 out2in_fast_node_index
Definition: nat.h:606
static_always_inline int get_icmp_o2i_ed_key(vlib_buffer_t *b, ip4_header_t *ip0, u32 rx_fib_index, u64 value, u8 *nat_proto, u16 *l_port, u16 *r_port, clib_bihash_kv_16_8_t *kv)
Definition: nat_inlines.h:568
#define hash_get_mem(h, key)
Definition: hash.h:269
u32 in2out_node_index
Definition: nat.h:598
#define SNAT_ICMP_TIMEOUT
Definition: nat.h:43
snat_get_worker_in2out_function_t * worker_in2out_cb
Definition: nat.h:530
snat_static_map_resolve_t * to_resolve
Definition: nat.h:576
static api_main_t * vlibapi_get_main(void)
Definition: api_common.h:379
#define vnet_buffer(b)
Definition: buffer.h:417
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:232
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1144
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
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, nat_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:862
u32 outside_vrf_id
Definition: nat66.h:62
u8 forwarding_enabled
Definition: nat.h:624
static u32 get_thread_idx_by_port(u16 e_port)
Definition: nat.c:749
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.
nat_protocol_t proto
Definition: nat.h:440
vlib_node_registration_t snat_in2out_output_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_output_node)
Definition: in2out.c:1682
f64 end
end of the time range
Definition: mactime.api:44
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1600
int nat44_add_del_lb_static_mapping(ip4_address_t e_addr, u16 e_port, nat_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:1325
int snat_set_workers(uword *bitmap)
Set NAT plugin workers.
Definition: nat.c:2324
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:636
#define is_twice_nat_session(s)
Check if NAT session is twice NAT.
Definition: nat.h:740
clib_bihash_16_8_t in2out_ed
Definition: nat.h:458
u32 vrf_id
Definition: nat.api:856
u8 endpoint_dependent
Definition: nat.h:631
static clib_error_t * snat_config(vlib_main_t *vm, unformat_input_t *input)
Definition: nat.c:3956
static u32 nat44_ed_get_worker_in2out_cb(ip4_header_t *ip, u32 rx_fib_index, u8 is_output)
Definition: nat.c:3296
#define pool_foreach_index(i, v, body)
Iterate pool by index.
Definition: pool.h:558
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:4474
NAT66 global declarations.
NAT plugin client-IP based session affinity for load-balancing.
vlib_simple_counter_main_t total_sessions
Definition: nat.h:660
#define SNAT_TCP_TRANSITORY_TIMEOUT
Definition: nat.h:41
ip_lookup_main_t * ip4_lookup_main
Definition: nat.h:673
#define NAT_STATIC_MAPPING_FLAG_LB
Definition: nat.h:249
static int is_snat_address_used_in_static_mapping(snat_main_t *sm, ip4_address_t addr)
Definition: nat.c:701
#define NAT_STATIC_MAPPING_FLAG_ADDR_ONLY
Definition: nat.h:246
snat_session_t * sessions
Definition: nat.h:467
snat_icmp_match_function_t * icmp_match_in2out_cb
Definition: nat.h:523
static void make_ed_kv(ip4_address_t *l_addr, ip4_address_t *r_addr, u8 proto, u32 fib_index, u16 l_port, u16 r_port, u64 value, clib_bihash_kv_16_8_t *kv)
Definition: nat_inlines.h:447
clib_bihash_8_8_t static_mapping_by_local
Definition: nat.h:539
u32 fib_index
Definition: nat.h:315
snat_interface_t * interfaces
Definition: nat.h:548
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:80
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:304
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171
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:2705
u32 tcp_established_timeout
Definition: nat.h:651
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128