FD.io VPP  v21.06-1-gbb7418cf9
Vector Packet Processing
nat44_ei.c
Go to the documentation of this file.
1 /*
2  * nat44_ei.c - nat44 endpoint dependent plugin
3  *
4  * Copyright (c) 2020 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, WITHOUT
13  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14  * License for the specific language governing permissions and limitations
15  * under the License.
16  */
17 
18 #include <vnet/plugin/plugin.h>
19 #include <vpp/app/version.h>
20 
21 #include <vnet/vnet.h>
22 #include <vnet/ip/ip.h>
23 #include <vnet/ip/ip4.h>
24 #include <vnet/ip/ip_table.h>
26 #include <vnet/fib/fib_table.h>
27 #include <vnet/fib/ip4_fib.h>
28 #include <vnet/plugin/plugin.h>
29 
30 // nat lib
31 #include <nat/lib/log.h>
32 #include <nat/lib/nat_syslog.h>
33 #include <nat/lib/nat_inlines.h>
34 #include <nat/lib/ipfix_logging.h>
35 
38 #include <nat/nat44-ei/nat44_ei.h>
39 
41 
48 
49 #define skip_if_disabled() \
50  do \
51  { \
52  nat44_ei_main_t *nm = &nat44_ei_main; \
53  if (PREDICT_FALSE (!nm->enabled)) \
54  return; \
55  } \
56  while (0)
57 
58 #define fail_if_enabled() \
59  do \
60  { \
61  nat44_ei_main_t *nm = &nat44_ei_main; \
62  if (PREDICT_FALSE (nm->enabled)) \
63  { \
64  nat44_ei_log_err ("plugin enabled"); \
65  return 1; \
66  } \
67  } \
68  while (0)
69 
70 #define fail_if_disabled() \
71  do \
72  { \
73  nat44_ei_main_t *nm = &nat44_ei_main; \
74  if (PREDICT_FALSE (!nm->enabled)) \
75  { \
76  nat44_ei_log_err ("plugin disabled"); \
77  return 1; \
78  } \
79  } \
80  while (0)
81 
82 /* Hook up input features */
83 VNET_FEATURE_INIT (ip4_nat_classify, static) = {
84  .arc_name = "ip4-unicast",
85  .node_name = "nat44-ei-classify",
86  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
87  "ip4-sv-reassembly-feature"),
88 };
89 VNET_FEATURE_INIT (ip4_nat_handoff_classify, static) = {
90  .arc_name = "ip4-unicast",
91  .node_name = "nat44-ei-handoff-classify",
92  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
93  "ip4-sv-reassembly-feature"),
94 };
95 VNET_FEATURE_INIT (ip4_nat44_ei_in2out, static) = {
96  .arc_name = "ip4-unicast",
97  .node_name = "nat44-ei-in2out",
98  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
99  "ip4-sv-reassembly-feature"),
100 };
101 VNET_FEATURE_INIT (ip4_nat44_ei_out2in, static) = {
102  .arc_name = "ip4-unicast",
103  .node_name = "nat44-ei-out2in",
104  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
105  "ip4-sv-reassembly-feature",
106  "ip4-dhcp-client-detect"),
107 };
108 VNET_FEATURE_INIT (ip4_nat44_ei_in2out_output, static) = {
109  .arc_name = "ip4-output",
110  .node_name = "nat44-ei-in2out-output",
111  .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa",
112  "ip4-sv-reassembly-output-feature"),
113 };
114 VNET_FEATURE_INIT (ip4_nat44_ei_in2out_fast, static) = {
115  .arc_name = "ip4-unicast",
116  .node_name = "nat44-ei-in2out-fast",
117  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
118  "ip4-sv-reassembly-feature"),
119 };
120 VNET_FEATURE_INIT (ip4_nat44_ei_out2in_fast, static) = {
121  .arc_name = "ip4-unicast",
122  .node_name = "nat44-ei-out2in-fast",
123  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
124  "ip4-sv-reassembly-feature",
125  "ip4-dhcp-client-detect"),
126 };
127 VNET_FEATURE_INIT (ip4_nat44_ei_hairpin_dst, static) = {
128  .arc_name = "ip4-unicast",
129  .node_name = "nat44-ei-hairpin-dst",
130  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
131  "ip4-sv-reassembly-feature"),
132 };
133 VNET_FEATURE_INIT (ip4_nat44_ei_hairpin_src, static) = {
134  .arc_name = "ip4-output",
135  .node_name = "nat44-ei-hairpin-src",
136  .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa",
137  "ip4-sv-reassembly-output-feature"),
138 };
139 VNET_FEATURE_INIT (ip4_nat44_ei_hairpinning, static) = {
140  .arc_name = "ip4-local",
141  .node_name = "nat44-ei-hairpinning",
142  .runs_before = VNET_FEATURES ("ip4-local-end-of-arc"),
143 };
144 VNET_FEATURE_INIT (ip4_nat44_ei_in2out_worker_handoff, static) = {
145  .arc_name = "ip4-unicast",
146  .node_name = "nat44-ei-in2out-worker-handoff",
147  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
148 };
149 VNET_FEATURE_INIT (ip4_nat44_ei_out2in_worker_handoff, static) = {
150  .arc_name = "ip4-unicast",
151  .node_name = "nat44-ei-out2in-worker-handoff",
152  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
153  "ip4-dhcp-client-detect"),
154 };
155 VNET_FEATURE_INIT (ip4_nat44_ei_in2out_output_worker_handoff, static) = {
156  .arc_name = "ip4-output",
157  .node_name = "nat44-ei-in2out-output-worker-handoff",
158  .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa",
159  "ip4-sv-reassembly-output-feature"),
160 };
161 
163  .version = VPP_BUILD_VER,
164  .description = "IPv4 Endpoint-Independent NAT (NAT44 EI)",
165 };
166 
167 #define foreach_nat44_ei_classify_error \
168  _ (NEXT_IN2OUT, "next in2out") \
169  _ (NEXT_OUT2IN, "next out2in") \
170  _ (FRAG_CACHED, "fragment cached")
171 
172 typedef enum
173 {
174 #define _(sym, str) NAT44_EI_CLASSIFY_ERROR_##sym,
176 #undef _
179 
181 #define _(sym, string) string,
183 #undef _
184 };
185 
186 typedef enum
187 {
193 
194 typedef struct
195 {
199 
201  u32 sw_if_index, int is_add);
202 
203 static u8 *
205 {
206  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
207  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
209  char *next;
210 
211  if (t->cached)
212  s = format (s, "nat44-ei-classify: fragment cached");
213  else
214  {
215  next = t->next_in2out ? "nat44-ei-in2out" : "nat44-ei-out2in";
216  s = format (s, "nat44-ei-classify: next %s", next);
217  }
218 
219  return s;
220 }
221 
222 static void nat44_ei_db_free ();
223 
224 static void nat44_ei_db_init (u32 translations, u32 translation_buckets,
225  u32 user_buckets);
226 
228  ip4_main_t *im, uword opaque, u32 sw_if_index, ip4_address_t *address,
229  u32 address_length, u32 if_address_index, u32 is_delete);
230 
232  ip4_main_t *im, uword opaque, u32 sw_if_index, ip4_address_t *address,
233  u32 address_length, u32 if_address_index, u32 is_delete);
234 
235 static void nat44_ei_update_outside_fib (ip4_main_t *im, uword opaque,
236  u32 sw_if_index, u32 new_fib_index,
237  u32 old_fib_index);
238 
239 void
241 {
242  vlib_node_t *node;
243  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ei-out2in");
244  nm->out2in_node_index = node->index;
245  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ei-in2out");
246  nm->in2out_node_index = node->index;
247  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ei-in2out-output");
248  nm->in2out_output_node_index = node->index;
249 }
250 
251 int
253 {
255  int i, j = 0;
256 
257  if (nm->num_workers < 2)
258  return VNET_API_ERROR_FEATURE_DISABLED;
259 
260  if (clib_bitmap_last_set (bitmap) >= nm->num_workers)
261  return VNET_API_ERROR_INVALID_WORKER;
262 
263  vec_free (nm->workers);
264  clib_bitmap_foreach (i, bitmap)
265  {
266  vec_add1 (nm->workers, i);
269  j++;
270  }
271 
272  nm->port_per_thread = (0xffff - 1024) / _vec_len (nm->workers);
273 
274  return 0;
275 }
276 
277 #define nat_validate_simple_counter(c, i) \
278  do \
279  { \
280  vlib_validate_simple_counter (&c, i); \
281  vlib_zero_simple_counter (&c, i); \
282  } \
283  while (0);
284 
285 #define nat_init_simple_counter(c, n, sn) \
286  do \
287  { \
288  c.name = n; \
289  c.stat_segment_name = sn; \
290  nat_validate_simple_counter (c, 0); \
291  } \
292  while (0);
293 
296 {
297 #define _(x) \
298  nat_validate_simple_counter (nm->counters.fastpath.in2out.x, sw_if_index); \
299  nat_validate_simple_counter (nm->counters.fastpath.out2in.x, sw_if_index); \
300  nat_validate_simple_counter (nm->counters.slowpath.in2out.x, sw_if_index); \
301  nat_validate_simple_counter (nm->counters.slowpath.out2in.x, sw_if_index);
303 #undef _
305 }
306 
307 clib_error_t *
309 {
314  ip4_table_bind_callback_t cbt = { 0 };
315  u32 i, num_threads = 0;
316  uword *p, *bitmap = 0;
317 
318  clib_memset (nm, 0, sizeof (*nm));
319 
320  // required
321  nm->vnet_main = vnet_get_main ();
322  // convenience
323  nm->ip4_main = &ip4_main;
324  nm->api_main = vlibapi_get_main ();
326 
327  // handoff stuff
328  nm->fq_out2in_index = ~0;
329  nm->fq_in2out_index = ~0;
330  nm->fq_in2out_output_index = ~0;
331 
332  nm->log_level = NAT_LOG_ERROR;
333 
334  nat44_ei_set_node_indexes (nm, vm);
335  nm->log_class = vlib_log_register_class ("nat44-ei", 0);
336 
337  nat_init_simple_counter (nm->total_users, "total-users",
338  "/nat44-ei/total-users");
339  nat_init_simple_counter (nm->total_sessions, "total-sessions",
340  "/nat44-ei/total-sessions");
341  nat_init_simple_counter (nm->user_limit_reached, "user-limit-reached",
342  "/nat44-ei/user-limit-reached");
343 
344 #define _(x) \
345  nat_init_simple_counter (nm->counters.fastpath.in2out.x, #x, \
346  "/nat44-ei/in2out/fastpath/" #x); \
347  nat_init_simple_counter (nm->counters.fastpath.out2in.x, #x, \
348  "/nat44-ei/out2in/fastpath/" #x); \
349  nat_init_simple_counter (nm->counters.slowpath.in2out.x, #x, \
350  "/nat44-ei/in2out/slowpath/" #x); \
351  nat_init_simple_counter (nm->counters.slowpath.out2in.x, #x, \
352  "/nat44-ei/out2in/slowpath/" #x);
354 #undef _
355  nat_init_simple_counter (nm->counters.hairpinning, "hairpinning",
356  "/nat44-ei/hairpinning");
357 
358  p = hash_get_mem (tm->thread_registrations_by_name, "workers");
359  if (p)
360  {
361  tr = (vlib_thread_registration_t *) p[0];
362  if (tr)
363  {
364  nm->num_workers = tr->count;
366  }
367  }
368  num_threads = tm->n_vlib_mains - 1;
369  nm->port_per_thread = 0xffff - 1024;
370  vec_validate (nm->per_thread_data, num_threads);
371 
372  /* Use all available workers by default */
373  if (nm->num_workers > 1)
374  {
375 
376  for (i = 0; i < nm->num_workers; i++)
377  bitmap = clib_bitmap_set (bitmap, i, 1);
378  nat44_ei_set_workers (bitmap);
379  clib_bitmap_free (bitmap);
380  }
381  else
383 
384  /* callbacks to call when interface address changes. */
389 
390  /* callbacks to call when interface to table biding changes */
393 
398 
399  // used only by out2in-dpo feature
401  nat_ha_init (vm, nm->num_workers, num_threads);
402 
413  return nat44_ei_api_hookup (vm);
414 }
415 
417 
418 int
420 {
422 
423  fail_if_enabled ();
424 
425  if (!c.users)
426  c.users = 1024;
427 
428  if (!c.sessions)
429  c.sessions = 10 * 1024;
430 
431  if (!c.user_sessions)
432  c.user_sessions = c.sessions;
433 
434  nm->rconfig = c;
435 
436  if (!nm->frame_queue_nelts)
438 
439  nm->translations = c.sessions;
442 
443  nm->pat = (!c.static_mapping_only ||
445 
448  nm->out2in_dpo = c.out2in_dpo;
449  nm->forwarding_enabled = 0;
450  nm->mss_clamping = 0;
451 
452  nm->max_users_per_thread = c.users;
455 
456  nm->inside_vrf_id = c.inside_vrf;
459 
460  nm->outside_vrf_id = c.outside_vrf;
463 
466  nm->user_buckets);
468 
469  // TODO: zero simple counter for all counters missing
470 
474 
475  nat_ha_enable ();
476  nm->enabled = 1;
477 
478  return 0;
479 }
480 
481 void
483 {
484  nat44_ei_address_t *ap;
485  vec_foreach (ap, *addresses)
486  {
487 #define _(N, i, n, s) vec_free (ap->busy_##n##_ports_per_thread);
489 #undef _
490  }
491  vec_free (*addresses);
492  *addresses = 0;
493 }
494 
495 int
497 {
498  const char *feature_name, *del_feature_name;
501  nat44_ei_address_t *ap;
503  nat44_ei_outside_fib_t *outside_fib;
504  u32 fib_index =
506 
507  fail_if_disabled ();
508 
509  if (nm->out2in_dpo && !is_inside)
510  {
511  nat44_ei_log_err ("error unsupported");
512  return VNET_API_ERROR_UNSUPPORTED;
513  }
514 
516  {
517  if (i->sw_if_index == sw_if_index)
518  {
519  nat44_ei_log_err ("error interface already configured");
520  return VNET_API_ERROR_VALUE_EXIST;
521  }
522  }
523 
525  feature_name = is_inside ? "nat44-ei-in2out-fast" : "nat44-ei-out2in-fast";
526  else
527  {
528  if (nm->num_workers > 1)
529  feature_name = is_inside ? "nat44-ei-in2out-worker-handoff" :
530  "nat44-ei-out2in-worker-handoff";
531  else
532  feature_name = is_inside ? "nat44-ei-in2out" : "nat44-ei-out2in";
533  }
534 
535  if (nm->fq_in2out_index == ~0 && nm->num_workers > 1)
537  nm->frame_queue_nelts);
538 
539  if (nm->fq_out2in_index == ~0 && nm->num_workers > 1)
541  nm->frame_queue_nelts);
542 
543  if (!is_inside)
544  {
545  vec_foreach (outside_fib, nm->outside_fibs)
546  {
547  if (outside_fib->fib_index == fib_index)
548  {
549  if (is_del)
550  {
551  outside_fib->refcount--;
552  if (!outside_fib->refcount)
553  vec_del1 (nm->outside_fibs,
554  outside_fib - nm->outside_fibs);
555  }
556  else
557  outside_fib->refcount++;
558  goto feature_set;
559  }
560  }
561  if (!is_del)
562  {
563  vec_add2 (nm->outside_fibs, outside_fib, 1);
564  outside_fib->refcount = 1;
565  outside_fib->fib_index = fib_index;
566  }
567  }
568 
569 feature_set:
570  pool_foreach (i, nm->interfaces)
571  {
572  if (i->sw_if_index == sw_if_index)
573  {
574  if (is_del)
575  {
578  {
579  if (is_inside)
581  else
583 
584  if (nm->num_workers > 1)
585  {
586  del_feature_name = "nat44-ei-handoff-classify";
587  clib_warning (
588  "del_feature_name = nat44-ei-handoff-classify");
589  feature_name = !is_inside ?
590  "nat44-ei-in2out-worker-handoff" :
591  "nat44-ei-out2in-worker-handoff";
592  }
593  else
594  {
595  del_feature_name = "nat44-ei-classify";
596  clib_warning ("del_feature_name = nat44-ei-classify");
597  feature_name =
598  !is_inside ? "nat44-ei-in2out" : "nat44-ei-out2in";
599  }
600 
601  int rv =
603  if (rv)
604  return rv;
606  "ip4-unicast", del_feature_name, sw_if_index, 0, 0, 0);
607  if (rv)
608  return rv;
610  "ip4-unicast", feature_name, sw_if_index, 1, 0, 0);
611  if (rv)
612  return rv;
613  if (!is_inside)
614  {
615  rv = vnet_feature_enable_disable ("ip4-local",
616  "nat44-ei-hairpinning",
617  sw_if_index, 1, 0, 0);
618  if (rv)
619  return rv;
620  }
621  }
622  else
623  {
624  int rv =
626  if (rv)
627  return rv;
629  "ip4-unicast", feature_name, sw_if_index, 0, 0, 0);
630  if (rv)
631  return rv;
632  pool_put (nm->interfaces, i);
633  if (is_inside)
634  {
635  rv = vnet_feature_enable_disable ("ip4-local",
636  "nat44-ei-hairpinning",
637  sw_if_index, 0, 0, 0);
638  if (rv)
639  return rv;
640  }
641  }
642  }
643  else
644  {
645  if ((nat44_ei_interface_is_inside (i) && is_inside) ||
646  (nat44_ei_interface_is_outside (i) && !is_inside))
647  return 0;
648 
649  if (nm->num_workers > 1)
650  {
651  del_feature_name = !is_inside ?
652  "nat44-ei-in2out-worker-handoff" :
653  "nat44-ei-out2in-worker-handoff";
654  feature_name = "nat44-ei-handoff-classify";
655  clib_warning ("feature_name = nat44-ei-handoff-classify");
656  }
657  else
658  {
659  del_feature_name =
660  !is_inside ? "nat44-ei-in2out" : "nat44-ei-out2in";
661  feature_name = "nat44-ei-classify";
662  clib_warning ("feature_name = nat44-ei-classify");
663  }
664 
665  int rv =
667  if (rv)
668  return rv;
670  "ip4-unicast", del_feature_name, sw_if_index, 0, 0, 0);
671  if (rv)
672  return rv;
673  rv = vnet_feature_enable_disable ("ip4-unicast", feature_name,
674  sw_if_index, 1, 0, 0);
675  if (rv)
676  return rv;
677  if (!is_inside)
678  {
680  "ip4-local", "nat44-ei-hairpinning", sw_if_index, 0, 0, 0);
681  if (rv)
682  return rv;
683  }
684  goto set_flags;
685  }
686 
687  goto fib;
688  }
689  }
690 
691  if (is_del)
692  {
693  nat44_ei_log_err ("error interface couldn't be found");
694  return VNET_API_ERROR_NO_SUCH_ENTRY;
695  }
696 
697  pool_get (nm->interfaces, i);
699  i->flags = 0;
700  nat_validate_interface_counters (nm, sw_if_index);
701 
702  int rv = vnet_feature_enable_disable ("ip4-unicast", feature_name,
703  sw_if_index, 1, 0, 0);
704  if (rv)
705  return rv;
706 
707  rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 1);
708  if (rv)
709  return rv;
710 
711  if (is_inside && !nm->out2in_dpo)
712  {
713  rv = vnet_feature_enable_disable ("ip4-local", "nat44-ei-hairpinning",
714  sw_if_index, 1, 0, 0);
715  if (rv)
716  return rv;
717  }
718 
719 set_flags:
720  if (is_inside)
721  {
723  return 0;
724  }
725  else
727 
728  /* Add/delete external addresses to FIB */
729 fib:
730  vec_foreach (ap, nm->addresses)
731  nat44_ei_add_del_addr_to_fib (&ap->addr, 32, sw_if_index, !is_del);
732 
734  {
737  continue;
738 
739  nat44_ei_add_del_addr_to_fib (&m->external_addr, 32, sw_if_index,
740  !is_del);
741  }
742 
743  return 0;
744 }
745 
746 int
748  int is_del)
749 {
752  nat44_ei_address_t *ap;
754  nat44_ei_outside_fib_t *outside_fib;
755  u32 fib_index =
757 
758  fail_if_disabled ();
759 
761  {
762  nat44_ei_log_err ("error unsupported");
763  return VNET_API_ERROR_UNSUPPORTED;
764  }
765 
766  pool_foreach (i, nm->interfaces)
767  {
768  if (i->sw_if_index == sw_if_index)
769  {
770  nat44_ei_log_err ("error interface already configured");
771  return VNET_API_ERROR_VALUE_EXIST;
772  }
773  }
774 
775  if (!is_inside)
776  {
777  vec_foreach (outside_fib, nm->outside_fibs)
778  {
779  if (outside_fib->fib_index == fib_index)
780  {
781  if (is_del)
782  {
783  outside_fib->refcount--;
784  if (!outside_fib->refcount)
785  vec_del1 (nm->outside_fibs,
786  outside_fib - nm->outside_fibs);
787  }
788  else
789  outside_fib->refcount++;
790  goto feature_set;
791  }
792  }
793  if (!is_del)
794  {
795  vec_add2 (nm->outside_fibs, outside_fib, 1);
796  outside_fib->refcount = 1;
797  outside_fib->fib_index = fib_index;
798  }
799  }
800 
801 feature_set:
802  if (is_inside)
803  {
804  int rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, !is_del);
805  if (rv)
806  return rv;
807  rv =
808  ip4_sv_reass_output_enable_disable_with_refcnt (sw_if_index, !is_del);
809  if (rv)
810  return rv;
811  rv = vnet_feature_enable_disable ("ip4-unicast", "nat44-ei-hairpin-dst",
812  sw_if_index, !is_del, 0, 0);
813  if (rv)
814  return rv;
815  rv = vnet_feature_enable_disable ("ip4-output", "nat44-ei-hairpin-src",
816  sw_if_index, !is_del, 0, 0);
817  if (rv)
818  return rv;
819  goto fq;
820  }
821 
822  if (nm->num_workers > 1)
823  {
824  int rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, !is_del);
825  if (rv)
826  return rv;
827  rv =
828  ip4_sv_reass_output_enable_disable_with_refcnt (sw_if_index, !is_del);
829  if (rv)
830  return rv;
831  rv = vnet_feature_enable_disable ("ip4-unicast",
832  "nat44-ei-out2in-worker-handoff",
833  sw_if_index, !is_del, 0, 0);
834  if (rv)
835  return rv;
837  "ip4-output", "nat44-ei-in2out-output-worker-handoff", sw_if_index,
838  !is_del, 0, 0);
839  if (rv)
840  return rv;
841  }
842  else
843  {
844  int rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, !is_del);
845  if (rv)
846  return rv;
847  rv =
848  ip4_sv_reass_output_enable_disable_with_refcnt (sw_if_index, !is_del);
849  if (rv)
850  return rv;
851  rv = vnet_feature_enable_disable ("ip4-unicast", "nat44-ei-out2in",
852  sw_if_index, !is_del, 0, 0);
853  if (rv)
854  return rv;
855  rv = vnet_feature_enable_disable ("ip4-output", "nat44-ei-in2out-output",
856  sw_if_index, !is_del, 0, 0);
857  if (rv)
858  return rv;
859  }
860 
861 fq:
862  if (nm->fq_in2out_output_index == ~0 && nm->num_workers > 1)
865 
866  if (nm->fq_out2in_index == ~0 && nm->num_workers > 1)
867  nm->fq_out2in_index =
869 
871  {
872  if (i->sw_if_index == sw_if_index)
873  {
874  if (is_del)
876  else
877  return VNET_API_ERROR_VALUE_EXIST;
878 
879  goto fib;
880  }
881  }
882 
883  if (is_del)
884  {
885  nat44_ei_log_err ("error interface couldn't be found");
886  return VNET_API_ERROR_NO_SUCH_ENTRY;
887  }
888 
891  i->flags = 0;
892  nat_validate_interface_counters (nm, sw_if_index);
893  if (is_inside)
895  else
897 
898  /* Add/delete external addresses to FIB */
899 fib:
900  if (is_inside)
901  return 0;
902 
903  vec_foreach (ap, nm->addresses)
904  nat44_ei_add_del_addr_to_fib (&ap->addr, 32, sw_if_index, !is_del);
905 
907  {
910  continue;
911 
912  nat44_ei_add_del_addr_to_fib (&m->external_addr, 32, sw_if_index,
913  !is_del);
914  }
915 
916  return 0;
917 }
918 
919 int
921 {
923  nat44_ei_interface_t *i, *vec;
924  int error = 0;
925 
926  // first unregister all nodes from interfaces
927  vec = vec_dup (nm->interfaces);
928  vec_foreach (i, vec)
929  {
931  error = nat44_ei_interface_add_del (i->sw_if_index, 1, 1);
933  error = nat44_ei_interface_add_del (i->sw_if_index, 0, 1);
934 
935  if (error)
936  {
937  nat44_ei_log_err ("error occurred while removing interface %u",
938  i->sw_if_index);
939  }
940  }
941  vec_free (vec);
942  nm->interfaces = 0;
943 
945  vec_foreach (i, vec)
946  {
948  error =
951  error =
953 
954  if (error)
955  {
956  nat44_ei_log_err ("error occurred while removing interface %u",
957  i->sw_if_index);
958  }
959  }
960  vec_free (vec);
962 
963  nat_ha_disable ();
964  nat44_ei_db_free ();
965 
967 
968  vec_free (nm->to_resolve);
970 
971  nm->to_resolve = 0;
972  nm->auto_add_sw_if_indices = 0;
973 
974  nm->forwarding_enabled = 0;
975 
976  nm->enabled = 0;
977  clib_memset (&nm->rconfig, 0, sizeof (nm->rconfig));
978 
979  return error;
980 }
981 
982 int
986 {
988  nat44_ei_address_t *a = 0;
989  u32 address_index;
990  u16 port_host_byte_order = clib_net_to_host_u16 (port);
991 
992  for (address_index = 0; address_index < vec_len (addresses); address_index++)
993  {
994  if (addresses[address_index].addr.as_u32 != addr.as_u32)
995  continue;
996 
997  a = addresses + address_index;
998  switch (protocol)
999  {
1000 #define _(N, j, n, s) \
1001  case NAT_PROTOCOL_##N: \
1002  if (a->busy_##n##_port_refcounts[port_host_byte_order]) \
1003  return VNET_API_ERROR_INSTANCE_IN_USE; \
1004  ++a->busy_##n##_port_refcounts[port_host_byte_order]; \
1005  a->busy_##n##_ports_per_thread[thread_index]++; \
1006  a->busy_##n##_ports++; \
1007  return 0;
1009 #undef _
1010  default : nat_elog_info (nm, "unknown protocol");
1011  return 1;
1012  }
1013  }
1014 
1015  return VNET_API_ERROR_NO_SUCH_ENTRY;
1016 }
1017 
1018 void
1020 {
1022  dpo_id_t dpo_v4 = DPO_INVALID;
1023  fib_prefix_t pfx = {
1025  .fp_len = 32,
1026  .fp_addr.ip4.as_u32 = addr.as_u32,
1027  };
1028 
1029  if (is_add)
1030  {
1031  nat_dpo_create (DPO_PROTO_IP4, 0, &dpo_v4);
1033  FIB_ENTRY_FLAG_EXCLUSIVE, &dpo_v4);
1034  dpo_reset (&dpo_v4);
1035  }
1036  else
1037  {
1039  }
1040 }
1041 
1042 void
1046 {
1049  u32 address_index;
1050  u16 port_host_byte_order = clib_net_to_host_u16 (port);
1051 
1052  for (address_index = 0; address_index < vec_len (addresses); address_index++)
1053  {
1054  if (addresses[address_index].addr.as_u32 == addr->as_u32)
1055  break;
1056  }
1057 
1058  ASSERT (address_index < vec_len (addresses));
1059 
1060  a = addresses + address_index;
1061 
1062  switch (protocol)
1063  {
1064 #define _(N, i, n, s) \
1065  case NAT_PROTOCOL_##N: \
1066  ASSERT (a->busy_##n##_port_refcounts[port_host_byte_order] >= 1); \
1067  --a->busy_##n##_port_refcounts[port_host_byte_order]; \
1068  a->busy_##n##_ports--; \
1069  a->busy_##n##_ports_per_thread[thread_index]--; \
1070  break;
1072 #undef _
1073  default : nat_elog_info (nm, "unknown protocol");
1074  return;
1075  }
1076 }
1077 
1078 void
1080  u32 thread_index, u8 is_ha)
1081 {
1083 
1084  /* session lookup tables */
1085  init_nat_i2o_k (&kv, s);
1086  if (clib_bihash_add_del_8_8 (&nm->in2out, &kv, 0))
1087  nat_elog_warn (nm, "in2out key del failed");
1088  init_nat_o2i_k (&kv, s);
1089  if (clib_bihash_add_del_8_8 (&nm->out2in, &kv, 0))
1090  nat_elog_warn (nm, "out2in key del failed");
1091 
1092  if (!is_ha)
1093  nat_syslog_nat44_apmdel (s->user_index, s->in2out.fib_index,
1094  &s->in2out.addr, s->in2out.port, &s->out2in.addr,
1095  s->out2in.port, s->nat_proto);
1096 
1098  return;
1099 
1100  if (!is_ha)
1101  {
1102  /* log NAT event */
1104  thread_index, s->in2out.addr.as_u32, s->out2in.addr.as_u32,
1105  s->nat_proto, s->in2out.port, s->out2in.port, s->in2out.fib_index);
1106 
1107  nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
1108  s->ext_host_port, s->nat_proto, s->out2in.fib_index,
1109  thread_index);
1110  }
1111 
1113  return;
1114 
1116  &s->out2in.addr, s->out2in.port,
1117  s->nat_proto);
1118 }
1119 
1120 nat44_ei_user_t *
1122  u32 fib_index, u32 thread_index)
1123 {
1124  nat44_ei_user_t *u = 0;
1125  nat44_ei_user_key_t user_key;
1128  dlist_elt_t *per_user_list_head_elt;
1129 
1130  user_key.addr.as_u32 = addr->as_u32;
1131  user_key.fib_index = fib_index;
1132  kv.key = user_key.as_u64;
1133 
1134  /* Ever heard of the "user" = src ip4 address before? */
1135  if (clib_bihash_search_8_8 (&tnm->user_hash, &kv, &value))
1136  {
1137  if (pool_elts (tnm->users) >= nm->max_users_per_thread)
1138  {
1140  0, 1);
1141  nat_elog_warn (nm, "maximum user limit reached");
1142  return NULL;
1143  }
1144  /* no, make a new one */
1145  pool_get (tnm->users, u);
1146  clib_memset (u, 0, sizeof (*u));
1147 
1148  u->addr.as_u32 = addr->as_u32;
1149  u->fib_index = fib_index;
1150 
1151  pool_get (tnm->list_pool, per_user_list_head_elt);
1152 
1153  u->sessions_per_user_list_head_index =
1154  per_user_list_head_elt - tnm->list_pool;
1155 
1156  clib_dlist_init (tnm->list_pool, u->sessions_per_user_list_head_index);
1157 
1158  kv.value = u - tnm->users;
1159 
1160  /* add user */
1161  if (clib_bihash_add_del_8_8 (&tnm->user_hash, &kv, 1))
1162  {
1163  nat_elog_warn (nm, "user_hash key add failed");
1164  nat44_ei_delete_user_with_no_session (nm, u, thread_index);
1165  return NULL;
1166  }
1167 
1168  vlib_set_simple_counter (&nm->total_users, thread_index, 0,
1169  pool_elts (tnm->users));
1170  }
1171  else
1172  {
1173  u = pool_elt_at_index (tnm->users, value.value);
1174  }
1175 
1176  return u;
1177 }
1178 
1179 nat44_ei_session_t *
1182 {
1183  nat44_ei_session_t *s;
1185  u32 oldest_per_user_translation_list_index, session_index;
1186  dlist_elt_t *oldest_per_user_translation_list_elt;
1187  dlist_elt_t *per_user_translation_list_elt;
1188 
1189  /* Over quota? Recycle the least recently used translation */
1190  if ((u->nsessions + u->nstaticsessions) >= nm->max_translations_per_user)
1191  {
1192  oldest_per_user_translation_list_index = clib_dlist_remove_head (
1193  tnm->list_pool, u->sessions_per_user_list_head_index);
1194 
1195  ASSERT (oldest_per_user_translation_list_index != ~0);
1196 
1197  /* Add it back to the end of the LRU list */
1198  clib_dlist_addtail (tnm->list_pool, u->sessions_per_user_list_head_index,
1199  oldest_per_user_translation_list_index);
1200  /* Get the list element */
1201  oldest_per_user_translation_list_elt = pool_elt_at_index (
1202  tnm->list_pool, oldest_per_user_translation_list_index);
1203 
1204  /* Get the session index from the list element */
1205  session_index = oldest_per_user_translation_list_elt->value;
1206 
1207  /* Get the session */
1208  s = pool_elt_at_index (tnm->sessions, session_index);
1209 
1210  nat44_ei_free_session_data_v2 (nm, s, thread_index, 0);
1212  u->nstaticsessions--;
1213  else
1214  u->nsessions--;
1215  s->flags = 0;
1216  s->total_bytes = 0;
1217  s->total_pkts = 0;
1218  s->state = 0;
1219  s->ext_host_addr.as_u32 = 0;
1220  s->ext_host_port = 0;
1221  s->ext_host_nat_addr.as_u32 = 0;
1222  s->ext_host_nat_port = 0;
1223  }
1224  else
1225  {
1226  pool_get (tnm->sessions, s);
1227  clib_memset (s, 0, sizeof (*s));
1228 
1229  /* Create list elts */
1230  pool_get (tnm->list_pool, per_user_translation_list_elt);
1231  clib_dlist_init (tnm->list_pool,
1232  per_user_translation_list_elt - tnm->list_pool);
1233 
1234  per_user_translation_list_elt->value = s - tnm->sessions;
1235  s->per_user_index = per_user_translation_list_elt - tnm->list_pool;
1236  s->per_user_list_head_index = u->sessions_per_user_list_head_index;
1237 
1238  clib_dlist_addtail (tnm->list_pool, s->per_user_list_head_index,
1239  per_user_translation_list_elt - tnm->list_pool);
1240 
1241  s->user_index = u - tnm->users;
1242  vlib_set_simple_counter (&nm->total_sessions, thread_index, 0,
1243  pool_elts (tnm->sessions));
1244  }
1245 
1246  s->ha_last_refreshed = now;
1247 
1248  return s;
1249 }
1250 
1251 void
1253  u32 thread_index, u8 is_ha)
1254 {
1256 
1257  init_nat_i2o_k (&kv, s);
1258  if (clib_bihash_add_del_8_8 (&nm->in2out, &kv, 0))
1259  nat_elog_warn (nm, "in2out key del failed");
1260 
1261  init_nat_o2i_k (&kv, s);
1262  if (clib_bihash_add_del_8_8 (&nm->out2in, &kv, 0))
1263  nat_elog_warn (nm, "out2in key del failed");
1264 
1265  if (!is_ha)
1266  {
1267  nat_syslog_nat44_apmdel (s->user_index, s->in2out.fib_index,
1268  &s->in2out.addr, s->in2out.port,
1269  &s->out2in.addr, s->out2in.port, s->nat_proto);
1270 
1272  thread_index, s->in2out.addr.as_u32, s->out2in.addr.as_u32,
1273  s->nat_proto, s->in2out.port, s->out2in.port, s->in2out.fib_index);
1274 
1275  nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
1276  s->ext_host_port, s->nat_proto, s->out2in.fib_index,
1277  thread_index);
1278  }
1279 
1281  return;
1282 
1284  &s->out2in.addr, s->out2in.port,
1285  s->nat_proto);
1286 }
1287 
1290 {
1291  dlist_elt_t *elt;
1292  nat44_ei_session_t *s;
1293 
1296 
1297  // get head
1298  elt =
1299  pool_elt_at_index (tnm->list_pool, u->sessions_per_user_list_head_index);
1300  // get first element
1301  elt = pool_elt_at_index (tnm->list_pool, elt->next);
1302 
1303  while (elt->value != ~0)
1304  {
1305  s = pool_elt_at_index (tnm->sessions, elt->value);
1306  elt = pool_elt_at_index (tnm->list_pool, elt->next);
1307 
1308  nat44_ei_free_session_data (nm, s, thread_index, 0);
1309  nat44_ei_delete_session (nm, s, thread_index);
1310  }
1311 }
1312 
1313 int
1315 {
1316  int rv = 1;
1317 
1320 
1321  nat44_ei_user_key_t user_key;
1323 
1324  user_key.addr.as_u32 = addr->as_u32;
1325  user_key.fib_index = fib_index;
1326  kv.key = user_key.as_u64;
1327 
1328  if (nm->num_workers > 1)
1329  {
1330  vec_foreach (tnm, nm->per_thread_data)
1331  {
1332  if (!clib_bihash_search_8_8 (&tnm->user_hash, &kv, &value))
1333  {
1335  pool_elt_at_index (tnm->users, value.value),
1336  tnm->thread_index);
1337  rv = 0;
1338  break;
1339  }
1340  }
1341  }
1342  else
1343  {
1344  tnm = vec_elt_at_index (nm->per_thread_data, nm->num_workers);
1345  if (!clib_bihash_search_8_8 (&tnm->user_hash, &kv, &value))
1346  {
1348  pool_elt_at_index (tnm->users, value.value), tnm->thread_index);
1349  rv = 0;
1350  }
1351  }
1352  return rv;
1353 }
1354 
1355 void
1358  nat44_ei_user_key_t u_key, int addr_only,
1359  ip4_address_t e_addr, u16 e_port)
1360 {
1362  kv.key = u_key.as_u64;
1363  u64 user_index;
1364  dlist_elt_t *head, *elt;
1365  nat44_ei_user_t *u;
1366  nat44_ei_session_t *s;
1367  u32 elt_index, head_index, ses_index;
1368 
1369  if (!clib_bihash_search_8_8 (&tnm->user_hash, &kv, &value))
1370  {
1371  user_index = value.value;
1372  u = pool_elt_at_index (tnm->users, user_index);
1373  if (u->nstaticsessions)
1374  {
1375  head_index = u->sessions_per_user_list_head_index;
1376  head = pool_elt_at_index (tnm->list_pool, head_index);
1377  elt_index = head->next;
1378  elt = pool_elt_at_index (tnm->list_pool, elt_index);
1379  ses_index = elt->value;
1380  while (ses_index != ~0)
1381  {
1382  s = pool_elt_at_index (tnm->sessions, ses_index);
1383  elt = pool_elt_at_index (tnm->list_pool, elt->next);
1384  ses_index = elt->value;
1385 
1386  if (!addr_only)
1387  {
1388  if ((s->out2in.addr.as_u32 != e_addr.as_u32) ||
1389  (s->out2in.port != e_port))
1390  continue;
1391  }
1392 
1393  if (!nat44_ei_is_session_static (s))
1394  continue;
1395 
1397  0);
1398  nat44_ei_delete_session (nm, s, tnm - nm->per_thread_data);
1399 
1400  if (!addr_only)
1401  break;
1402  }
1403  }
1404  }
1405 }
1406 
1407 u32
1409  u8 is_output)
1410 {
1412  u32 next_worker_index = 0;
1413  u32 hash;
1414 
1415  next_worker_index = nm->first_worker_index;
1416  hash = ip0->src_address.as_u32 + (ip0->src_address.as_u32 >> 8) +
1417  (ip0->src_address.as_u32 >> 16) + (ip0->src_address.as_u32 >> 24);
1418 
1419  if (PREDICT_TRUE (is_pow2 (_vec_len (nm->workers))))
1420  next_worker_index += nm->workers[hash & (_vec_len (nm->workers) - 1)];
1421  else
1422  next_worker_index += nm->workers[hash % _vec_len (nm->workers)];
1423 
1424  return next_worker_index;
1425 }
1426 
1427 u32
1429  u32 rx_fib_index0, u8 is_output)
1430 {
1432  udp_header_t *udp;
1433  u16 port;
1436  u32 proto;
1437  u32 next_worker_index = 0;
1438 
1439  /* first try static mappings without port */
1441  {
1442  init_nat_k (&kv, ip0->dst_address, 0, rx_fib_index0, 0);
1443  if (!clib_bihash_search_8_8 (&nm->static_mapping_by_external, &kv,
1444  &value))
1445  {
1446  m = pool_elt_at_index (nm->static_mappings, value.value);
1447  return m->workers[0];
1448  }
1449  }
1450 
1451  proto = ip_proto_to_nat_proto (ip0->protocol);
1452  udp = ip4_next_header (ip0);
1453  port = vnet_buffer (b)->ip.reass.l4_dst_port;
1454 
1455  /* unknown protocol */
1456  if (PREDICT_FALSE (proto == NAT_PROTOCOL_OTHER))
1457  {
1458  /* use current thread */
1459  return vlib_get_thread_index ();
1460  }
1461 
1462  if (PREDICT_FALSE (ip0->protocol == IP_PROTOCOL_ICMP))
1463  {
1464  icmp46_header_t *icmp = (icmp46_header_t *) udp;
1465  icmp_echo_header_t *echo = (icmp_echo_header_t *) (icmp + 1);
1467  vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags))
1468  port = vnet_buffer (b)->ip.reass.l4_src_port;
1469  else
1470  {
1471  /* if error message, then it's not fragmented and we can access it */
1472  ip4_header_t *inner_ip = (ip4_header_t *) (echo + 1);
1473  proto = ip_proto_to_nat_proto (inner_ip->protocol);
1474  void *l4_header = ip4_next_header (inner_ip);
1475  switch (proto)
1476  {
1477  case NAT_PROTOCOL_ICMP:
1478  icmp = (icmp46_header_t *) l4_header;
1479  echo = (icmp_echo_header_t *) (icmp + 1);
1480  port = echo->identifier;
1481  break;
1482  case NAT_PROTOCOL_UDP:
1483  case NAT_PROTOCOL_TCP:
1484  port = ((tcp_udp_header_t *) l4_header)->src_port;
1485  break;
1486  default:
1487  return vlib_get_thread_index ();
1488  }
1489  }
1490  }
1491 
1492  /* try static mappings with port */
1494  {
1495  init_nat_k (&kv, ip0->dst_address, port, rx_fib_index0, proto);
1496  if (!clib_bihash_search_8_8 (&nm->static_mapping_by_external, &kv,
1497  &value))
1498  {
1499  m = pool_elt_at_index (nm->static_mappings, value.value);
1500  return m->workers[0];
1501  }
1502  }
1503 
1504  /* worker by outside port */
1505  next_worker_index = nm->first_worker_index;
1506  next_worker_index +=
1507  nm->workers[(clib_net_to_host_u16 (port) - 1024) / nm->port_per_thread];
1508  return next_worker_index;
1509 }
1510 
1511 static int
1514  ip4_address_t s_addr, ip4_address_t *addr,
1515  u16 *port, u16 port_per_thread,
1516  u32 snat_thread_index)
1517 {
1519  nat44_ei_address_t *a, *ga = 0;
1520  u32 portnum;
1521  int i;
1522 
1523  if (vec_len (addresses) > 0)
1524  {
1525 
1526  int s_addr_offset = s_addr.as_u32 % vec_len (addresses);
1527 
1528  for (i = s_addr_offset; i < vec_len (addresses); ++i)
1529  {
1530  a = addresses + i;
1531  switch (proto)
1532  {
1533 #define _(N, j, n, s) \
1534  case NAT_PROTOCOL_##N: \
1535  if (a->busy_##n##_ports_per_thread[thread_index] < port_per_thread) \
1536  { \
1537  if (a->fib_index == fib_index) \
1538  { \
1539  while (1) \
1540  { \
1541  portnum = (port_per_thread * snat_thread_index) + \
1542  nat_random_port (&nm->random_seed, 0, \
1543  port_per_thread - 1) + \
1544  1024; \
1545  if (a->busy_##n##_port_refcounts[portnum]) \
1546  continue; \
1547  --a->busy_##n##_port_refcounts[portnum]; \
1548  a->busy_##n##_ports_per_thread[thread_index]++; \
1549  a->busy_##n##_ports++; \
1550  *addr = a->addr; \
1551  *port = clib_host_to_net_u16 (portnum); \
1552  return 0; \
1553  } \
1554  } \
1555  else if (a->fib_index == ~0) \
1556  { \
1557  ga = a; \
1558  } \
1559  } \
1560  break;
1562  default:
1563  nat_elog_info (nm, "unknown protocol");
1564  return 1;
1565  }
1566  }
1567 
1568  for (i = 0; i < s_addr_offset; ++i)
1569  {
1570  a = addresses + i;
1571  switch (proto)
1572  {
1574  default:
1575  nat_elog_info (nm, "unknown protocol");
1576  return 1;
1577  }
1578  }
1579  if (ga)
1580  {
1581  a = ga;
1582  // fake fib index to reuse macro
1583  fib_index = ~0;
1584  switch (proto)
1585  {
1587  default : nat_elog_info (nm, "unknown protocol");
1588  return 1;
1589  }
1590  }
1591  }
1592 
1593 #undef _
1594 
1595  /* Totally out of translations to use... */
1596  nat_ipfix_logging_addresses_exhausted (thread_index, 0);
1597  return 1;
1598 }
1599 
1600 static int
1604  u16 port_per_thread, u32 snat_thread_index)
1605 {
1607  nat44_ei_address_t *a = addresses;
1608  u16 portnum, ports;
1609 
1610  ports = nm->end_port - nm->start_port + 1;
1611 
1612  if (!vec_len (addresses))
1613  goto exhausted;
1614 
1615  switch (proto)
1616  {
1617 #define _(N, i, n, s) \
1618  case NAT_PROTOCOL_##N: \
1619  if (a->busy_##n##_ports < ports) \
1620  { \
1621  while (1) \
1622  { \
1623  portnum = nat_random_port (&nm->random_seed, nm->start_port, \
1624  nm->end_port); \
1625  if (a->busy_##n##_port_refcounts[portnum]) \
1626  continue; \
1627  ++a->busy_##n##_port_refcounts[portnum]; \
1628  a->busy_##n##_ports++; \
1629  *addr = a->addr; \
1630  *port = clib_host_to_net_u16 (portnum); \
1631  return 0; \
1632  } \
1633  } \
1634  break;
1636 #undef _
1637  default : nat_elog_info (nm, "unknown protocol");
1638  return 1;
1639  }
1640 
1641 exhausted:
1642  /* Totally out of translations to use... */
1643  nat_ipfix_logging_addresses_exhausted (thread_index, 0);
1644  return 1;
1645 }
1646 
1647 static int
1651  u16 port_per_thread, u32 snat_thread_index)
1652 {
1654  nat44_ei_address_t *a = addresses;
1655  u16 m, ports, portnum, A, j;
1656  m = 16 - (nm->psid_offset + nm->psid_length);
1657  ports = (1 << (16 - nm->psid_length)) - (1 << m);
1658 
1659  if (!vec_len (addresses))
1660  goto exhausted;
1661 
1662  switch (proto)
1663  {
1664 #define _(N, i, n, s) \
1665  case NAT_PROTOCOL_##N: \
1666  if (a->busy_##n##_ports < ports) \
1667  { \
1668  while (1) \
1669  { \
1670  A = nat_random_port (&nm->random_seed, 1, \
1671  pow2_mask (nm->psid_offset)); \
1672  j = nat_random_port (&nm->random_seed, 0, pow2_mask (m)); \
1673  portnum = A | (nm->psid << nm->psid_offset) | (j << (16 - m)); \
1674  if (a->busy_##n##_port_refcounts[portnum]) \
1675  continue; \
1676  ++a->busy_##n##_port_refcounts[portnum]; \
1677  a->busy_##n##_ports++; \
1678  *addr = a->addr; \
1679  *port = clib_host_to_net_u16 (portnum); \
1680  return 0; \
1681  } \
1682  } \
1683  break;
1685 #undef _
1686  default : nat_elog_info (nm, "unknown protocol");
1687  return 1;
1688  }
1689 
1690 exhausted:
1691  /* Totally out of translations to use... */
1692  nat_ipfix_logging_addresses_exhausted (thread_index, 0);
1693  return 1;
1694 }
1695 
1696 void
1698 {
1700 
1701  nm->addr_and_port_alloc_alg = NAT44_EI_ADDR_AND_PORT_ALLOC_ALG_DEFAULT;
1703 }
1704 
1705 void
1707 {
1709 
1710  nm->addr_and_port_alloc_alg = NAT44_EI_ADDR_AND_PORT_ALLOC_ALG_RANGE;
1712  nm->start_port = start_port;
1713  nm->end_port = end_port;
1714 }
1715 
1716 void
1717 nat44_ei_set_alloc_mape (u16 psid, u16 psid_offset, u16 psid_length)
1718 {
1720 
1721  nm->addr_and_port_alloc_alg = NAT44_EI_ADDR_AND_PORT_ALLOC_ALG_MAPE;
1723  nm->psid = psid;
1724  nm->psid_offset = psid_offset;
1725  nm->psid_length = psid_length;
1726 }
1727 
1728 static void
1730  u16 e_port, nat_protocol_t proto,
1732  int addr_only, int identity_nat,
1733  u8 *tag)
1734 {
1737 
1738  vec_add2 (nm->to_resolve, rp, 1);
1739  clib_memset (rp, 0, sizeof (*rp));
1740 
1741  rp->l_addr.as_u32 = l_addr.as_u32;
1742  rp->l_port = l_port;
1743  rp->e_port = e_port;
1744  rp->sw_if_index = sw_if_index;
1745  rp->vrf_id = vrf_id;
1746  rp->proto = proto;
1747  rp->addr_only = addr_only;
1748  rp->identity_nat = identity_nat;
1749  rp->tag = vec_dup (tag);
1750 }
1751 
1752 void
1753 nat44_ei_delete_session (nat44_ei_main_t *nm, nat44_ei_session_t *ses,
1754  u32 thread_index)
1755 {
1757  vec_elt_at_index (nm->per_thread_data, thread_index);
1759  nat44_ei_user_t *u;
1760  const nat44_ei_user_key_t u_key = { .addr = ses->in2out.addr,
1761  .fib_index = ses->in2out.fib_index };
1762  const u8 u_static = nat44_ei_is_session_static (ses);
1763 
1764  clib_dlist_remove (tnm->list_pool, ses->per_user_index);
1765  pool_put_index (tnm->list_pool, ses->per_user_index);
1766 
1767  pool_put (tnm->sessions, ses);
1768  vlib_set_simple_counter (&nm->total_sessions, thread_index, 0,
1769  pool_elts (tnm->sessions));
1770 
1771  kv.key = u_key.as_u64;
1772  if (!clib_bihash_search_8_8 (&tnm->user_hash, &kv, &value))
1773  {
1774  u = pool_elt_at_index (tnm->users, value.value);
1775  if (u_static)
1776  u->nstaticsessions--;
1777  else
1778  u->nsessions--;
1779 
1780  nat44_ei_delete_user_with_no_session (nm, u, thread_index);
1781  }
1782 }
1783 
1784 int
1786  nat_protocol_t proto, u32 vrf_id, int is_in)
1787 {
1790  u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
1791  nat44_ei_session_t *s;
1792  clib_bihash_8_8_t *t;
1793 
1794  init_nat_k (&kv, *addr, port, fib_index, proto);
1795  t = is_in ? &nm->in2out : &nm->out2in;
1796  if (!clib_bihash_search_8_8 (t, &kv, &value))
1797  {
1798  // this is called from API/CLI, so the world is stopped here
1799  // it's safe to manipulate arbitrary per-thread data
1801  tnm = vec_elt_at_index (nm->per_thread_data, thread_index);
1802  u32 session_index = nat_value_get_session_index (&value);
1803  if (pool_is_free_index (tnm->sessions, session_index))
1804  return VNET_API_ERROR_UNSPECIFIED;
1805 
1806  s = pool_elt_at_index (tnm->sessions, session_index);
1807  nat44_ei_free_session_data_v2 (nm, s, tnm - nm->per_thread_data, 0);
1808  nat44_ei_delete_session (nm, s, tnm - nm->per_thread_data);
1809  return 0;
1810  }
1811 
1812  return VNET_API_ERROR_NO_SUCH_ENTRY;
1813 }
1814 
1815 u32
1817 {
1819  u32 thread_idx = nm->num_workers;
1820  if (nm->num_workers > 1)
1821  {
1822  thread_idx = nm->first_worker_index +
1823  nm->workers[(e_port - 1024) / nm->port_per_thread];
1824  }
1825  return thread_idx;
1826 }
1827 
1828 void
1830  int is_add)
1831 {
1833  fib_prefix_t prefix = {
1834  .fp_len = p_len,
1835  .fp_proto = FIB_PROTOCOL_IP4,
1836  .fp_addr = {
1837  .ip4.as_u32 = addr->as_u32,
1838  },
1839  };
1840  u32 fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
1841 
1842  if (is_add)
1844  fib_index, &prefix, nm->fib_src_low,
1847  DPO_PROTO_IP4, NULL, sw_if_index, ~0, 1, NULL, FIB_ROUTE_PATH_FLAG_NONE);
1848  else
1849  fib_table_entry_delete (fib_index, &prefix, nm->fib_src_low);
1850 }
1851 
1852 int
1854  u16 l_port, u16 e_port, nat_protocol_t proto,
1855  u32 sw_if_index, u32 vrf_id, u8 addr_only,
1856  u8 identity_nat, u8 *tag, u8 is_add)
1857 {
1861  nat44_ei_address_t *a = 0;
1862  u32 fib_index = ~0;
1863  nat44_ei_interface_t *interface;
1865  nat44_ei_user_key_t u_key;
1866  nat44_ei_user_t *u;
1867  dlist_elt_t *head, *elt;
1868  u32 elt_index, head_index;
1869  u32 ses_index;
1870  u64 user_index;
1871  nat44_ei_session_t *s;
1872  nat44_ei_static_map_resolve_t *rp, *rp_match = 0;
1873  nat44_ei_lb_addr_port_t *local;
1874  u32 find = ~0;
1875  int i;
1876 
1877  if (sw_if_index != ~0)
1878  {
1879  ip4_address_t *first_int_addr;
1880 
1881  for (i = 0; i < vec_len (nm->to_resolve); i++)
1882  {
1883  rp = nm->to_resolve + i;
1884  if (rp->sw_if_index != sw_if_index ||
1885  rp->l_addr.as_u32 != l_addr.as_u32 || rp->vrf_id != vrf_id ||
1886  rp->addr_only != addr_only)
1887  continue;
1888 
1889  if (!addr_only)
1890  {
1891  if ((rp->l_port != l_port && rp->e_port != e_port) ||
1892  rp->proto != proto)
1893  continue;
1894  }
1895 
1896  rp_match = rp;
1897  break;
1898  }
1899 
1900  /* Might be already set... */
1901  first_int_addr = ip4_interface_first_address (
1902  nm->ip4_main, sw_if_index, 0 /* just want the address */);
1903 
1904  if (is_add)
1905  {
1906  if (rp_match)
1907  return VNET_API_ERROR_VALUE_EXIST;
1908 
1910  l_addr, l_port, e_port, proto, sw_if_index, vrf_id, addr_only,
1911  identity_nat, tag);
1912 
1913  /* DHCP resolution required? */
1914  if (!first_int_addr)
1915  return 0;
1916 
1917  e_addr.as_u32 = first_int_addr->as_u32;
1918  /* Identity mapping? */
1919  if (l_addr.as_u32 == 0)
1920  l_addr.as_u32 = e_addr.as_u32;
1921  }
1922  else
1923  {
1924  if (!rp_match)
1925  return VNET_API_ERROR_NO_SUCH_ENTRY;
1926 
1927  vec_del1 (nm->to_resolve, i);
1928 
1929  if (!first_int_addr)
1930  return 0;
1931 
1932  e_addr.as_u32 = first_int_addr->as_u32;
1933  /* Identity mapping? */
1934  if (l_addr.as_u32 == 0)
1935  l_addr.as_u32 = e_addr.as_u32;
1936  }
1937  }
1938 
1939  init_nat_k (&kv, e_addr, addr_only ? 0 : e_port, 0, addr_only ? 0 : proto);
1940  if (!clib_bihash_search_8_8 (&nm->static_mapping_by_external, &kv, &value))
1941  m = pool_elt_at_index (nm->static_mappings, value.value);
1942 
1943  if (is_add)
1944  {
1945  if (m)
1946  {
1947  // identity mapping for second vrf
1949  {
1950  pool_foreach (local, m->locals)
1951  {
1952  if (local->vrf_id == vrf_id)
1953  return VNET_API_ERROR_VALUE_EXIST;
1954  }
1955  pool_get (m->locals, local);
1956  local->vrf_id = vrf_id;
1958  FIB_PROTOCOL_IP4, vrf_id, nm->fib_src_low);
1959  init_nat_kv (&kv, m->local_addr, m->local_port, local->fib_index,
1960  m->proto, 0, m - nm->static_mappings);
1961  clib_bihash_add_del_8_8 (&nm->static_mapping_by_local, &kv, 1);
1962  return 0;
1963  }
1964  return VNET_API_ERROR_VALUE_EXIST;
1965  }
1966 
1967  /* Convert VRF id to FIB index */
1968  if (vrf_id != ~0)
1969  {
1970  fib_index = fib_table_find_or_create_and_lock (
1971  FIB_PROTOCOL_IP4, vrf_id, nm->fib_src_low);
1972  }
1973  /* If not specified use inside VRF id from NAT44 plugin config */
1974  else
1975  {
1976  fib_index = nm->inside_fib_index;
1977  vrf_id = nm->inside_vrf_id;
1978  fib_table_lock (fib_index, FIB_PROTOCOL_IP4, nm->fib_src_low);
1979  }
1980 
1981  if (!identity_nat)
1982  {
1983  init_nat_k (&kv, l_addr, addr_only ? 0 : l_port, fib_index,
1984  addr_only ? 0 : proto);
1985  if (!clib_bihash_search_8_8 (&nm->static_mapping_by_local, &kv,
1986  &value))
1987  return VNET_API_ERROR_VALUE_EXIST;
1988  }
1989 
1990  /* Find external address in allocated addresses and reserve port for
1991  address and port pair mapping when dynamic translations enabled */
1992  if (!(addr_only || nm->static_mapping_only))
1993  {
1994  for (i = 0; i < vec_len (nm->addresses); i++)
1995  {
1996  if (nm->addresses[i].addr.as_u32 == e_addr.as_u32)
1997  {
1998  a = nm->addresses + i;
1999  /* External port must be unused */
2000  switch (proto)
2001  {
2002 #define _(N, j, n, s) \
2003  case NAT_PROTOCOL_##N: \
2004  if (a->busy_##n##_port_refcounts[e_port]) \
2005  return VNET_API_ERROR_INVALID_VALUE; \
2006  ++a->busy_##n##_port_refcounts[e_port]; \
2007  if (e_port > 1024) \
2008  { \
2009  a->busy_##n##_ports++; \
2010  a->busy_##n##_ports_per_thread[nat44_ei_get_thread_idx_by_port ( \
2011  e_port)]++; \
2012  } \
2013  break;
2015 #undef _
2016  default : nat_elog_info (nm, "unknown protocol");
2017  return VNET_API_ERROR_INVALID_VALUE_2;
2018  }
2019  break;
2020  }
2021  }
2022  /* External address must be allocated */
2023  if (!a && (l_addr.as_u32 != e_addr.as_u32))
2024  {
2025  if (sw_if_index != ~0)
2026  {
2027  for (i = 0; i < vec_len (nm->to_resolve); i++)
2028  {
2029  rp = nm->to_resolve + i;
2030  if (rp->addr_only)
2031  continue;
2032  if (rp->sw_if_index != sw_if_index &&
2033  rp->l_addr.as_u32 != l_addr.as_u32 &&
2034  rp->vrf_id != vrf_id && rp->l_port != l_port &&
2035  rp->e_port != e_port && rp->proto != proto)
2036  continue;
2037 
2038  vec_del1 (nm->to_resolve, i);
2039  break;
2040  }
2041  }
2042  return VNET_API_ERROR_NO_SUCH_ENTRY;
2043  }
2044  }
2045 
2046  pool_get (nm->static_mappings, m);
2047  clib_memset (m, 0, sizeof (*m));
2048  m->tag = vec_dup (tag);
2049  m->local_addr = l_addr;
2050  m->external_addr = e_addr;
2051 
2052  if (addr_only)
2054  else
2055  {
2056  m->local_port = l_port;
2057  m->external_port = e_port;
2058  m->proto = proto;
2059  }
2060 
2061  if (identity_nat)
2062  {
2064  pool_get (m->locals, local);
2065  local->vrf_id = vrf_id;
2066  local->fib_index = fib_index;
2067  }
2068  else
2069  {
2070  m->vrf_id = vrf_id;
2071  m->fib_index = fib_index;
2072  }
2073 
2074  if (nm->num_workers > 1)
2075  {
2076  ip4_header_t ip = {
2077  .src_address = m->local_addr,
2078  };
2079  vec_add1 (m->workers,
2081  tnm = vec_elt_at_index (nm->per_thread_data, m->workers[0]);
2082  }
2083  else
2084  tnm = vec_elt_at_index (nm->per_thread_data, nm->num_workers);
2085 
2086  init_nat_kv (&kv, m->local_addr, m->local_port, fib_index, m->proto, 0,
2087  m - nm->static_mappings);
2088  clib_bihash_add_del_8_8 (&nm->static_mapping_by_local, &kv, 1);
2089 
2090  init_nat_kv (&kv, m->external_addr, m->external_port, 0, m->proto, 0,
2091  m - nm->static_mappings);
2092  clib_bihash_add_del_8_8 (&nm->static_mapping_by_external, &kv, 1);
2093 
2094  /* Delete dynamic sessions matching local address (+ local port) */
2095  // TODO: based on type of NAT EI/ED
2096  if (!(nm->static_mapping_only))
2097  {
2098  u_key.addr = m->local_addr;
2099  u_key.fib_index = m->fib_index;
2100  kv.key = u_key.as_u64;
2101  if (!clib_bihash_search_8_8 (&tnm->user_hash, &kv, &value))
2102  {
2103  user_index = value.value;
2104  u = pool_elt_at_index (tnm->users, user_index);
2105  if (u->nsessions)
2106  {
2107  head_index = u->sessions_per_user_list_head_index;
2108  head = pool_elt_at_index (tnm->list_pool, head_index);
2109  elt_index = head->next;
2110  elt = pool_elt_at_index (tnm->list_pool, elt_index);
2111  ses_index = elt->value;
2112  while (ses_index != ~0)
2113  {
2114  s = pool_elt_at_index (tnm->sessions, ses_index);
2115  elt = pool_elt_at_index (tnm->list_pool, elt->next);
2116  ses_index = elt->value;
2117 
2119  continue;
2120 
2121  if (!addr_only && s->in2out.port != m->local_port)
2122  continue;
2123 
2125  nm, s, tnm - nm->per_thread_data, 0);
2126  nat44_ei_delete_session (nm, s,
2127  tnm - nm->per_thread_data);
2128 
2129  if (!addr_only)
2130  break;
2131  }
2132  }
2133  }
2134  }
2135  }
2136  else
2137  {
2138  if (!m)
2139  {
2140  if (sw_if_index != ~0)
2141  return 0;
2142  else
2143  return VNET_API_ERROR_NO_SUCH_ENTRY;
2144  }
2145 
2146  if (identity_nat)
2147  {
2148  if (vrf_id == ~0)
2149  vrf_id = nm->inside_vrf_id;
2150 
2151  pool_foreach (local, m->locals)
2152  {
2153  if (local->vrf_id == vrf_id)
2154  find = local - m->locals;
2155  }
2156  if (find == ~0)
2157  return VNET_API_ERROR_NO_SUCH_ENTRY;
2158 
2159  local = pool_elt_at_index (m->locals, find);
2160  fib_index = local->fib_index;
2161  pool_put (m->locals, local);
2162  }
2163  else
2164  fib_index = m->fib_index;
2165 
2166  /* Free external address port */
2167  if (!(addr_only || nm->static_mapping_only))
2168  {
2169  for (i = 0; i < vec_len (nm->addresses); i++)
2170  {
2171  if (nm->addresses[i].addr.as_u32 == e_addr.as_u32)
2172  {
2173  a = nm->addresses + i;
2174  switch (proto)
2175  {
2176 #define _(N, j, n, s) \
2177  case NAT_PROTOCOL_##N: \
2178  --a->busy_##n##_port_refcounts[e_port]; \
2179  if (e_port > 1024) \
2180  { \
2181  a->busy_##n##_ports--; \
2182  a->busy_##n##_ports_per_thread[nat44_ei_get_thread_idx_by_port ( \
2183  e_port)]--; \
2184  } \
2185  break;
2187 #undef _
2188  default : return VNET_API_ERROR_INVALID_VALUE_2;
2189  }
2190  break;
2191  }
2192  }
2193  }
2194 
2195  if (nm->num_workers > 1)
2196  tnm = vec_elt_at_index (nm->per_thread_data, m->workers[0]);
2197  else
2198  tnm = vec_elt_at_index (nm->per_thread_data, nm->num_workers);
2199 
2200  init_nat_k (&kv, m->local_addr, m->local_port, fib_index, m->proto);
2201  clib_bihash_add_del_8_8 (&nm->static_mapping_by_local, &kv, 0);
2202 
2203  /* Delete session(s) for static mapping if exist */
2204  if (!(nm->static_mapping_only) ||
2206  {
2207  u_key.addr = m->local_addr;
2208  u_key.fib_index = fib_index;
2209  kv.key = u_key.as_u64;
2210  nat44_ei_static_mapping_del_sessions (nm, tnm, u_key, addr_only,
2211  e_addr, e_port);
2212  }
2213 
2214  fib_table_unlock (fib_index, FIB_PROTOCOL_IP4, nm->fib_src_low);
2215  if (pool_elts (m->locals))
2216  return 0;
2217 
2218  init_nat_k (&kv, m->external_addr, m->external_port, 0, m->proto);
2219  clib_bihash_add_del_8_8 (&nm->static_mapping_by_external, &kv, 0);
2220 
2221  vec_free (m->tag);
2222  vec_free (m->workers);
2223  /* Delete static mapping from pool */
2224  pool_put (nm->static_mappings, m);
2225  }
2226 
2227  if (!addr_only || (l_addr.as_u32 == e_addr.as_u32))
2228  return 0;
2229 
2230  /* Add/delete external address to FIB */
2231  pool_foreach (interface, nm->interfaces)
2232  {
2233  if (nat44_ei_interface_is_inside (interface) || nm->out2in_dpo)
2234  continue;
2235 
2236  nat44_ei_add_del_addr_to_fib (&e_addr, 32, interface->sw_if_index,
2237  is_add);
2238  break;
2239  }
2240  pool_foreach (interface, nm->output_feature_interfaces)
2241  {
2242  if (nat44_ei_interface_is_inside (interface) || nm->out2in_dpo)
2243  continue;
2244 
2245  nat44_ei_add_del_addr_to_fib (&e_addr, 32, interface->sw_if_index,
2246  is_add);
2247  break;
2248  }
2249  return 0;
2250 }
2251 
2252 int
2254  u32 match_fib_index,
2255  nat_protocol_t match_protocol,
2256  ip4_address_t *mapping_addr, u16 *mapping_port,
2257  u32 *mapping_fib_index, u8 by_external,
2258  u8 *is_addr_only, u8 *is_identity_nat)
2259 {
2263  u16 port;
2264 
2265  if (by_external)
2266  {
2267  init_nat_k (&kv, match_addr, match_port, 0, match_protocol);
2268  if (clib_bihash_search_8_8 (&nm->static_mapping_by_external, &kv,
2269  &value))
2270  {
2271  /* Try address only mapping */
2272  init_nat_k (&kv, match_addr, 0, 0, 0);
2273  if (clib_bihash_search_8_8 (&nm->static_mapping_by_external, &kv,
2274  &value))
2275  return 1;
2276  }
2277  m = pool_elt_at_index (nm->static_mappings, value.value);
2278 
2279  *mapping_fib_index = m->fib_index;
2280  *mapping_addr = m->local_addr;
2281  port = m->local_port;
2282  }
2283  else
2284  {
2285  init_nat_k (&kv, match_addr, match_port, match_fib_index,
2286  match_protocol);
2287  if (clib_bihash_search_8_8 (&nm->static_mapping_by_local, &kv, &value))
2288  {
2289  /* Try address only mapping */
2290  init_nat_k (&kv, match_addr, 0, match_fib_index, 0);
2291  if (clib_bihash_search_8_8 (&nm->static_mapping_by_local, &kv,
2292  &value))
2293  return 1;
2294  }
2295  m = pool_elt_at_index (nm->static_mappings, value.value);
2296 
2297  *mapping_fib_index = nm->outside_fib_index;
2298  *mapping_addr = m->external_addr;
2299  port = m->external_port;
2300  }
2301 
2302  /* Address only mapping doesn't change port */
2304  *mapping_port = match_port;
2305  else
2306  *mapping_port = port;
2307 
2308  if (PREDICT_FALSE (is_addr_only != 0))
2309  *is_addr_only = nat44_ei_is_addr_only_static_mapping (m);
2310 
2311  if (PREDICT_FALSE (is_identity_nat != 0))
2312  *is_identity_nat = nat44_ei_is_identity_static_mapping (m);
2313 
2314  return 0;
2315 }
2316 
2317 static void
2319 {
2320  pool_free (tnm->list_pool);
2321  pool_free (tnm->lru_pool);
2322  pool_free (tnm->sessions);
2323  pool_free (tnm->users);
2324 
2325  clib_bihash_free_8_8 (&tnm->user_hash);
2326 }
2327 
2328 u8 *
2329 format_nat44_ei_key (u8 *s, va_list *args)
2330 {
2331  u64 key = va_arg (*args, u64);
2332 
2334  u16 port;
2336  u32 fib_index;
2337 
2338  split_nat_key (key, &addr, &port, &fib_index, &protocol);
2339 
2340  s = format (s, "%U proto %U port %d fib %d", format_ip4_address, &addr,
2341  format_nat_protocol, protocol, clib_net_to_host_u16 (port),
2342  fib_index);
2343  return s;
2344 }
2345 
2346 u8 *
2347 format_nat44_ei_user_kvp (u8 *s, va_list *args)
2348 {
2349  clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
2351 
2352  k.as_u64 = v->key;
2353 
2354  s = format (s, "%U fib %d user-index %llu", format_ip4_address, &k.addr,
2355  k.fib_index, v->value);
2356 
2357  return s;
2358 }
2359 
2360 u8 *
2361 format_nat44_ei_session_kvp (u8 *s, va_list *args)
2362 {
2363  clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
2364 
2365  s = format (s, "%U thread-index %llu session-index %llu",
2368 
2369  return s;
2370 }
2371 
2372 u8 *
2374 {
2375  clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
2376 
2377  s = format (s, "%U static-mapping-index %llu", format_nat44_ei_key, v->key,
2378  v->value);
2379 
2380  return s;
2381 }
2382 
2383 static void
2385  u32 translations, u32 translation_buckets,
2386  u32 user_buckets)
2387 {
2388  dlist_elt_t *head;
2389 
2390  pool_alloc (tnm->list_pool, translations);
2391  pool_alloc (tnm->lru_pool, translations);
2392  pool_alloc (tnm->sessions, translations);
2393 
2394  clib_bihash_init_8_8 (&tnm->user_hash, "users", user_buckets, 0);
2395 
2396  clib_bihash_set_kvp_format_fn_8_8 (&tnm->user_hash,
2398 
2399  pool_get (tnm->lru_pool, head);
2400  tnm->tcp_trans_lru_head_index = head - tnm->lru_pool;
2402 
2403  pool_get (tnm->lru_pool, head);
2404  tnm->tcp_estab_lru_head_index = head - tnm->lru_pool;
2406 
2407  pool_get (tnm->lru_pool, head);
2408  tnm->udp_lru_head_index = head - tnm->lru_pool;
2410 
2411  pool_get (tnm->lru_pool, head);
2412  tnm->icmp_lru_head_index = head - tnm->lru_pool;
2414 
2415  pool_get (tnm->lru_pool, head);
2416  tnm->unk_proto_lru_head_index = head - tnm->lru_pool;
2418 }
2419 
2420 static void
2422 {
2425 
2426  pool_free (nm->static_mappings);
2427  clib_bihash_free_8_8 (&nm->static_mapping_by_local);
2428  clib_bihash_free_8_8 (&nm->static_mapping_by_external);
2429 
2430  if (nm->pat)
2431  {
2432  clib_bihash_free_8_8 (&nm->in2out);
2433  clib_bihash_free_8_8 (&nm->out2in);
2434  vec_foreach (tnm, nm->per_thread_data)
2435  {
2437  }
2438  }
2439 }
2440 
2441 static void
2442 nat44_ei_db_init (u32 translations, u32 translation_buckets, u32 user_buckets)
2443 {
2446 
2447  u32 static_mapping_buckets = 1024;
2448  u32 static_mapping_memory_size = 64 << 20;
2449 
2450  clib_bihash_init_8_8 (&nm->static_mapping_by_local,
2451  "static_mapping_by_local", static_mapping_buckets,
2452  static_mapping_memory_size);
2453  clib_bihash_init_8_8 (&nm->static_mapping_by_external,
2454  "static_mapping_by_external", static_mapping_buckets,
2455  static_mapping_memory_size);
2456  clib_bihash_set_kvp_format_fn_8_8 (&nm->static_mapping_by_local,
2458  clib_bihash_set_kvp_format_fn_8_8 (&nm->static_mapping_by_external,
2460 
2461  if (nm->pat)
2462  {
2463  clib_bihash_init_8_8 (&nm->in2out, "in2out", translation_buckets, 0);
2464  clib_bihash_init_8_8 (&nm->out2in, "out2in", translation_buckets, 0);
2465  clib_bihash_set_kvp_format_fn_8_8 (&nm->in2out,
2467  clib_bihash_set_kvp_format_fn_8_8 (&nm->out2in,
2469  vec_foreach (tnm, nm->per_thread_data)
2470  {
2471  nat44_ei_worker_db_init (tnm, translations, translation_buckets,
2472  user_buckets);
2473  }
2474  }
2475 }
2476 
2477 void
2479 {
2482 
2483  if (nm->pat)
2484  {
2485  clib_bihash_free_8_8 (&nm->in2out);
2486  clib_bihash_free_8_8 (&nm->out2in);
2487  clib_bihash_init_8_8 (&nm->in2out, "in2out", nm->translation_buckets, 0);
2488  clib_bihash_init_8_8 (&nm->out2in, "out2in", nm->translation_buckets, 0);
2489  clib_bihash_set_kvp_format_fn_8_8 (&nm->in2out,
2491  clib_bihash_set_kvp_format_fn_8_8 (&nm->out2in,
2493  vec_foreach (tnm, nm->per_thread_data)
2494  {
2498  }
2499  }
2500 
2504 }
2505 
2506 static void
2508  u32 new_fib_index, u32 old_fib_index)
2509 {
2511  nat44_ei_outside_fib_t *outside_fib;
2513  u8 is_add = 1;
2514  u8 match = 0;
2515 
2516  if (!nm->enabled || (new_fib_index == old_fib_index) ||
2517  (!vec_len (nm->outside_fibs)))
2518  {
2519  return;
2520  }
2521 
2522  pool_foreach (i, nm->interfaces)
2523  {
2524  if (i->sw_if_index == sw_if_index)
2525  {
2526  if (!(nat44_ei_interface_is_outside (i)))
2527  return;
2528  match = 1;
2529  }
2530  }
2531 
2533  {
2534  if (i->sw_if_index == sw_if_index)
2535  {
2536  if (!(nat44_ei_interface_is_outside (i)))
2537  return;
2538  match = 1;
2539  }
2540  }
2541 
2542  if (!match)
2543  return;
2544 
2545  vec_foreach (outside_fib, nm->outside_fibs)
2546  {
2547  if (outside_fib->fib_index == old_fib_index)
2548  {
2549  outside_fib->refcount--;
2550  if (!outside_fib->refcount)
2551  vec_del1 (nm->outside_fibs, outside_fib - nm->outside_fibs);
2552  break;
2553  }
2554  }
2555 
2556  vec_foreach (outside_fib, nm->outside_fibs)
2557  {
2558  if (outside_fib->fib_index == new_fib_index)
2559  {
2560  outside_fib->refcount++;
2561  is_add = 0;
2562  break;
2563  }
2564  }
2565 
2566  if (is_add)
2567  {
2568  vec_add2 (nm->outside_fibs, outside_fib, 1);
2569  outside_fib->refcount = 1;
2570  outside_fib->fib_index = new_fib_index;
2571  }
2572 }
2573 
2574 int
2576 {
2577  nat44_ei_address_t *ap;
2580 
2581  /* Check if address already exists */
2582  vec_foreach (ap, nm->addresses)
2583  {
2584  if (ap->addr.as_u32 == addr->as_u32)
2585  {
2586  nat44_ei_log_err ("address exist");
2587  return VNET_API_ERROR_VALUE_EXIST;
2588  }
2589  }
2590 
2591  vec_add2 (nm->addresses, ap, 1);
2592 
2593  ap->addr = *addr;
2594  if (vrf_id != ~0)
2596  FIB_PROTOCOL_IP4, vrf_id, nm->fib_src_low);
2597  else
2598  ap->fib_index = ~0;
2599 
2600 #define _(N, i, n, s) \
2601  clib_memset (ap->busy_##n##_port_refcounts, 0, \
2602  sizeof (ap->busy_##n##_port_refcounts)); \
2603  ap->busy_##n##_ports = 0; \
2604  ap->busy_##n##_ports_per_thread = 0; \
2605  vec_validate_init_empty (ap->busy_##n##_ports_per_thread, \
2606  tm->n_vlib_mains - 1, 0);
2608 #undef _
2609 
2610  /* Add external address to FIB */
2611  pool_foreach (i, nm->interfaces)
2612  {
2614  continue;
2615 
2616  nat44_ei_add_del_addr_to_fib (addr, 32, i->sw_if_index, 1);
2617  break;
2618  }
2620  {
2622  continue;
2623 
2624  nat44_ei_add_del_addr_to_fib (addr, 32, i->sw_if_index, 1);
2625  break;
2626  }
2627 
2628  return 0;
2629 }
2630 
2631 int
2633  int is_del)
2634 {
2635  ip4_main_t *ip4_main = nm->ip4_main;
2636  ip4_address_t *first_int_addr;
2638  u32 *indices_to_delete = 0;
2639  int i, j;
2640  u32 *auto_add_sw_if_indices = nm->auto_add_sw_if_indices;
2641 
2642  first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index,
2643  0 /* just want the address */);
2644 
2645  for (i = 0; i < vec_len (auto_add_sw_if_indices); i++)
2646  {
2647  if (auto_add_sw_if_indices[i] == sw_if_index)
2648  {
2649  if (is_del)
2650  {
2651  /* if have address remove it */
2652  if (first_int_addr)
2653  (void) nat44_ei_del_address (nm, first_int_addr[0], 1);
2654  else
2655  {
2656  for (j = 0; j < vec_len (nm->to_resolve); j++)
2657  {
2658  rp = nm->to_resolve + j;
2659  if (rp->sw_if_index == sw_if_index)
2660  vec_add1 (indices_to_delete, j);
2661  }
2662  if (vec_len (indices_to_delete))
2663  {
2664  for (j = vec_len (indices_to_delete) - 1; j >= 0; j--)
2665  vec_del1 (nm->to_resolve, j);
2666  vec_free (indices_to_delete);
2667  }
2668  }
2670  }
2671  else
2672  return VNET_API_ERROR_VALUE_EXIST;
2673 
2674  return 0;
2675  }
2676  }
2677 
2678  if (is_del)
2679  return VNET_API_ERROR_NO_SUCH_ENTRY;
2680 
2681  /* add to the auto-address list */
2682  vec_add1 (nm->auto_add_sw_if_indices, sw_if_index);
2683 
2684  /* If the address is already bound - or static - add it now */
2685  if (first_int_addr)
2686  (void) nat44_ei_add_address (nm, first_int_addr, ~0);
2687 
2688  return 0;
2689 }
2690 
2691 static int
2693 {
2696  pool_foreach (m, nm->static_mappings)
2697  {
2700  continue;
2701  if (m->external_addr.as_u32 == addr.as_u32)
2702  return 1;
2703  }
2704  return 0;
2705 }
2706 
2707 int
2709 {
2710  nat44_ei_address_t *a = 0;
2711  nat44_ei_session_t *ses;
2712  u32 *ses_to_be_removed = 0, *ses_index;
2714  nat44_ei_interface_t *interface;
2716  int i;
2717 
2718  /* Find SNAT address */
2719  for (i = 0; i < vec_len (nm->addresses); i++)
2720  {
2721  if (nm->addresses[i].addr.as_u32 == addr.as_u32)
2722  {
2723  a = nm->addresses + i;
2724  break;
2725  }
2726  }
2727  if (!a)
2728  {
2729  nat44_ei_log_err ("no such address");
2730  return VNET_API_ERROR_NO_SUCH_ENTRY;
2731  }
2732 
2733  if (delete_sm)
2734  {
2735  pool_foreach (m, nm->static_mappings)
2736  {
2737  if (m->external_addr.as_u32 == addr.as_u32)
2740  m->proto, ~0 /* sw_if_index */, m->vrf_id,
2743  }
2744  }
2745  else
2746  {
2747  /* Check if address is used in some static mapping */
2749  {
2750  nat44_ei_log_err ("address used in static mapping");
2751  return VNET_API_ERROR_UNSPECIFIED;
2752  }
2753  }
2754 
2755  if (a->fib_index != ~0)
2757 
2758  /* Delete sessions using address */
2759  if (a->busy_tcp_ports || a->busy_udp_ports || a->busy_icmp_ports)
2760  {
2761  vec_foreach (tnm, nm->per_thread_data)
2762  {
2763  pool_foreach (ses, tnm->sessions)
2764  {
2765  if (ses->out2in.addr.as_u32 == addr.as_u32)
2766  {
2767  nat44_ei_free_session_data (nm, ses,
2768  tnm - nm->per_thread_data, 0);
2769  vec_add1 (ses_to_be_removed, ses - tnm->sessions);
2770  }
2771  }
2772  vec_foreach (ses_index, ses_to_be_removed)
2773  {
2774  ses = pool_elt_at_index (tnm->sessions, ses_index[0]);
2775  nat44_ei_delete_session (nm, ses, tnm - nm->per_thread_data);
2776  }
2777  vec_free (ses_to_be_removed);
2778  }
2779  }
2780 
2781 #define _(N, i, n, s) vec_free (a->busy_##n##_ports_per_thread);
2783 #undef _
2784  vec_del1 (nm->addresses, i);
2785 
2786  /* Delete external address from FIB */
2787  pool_foreach (interface, nm->interfaces)
2788  {
2789  if (nat44_ei_interface_is_inside (interface) || nm->out2in_dpo)
2790  continue;
2791  nat44_ei_add_del_addr_to_fib (&addr, 32, interface->sw_if_index, 0);
2792  break;
2793  }
2794 
2795  pool_foreach (interface, nm->output_feature_interfaces)
2796  {
2797  if (nat44_ei_interface_is_inside (interface) || nm->out2in_dpo)
2798  continue;
2799  nat44_ei_add_del_addr_to_fib (&addr, 32, interface->sw_if_index, 0);
2800  break;
2801  }
2802 
2803  return 0;
2804 }
2805 
2806 static void
2808  u32 sw_if_index,
2809  ip4_address_t *address,
2810  u32 address_length,
2811  u32 if_address_index, u32 is_delete)
2812 {
2815  ip4_address_t l_addr;
2816  int i, j;
2817  int rv;
2818  nat44_ei_address_t *addresses = nm->addresses;
2819 
2820  if (!nm->enabled)
2821  return;
2822 
2823  for (i = 0; i < vec_len (nm->auto_add_sw_if_indices); i++)
2824  {
2825  if (sw_if_index == nm->auto_add_sw_if_indices[i])
2826  goto match;
2827  }
2828 
2829  return;
2830 
2831 match:
2832  if (!is_delete)
2833  {
2834  /* Don't trip over lease renewal, static config */
2835  for (j = 0; j < vec_len (addresses); j++)
2836  if (addresses[j].addr.as_u32 == address->as_u32)
2837  return;
2838 
2839  (void) nat44_ei_add_address (nm, address, ~0);
2840  /* Scan static map resolution vector */
2841  for (j = 0; j < vec_len (nm->to_resolve); j++)
2842  {
2843  rp = nm->to_resolve + j;
2844  if (rp->addr_only)
2845  continue;
2846  /* On this interface? */
2847  if (rp->sw_if_index == sw_if_index)
2848  {
2849  /* Indetity mapping? */
2850  if (rp->l_addr.as_u32 == 0)
2851  l_addr.as_u32 = address[0].as_u32;
2852  else
2853  l_addr.as_u32 = rp->l_addr.as_u32;
2854  /* Add the static mapping */
2856  l_addr, address[0], rp->l_port, rp->e_port, rp->proto,
2857  ~0 /* sw_if_index */, rp->vrf_id, rp->addr_only,
2858  rp->identity_nat, rp->tag, 1);
2859  if (rv)
2861  nm, "nat44_ei_add_del_static_mapping returned %d", "i4", rv);
2862  }
2863  }
2864  return;
2865  }
2866  else
2867  {
2868  (void) nat44_ei_del_address (nm, address[0], 1);
2869  return;
2870  }
2871 }
2872 
2873 int
2875 {
2876  fail_if_enabled ();
2878  nm->frame_queue_nelts = frame_queue_nelts;
2879  return 0;
2880 }
2881 
2882 static void
2884  u32 sw_if_index, ip4_address_t *address,
2885  u32 address_length, u32 if_address_index,
2886  u32 is_delete)
2887 {
2892  int i, rv;
2893  ip4_address_t l_addr;
2894 
2895  if (!nm->enabled)
2896  return;
2897 
2898  for (i = 0; i < vec_len (nm->to_resolve); i++)
2899  {
2900  rp = nm->to_resolve + i;
2901  if (rp->addr_only == 0)
2902  continue;
2903  if (rp->sw_if_index == sw_if_index)
2904  goto match;
2905  }
2906 
2907  return;
2908 
2909 match:
2910  init_nat_k (&kv, *address, rp->addr_only ? 0 : rp->e_port,
2911  nm->outside_fib_index, rp->addr_only ? 0 : rp->proto);
2912  if (clib_bihash_search_8_8 (&nm->static_mapping_by_external, &kv, &value))
2913  m = 0;
2914  else
2915  m = pool_elt_at_index (nm->static_mappings, value.value);
2916 
2917  if (!is_delete)
2918  {
2919  /* Don't trip over lease renewal, static config */
2920  if (m)
2921  return;
2922  }
2923  else
2924  {
2925  if (!m)
2926  return;
2927  }
2928 
2929  /* Indetity mapping? */
2930  if (rp->l_addr.as_u32 == 0)
2931  l_addr.as_u32 = address[0].as_u32;
2932  else
2933  l_addr.as_u32 = rp->l_addr.as_u32;
2934  /* Add the static mapping */
2935 
2937  l_addr, address[0], rp->l_port, rp->e_port, rp->proto,
2938  ~0 /* sw_if_index */, rp->vrf_id, rp->addr_only, rp->identity_nat, rp->tag,
2939  !is_delete);
2940  if (rv)
2941  nat_elog_notice_X1 (nm, "nat44_ei_add_del_static_mapping returned %d",
2942  "i4", rv);
2943 }
2944 
2948 {
2949  u32 n_left_from, *from, *to_next;
2953  u32 next_in2out = 0, next_out2in = 0;
2954 
2955  from = vlib_frame_vector_args (frame);
2956  n_left_from = frame->n_vectors;
2957  next_index = node->cached_next_index;
2958 
2959  while (n_left_from > 0)
2960  {
2961  u32 n_left_to_next;
2962 
2963  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2964 
2965  while (n_left_from > 0 && n_left_to_next > 0)
2966  {
2967  u32 bi0;
2968  vlib_buffer_t *b0;
2970  ip4_header_t *ip0;
2971  nat44_ei_address_t *ap;
2972  clib_bihash_kv_8_8_t kv0, value0;
2973 
2974  /* speculatively enqueue b0 to the current next frame */
2975  bi0 = from[0];
2976  to_next[0] = bi0;
2977  from += 1;
2978  to_next += 1;
2979  n_left_from -= 1;
2980  n_left_to_next -= 1;
2981 
2982  b0 = vlib_get_buffer (vm, bi0);
2983  ip0 = vlib_buffer_get_current (b0);
2984 
2985  vec_foreach (ap, nm->addresses)
2986  {
2987  if (ip0->dst_address.as_u32 == ap->addr.as_u32)
2988  {
2990  goto enqueue0;
2991  }
2992  }
2993 
2995  {
2996  init_nat_k (&kv0, ip0->dst_address, 0, 0, 0);
2997  /* try to classify the fragment based on IP header alone */
2998  if (!clib_bihash_search_8_8 (&nm->static_mapping_by_external,
2999  &kv0, &value0))
3000  {
3001  m = pool_elt_at_index (nm->static_mappings, value0.value);
3002  if (m->local_addr.as_u32 != m->external_addr.as_u32)
3004  goto enqueue0;
3005  }
3006  init_nat_k (&kv0, ip0->dst_address,
3007  vnet_buffer (b0)->ip.reass.l4_dst_port, 0,
3009  if (!clib_bihash_search_8_8 (&nm->static_mapping_by_external,
3010  &kv0, &value0))
3011  {
3012  m = pool_elt_at_index (nm->static_mappings, value0.value);
3013  if (m->local_addr.as_u32 != m->external_addr.as_u32)
3015  }
3016  }
3017 
3018  enqueue0:
3019  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
3020  (b0->flags & VLIB_BUFFER_IS_TRACED)))
3021  {
3023  vlib_add_trace (vm, node, b0, sizeof (*t));
3024  t->cached = 0;
3025  t->next_in2out = next0 == NAT44_EI_CLASSIFY_NEXT_IN2OUT ? 1 : 0;
3026  }
3027 
3028  next_in2out += next0 == NAT44_EI_CLASSIFY_NEXT_IN2OUT;
3029  next_out2in += next0 == NAT44_EI_CLASSIFY_NEXT_OUT2IN;
3030 
3031  /* verify speculative enqueue, maybe switch current next frame */
3032  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
3033  n_left_to_next, bi0, next0);
3034  }
3035 
3036  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
3037  }
3038 
3040  vm, node->node_index, NAT44_EI_CLASSIFY_ERROR_NEXT_IN2OUT, next_in2out);
3042  vm, node->node_index, NAT44_EI_CLASSIFY_ERROR_NEXT_OUT2IN, next_out2in);
3043  return frame->n_vectors;
3044 }
3045 
3049  return nat44_ei_classify_inline_fn (vm, node, frame);
3050 }
3051 
3053  .name = "nat44-ei-classify",
3054  .vector_size = sizeof (u32),
3055  .format_trace = format_nat44_ei_classify_trace,
3058  .error_strings = nat44_ei_classify_error_strings,
3059  .n_next_nodes = NAT44_EI_CLASSIFY_N_NEXT,
3060  .next_nodes = {
3061  [NAT44_EI_CLASSIFY_NEXT_IN2OUT] = "nat44-ei-in2out",
3062  [NAT44_EI_CLASSIFY_NEXT_OUT2IN] = "nat44-ei-out2in",
3063  [NAT44_EI_CLASSIFY_NEXT_DROP] = "error-drop",
3064  },
3065 };
3066 
3069 {
3070  return nat44_ei_classify_inline_fn (vm, node, frame);
3071 }
3072 
3074  .name = "nat44-ei-handoff-classify",
3075  .vector_size = sizeof (u32),
3076  .format_trace = format_nat44_ei_classify_trace,
3079  .error_strings = nat44_ei_classify_error_strings,
3080  .n_next_nodes = NAT44_EI_CLASSIFY_N_NEXT,
3081  .next_nodes = {
3082  [NAT44_EI_CLASSIFY_NEXT_IN2OUT] = "nat44-ei-in2out-worker-handoff",
3083  [NAT44_EI_CLASSIFY_NEXT_OUT2IN] = "nat44-ei-out2in-worker-handoff",
3084  [NAT44_EI_CLASSIFY_NEXT_DROP] = "error-drop",
3085  },
3086 };
3087 
3088 /*
3089  * fd.io coding-style-patch-verification: ON
3090  *
3091  * Local Variables:
3092  * eval: (c-set-style "gnu")
3093  * End:
3094  */
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:339
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:524
static u8 * format_nat44_ei_classify_trace(u8 *s, va_list *args)
Definition: nat44_ei.c:204
u32 next
Definition: dlist.h:30
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:133
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:211
vlib_node_registration_t nat44_ei_in2out_hairpinning_finish_interface_output_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_in2out_hairpinning_finish_interface_output_node) ...
ip4_address_t addr
Definition: nat44_ei.h:69
static void nat44_ei_delete_user_with_no_session(nat44_ei_main_t *nm, nat44_ei_user_t *u, u32 thread_index)
u8 * format_nat44_ei_key(u8 *s, va_list *args)
Definition: nat44_ei.c:2329
int nat44_ei_add_interface_address(nat44_ei_main_t *nm, u32 sw_if_index, int is_del)
Definition: nat44_ei.c:2632
int ip4_sv_reass_output_enable_disable_with_refcnt(u32 sw_if_index, int is_enable)
ip4_table_bind_function_t * function
Definition: ip4.h:94
#define CLIB_UNUSED(x)
Definition: clib.h:90
void nat44_ei_free_session_data_v2(nat44_ei_main_t *nm, nat44_ei_session_t *s, u32 thread_index, u8 is_ha)
Definition: nat44_ei.c:1079
#define nat_elog_info(_pm, nat_elog_str)
Definition: log.h:183
static int nat44_ei_alloc_range_cb(nat44_ei_address_t *addresses, u32 fib_index, u32 thread_index, nat_protocol_t proto, ip4_address_t s_addr, ip4_address_t *addr, u16 *port, u16 port_per_thread, u32 snat_thread_index)
Definition: nat44_ei.c:1601
u16 port_per_thread
Definition: nat44_ei.h:359
ip4_add_del_interface_address_callback_t * add_del_interface_address_callbacks
Functions to call when interface address changes.
Definition: ip4.h:141
u32 fq_out2in_index
Definition: nat44_ei.h:400
a
Definition: bitmap.h:544
static void clib_dlist_init(dlist_elt_t *pool, u32 index)
Definition: dlist.h:36
nat44_ei_user_t * users
Definition: nat44_ei.h:280
static void nat44_ei_db_free()
Definition: nat44_ei.c:2421
ip4_address_t src_address
Definition: ip4_packet.h:125
nat44_ei_config_t rconfig
Definition: nat44_ei.h:472
u32 fq_in2out_output_index
Definition: nat44_ei.h:399
#define fail_if_disabled()
Definition: nat44_ei.c:70
void nat_ipfix_logging_addresses_exhausted(u32 thread_index, u32 pool_id)
Generate NAT addresses exhausted event.
nat44_ei_interface_t * interfaces
Definition: nat44_ei.h:339
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:534
#define pool_alloc(P, N)
Allocate N more free elements to pool (unspecified alignment).
Definition: pool.h:367
u32 thread_index
#define PREDICT_TRUE(x)
Definition: clib.h:125
unsigned long u64
Definition: types.h:89
u32 vrf_id
Definition: nat44_ed.api:1053
vl_api_ip_proto_t protocol
Definition: lb_types.api:72
nat44_ei_lb_addr_port_t * locals
Definition: nat44_ei.h:183
VLIB_PLUGIN_REGISTER()
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
u32 index
Definition: node.h:270
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
int nat44_ei_add_del_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port, nat_protocol_t proto, u32 sw_if_index, u32 vrf_id, u8 addr_only, u8 identity_nat, u8 *tag, u8 is_add)
Add/delete NAT44-EI static mapping.
Definition: nat44_ei.c:1853
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:998
u32 nat44_ei_get_thread_idx_by_port(u16 e_port)
Definition: nat44_ei.c:1816
#define clib_bitmap_foreach(i, ai)
Macro to iterate across set bits in a bitmap.
Definition: bitmap.h:361
u32 outside_fib_index
Definition: nat44_ei.h:353
u32 vlib_frame_queue_main_init(u32 node_index, u32 frame_queue_nelts)
Definition: threads.c:1572
#define thread_idx
Definition: tls_async.c:40
add paths without path extensions
Definition: fib_source.h:210
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:607
NAT44 endpoint independent plugin declarations.
nat44_ei_session_t * sessions
Definition: nat44_ei.h:283
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:645
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
ip_lookup_main_t lookup_main
Definition: ip4.h:109
static void vlib_increment_simple_counter(vlib_simple_counter_main_t *cm, u32 thread_index, u32 index, u64 increment)
Increment a simple counter.
Definition: counter.h:74
static_always_inline void nat44_ei_user_del_sessions(nat44_ei_user_t *u, u32 thread_index)
Definition: nat44_ei.c:1289
void nat_dpo_create(dpo_proto_t dproto, u32 aftr_index, dpo_id_t *dpo)
Definition: nat44_ei_dpo.c:22
static u32 nat_value_get_thread_index(clib_bihash_kv_8_8_t *value)
static void init_nat_i2o_k(clib_bihash_kv_8_8_t *kv, nat44_ei_session_t *s)
nat_protocol_t
Definition: lib.h:63
#define VLIB_NODE_FN(node)
Definition: node.h:202
int nat44_ei_plugin_disable()
Definition: nat44_ei.c:920
vl_api_prefix_t prefix
Definition: ip.api:146
u16 start_port
Definition: ikev2_types.api:35
u32 out2in_node_index
Definition: nat44_ei.h:395
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:255
clib_bihash_8_8_t static_mapping_by_external
Definition: nat44_ei.h:333
vhost_vring_addr_t addr
Definition: vhost_user.h:130
static void split_nat_key(u64 key, ip4_address_t *addr, u16 *port, u32 *fib_index, nat_protocol_t *proto)
int nat44_ei_set_outside_address_and_port(nat44_ei_address_t *addresses, u32 thread_index, ip4_address_t addr, u16 port, nat_protocol_t protocol)
Definition: nat44_ei.c:983
int nat44_ei_user_del(ip4_address_t *addr, u32 fib_index)
Delete specific NAT44 EI user and his sessions.
Definition: nat44_ei.c:1314
unsigned char u8
Definition: types.h:56
vlib_buffer_t ** b
static_always_inline void nat_reset_timeouts(nat_timeouts_t *timeouts)
Definition: lib.h:90
#define nat44_ei_is_addr_only_static_mapping(mp)
Definition: nat44_ei.h:676
int nat44_ei_interface_add_del(u32 sw_if_index, u8 is_inside, int is_del)
Definition: nat44_ei.c:496
static_always_inline u8 icmp_type_is_error_message(u8 icmp_type)
Definition: cnat_node.h:109
nat44_ei_static_mapping_t * static_mappings
Definition: nat44_ei.h:336
double f64
Definition: types.h:142
u16 end_port
Definition: ikev2_types.api:36
unsigned int u32
Definition: types.h:88
fib_source_t fib_src_hi
Definition: nat44_ei.h:459
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:814
void nat44_ei_free_session_data(nat44_ei_main_t *nm, nat44_ei_session_t *s, u32 thread_index, u8 is_ha)
Definition: nat44_ei.c:1252
void nat44_ei_set_alloc_range(u16 start_port, u16 end_port)
Set address and port assignment algorithm for port range.
Definition: nat44_ei.c:1706
format_function_t format_ip4_address
Definition: format.h:73
u32 nat44_ei_get_in2out_worker_index(ip4_header_t *ip0, u32 rx_fib_index0, u8 is_output)
Definition: nat44_ei.c:1408
#define static_always_inline
Definition: clib.h:112
int nat44_ei_set_workers(uword *bitmap)
Definition: nat44_ei.c:252
#define nat_init_simple_counter(c, n, sn)
Definition: nat44_ei.c:285
nat44_ei_main_per_thread_data_t * tnm
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:172
static nat_protocol_t ip_proto_to_nat_proto(u8 ip_proto)
Common NAT inline functions.
Definition: inlines.h:24
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
nat44_ei_address_t * addresses
Definition: nat44_ei.h:369
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
ip4_address_t dst_address
Definition: ip4_packet.h:125
#define nat_elog_notice_X1(_pm, nat_elog_fmt_str, nat_elog_fmt_arg, nat_elog_val1)
Definition: log.h:186
#define nat_validate_simple_counter(c, i)
Definition: nat44_ei.c:277
void nat_dpo_module_init(void)
Definition: nat44_ei_dpo.c:68
#define NAT44_EI_INTERFACE_FLAG_IS_OUTSIDE
Definition: nat44_ei.h:57
description fragment has unexpected format
Definition: map.api:433
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
#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:202
#define nat_elog_warn(_pm, nat_elog_str)
Definition: log.h:177
static void init_nat_kv(clib_bihash_kv_8_8_t *kv, ip4_address_t addr, u16 port, u32 fib_index, nat_protocol_t proto, u32 thread_index, u32 session_index)
vlib_simple_counter_main_t hairpinning
Definition: nat44_ei.h:442
vnet_main_t * vnet_get_main(void)
u32 in2out_node_index
Definition: nat44_ei.h:394
static u32 nat_value_get_session_index(clib_bihash_kv_8_8_t *value)
u32 hairpin_dst_fq_index
Definition: nat44_ei.h:477
int nat44_ei_del_session(nat44_ei_main_t *nm, ip4_address_t *addr, u16 port, nat_protocol_t proto, u32 vrf_id, int is_in)
Delete NAT44-EI session.
Definition: nat44_ei.c:1785
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:196
vlib_node_registration_t nat44_ei_handoff_classify_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_handoff_classify_node)
Definition: nat44_ei.c:3073
int ip4_sv_reass_enable_disable_with_refcnt(u32 sw_if_index, int is_enable)
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:1106
int __clib_unused rv
Definition: application.c:491
#define nat44_ei_is_session_static(sp)
Definition: nat44_ei.h:666
struct nat44_ei_main_s::@81 counters
int nat44_ei_del_address(nat44_ei_main_t *nm, ip4_address_t addr, u8 delete_sm)
Definition: nat44_ei.c:2708
nat44_ei_classify_error_t
Definition: nat44_ei.c:172
static int nat44_ei_alloc_mape_cb(nat44_ei_address_t *addresses, u32 fib_index, u32 thread_index, nat_protocol_t proto, ip4_address_t s_addr, ip4_address_t *addr, u16 *port, u16 port_per_thread, u32 snat_thread_index)
Definition: nat44_ei.c:1648
vlib_node_registration_t nat44_ei_hairpin_dst_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_hairpin_dst_node)
int nat44_ei_add_address(nat44_ei_main_t *nm, ip4_address_t *addr, u32 vrf_id)
Definition: nat44_ei.c:2575
fib_source_t fib_source_allocate(const char *name, fib_source_priority_t prio, fib_source_behaviour_t bh)
Definition: fib_source.c:118
vl_api_fib_path_type_t type
Definition: fib_types.api:123
u32 inside_fib_index
Definition: nat44_ei.h:350
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:172
Definition: fib_entry.h:117
Definition: cJSON.c:88
u32 max_users_per_thread
Definition: nat44_ei.h:345
Definition: fib_entry.h:116
u16 * next
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:553
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
vlib_node_registration_t nat44_ei_classify_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_classify_node)
Definition: nat44_ei.c:3052
nat44_ei_static_map_resolve_t * to_resolve
Definition: nat44_ei.h:392
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
static void nat44_ei_add_static_mapping_when_resolved(ip4_address_t l_addr, u16 l_port, u16 e_port, nat_protocol_t proto, u32 sw_if_index, u32 vrf_id, int addr_only, int identity_nat, u8 *tag)
Definition: nat44_ei.c:1729
#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:284
void nat44_ei_static_mapping_del_sessions(nat44_ei_main_t *nm, nat44_ei_main_per_thread_data_t *tnm, nat44_ei_user_key_t u_key, int addr_only, ip4_address_t e_addr, u16 e_port)
Delete session for static mapping.
Definition: nat44_ei.c:1356
static uword clib_bitmap_last_set(uword *ai)
Return the higest numbered set bit in a bitmap.
Definition: bitmap.h:429
vl_api_ip_proto_t proto
Definition: acl_types.api:51
u64 key
the key
Definition: bihash_8_8.h:43
IPv4 shallow virtual reassembly.
icmp
Definition: map.api:387
nat44_ei_interface_t * output_feature_interfaces
Definition: nat44_ei.h:340
static void clib_dlist_addtail(dlist_elt_t *pool, u32 head_index, u32 new_index)
Definition: dlist.h:43
format_function_t format_nat_protocol
Definition: nat64.h:506
void nat44_ei_free_outside_address_and_port(nat44_ei_address_t *addresses, u32 thread_index, ip4_address_t *addr, u16 port, nat_protocol_t protocol)
Definition: nat44_ei.c:1043
unsigned short u16
Definition: types.h:57
u8 static_mapping_only
Definition: nat44_ei.h:324
#define NAT44_EI_STATIC_MAPPING_FLAG_IDENTITY_NAT
Definition: nat44_ei.h:65
static void nat44_ei_worker_db_init(nat44_ei_main_per_thread_data_t *tnm, u32 translations, u32 translation_buckets, u32 user_buckets)
Definition: nat44_ei.c:2384
int nat44_ei_interface_add_del_output_feature(u32 sw_if_index, u8 is_inside, int is_del)
Definition: nat44_ei.c:747
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:257
static_always_inline uword nat44_ei_classify_inline_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: nat44_ei.c:2946
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:305
clib_error_t * nat44_ei_api_hookup(vlib_main_t *vm)
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:444
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)
#define PREDICT_FALSE(x)
Definition: clib.h:124
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:897
#define A(x)
Definition: main.c:57
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
u32 node_index
Node index.
Definition: node.h:479
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:109
u32 max_translations_per_user
Definition: nat44_ei.h:347
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:224
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:395
void nat_ha_enable()
Enable NAT HA.
Definition: nat44_ei_ha.c:443
static char * nat44_ei_classify_error_strings[]
Definition: nat44_ei.c:180
#define NAT_FQ_NELTS_DEFAULT
Definition: nat44_ei.h:40
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:1336
u32 nat44_ei_get_out2in_worker_index(vlib_buffer_t *b, ip4_header_t *ip0, u32 rx_fib_index0, u8 is_output)
Definition: nat44_ei.c:1428
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1244
u32 frame_queue_nelts
Definition: nat44_ei.h:467
static void nat44_ei_update_outside_fib(ip4_main_t *im, uword opaque, u32 sw_if_index, u32 new_fib_index, u32 old_fib_index)
Definition: nat44_ei.c:2507
clib_bihash_8_8_t static_mapping_by_local
Definition: nat44_ei.h:330
u32 * auto_add_sw_if_indices
Definition: nat44_ei.h:389
vnet_main_t * vnet_main
Definition: nat44_ei.h:479
#define pool_free(p)
Free a pool.
Definition: pool.h:447
void nat_ha_init(vlib_main_t *vm, u32 num_workers, u32 num_threads)
Initialize NAT HA.
Definition: nat44_ei_ha.c:473
u64 value
the value
Definition: bihash_8_8.h:44
u32 outside_vrf_id
Definition: nat44_ei.h:352
void nat44_ei_set_alloc_default()
Set address and port assignment algorithm to default/standard.
Definition: nat44_ei.c:1697
static void nat44_ei_db_init(u32 translations, u32 translation_buckets, u32 user_buckets)
Definition: nat44_ei.c:2442
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
nat44_ei_main_per_thread_data_t * per_thread_data
Definition: nat44_ei.h:366
int nat44_ei_plugin_enable(nat44_ei_config_t c)
Definition: nat44_ei.c:419
svmdb_client_t * c
u16 n_vectors
Definition: node.h:388
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:208
u8 static_mapping_connection_tracking
Definition: nat44_ei.h:325
u32 first_worker_index
Definition: nat44_ei.h:357
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:395
nat_protocol_t proto
Definition: nat44_ei.h:177
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:895
ip4_add_del_interface_address_function_t * function
Definition: ip4.h:75
#define clib_warning(format, args...)
Definition: error.h:59
u32 translation_buckets
Definition: nat44_ei.h:319
ip4_address_t addr
Definition: nat44_ei.h:104
u32 in2out_hairpinning_finish_interface_output_node_fq_index
Definition: nat44_ei.h:475
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:302
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:41
#define ARRAY_LEN(x)
Definition: clib.h:70
fib_source_t fib_src_low
Definition: nat44_ei.h:460
#define nat44_ei_is_identity_static_mapping(mp)
Definition: nat44_ei.h:678
void fib_table_lock(u32 fib_index, fib_protocol_t proto, fib_source_t source)
Release a reference counting lock on the table.
Definition: fib_table.c:1355
#define NAT44_EI_STATIC_MAPPING_FLAG_ADDR_ONLY
Definition: nat44_ei.h:64
#define nat44_ei_log_err(...)
Definition: nat44_ei.h:682
nat44_ei_classify_next_t
Definition: nat44_ei.c:186
clib_error_t * nat44_ei_init(vlib_main_t *vm)
Definition: nat44_ei.c:308
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
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:498
u8 value
Definition: qos.api:54
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:337
#define ASSERT(truth)
u32 hairpinning_fq_index
Definition: nat44_ei.h:476
nat_timeouts_t timeouts
Definition: nat44_ei.h:405
u32 in2out_hairpinning_finish_ip4_lookup_node_fq_index
Definition: nat44_ei.h:474
vlib_simple_counter_main_t user_limit_reached
Definition: nat44_ei.h:410
ip4_main_t * ip4_main
Definition: nat44_ei.h:456
VNET_FEATURE_INIT(ip4_nat_classify, static)
clib_bihash_8_8_t out2in
Definition: nat44_ei.h:362
u32 fq_in2out_index
Definition: nat44_ei.h:398
app_rx_mq_elt_t * elt
Definition: application.c:488
IPv4 main type.
Definition: ip4.h:107
ip4_address_t external_addr
Definition: nat44_ei.h:168
#define foreach_nat_counter
Definition: lib.h:42
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:1165
vlib_put_next_frame(vm, node, next_index, 0)
#define clib_bitmap_free(v)
Free a bitmap.
Definition: bitmap.h:92
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:154
uword * thread_registrations_by_name
Definition: threads.h:272
static void clib_dlist_remove(dlist_elt_t *pool, u32 index)
Definition: dlist.h:99
nat44_ei_hairpin_src_next_t next_index
void nat44_ei_set_alloc_mape(u16 psid, u16 psid_offset, u16 psid_length)
Set address and port assignment algorithm for MAP-E CE.
Definition: nat44_ei.c:1717
ip_lookup_main_t * ip4_lookup_main
Definition: nat44_ei.h:457
#define FIB_SOURCE_PRIORITY_LOW
Definition: fib_source.h:285
void nat44_ei_add_del_address_dpo(ip4_address_t addr, u8 is_add)
Definition: nat44_ei.c:1019
#define VNET_FEATURES(...)
Definition: feature.h:470
u8 * format_nat44_ei_user_kvp(u8 *s, va_list *args)
Definition: nat44_ei.c:2347
static int nat44_ei_alloc_default_cb(nat44_ei_address_t *addresses, u32 fib_index, u32 thread_index, nat_protocol_t proto, ip4_address_t s_addr, ip4_address_t *addr, u16 *port, u16 port_per_thread, u32 snat_thread_index)
Definition: nat44_ei.c:1512
static uword is_pow2(uword x)
Definition: clib.h:267
vlib_simple_counter_main_t total_sessions
Definition: nat44_ei.h:409
u32 value
Definition: dlist.h:32
#define foreach_nat44_ei_classify_error
Definition: nat44_ei.c:167
ip4_table_bind_callback_t * table_bind_callbacks
Functions to call when interface to table biding changes.
Definition: ip4.h:148
typedef key
Definition: ipsec_types.api:88
struct _vlib_node_registration vlib_node_registration_t
void nat44_ei_delete_session(nat44_ei_main_t *nm, nat44_ei_session_t *ses, u32 thread_index)
Definition: nat44_ei.c:1753
void nat44_ei_set_node_indexes(nat44_ei_main_t *nm, vlib_main_t *vm)
Definition: nat44_ei.c:240
vlib_log_class_t log_class
Definition: nat44_ei.h:450
#define NAT44_EI_INTERFACE_FLAG_IS_INSIDE
Definition: nat44_ei.h:56
vl_api_address_t ip
Definition: l2.api:558
static_always_inline void nat_validate_interface_counters(nat44_ei_main_t *nm, u32 sw_if_index)
Definition: nat44_ei.c:295
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
void nat44_ei_sessions_clear()
Clear all active NAT44-EI sessions.
Definition: nat44_ei.c:2478
#define nat44_ei_is_unk_proto_session(sp)
Definition: nat44_ei.h:668
Definition: fib_entry.h:113
VLIB buffer representation.
Definition: buffer.h:111
nat44_ei_outside_fib_t * outside_fibs
Definition: nat44_ei.h:386
u64 uword
Definition: types.h:112
static void nat44_ei_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: nat44_ei.c:2883
api_main_t * api_main
Definition: nat44_ei.h:455
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:301
nat44_ei_main_t nat44_ei_main
Definition: nat44_ei.c:40
NAT syslog logging.
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:204
static void init_nat_o2i_k(clib_bihash_kv_8_8_t *kv, nat44_ei_session_t *s)
static void nat44_ei_worker_db_free(nat44_ei_main_per_thread_data_t *tnm)
Definition: nat44_ei.c:2318
u16 port
Definition: lb_types.api:73
#define fail_if_enabled()
Definition: nat44_ei.c:58
nat44_ei_session_t * nat44_ei_session_alloc_or_recycle(nat44_ei_main_t *nm, nat44_ei_user_t *u, u32 thread_index, f64 now)
Definition: nat44_ei.c:1180
#define hash_get_mem(h, key)
Definition: hash.h:269
static api_main_t * vlibapi_get_main(void)
Definition: api_common.h:390
#define vnet_buffer(b)
Definition: buffer.h:437
u32 in2out_output_node_index
Definition: nat44_ei.h:396
ip4_address_t local_addr
Definition: nat44_ei.h:166
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1105
nat44_ei_main_t * nm
NAT port/address allocation lib.
int nat44_ei_set_frame_queue_nelts(u32 frame_queue_nelts)
Definition: nat44_ei.c:2874
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:56
u8 * format_nat44_ei_session_kvp(u8 *s, va_list *args)
Definition: nat44_ei.c:2361
clib_bihash_8_8_t in2out
Definition: nat44_ei.h:363
f64 now
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:234
#define vec_foreach(var, vec)
Vector iterator.
void nat44_ei_add_del_addr_to_fib(ip4_address_t *addr, u8 p_len, u32 sw_if_index, int is_add)
Definition: nat44_ei.c:1829
u16 flags
Copy of main node flags.
Definition: node.h:492
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 session_thread_index)
Create session delete HA event.
Definition: nat44_ei_ha.c:860
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:628
nat44_ei_alloc_out_addr_and_port_function_t * alloc_addr_and_port
Definition: nat44_ei.h:371
static_always_inline u32 nat_calc_bihash_buckets(u32 n_elts)
Definition: lib.h:122
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:292
nat44_ei_addr_and_port_alloc_alg_t addr_and_port_alloc_alg
Definition: nat44_ei.h:373
u8 * format_nat44_ei_static_mapping_kvp(u8 *s, va_list *args)
Definition: nat44_ei.c:2373
u32 max_translations_per_thread
Definition: nat44_ei.h:346
int nat44_ei_static_mapping_match(ip4_address_t match_addr, u16 match_port, u32 match_fib_index, nat_protocol_t match_protocol, ip4_address_t *mapping_addr, u16 *mapping_port, u32 *mapping_fib_index, u8 by_external, u8 *is_addr_only, u8 *is_identity_nat)
Match NAT44-EI static mapping.
Definition: nat44_ei.c:2253
u8 forwarding_enabled
Definition: nat44_ei.h:323
#define nat44_ei_interface_is_inside(ip)
Definition: nat44_ei.h:671
static void init_nat_k(clib_bihash_kv_8_8_t *kv, ip4_address_t addr, u16 port, u32 fib_index, nat_protocol_t proto)
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:111
static void nat44_ei_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: nat44_ei.c:2807
void nat_ha_disable()
Disable NAT HA.
Definition: nat44_ei_ha.c:450
void nat44_ei_addresses_free(nat44_ei_address_t **addresses)
Definition: nat44_ei.c:482
nat44_ei_user_t * nat44_ei_user_get_or_create(nat44_ei_main_t *nm, ip4_address_t *addr, u32 fib_index, u32 thread_index)
Definition: nat44_ei.c:1121
clib_bihash_8_8_t user_hash
Definition: nat44_ei.h:277
vlib_node_registration_t nat44_ei_hairpinning_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_hairpinning_node)
#define nat44_ei_interface_is_outside(ip)
Definition: nat44_ei.h:673
void nat_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 fib_index)
Generate NAT44 session delete event.
vlib_node_registration_t nat44_ei_in2out_hairpinning_finish_ip4_lookup_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_in2out_hairpinning_finish_ip4_lookup_node) ...
static int nat44_ei_is_address_used_in_static_mapping(ip4_address_t addr)
Definition: nat44_ei.c:2692
static u32 clib_dlist_remove_head(dlist_elt_t *pool, u32 head_index)
Definition: dlist.h:117
vlib_simple_counter_main_t total_users
Definition: nat44_ei.h:408
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:127