FD.io VPP  v21.10.1-2-g0a485f517
Vector Packet Processing
nat44_ed.c
Go to the documentation of this file.
1 /*
2  * snat.c - simple nat plugin
3  *
4  * Copyright (c) 2016 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <vpp/app/version.h>
19 
20 #include <vnet/vnet.h>
21 #include <vnet/ip/ip.h>
22 #include <vnet/ip/ip4.h>
23 #include <vnet/ip/ip_table.h>
25 #include <vnet/fib/fib_table.h>
26 #include <vnet/fib/ip4_fib.h>
27 #include <vnet/plugin/plugin.h>
28 #include <vppinfra/bihash_16_8.h>
29 
30 #include <nat/lib/log.h>
31 #include <nat/lib/nat_syslog.h>
32 #include <nat/lib/nat_inlines.h>
33 #include <nat/lib/ipfix_logging.h>
34 
35 #include <nat/nat44-ed/nat44_ed.h>
38 
39 #include <vpp/stats/stat_segment.h>
40 
42 
45 
46 #define skip_if_disabled() \
47  do \
48  { \
49  snat_main_t *sm = &snat_main; \
50  if (PREDICT_FALSE (!sm->enabled)) \
51  return; \
52  } \
53  while (0)
54 
55 #define fail_if_enabled() \
56  do \
57  { \
58  snat_main_t *sm = &snat_main; \
59  if (PREDICT_FALSE (sm->enabled)) \
60  { \
61  nat_log_err ("plugin enabled"); \
62  return 1; \
63  } \
64  } \
65  while (0)
66 
67 #define fail_if_disabled() \
68  do \
69  { \
70  snat_main_t *sm = &snat_main; \
71  if (PREDICT_FALSE (!sm->enabled)) \
72  { \
73  nat_log_err ("plugin disabled"); \
74  return 1; \
75  } \
76  } \
77  while (0)
78 
79 /* Hook up input features */
80 VNET_FEATURE_INIT (nat_pre_in2out, static) = {
81  .arc_name = "ip4-unicast",
82  .node_name = "nat-pre-in2out",
83  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
84  "ip4-sv-reassembly-feature"),
85 };
86 VNET_FEATURE_INIT (nat_pre_out2in, static) = {
87  .arc_name = "ip4-unicast",
88  .node_name = "nat-pre-out2in",
89  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
90  "ip4-dhcp-client-detect",
91  "ip4-sv-reassembly-feature"),
92 };
93 VNET_FEATURE_INIT (snat_in2out_worker_handoff, static) = {
94  .arc_name = "ip4-unicast",
95  .node_name = "nat44-in2out-worker-handoff",
96  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
97 };
98 VNET_FEATURE_INIT (snat_out2in_worker_handoff, static) = {
99  .arc_name = "ip4-unicast",
100  .node_name = "nat44-out2in-worker-handoff",
101  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
102  "ip4-dhcp-client-detect"),
103 };
104 VNET_FEATURE_INIT (ip4_snat_in2out, static) = {
105  .arc_name = "ip4-unicast",
106  .node_name = "nat44-in2out",
107  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"),
108 };
109 VNET_FEATURE_INIT (ip4_snat_out2in, static) = {
110  .arc_name = "ip4-unicast",
111  .node_name = "nat44-out2in",
112  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature",
113  "ip4-dhcp-client-detect"),
114 };
115 VNET_FEATURE_INIT (ip4_nat44_ed_in2out, static) = {
116  .arc_name = "ip4-unicast",
117  .node_name = "nat44-ed-in2out",
118  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"),
119 };
120 VNET_FEATURE_INIT (ip4_nat44_ed_out2in, static) = {
121  .arc_name = "ip4-unicast",
122  .node_name = "nat44-ed-out2in",
123  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature",
124  "ip4-dhcp-client-detect"),
125 };
126 VNET_FEATURE_INIT (ip4_nat44_ed_classify, static) = {
127  .arc_name = "ip4-unicast",
128  .node_name = "nat44-ed-classify",
129  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"),
130 };
131 VNET_FEATURE_INIT (ip4_nat_handoff_classify, static) = {
132  .arc_name = "ip4-unicast",
133  .node_name = "nat44-handoff-classify",
134  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"),
135 };
136 VNET_FEATURE_INIT (ip4_snat_in2out_fast, static) = {
137  .arc_name = "ip4-unicast",
138  .node_name = "nat44-in2out-fast",
139  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"),
140 };
141 VNET_FEATURE_INIT (ip4_snat_out2in_fast, static) = {
142  .arc_name = "ip4-unicast",
143  .node_name = "nat44-out2in-fast",
144  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature",
145  "ip4-dhcp-client-detect"),
146 };
147 
148 /* Hook up output features */
149 VNET_FEATURE_INIT (ip4_snat_in2out_output, static) = {
150  .arc_name = "ip4-output",
151  .node_name = "nat44-in2out-output",
152  .runs_after = VNET_FEATURES ("ip4-sv-reassembly-output-feature"),
153  .runs_before = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
154 };
155 VNET_FEATURE_INIT (ip4_snat_in2out_output_worker_handoff, static) = {
156  .arc_name = "ip4-output",
157  .node_name = "nat44-in2out-output-worker-handoff",
158  .runs_after = VNET_FEATURES ("ip4-sv-reassembly-output-feature"),
159  .runs_before = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
160 };
161 VNET_FEATURE_INIT (nat_pre_in2out_output, static) = {
162  .arc_name = "ip4-output",
163  .node_name = "nat-pre-in2out-output",
164  .runs_after = VNET_FEATURES ("ip4-sv-reassembly-output-feature"),
165  .runs_before = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
166 };
167 VNET_FEATURE_INIT (ip4_nat44_ed_in2out_output, static) = {
168  .arc_name = "ip4-output",
169  .node_name = "nat44-ed-in2out-output",
170  .runs_after = VNET_FEATURES ("ip4-sv-reassembly-output-feature"),
171  .runs_before = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
172 };
173 
175  .version = VPP_BUILD_VER,
176  .description = "Network Address Translation (NAT)",
177 };
178 
179 static void nat44_ed_db_init (u32 translations, u32 translation_buckets);
180 
181 static void nat44_ed_db_free ();
182 
184 
185 u8 *
186 format_session_kvp (u8 * s, va_list * args)
187 {
188  clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
189 
190  s = format (s, "%U thread-index %llu session-index %llu", format_snat_key,
193 
194  return s;
195 }
196 
197 u8 *
198 format_static_mapping_kvp (u8 * s, va_list * args)
199 {
200  clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
201 
202  s = format (s, "%U static-mapping-index %llu",
203  format_snat_key, v->key, v->value);
204 
205  return s;
206 }
207 
208 u8 *
209 format_ed_session_kvp (u8 * s, va_list * args)
210 {
211  clib_bihash_kv_16_8_t *v = va_arg (*args, clib_bihash_kv_16_8_t *);
212 
213  u8 proto;
214  u16 r_port, l_port;
215  ip4_address_t l_addr, r_addr;
216  u32 fib_index;
217 
218  split_ed_kv (v, &l_addr, &r_addr, &proto, &fib_index, &l_port, &r_port);
219  s = format (s,
220  "local %U:%d remote %U:%d proto %U fib %d thread-index %u "
221  "session-index %u",
222  format_ip4_address, &l_addr, clib_net_to_host_u16 (l_port),
223  format_ip4_address, &r_addr, clib_net_to_host_u16 (r_port),
224  format_ip_protocol, proto, fib_index,
226 
227  return s;
228 }
229 
230 void
232  u8 is_ha)
233 {
235 
237  nat_elog_warn (sm, "flow hash del failed");
238 
240  nat_elog_warn (sm, "flow hash del failed");
241 
243  {
244  return;
245  }
246 
248  nat_affinity_unlock (s->ext_host_addr, s->out2in.addr, s->nat_proto,
249  s->out2in.port);
250 
251  if (!is_ha)
253  0, s->in2out.fib_index, &s->in2out.addr, s->in2out.port,
254  &s->ext_host_nat_addr, s->ext_host_nat_port, &s->out2in.addr,
255  s->out2in.port, &s->ext_host_addr, s->ext_host_port, s->nat_proto,
257 
259  return;
260 
261  if (!is_ha)
262  {
263  /* log NAT event */
265  thread_index, s->in2out.addr.as_u32, s->out2in.addr.as_u32,
266  s->nat_proto, s->in2out.port, s->out2in.port, s->in2out.fib_index);
267  }
268 
269  /* Twice NAT address and port for external host */
271  {
273  sm->twice_nat_addresses, thread_index, &s->ext_host_nat_addr,
274  s->ext_host_nat_port, s->nat_proto);
275  }
276 
278  return;
279 
281  &s->out2in.addr, s->out2in.port,
282  s->nat_proto);
283 }
284 
285 static int
287 {
290  {
291  if (is_sm_addr_only (m->flags) || is_sm_out2in_only (m->flags) ||
293  {
294  continue;
295  }
296  if (m->external_addr.as_u32 == addr.as_u32)
297  {
298  return 1;
299  }
300  }
301  return 0;
302 }
303 
304 static void
306  int is_add)
307 {
308  // Add the external NAT address to the FIB as receive entries. This ensures
309  // that VPP will reply to ARP for this address and we don't need to enable
310  // proxy ARP on the outside interface.
311 
312  snat_main_t *sm = &snat_main;
313  fib_prefix_t prefix = {
314  .fp_len = p_len,
315  .fp_proto = FIB_PROTOCOL_IP4,
316  .fp_addr = {
317  .ip4.as_u32 = addr->as_u32,
318  },
319  };
321 
322  if (is_add)
323  {
328  DPO_PROTO_IP4, NULL, sw_if_index, ~0, 1,
330  }
331  else
332  {
333  fib_table_entry_delete (fib_index, &prefix, sm->fib_src_low);
334  }
335 }
336 
337 static void
339 {
340  snat_main_t *sm = &snat_main;
342 
343  pool_foreach (i, sm->interfaces)
344  {
346  {
347  nat44_ed_add_del_addr_to_fib (addr, 32, i->sw_if_index, is_add);
348  }
349  }
351  {
353  {
354  nat44_ed_add_del_addr_to_fib (addr, 32, i->sw_if_index, is_add);
355  }
356  }
357 }
358 
361 {
362  snat_main_t *sm = &snat_main;
363  snat_address_t *ap;
364 
365  vec_foreach (ap, sm->addresses)
366  {
367  nat44_ed_add_del_addr_to_fib (&ap->addr, 32, sw_if_index, is_add);
368  }
369 }
370 
373 {
374  snat_main_t *sm = &snat_main;
376 
378  {
379  if (is_sm_addr_only (m->flags) && !is_sm_identity_nat (m->flags))
380  {
382  is_add);
383  }
384  }
385 }
386 
387 int
389 {
390  snat_main_t *sm = &snat_main;
392  snat_address_t *ap, *addresses;
393 
394  addresses = twice_nat ? sm->twice_nat_addresses : sm->addresses;
395 
396  if (!sm->enabled)
397  {
398  return VNET_API_ERROR_UNSUPPORTED;
399  }
400 
401  // check if address already exists
402  vec_foreach (ap, addresses)
403  {
404  if (ap->addr.as_u32 == addr->as_u32)
405  {
406  nat_log_err ("address exist");
407  return VNET_API_ERROR_VALUE_EXIST;
408  }
409  }
410 
411  if (twice_nat)
412  {
413  vec_add2 (sm->twice_nat_addresses, ap, 1);
414  }
415  else
416  {
417  vec_add2 (sm->addresses, ap, 1);
418  }
419 
420  ap->fib_index = ~0;
421  ap->addr = *addr;
422 
423  if (vrf_id != ~0)
424  {
427  }
428 
429 #define _(N, i, n, s) \
430  clib_memset (ap->busy_##n##_port_refcounts, 0, \
431  sizeof (ap->busy_##n##_port_refcounts)); \
432  ap->busy_##n##_ports = 0; \
433  ap->busy_##n##_ports_per_thread = 0; \
434  vec_validate_init_empty (ap->busy_##n##_ports_per_thread, \
435  tm->n_vlib_mains - 1, 0);
437 #undef _
438 
439  if (!twice_nat)
440  {
441  // if we don't have enabled interface we don't add address
442  // to fib
444  }
445  return 0;
446 }
447 
448 int
449 nat44_ed_del_address (ip4_address_t addr, u8 delete_sm, u8 twice_nat)
450 {
451  snat_main_t *sm = &snat_main;
452  snat_address_t *a = 0, *addresses;
453  snat_session_t *ses;
454  u32 *ses_to_be_removed = 0, *ses_index;
457  int j;
458 
459  addresses = twice_nat ? sm->twice_nat_addresses : sm->addresses;
460 
461  for (j = 0; j < vec_len (addresses); j++)
462  {
463  if (addresses[j].addr.as_u32 == addr.as_u32)
464  {
465  a = addresses + j;
466  break;
467  }
468  }
469  if (!a)
470  {
471  nat_log_err ("no such address");
472  return VNET_API_ERROR_NO_SUCH_ENTRY;
473  }
474 
475  if (delete_sm)
476  {
478  {
479  if (m->external_addr.as_u32 == addr.as_u32)
480  {
482  m->local_port, m->external_port,
483  m->proto, m->vrf_id, ~0, m->flags);
484  }
485  }
486  }
487  else
488  {
489  // TODO: why ?
490  // check if address is used in some static mapping
492  {
493  nat_log_err ("address used in static mapping");
494  return VNET_API_ERROR_UNSPECIFIED;
495  }
496  }
497 
498  if (a->fib_index != ~0)
499  {
500  fib_table_unlock (a->fib_index, FIB_PROTOCOL_IP4, sm->fib_src_low);
501  }
502 
503  // delete sessions using address
504  if (a->busy_tcp_ports || a->busy_udp_ports || a->busy_icmp_ports)
505  {
506  vec_foreach (tsm, sm->per_thread_data)
507  {
508  pool_foreach (ses, tsm->sessions)
509  {
510  if (ses->out2in.addr.as_u32 == addr.as_u32)
511  {
512  nat_free_session_data (sm, ses, tsm - sm->per_thread_data,
513  0);
514  vec_add1 (ses_to_be_removed, ses - tsm->sessions);
515  }
516  }
517  vec_foreach (ses_index, ses_to_be_removed)
518  {
519  ses = pool_elt_at_index (tsm->sessions, ses_index[0]);
520  nat_ed_session_delete (sm, ses, tsm - sm->per_thread_data, 1);
521  }
522  vec_free (ses_to_be_removed);
523  }
524  }
525 
526 #define _(N, i, n, s) vec_free (a->busy_##n##_ports_per_thread);
528 #undef _
529 
530  if (!twice_nat)
531  {
532  vec_del1 (sm->addresses, j);
534  }
535  else { vec_del1 (sm->twice_nat_addresses, j); }
536  return 0;
537 }
538 
539 u32
541 {
542  snat_main_t *sm = &snat_main;
543  u32 thread_idx = sm->num_workers;
544  if (sm->num_workers > 1)
545  {
546  thread_idx =
547  sm->first_worker_index +
548  sm->workers[(e_port - 1024) / sm->port_per_thread];
549  }
550  return thread_idx;
551 }
552 
553 void
556  ip4_address_t l_addr,
557  u16 l_port,
558  u8 protocol,
559  u32 fib_index, int addr_only,
560  ip4_address_t e_addr, u16 e_port)
561 {
562  snat_session_t *s;
563  u32 *indexes_to_free = NULL;
564  pool_foreach (s, tsm->sessions) {
565  if (s->in2out.fib_index != fib_index ||
566  s->in2out.addr.as_u32 != l_addr.as_u32)
567  {
568  continue;
569  }
570  if (!addr_only)
571  {
572  if ((s->out2in.addr.as_u32 != e_addr.as_u32) ||
573  s->out2in.port != e_port ||
574  s->in2out.port != l_port ||
575  s->nat_proto != protocol)
576  continue;
577  }
578 
579  if (nat44_ed_is_lb_session (s))
580  continue;
582  continue;
583  nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
584  vec_add1 (indexes_to_free, s - tsm->sessions);
585  if (!addr_only)
586  break;
587  }
588  u32 *ses_index;
589  vec_foreach (ses_index, indexes_to_free)
590  {
591  s = pool_elt_at_index (tsm->sessions, *ses_index);
592  nat_ed_session_delete (sm, s, tsm - sm->per_thread_data, 1);
593  }
594  vec_free (indexes_to_free);
595 }
596 
597 int
599 {
601  snat_main_t *sm = &snat_main;
602  snat_address_t *a = 0;
603  int i;
604 
605  for (i = 0; i < vec_len (sm->addresses); i++)
606  {
607  a = sm->addresses + i;
608 
609  if (a->addr.as_u32 != addr.as_u32)
610  continue;
611 
612  switch (proto)
613  {
614 #define _(N, j, n, s) \
615  case NAT_PROTOCOL_##N: \
616  if (a->busy_##n##_port_refcounts[port]) \
617  goto done; \
618  ++a->busy_##n##_port_refcounts[port]; \
619  if (port > 1024) \
620  { \
621  a->busy_##n##_ports++; \
622  a->busy_##n##_ports_per_thread[ti]++; \
623  } \
624  break;
626 #undef _
627  default : nat_elog_info (sm, "unknown protocol");
628  goto done;
629  }
630 
631  return 0;
632  }
633 
634 done:
635  return 1;
636 }
637 
638 int
640 {
642  snat_main_t *sm = &snat_main;
643  snat_address_t *a = 0;
644  int i;
645 
646  for (i = 0; i < vec_len (sm->addresses); i++)
647  {
648  a = sm->addresses + i;
649 
650  if (a->addr.as_u32 != addr.as_u32)
651  continue;
652 
653  switch (proto)
654  {
655 #define _(N, j, n, s) \
656  case NAT_PROTOCOL_##N: \
657  --a->busy_##n##_port_refcounts[port]; \
658  if (port > 1024) \
659  { \
660  a->busy_##n##_ports--; \
661  a->busy_##n##_ports_per_thread[ti]--; \
662  } \
663  break;
665 #undef _
666  default : nat_elog_info (sm, "unknown protocol");
667  goto done;
668  }
669 
670  return 0;
671  }
672 
673 done:
674  return 1;
675 }
676 
677 void
680  u32 flags, ip4_address_t pool_addr, u8 *tag)
681 {
683  snat_main_t *sm = &snat_main;
684 
685  vec_add2 (sm->to_resolve, rp, 1);
686  rp->l_addr.as_u32 = l_addr.as_u32;
687  rp->l_port = l_port;
688  rp->e_port = e_port;
689  rp->sw_if_index = sw_if_index;
690  rp->vrf_id = vrf_id;
691  rp->proto = proto;
692  rp->flags = flags;
693  rp->pool_addr = pool_addr;
694  rp->tag = vec_dup (tag);
695 }
696 
697 int
700  u32 flags, int *out)
701 {
703  snat_main_t *sm = &snat_main;
704  int i;
705 
706  for (i = 0; i < vec_len (sm->to_resolve); i++)
707  {
708  rp = sm->to_resolve + i;
709 
710  if (rp->sw_if_index == sw_if_index && rp->vrf_id == vrf_id)
711  {
713  {
714  if (!(is_sm_addr_only (rp->flags) && is_sm_addr_only (flags)))
715  {
716  if (rp->e_port != e_port || rp->proto != proto)
717  {
718  continue;
719  }
720  }
721  }
722  else if (rp->l_addr.as_u32 == l_addr.as_u32)
723  {
724  if (!(is_sm_addr_only (rp->flags) && is_sm_addr_only (flags)))
725  {
726  if (rp->l_port != l_port || rp->e_port != e_port ||
727  rp->proto != proto)
728  {
729  continue;
730  }
731  }
732  }
733  else
734  {
735  continue;
736  }
737  if (out)
738  {
739  *out = i;
740  }
741  return 0;
742  }
743  }
744  return 1;
745 }
746 
747 int
750  u32 flags)
751 {
752  snat_main_t *sm = &snat_main;
753  int i;
754  if (!nat44_ed_get_resolve_record (l_addr, l_port, e_port, proto, vrf_id,
755  sw_if_index, flags, &i))
756  {
757  vec_del1 (sm->to_resolve, i);
758  return 0;
759  }
760  return 1;
761 }
762 
765 {
766  // identity nat can be initiated only from inside interface
768  {
769  return VNET_API_ERROR_UNSUPPORTED;
770  }
771 
773  {
775  {
776  return VNET_API_ERROR_UNSUPPORTED;
777  }
778  }
779  return 0;
780 }
781 
782 int
784  u16 l_port, u16 e_port, nat_protocol_t proto,
786  ip4_address_t pool_addr, u8 *tag)
787 {
788  snat_main_t *sm = &snat_main;
790  nat44_lb_addr_port_t *local;
792  u32 fib_index = ~0;
793  int rv;
794 
795  if (!sm->enabled)
796  {
797  return VNET_API_ERROR_UNSUPPORTED;
798  }
799 
801  if (rv != 0)
802  {
803  return rv;
804  }
805 
806  if (is_sm_addr_only (flags))
807  {
808  e_port = l_port = proto = 0;
809  }
810 
812  {
813  // this mapping is interface bound
814  ip4_address_t *first_int_addr;
815 
816  // check if this record isn't registered for resolve
817  if (!nat44_ed_get_resolve_record (l_addr, l_port, e_port, proto, vrf_id,
818  sw_if_index, flags, 0))
819  {
820  return VNET_API_ERROR_VALUE_EXIST;
821  }
822  // register record for resolve
823  nat44_ed_add_resolve_record (l_addr, l_port, e_port, proto, vrf_id,
824  sw_if_index, flags, pool_addr, tag);
825 
826  first_int_addr =
828  if (!first_int_addr)
829  {
830  // dhcp resolution required
831  return 0;
832  }
833 
834  e_addr.as_u32 = first_int_addr->as_u32;
835  }
836 
838  {
839  l_port = e_port;
840  l_addr.as_u32 = e_addr.as_u32;
841  }
842 
843  // fib index 0
844  init_nat_k (&kv, e_addr, e_port, 0, proto);
845 
846  if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
847  {
848  m = pool_elt_at_index (sm->static_mappings, value.value);
849  if (!is_sm_identity_nat (m->flags))
850  {
851  return VNET_API_ERROR_VALUE_EXIST;
852  }
853 
854  // case:
855  // adding local identity nat record for different vrf table
856  pool_foreach (local, m->locals)
857  {
858  if (local->vrf_id == vrf_id)
859  {
860  return VNET_API_ERROR_VALUE_EXIST;
861  }
862  }
863 
864  pool_get (m->locals, local);
865 
866  local->vrf_id = vrf_id;
869 
870  init_nat_kv (&kv, m->local_addr, m->local_port, local->fib_index,
871  m->proto, 0, m - sm->static_mappings);
872  clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1);
873 
874  return 0;
875  }
876 
877  if (vrf_id != ~0)
878  {
880  sm->fib_src_low);
881  }
882  else
883  {
884  // fallback to default vrf
885  vrf_id = sm->inside_vrf_id;
886  fib_index = sm->inside_fib_index;
887  fib_table_lock (fib_index, FIB_PROTOCOL_IP4, sm->fib_src_low);
888  }
889 
890  // test if local mapping record doesn't exist
891  // identity nat supports multiple records in local mapping
893  {
894  init_nat_k (&kv, l_addr, l_port, fib_index, proto);
895  if (!clib_bihash_search_8_8 (&sm->static_mapping_by_local, &kv, &value))
896  {
897  return VNET_API_ERROR_VALUE_EXIST;
898  }
899  }
900 
902  sm->static_mapping_only))
903  {
904  if (nat44_ed_reserve_port (e_addr, e_port, proto))
905  {
906  // remove resolve record
908  {
909  nat44_ed_del_resolve_record (l_addr, l_port, e_port, proto,
911  }
912  return VNET_API_ERROR_NO_SUCH_ENTRY;
913  }
914  }
915 
916  pool_get (sm->static_mappings, m);
917  clib_memset (m, 0, sizeof (*m));
918 
919  m->flags = flags;
920  m->local_addr = l_addr;
921  m->external_addr = e_addr;
922 
923  m->tag = vec_dup (tag);
924 
926  {
927  m->pool_addr = pool_addr;
928  }
929 
930  if (!is_sm_addr_only (flags))
931  {
932  m->local_port = l_port;
933  m->external_port = e_port;
934  m->proto = proto;
935  }
936 
938  {
939  pool_get (m->locals, local);
940 
941  local->vrf_id = vrf_id;
942  local->fib_index = fib_index;
943  }
944  else
945  {
946  m->vrf_id = vrf_id;
947  m->fib_index = fib_index;
948 
949  // not identity && addr only
950  if (is_sm_addr_only (flags))
951  {
953  }
954  }
955 
956  if (!is_sm_out2in_only (flags))
957  {
958  init_nat_kv (&kv, m->local_addr, m->local_port, fib_index, m->proto, 0,
959  m - sm->static_mappings);
960  clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1);
961  }
962 
963  init_nat_kv (&kv, m->external_addr, m->external_port, 0, m->proto, 0,
964  m - sm->static_mappings);
965  clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 1);
966 
967  if (sm->num_workers > 1)
968  {
969  // store worker index for this record
970  ip4_header_t ip = {
971  .src_address = m->local_addr,
972  };
973  u32 worker_index;
974  worker_index =
976  vec_add1 (m->workers, worker_index);
977  }
978 
979  return 0;
980 }
981 
982 int
984  u16 l_port, u16 e_port, nat_protocol_t proto,
986 {
988  snat_main_t *sm = &snat_main;
989 
991  nat44_lb_addr_port_t *local;
993  u32 fib_index = ~0;
994  int rv;
995 
996  if (!sm->enabled)
997  {
998  return VNET_API_ERROR_UNSUPPORTED;
999  }
1000 
1002  if (rv != 0)
1003  {
1004  return rv;
1005  }
1006 
1007  if (is_sm_addr_only (flags))
1008  {
1009  e_port = l_port = proto = 0;
1010  }
1011 
1013  {
1014  // this mapping is interface bound
1015  ip4_address_t *first_int_addr;
1016 
1017  // delete record registered for resolve
1018  if (nat44_ed_del_resolve_record (l_addr, l_port, e_port, proto, vrf_id,
1019  sw_if_index, flags))
1020  {
1021  return VNET_API_ERROR_NO_SUCH_ENTRY;
1022  }
1023 
1024  first_int_addr =
1026  if (!first_int_addr)
1027  {
1028  // dhcp resolution required
1029  return 0;
1030  }
1031 
1032  e_addr.as_u32 = first_int_addr->as_u32;
1033  }
1034 
1035  if (is_sm_identity_nat (flags))
1036  {
1037  l_port = e_port;
1038  l_addr.as_u32 = e_addr.as_u32;
1039  }
1040 
1041  // fib index 0
1042  init_nat_k (&kv, e_addr, e_port, 0, proto);
1043 
1044  if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
1045  {
1047  {
1048  return 0;
1049  }
1050  return VNET_API_ERROR_NO_SUCH_ENTRY;
1051  }
1052 
1053  m = pool_elt_at_index (sm->static_mappings, value.value);
1054 
1055  if (is_sm_identity_nat (flags))
1056  {
1057  u8 failure = 1;
1058 
1059  if (!is_sm_switch_address (flags))
1060  {
1061  vrf_id = sm->inside_vrf_id;
1062  }
1063 
1064  pool_foreach (local, m->locals)
1065  {
1066  if (local->vrf_id == vrf_id)
1067  {
1068  local = pool_elt_at_index (m->locals, local - m->locals);
1069  fib_index = local->fib_index;
1070  pool_put (m->locals, local);
1071  failure = 0;
1072  }
1073  }
1074 
1075  if (failure)
1076  {
1077  return VNET_API_ERROR_NO_SUCH_ENTRY;
1078  }
1079  }
1080  else
1081  {
1082  fib_index = m->fib_index;
1083  }
1084 
1086  sm->static_mapping_only))
1087  {
1088  if (nat44_ed_free_port (e_addr, e_port, proto))
1089  {
1090  return VNET_API_ERROR_INVALID_VALUE;
1091  }
1092  }
1093 
1094  if (!is_sm_out2in_only (flags))
1095  {
1096  init_nat_k (&kv, l_addr, l_port, fib_index, proto);
1097  clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 0);
1098  }
1099 
1101  {
1102  // delete sessions for static mapping
1103  if (sm->num_workers > 1)
1104  tsm = vec_elt_at_index (sm->per_thread_data, m->workers[0]);
1105  else
1106  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1107 
1109  sm, tsm, m->local_addr, m->local_port, m->proto, fib_index,
1110  is_sm_addr_only (flags), e_addr, e_port);
1111  }
1112 
1113  fib_table_unlock (fib_index, FIB_PROTOCOL_IP4, sm->fib_src_low);
1114 
1115  if (!pool_elts (m->locals))
1116  {
1117  // this is last record remove all required stuff
1118  // fib_index 0
1119  init_nat_k (&kv, e_addr, e_port, 0, proto);
1120  clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 0);
1121 
1122  vec_free (m->tag);
1123  vec_free (m->workers);
1124  pool_put (sm->static_mappings, m);
1125 
1127  {
1129  }
1130  }
1131 
1132  return 0;
1133 }
1134 
1135 int
1138  nat44_lb_addr_port_t *locals, u32 flags,
1139  u8 *tag, u32 affinity)
1140 {
1141  snat_main_t *sm = &snat_main;
1144  snat_address_t *a = 0;
1145 
1146  nat44_lb_addr_port_t *local;
1147  uword *bitmap = 0;
1148 
1149  int i;
1150 
1151  if (!sm->enabled)
1152  {
1153  return VNET_API_ERROR_UNSUPPORTED;
1154  }
1155 
1156  init_nat_k (&kv, e_addr, e_port, 0, proto);
1157  if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
1158  {
1159  m = 0;
1160  }
1161  else
1162  {
1163  m = pool_elt_at_index (sm->static_mappings, value.value);
1164  }
1165 
1166  if (m)
1167  {
1168  return VNET_API_ERROR_VALUE_EXIST;
1169  }
1170 
1171  if (vec_len (locals) < 2)
1172  {
1173  return VNET_API_ERROR_INVALID_VALUE;
1174  }
1175 
1177  {
1178  /* Find external address in allocated addresses and reserve port for
1179  address and port pair mapping when dynamic translations enabled */
1180  for (i = 0; i < vec_len (sm->addresses); i++)
1181  {
1182  if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
1183  {
1184  a = sm->addresses + i;
1185  /* External port must be unused */
1186  switch (proto)
1187  {
1188 #define _(N, j, n, s) \
1189  case NAT_PROTOCOL_##N: \
1190  if (a->busy_##n##_port_refcounts[e_port]) \
1191  return VNET_API_ERROR_INVALID_VALUE; \
1192  ++a->busy_##n##_port_refcounts[e_port]; \
1193  if (e_port > 1024) \
1194  { \
1195  a->busy_##n##_ports++; \
1196  a->busy_##n##_ports_per_thread[get_thread_idx_by_port (e_port)]++; \
1197  } \
1198  break;
1200 #undef _
1201  default : nat_elog_info (sm, "unknown protocol");
1202  return VNET_API_ERROR_INVALID_VALUE_2;
1203  }
1204  break;
1205  }
1206  }
1207  // external address must be allocated
1208  if (!a)
1209  {
1210  return VNET_API_ERROR_NO_SUCH_ENTRY;
1211  }
1212  }
1213 
1214  pool_get (sm->static_mappings, m);
1215  clib_memset (m, 0, sizeof (*m));
1216  m->tag = vec_dup (tag);
1217  m->external_addr = e_addr;
1218  m->external_port = e_port;
1219  m->affinity = affinity;
1220  m->proto = proto;
1221 
1222  m->flags = flags;
1223  m->flags |= NAT_SM_FLAG_LB;
1224 
1225  if (affinity)
1228  else
1230 
1231  init_nat_kv (&kv, m->external_addr, m->external_port, 0, m->proto, 0,
1232  m - sm->static_mappings);
1233  if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 1))
1234  {
1235  nat_elog_err (sm, "static_mapping_by_external key add failed");
1236  return VNET_API_ERROR_UNSPECIFIED;
1237  }
1238 
1239  for (i = 0; i < vec_len (locals); i++)
1240  {
1242  FIB_PROTOCOL_IP4, locals[i].vrf_id, sm->fib_src_low);
1243  if (!is_sm_out2in_only (flags))
1244  {
1245  init_nat_kv (&kv, locals[i].addr, locals[i].port,
1246  locals[i].fib_index, m->proto, 0,
1247  m - sm->static_mappings);
1248  clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1);
1249  }
1250  locals[i].prefix = (i == 0) ?
1251  locals[i].probability :
1252  (locals[i - 1].prefix + locals[i].probability);
1253  pool_get (m->locals, local);
1254  *local = locals[i];
1255  if (sm->num_workers > 1)
1256  {
1257  ip4_header_t ip = {
1258  .src_address = locals[i].addr,
1259  };
1260  bitmap = clib_bitmap_set (
1261  bitmap, nat44_ed_get_in2out_worker_index (0, &ip, m->fib_index, 0),
1262  1);
1263  }
1264  }
1265 
1266  /* Assign workers */
1267  if (sm->num_workers > 1)
1268  {
1269  clib_bitmap_foreach (i, bitmap)
1270  {
1271  vec_add1 (m->workers, i);
1272  }
1273  }
1274 
1275  return 0;
1276 }
1277 
1278 int
1281 {
1282  snat_main_t *sm = &snat_main;
1285  snat_address_t *a = 0;
1286 
1287  nat44_lb_addr_port_t *local;
1289  snat_session_t *s;
1290  int i;
1291 
1292  if (!sm->enabled)
1293  {
1294  return VNET_API_ERROR_UNSUPPORTED;
1295  }
1296 
1297  init_nat_k (&kv, e_addr, e_port, 0, proto);
1298  if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
1299  m = 0;
1300  else
1301  m = pool_elt_at_index (sm->static_mappings, value.value);
1302 
1303  if (!m)
1304  return VNET_API_ERROR_NO_SUCH_ENTRY;
1305 
1306  if (!is_sm_lb (m->flags))
1307  return VNET_API_ERROR_INVALID_VALUE;
1308 
1310  {
1311  for (i = 0; i < vec_len (sm->addresses); i++)
1312  {
1313  if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
1314  {
1315  a = sm->addresses + i;
1316  switch (proto)
1317  {
1318 #define _(N, j, n, s) \
1319  case NAT_PROTOCOL_##N: \
1320  --a->busy_##n##_port_refcounts[e_port]; \
1321  if (e_port > 1024) \
1322  { \
1323  a->busy_##n##_ports--; \
1324  a->busy_##n##_ports_per_thread[get_thread_idx_by_port (e_port)]--; \
1325  } \
1326  break;
1328 #undef _
1329  default : nat_elog_info (sm, "unknown protocol");
1330  return VNET_API_ERROR_INVALID_VALUE_2;
1331  }
1332  break;
1333  }
1334  }
1335  }
1336 
1337  init_nat_k (&kv, m->external_addr, m->external_port, 0, m->proto);
1338  if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 0))
1339  {
1340  nat_elog_err (sm, "static_mapping_by_external key del failed");
1341  return VNET_API_ERROR_UNSPECIFIED;
1342  }
1343 
1344  pool_foreach (local, m->locals)
1345  {
1347  if (!is_sm_out2in_only (flags))
1348  {
1349  init_nat_k (&kv, local->addr, local->port, local->fib_index,
1350  m->proto);
1351  if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 0))
1352  {
1353  nat_elog_err (sm, "static_mapping_by_local key del failed");
1354  return VNET_API_ERROR_UNSPECIFIED;
1355  }
1356  }
1357 
1358  if (sm->num_workers > 1)
1359  {
1360  ip4_header_t ip = {
1361  .src_address = local->addr,
1362  };
1363  tsm = vec_elt_at_index (
1364  sm->per_thread_data,
1366  }
1367  else
1368  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1369 
1370  /* Delete sessions */
1371  pool_foreach (s, tsm->sessions)
1372  {
1373  if (!(nat44_ed_is_lb_session (s)))
1374  continue;
1375 
1376  if ((s->in2out.addr.as_u32 != local->addr.as_u32) ||
1377  s->in2out.port != local->port)
1378  continue;
1379 
1380  nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
1381  nat_ed_session_delete (sm, s, tsm - sm->per_thread_data, 1);
1382  }
1383  }
1384 
1385  if (m->affinity)
1386  {
1388  }
1389 
1390  pool_free (m->locals);
1391  vec_free (m->tag);
1392  vec_free (m->workers);
1393  pool_put (sm->static_mappings, m);
1394 
1395  return 0;
1396 }
1397 
1398 int
1400  ip4_address_t l_addr, u16 l_port,
1402  u8 probability, u8 is_add)
1403 {
1404  snat_main_t *sm = &snat_main;
1405  snat_static_mapping_t *m = 0;
1407  nat44_lb_addr_port_t *local, *prev_local, *match_local = 0;
1409  snat_session_t *s;
1410  u32 *locals = 0;
1411  uword *bitmap = 0;
1412  int i;
1413 
1414  if (!sm->enabled)
1415  {
1416  return VNET_API_ERROR_UNSUPPORTED;
1417  }
1418 
1419  init_nat_k (&kv, e_addr, e_port, 0, proto);
1420  if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
1421  m = pool_elt_at_index (sm->static_mappings, value.value);
1422 
1423  if (!m)
1424  {
1425  return VNET_API_ERROR_NO_SUCH_ENTRY;
1426  }
1427 
1428  if (!is_sm_lb (m->flags))
1429  {
1430  return VNET_API_ERROR_INVALID_VALUE;
1431  }
1432 
1433  pool_foreach (local, m->locals)
1434  {
1435  if ((local->addr.as_u32 == l_addr.as_u32) && (local->port == l_port) &&
1436  (local->vrf_id == vrf_id))
1437  {
1438  match_local = local;
1439  break;
1440  }
1441  }
1442 
1443  if (is_add)
1444  {
1445  if (match_local)
1446  {
1447  return VNET_API_ERROR_VALUE_EXIST;
1448  }
1449 
1450  pool_get (m->locals, local);
1451  clib_memset (local, 0, sizeof (*local));
1452  local->addr.as_u32 = l_addr.as_u32;
1453  local->port = l_port;
1454  local->probability = probability;
1455  local->vrf_id = vrf_id;
1456  local->fib_index =
1458  sm->fib_src_low);
1459 
1460  if (!is_sm_out2in_only (m->flags))
1461  {
1462  init_nat_kv (&kv, l_addr, l_port, local->fib_index, proto, 0,
1463  m - sm->static_mappings);
1464  if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1))
1465  nat_elog_err (sm, "static_mapping_by_local key add failed");
1466  }
1467  }
1468  else
1469  {
1470  if (!match_local)
1471  return VNET_API_ERROR_NO_SUCH_ENTRY;
1472 
1473  if (pool_elts (m->locals) < 3)
1474  return VNET_API_ERROR_UNSPECIFIED;
1475 
1477  sm->fib_src_low);
1478 
1479  if (!is_sm_out2in_only (m->flags))
1480  {
1481  init_nat_k (&kv, l_addr, l_port, match_local->fib_index, proto);
1482  if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 0))
1483  nat_elog_err (sm, "static_mapping_by_local key del failed");
1484  }
1485 
1486  if (sm->num_workers > 1)
1487  {
1488  ip4_header_t ip = {
1489  .src_address = local->addr,
1490  };
1491  tsm = vec_elt_at_index (
1492  sm->per_thread_data,
1494  }
1495  else
1496  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1497 
1498  /* Delete sessions */
1499  pool_foreach (s, tsm->sessions) {
1500  if (!(nat44_ed_is_lb_session (s)))
1501  continue;
1502 
1503  if ((s->in2out.addr.as_u32 != match_local->addr.as_u32) ||
1504  s->in2out.port != match_local->port)
1505  continue;
1506 
1507  nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
1508  nat_ed_session_delete (sm, s, tsm - sm->per_thread_data, 1);
1509  }
1510 
1511  pool_put (m->locals, match_local);
1512  }
1513 
1514  vec_free (m->workers);
1515 
1516  pool_foreach (local, m->locals)
1517  {
1518  vec_add1 (locals, local - m->locals);
1519  if (sm->num_workers > 1)
1520  {
1521  ip4_header_t ip;
1522  ip.src_address.as_u32 = local->addr.as_u32,
1523  bitmap = clib_bitmap_set (
1524  bitmap,
1525  nat44_ed_get_in2out_worker_index (0, &ip, local->fib_index, 0), 1);
1526  }
1527  }
1528 
1529  ASSERT (vec_len (locals) > 1);
1530 
1531  local = pool_elt_at_index (m->locals, locals[0]);
1532  local->prefix = local->probability;
1533  for (i = 1; i < vec_len (locals); i++)
1534  {
1535  local = pool_elt_at_index (m->locals, locals[i]);
1536  prev_local = pool_elt_at_index (m->locals, locals[i - 1]);
1537  local->prefix = local->probability + prev_local->prefix;
1538  }
1539 
1540  /* Assign workers */
1541  if (sm->num_workers > 1)
1542  {
1543  clib_bitmap_foreach (i, bitmap) { vec_add1(m->workers, i); }
1544  }
1545 
1546  return 0;
1547 }
1548 
1549 void
1551 {
1552  per_vrf_sessions_t *per_vrf_sessions;
1554  snat_main_t *sm = &snat_main;
1555 
1556  vec_foreach (tsm, sm->per_thread_data)
1557  {
1558  vec_foreach (per_vrf_sessions, tsm->per_vrf_sessions_vec)
1559  {
1560  if ((per_vrf_sessions->rx_fib_index == fib_index) ||
1561  (per_vrf_sessions->tx_fib_index == fib_index))
1562  {
1563  per_vrf_sessions->expired = 1;
1564  }
1565  }
1566  }
1567 }
1568 
1569 void
1570 update_per_vrf_sessions_vec (u32 fib_index, int is_del)
1571 {
1572  snat_main_t *sm = &snat_main;
1573  nat_fib_t *fib;
1574 
1575  // we don't care if it is outside/inside fib
1576  // we just care about their ref_count
1577  // if it reaches 0 sessions should expire
1578  // because the fib isn't valid for NAT anymore
1579 
1580  vec_foreach (fib, sm->fibs)
1581  {
1582  if (fib->fib_index == fib_index)
1583  {
1584  if (is_del)
1585  {
1586  fib->ref_count--;
1587  if (!fib->ref_count)
1588  {
1589  vec_del1 (sm->fibs, fib - sm->fibs);
1590  expire_per_vrf_sessions (fib_index);
1591  }
1592  return;
1593  }
1594  else
1595  fib->ref_count++;
1596  }
1597  }
1598  if (!is_del)
1599  {
1600  vec_add2 (sm->fibs, fib, 1);
1601  fib->ref_count = 1;
1602  fib->fib_index = fib_index;
1603  }
1604 }
1605 
1608 {
1610  vec_foreach (f, outside_fibs)
1611  {
1612  if (f->fib_index == fib_index)
1613  {
1614  return f;
1615  }
1616  }
1617  return 0;
1618 }
1619 
1622 {
1624  pool_foreach (i, interfaces)
1625  {
1626  if (i->sw_if_index == sw_if_index)
1627  {
1628  return i;
1629  }
1630  }
1631  return 0;
1632 }
1633 
1634 int
1636 {
1637  const char *del_feature_name, *feature_name;
1638  snat_main_t *sm = &snat_main;
1639 
1640  nat_outside_fib_t *outside_fib;
1642  u32 fib_index;
1643  int rv;
1644 
1645  if (!sm->enabled)
1646  {
1647  nat_log_err ("nat44 is disabled");
1648  return VNET_API_ERROR_UNSUPPORTED;
1649  }
1650 
1652  {
1653  nat_log_err ("error interface already configured");
1654  return VNET_API_ERROR_VALUE_EXIST;
1655  }
1656 
1658  if (i)
1659  {
1660  if ((nat44_ed_is_interface_inside (i) && is_inside) ||
1661  (nat44_ed_is_interface_outside (i) && !is_inside))
1662  {
1663  return 0;
1664  }
1665  if (sm->num_workers > 1)
1666  {
1667  del_feature_name = !is_inside ? "nat44-in2out-worker-handoff" :
1668  "nat44-out2in-worker-handoff";
1669  feature_name = "nat44-handoff-classify";
1670  }
1671  else
1672  {
1673  del_feature_name = !is_inside ? "nat-pre-in2out" : "nat-pre-out2in";
1674 
1675  feature_name = "nat44-ed-classify";
1676  }
1677 
1679  if (rv)
1680  return rv;
1681  vnet_feature_enable_disable ("ip4-unicast", del_feature_name,
1682  sw_if_index, 0, 0, 0);
1683  vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, 1,
1684  0, 0);
1685  }
1686  else
1687  {
1688  if (sm->num_workers > 1)
1689  {
1690  feature_name = is_inside ? "nat44-in2out-worker-handoff" :
1691  "nat44-out2in-worker-handoff";
1692  }
1693  else
1694  {
1695  feature_name = is_inside ? "nat-pre-in2out" : "nat-pre-out2in";
1696  }
1697 
1700  if (rv)
1701  return rv;
1702  vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, 1,
1703  0, 0);
1704 
1705  pool_get (sm->interfaces, i);
1706  i->sw_if_index = sw_if_index;
1707  i->flags = 0;
1708  }
1709 
1710  fib_index =
1712 
1713  update_per_vrf_sessions_vec (fib_index, 0 /*is_del*/);
1714 
1715  if (!is_inside)
1716  {
1717  i->flags |= NAT_INTERFACE_FLAG_IS_OUTSIDE;
1718 
1719  outside_fib = nat44_ed_get_outside_fib (sm->outside_fibs, fib_index);
1720  if (outside_fib)
1721  {
1722  outside_fib->refcount++;
1723  }
1724  else
1725  {
1726  vec_add2 (sm->outside_fibs, outside_fib, 1);
1727  outside_fib->fib_index = fib_index;
1728  outside_fib->refcount = 1;
1729  }
1730 
1733  }
1734  else
1735  {
1736  i->flags |= NAT_INTERFACE_FLAG_IS_INSIDE;
1737  }
1738 
1739  return 0;
1740 }
1741 
1742 int
1744 {
1745  const char *del_feature_name, *feature_name;
1746  snat_main_t *sm = &snat_main;
1747 
1748  nat_outside_fib_t *outside_fib;
1750  u32 fib_index;
1751  int rv;
1752 
1753  if (!sm->enabled)
1754  {
1755  nat_log_err ("nat44 is disabled");
1756  return VNET_API_ERROR_UNSUPPORTED;
1757  }
1758 
1760  if (i == 0)
1761  {
1762  nat_log_err ("error interface couldn't be found");
1763  return VNET_API_ERROR_NO_SUCH_ENTRY;
1764  }
1765 
1767  {
1768  if (sm->num_workers > 1)
1769  {
1770  del_feature_name = "nat44-handoff-classify";
1771  feature_name = !is_inside ? "nat44-in2out-worker-handoff" :
1772  "nat44-out2in-worker-handoff";
1773  }
1774  else
1775  {
1776  del_feature_name = "nat44-ed-classify";
1777  feature_name = !is_inside ? "nat-pre-in2out" : "nat-pre-out2in";
1778  }
1779 
1781  if (rv)
1782  {
1783  return rv;
1784  }
1785  vnet_feature_enable_disable ("ip4-unicast", del_feature_name,
1786  sw_if_index, 0, 0, 0);
1787  vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, 1,
1788  0, 0);
1789 
1790  if (is_inside)
1791  {
1792  i->flags &= ~NAT_INTERFACE_FLAG_IS_INSIDE;
1793  }
1794  else
1795  {
1796  i->flags &= ~NAT_INTERFACE_FLAG_IS_OUTSIDE;
1797  }
1798  }
1799  else
1800  {
1801  if (sm->num_workers > 1)
1802  {
1803  feature_name = is_inside ? "nat44-in2out-worker-handoff" :
1804  "nat44-out2in-worker-handoff";
1805  }
1806  else
1807  {
1808  feature_name = is_inside ? "nat-pre-in2out" : "nat-pre-out2in";
1809  }
1810 
1812  if (rv)
1813  {
1814  return rv;
1815  }
1816  vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, 0,
1817  0, 0);
1818 
1819  // remove interface
1820  pool_put (sm->interfaces, i);
1821  }
1822 
1823  fib_index =
1825 
1826  update_per_vrf_sessions_vec (fib_index, 1 /*is_del*/);
1827 
1828  if (!is_inside)
1829  {
1830  outside_fib = nat44_ed_get_outside_fib (sm->outside_fibs, fib_index);
1831  if (outside_fib)
1832  {
1833  outside_fib->refcount--;
1834  if (!outside_fib->refcount)
1835  {
1836  vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs);
1837  }
1838  }
1839 
1842  }
1843 
1844  return 0;
1845 }
1846 
1847 int
1849 {
1850  snat_main_t *sm = &snat_main;
1851 
1852  nat_outside_fib_t *outside_fib;
1854  u32 fib_index;
1855  int rv;
1856 
1857  if (!sm->enabled)
1858  {
1859  nat_log_err ("nat44 is disabled");
1860  return VNET_API_ERROR_UNSUPPORTED;
1861  }
1862 
1864  {
1865  nat_log_err ("error interface already configured");
1866  return VNET_API_ERROR_VALUE_EXIST;
1867  }
1868 
1870  {
1871  nat_log_err ("error interface already configured");
1872  return VNET_API_ERROR_VALUE_EXIST;
1873  }
1874 
1875  if (sm->num_workers > 1)
1876  {
1878  if (rv)
1879  {
1880  return rv;
1881  }
1882 
1884  if (rv)
1885  {
1886  return rv;
1887  }
1888 
1890  "ip4-unicast", "nat44-out2in-worker-handoff", sw_if_index, 1, 0, 0);
1891  vnet_feature_enable_disable ("ip4-output",
1892  "nat44-in2out-output-worker-handoff",
1893  sw_if_index, 1, 0, 0);
1894  }
1895  else
1896  {
1898  if (rv)
1899  {
1900  return rv;
1901  }
1902 
1904  if (rv)
1905  {
1906  return rv;
1907  }
1908 
1909  vnet_feature_enable_disable ("ip4-unicast", "nat-pre-out2in",
1910  sw_if_index, 1, 0, 0);
1911  vnet_feature_enable_disable ("ip4-output", "nat-pre-in2out-output",
1912  sw_if_index, 1, 0, 0);
1913  }
1914 
1916 
1918  i->sw_if_index = sw_if_index;
1919  i->flags = 0;
1920  i->flags |= NAT_INTERFACE_FLAG_IS_INSIDE;
1921  i->flags |= NAT_INTERFACE_FLAG_IS_OUTSIDE;
1922 
1923  fib_index =
1925  update_per_vrf_sessions_vec (fib_index, 0 /*is_del*/);
1926 
1927  outside_fib = nat44_ed_get_outside_fib (sm->outside_fibs, fib_index);
1928  if (outside_fib)
1929  {
1930  outside_fib->refcount++;
1931  }
1932  else
1933  {
1934  vec_add2 (sm->outside_fibs, outside_fib, 1);
1935  outside_fib->fib_index = fib_index;
1936  outside_fib->refcount = 1;
1937  }
1938 
1941 
1942  return 0;
1943 }
1944 
1945 int
1947 {
1948  snat_main_t *sm = &snat_main;
1949 
1950  nat_outside_fib_t *outside_fib;
1952  u32 fib_index;
1953  int rv;
1954 
1955  if (!sm->enabled)
1956  {
1957  nat_log_err ("nat44 is disabled");
1958  return VNET_API_ERROR_UNSUPPORTED;
1959  }
1960 
1962  if (!i)
1963  {
1964  nat_log_err ("error interface couldn't be found");
1965  return VNET_API_ERROR_NO_SUCH_ENTRY;
1966  }
1967 
1968  if (sm->num_workers > 1)
1969  {
1971  if (rv)
1972  {
1973  return rv;
1974  }
1975 
1977  if (rv)
1978  {
1979  return rv;
1980  }
1981 
1983  "ip4-unicast", "nat44-out2in-worker-handoff", sw_if_index, 0, 0, 0);
1984  vnet_feature_enable_disable ("ip4-output",
1985  "nat44-in2out-output-worker-handoff",
1986  sw_if_index, 0, 0, 0);
1987  }
1988  else
1989  {
1991  if (rv)
1992  {
1993  return rv;
1994  }
1995 
1997  if (rv)
1998  {
1999  return rv;
2000  }
2001 
2002  vnet_feature_enable_disable ("ip4-unicast", "nat-pre-out2in",
2003  sw_if_index, 0, 0, 0);
2004  vnet_feature_enable_disable ("ip4-output", "nat-pre-in2out-output",
2005  sw_if_index, 0, 0, 0);
2006  }
2007 
2008  // remove interface
2010 
2011  fib_index =
2013  update_per_vrf_sessions_vec (fib_index, 1 /*is_del*/);
2014 
2015  outside_fib = nat44_ed_get_outside_fib (sm->outside_fibs, fib_index);
2016  if (outside_fib)
2017  {
2018  outside_fib->refcount--;
2019  if (!outside_fib->refcount)
2020  {
2021  vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs);
2022  }
2023  }
2024 
2027 
2028  return 0;
2029 }
2030 
2031 int
2033 {
2034  snat_main_t *sm = &snat_main;
2035  int i, j = 0;
2036 
2037  if (sm->num_workers < 2)
2038  return VNET_API_ERROR_FEATURE_DISABLED;
2039 
2040  if (clib_bitmap_last_set (bitmap) >= sm->num_workers)
2041  return VNET_API_ERROR_INVALID_WORKER;
2042 
2043  vec_free (sm->workers);
2044  clib_bitmap_foreach (i, bitmap)
2045  {
2046  vec_add1(sm->workers, i);
2049  j++;
2050  }
2051 
2052  sm->port_per_thread = (0xffff - 1024) / _vec_len (sm->workers);
2053 
2054  return 0;
2055 }
2056 
2057 int
2059 {
2060  fail_if_enabled ();
2061  snat_main_t *sm = &snat_main;
2062  sm->frame_queue_nelts = frame_queue_nelts;
2063  return 0;
2064 }
2065 
2066 static void
2068  u32 new_fib_index, u32 old_fib_index)
2069 {
2070  snat_main_t *sm = &snat_main;
2071  nat_outside_fib_t *outside_fib;
2073  u8 is_add = 1;
2074  u8 match = 0;
2075 
2076  if (!sm->enabled || (new_fib_index == old_fib_index)
2077  || (!vec_len (sm->outside_fibs)))
2078  {
2079  return;
2080  }
2081 
2082  pool_foreach (i, sm->interfaces)
2083  {
2084  if (i->sw_if_index == sw_if_index)
2085  {
2087  return;
2088  match = 1;
2089  }
2090  }
2091 
2093  {
2094  if (i->sw_if_index == sw_if_index)
2095  {
2097  return;
2098  match = 1;
2099  }
2100  }
2101 
2102  if (!match)
2103  return;
2104 
2105  vec_foreach (outside_fib, sm->outside_fibs)
2106  {
2107  if (outside_fib->fib_index == old_fib_index)
2108  {
2109  outside_fib->refcount--;
2110  if (!outside_fib->refcount)
2111  vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs);
2112  break;
2113  }
2114  }
2115 
2116  vec_foreach (outside_fib, sm->outside_fibs)
2117  {
2118  if (outside_fib->fib_index == new_fib_index)
2119  {
2120  outside_fib->refcount++;
2121  is_add = 0;
2122  break;
2123  }
2124  }
2125 
2126  if (is_add)
2127  {
2128  vec_add2 (sm->outside_fibs, outside_fib, 1);
2129  outside_fib->refcount = 1;
2130  outside_fib->fib_index = new_fib_index;
2131  }
2132 }
2133 
2134 static void nat44_ed_update_outside_fib_cb (ip4_main_t *im, uword opaque,
2135  u32 sw_if_index, u32 new_fib_index,
2136  u32 old_fib_index);
2137 
2140  u32 address_length, u32 if_address_index, u32 is_delete);
2141 
2144  u32 address_length, u32 if_address_index, u32 is_delete);
2145 
2146 void
2148 {
2149  ip4_address_t l_addr;
2150  l_addr.as_u8[0] = 1;
2151  l_addr.as_u8[1] = 1;
2152  l_addr.as_u8[2] = 1;
2153  l_addr.as_u8[3] = 1;
2154  ip4_address_t r_addr;
2155  r_addr.as_u8[0] = 2;
2156  r_addr.as_u8[1] = 2;
2157  r_addr.as_u8[2] = 2;
2158  r_addr.as_u8[3] = 2;
2159  u16 l_port = 40001;
2160  u16 r_port = 40301;
2161  u8 proto = 9;
2162  u32 fib_index = 9000001;
2163  u32 thread_index = 3000000001;
2164  u32 session_index = 3000000221;
2166  init_ed_kv (&kv, l_addr, l_port, r_addr, r_port, fib_index, proto,
2167  thread_index, session_index);
2168  ip4_address_t l_addr2;
2169  ip4_address_t r_addr2;
2170  clib_memset (&l_addr2, 0, sizeof (l_addr2));
2171  clib_memset (&r_addr2, 0, sizeof (r_addr2));
2172  u16 l_port2 = 0;
2173  u16 r_port2 = 0;
2174  u8 proto2 = 0;
2175  u32 fib_index2 = 0;
2176  split_ed_kv (&kv, &l_addr2, &r_addr2, &proto2, &fib_index2, &l_port2,
2177  &r_port2);
2178  ASSERT (l_addr.as_u32 == l_addr2.as_u32);
2179  ASSERT (r_addr.as_u32 == r_addr2.as_u32);
2180  ASSERT (l_port == l_port2);
2181  ASSERT (r_port == r_port2);
2182  ASSERT (proto == proto2);
2183  ASSERT (fib_index == fib_index2);
2185  ASSERT (session_index == ed_value_get_session_index (&kv));
2186 
2187  fib_index = 7001;
2188  proto = 5;
2189  nat_protocol_t proto3 = ~0;
2190  u64 key = calc_nat_key (l_addr, l_port, fib_index, proto);
2191  split_nat_key (key, &l_addr2, &l_port2, &fib_index2, &proto3);
2192  ASSERT (l_addr.as_u32 == l_addr2.as_u32);
2193  ASSERT (l_port == l_port2);
2194  ASSERT (proto == proto3);
2195  ASSERT (fib_index == fib_index2);
2196 }
2197 
2198 static clib_error_t *
2200 {
2201  u32 fib_index;
2202  if (!is_add)
2203  {
2204  fib_index = ip4_fib_index_from_table_id (table_id);
2205  if (fib_index != ~0)
2206  {
2207  expire_per_vrf_sessions (fib_index);
2208  }
2209  }
2210  return 0;
2211 }
2212 
2214 
2215 void
2217 {
2218  vlib_node_t *node;
2219 
2220  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-out2in");
2221  sm->out2in_node_index = node->index;
2222 
2223  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-in2out");
2224  sm->in2out_node_index = node->index;
2225 
2226  node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-in2out-output");
2227  sm->in2out_output_node_index = node->index;
2228 }
2229 
2230 #define nat_validate_simple_counter(c, i) \
2231  do \
2232  { \
2233  vlib_validate_simple_counter (&c, i); \
2234  vlib_zero_simple_counter (&c, i); \
2235  } \
2236  while (0);
2237 
2238 #define nat_init_simple_counter(c, n, sn) \
2239  do \
2240  { \
2241  c.name = n; \
2242  c.stat_segment_name = sn; \
2243  nat_validate_simple_counter (c, 0); \
2244  } \
2245  while (0);
2246 
2249 {
2250 #define _(x) \
2251  nat_validate_simple_counter (sm->counters.fastpath.in2out.x, sw_if_index); \
2252  nat_validate_simple_counter (sm->counters.fastpath.out2in.x, sw_if_index); \
2253  nat_validate_simple_counter (sm->counters.slowpath.in2out.x, sw_if_index); \
2254  nat_validate_simple_counter (sm->counters.slowpath.out2in.x, sw_if_index);
2256 #undef _
2258 }
2259 
2260 static clib_error_t *
2262 {
2263  snat_main_t *sm = &snat_main;
2267  ip4_table_bind_callback_t cbt = { 0 };
2268  u32 i, num_threads = 0;
2269  uword *p, *bitmap = 0;
2270 
2271  clib_memset (sm, 0, sizeof (*sm));
2272 
2273  // required
2274  sm->vnet_main = vnet_get_main ();
2275  // convenience
2276  sm->ip4_main = &ip4_main;
2277  sm->api_main = vlibapi_get_main ();
2279 
2280  // frame queue indices used for handoff
2281  sm->fq_out2in_index = ~0;
2282  sm->fq_in2out_index = ~0;
2283  sm->fq_in2out_output_index = ~0;
2284 
2285  sm->log_level = NAT_LOG_ERROR;
2286 
2287  nat44_set_node_indexes (sm, vm);
2288 
2289  sm->log_class = vlib_log_register_class ("nat", 0);
2291 
2292  nat_init_simple_counter (sm->total_sessions, "total-sessions",
2293  "/nat44-ed/total-sessions");
2295  (u8 *) "/nat44-ed/max-cfg-sessions", STAT_DIR_TYPE_SCALAR_INDEX);
2296 
2297 #define _(x) \
2298  nat_init_simple_counter (sm->counters.fastpath.in2out.x, #x, \
2299  "/nat44-ed/in2out/fastpath/" #x); \
2300  nat_init_simple_counter (sm->counters.fastpath.out2in.x, #x, \
2301  "/nat44-ed/out2in/fastpath/" #x); \
2302  nat_init_simple_counter (sm->counters.slowpath.in2out.x, #x, \
2303  "/nat44-ed/in2out/slowpath/" #x); \
2304  nat_init_simple_counter (sm->counters.slowpath.out2in.x, #x, \
2305  "/nat44-ed/out2in/slowpath/" #x);
2307 #undef _
2308  nat_init_simple_counter (sm->counters.hairpinning, "hairpinning",
2309  "/nat44-ed/hairpinning");
2310 
2311  p = hash_get_mem (tm->thread_registrations_by_name, "workers");
2312  if (p)
2313  {
2314  tr = (vlib_thread_registration_t *) p[0];
2315  if (tr)
2316  {
2317  sm->num_workers = tr->count;
2318  sm->first_worker_index = tr->first_index;
2319  }
2320  }
2321  num_threads = tm->n_vlib_mains - 1;
2322  sm->port_per_thread = 0xffff - 1024;
2323  vec_validate (sm->per_thread_data, num_threads);
2324 
2325  /* Use all available workers by default */
2326  if (sm->num_workers > 1)
2327  {
2328  for (i = 0; i < sm->num_workers; i++)
2329  bitmap = clib_bitmap_set (bitmap, i, 1);
2330  snat_set_workers (bitmap);
2331  clib_bitmap_free (bitmap);
2332  }
2333  else
2334  {
2336  }
2337 
2338  /* callbacks to call when interface address changes. */
2343 
2344  /* callbacks to call when interface to table biding changes */
2347 
2348  sm->fib_src_low =
2351  sm->fib_src_hi =
2354 
2357 
2358  return nat44_api_hookup (vm);
2359 }
2360 
2362 
2363 int
2365 {
2366  snat_main_t *sm = &snat_main;
2367 
2368  fail_if_enabled ();
2369 
2370  if (c.static_mapping_only && !c.connection_tracking)
2371  {
2372  nat_log_err ("unsupported combination of configuration");
2373  return 1;
2374  }
2375 
2376  sm->static_mapping_only = c.static_mapping_only;
2377  sm->static_mapping_connection_tracking = c.connection_tracking;
2378 
2379  sm->forwarding_enabled = 0;
2380  sm->mss_clamping = 0;
2381  sm->pat = (!c.static_mapping_only ||
2382  (c.static_mapping_only && c.connection_tracking));
2383 
2384  if (!c.sessions)
2385  c.sessions = 63 * 1024;
2386 
2387  sm->max_translations_per_thread = c.sessions;
2391 
2393 
2394  sm->inside_vrf_id = c.inside_vrf;
2395  sm->inside_fib_index =
2397  (FIB_PROTOCOL_IP4, c.inside_vrf, sm->fib_src_hi);
2398 
2399  sm->outside_vrf_id = c.outside_vrf;
2401  FIB_PROTOCOL_IP4, c.outside_vrf, sm->fib_src_hi);
2402 
2404 
2406 
2408 
2410 
2411  if (!sm->frame_queue_nelts)
2412  {
2414  }
2415 
2416  if (sm->num_workers > 1)
2417  {
2418  if (sm->fq_in2out_index == ~0)
2419  {
2422  }
2423  if (sm->fq_out2in_index == ~0)
2424  {
2427  }
2428  if (sm->fq_in2out_output_index == ~0)
2429  {
2432  }
2433  }
2434 
2435  sm->enabled = 1;
2436  sm->rconfig = c;
2437 
2438  return 0;
2439 }
2440 
2441 void
2443 {
2444  snat_address_t *ap;
2445  vec_foreach (ap, *addresses)
2446  {
2447  #define _(N, i, n, s) \
2448  vec_free (ap->busy_##n##_ports_per_thread);
2450  #undef _
2451  }
2452  vec_free (*addresses);
2453  *addresses = 0;
2454 }
2455 
2456 int
2458 {
2459  snat_main_t *sm = &snat_main;
2460  snat_interface_t *i, *pool;
2461  int error = 0;
2462 
2463  fail_if_disabled ();
2464 
2465  pool = pool_dup (sm->interfaces);
2466  pool_foreach (i, pool)
2467  {
2469  {
2470  error = nat44_ed_del_interface (i->sw_if_index, 1);
2471  }
2473  {
2474  error = nat44_ed_del_interface (i->sw_if_index, 0);
2475  }
2476  if (error)
2477  {
2478  nat_log_err ("error occurred while removing interface %u",
2479  i->sw_if_index);
2480  }
2481  }
2482  pool_free (sm->interfaces);
2483  pool_free (pool);
2484  sm->interfaces = 0;
2485 
2486  pool = pool_dup (sm->output_feature_interfaces);
2487  pool_foreach (i, pool)
2488  {
2489  error = nat44_ed_del_output_interface (i->sw_if_index);
2490  if (error)
2491  {
2492  nat_log_err ("error occurred while removing interface %u",
2493  i->sw_if_index);
2494  }
2495  }
2497  pool_free (pool);
2498  sm->output_feature_interfaces = 0;
2499 
2501 
2502  nat44_ed_db_free ();
2503 
2506 
2507  vec_free (sm->to_resolve);
2510 
2511  sm->to_resolve = 0;
2512  sm->auto_add_sw_if_indices = 0;
2514 
2515  sm->forwarding_enabled = 0;
2516 
2517  sm->enabled = 0;
2518  clib_memset (&sm->rconfig, 0, sizeof (sm->rconfig));
2519 
2520  return 0;
2521 }
2522 
2523 void
2525 {
2527  snat_main_t *sm = &snat_main;
2528  snat_session_t *s;
2529 
2530  u32 *ses_to_be_removed = 0, *ses_index;
2531 
2532  sm->forwarding_enabled = is_enable != 0;
2533 
2534  if (!sm->enabled || is_enable)
2535  {
2536  return;
2537  }
2538 
2539  vec_foreach (tsm, sm->per_thread_data)
2540  {
2541  pool_foreach (s, tsm->sessions)
2542  {
2544  {
2545  vec_add1 (ses_to_be_removed, s - tsm->sessions);
2546  }
2547  }
2548  vec_foreach (ses_index, ses_to_be_removed)
2549  {
2550  s = pool_elt_at_index (tsm->sessions, ses_index[0]);
2551  nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
2552  nat_ed_session_delete (sm, s, tsm - sm->per_thread_data, 1);
2553  }
2554 
2555  vec_free (ses_to_be_removed);
2556  }
2557 }
2558 
2559 void
2563 {
2564  snat_main_t *sm = &snat_main;
2565  snat_address_t *a;
2566  u32 address_index;
2567  u16 port_host_byte_order = clib_net_to_host_u16 (port);
2568 
2569  for (address_index = 0; address_index < vec_len (addresses);
2570  address_index++)
2571  {
2572  if (addresses[address_index].addr.as_u32 == addr->as_u32)
2573  break;
2574  }
2575 
2576  ASSERT (address_index < vec_len (addresses));
2577 
2578  a = addresses + address_index;
2579 
2580  switch (protocol)
2581  {
2582 #define _(N, i, n, s) \
2583  case NAT_PROTOCOL_##N: \
2584  ASSERT (a->busy_##n##_port_refcounts[port_host_byte_order] >= 1); \
2585  --a->busy_##n##_port_refcounts[port_host_byte_order]; \
2586  a->busy_##n##_ports--; \
2587  a->busy_##n##_ports_per_thread[thread_index]--; \
2588  break;
2590 #undef _
2591  default : nat_elog_info (sm, "unknown protocol");
2592  return;
2593  }
2594 }
2595 
2596 int
2598  ip4_address_t match_addr, u16 match_port,
2599  u32 match_fib_index, nat_protocol_t match_protocol,
2600  ip4_address_t *mapping_addr, u16 *mapping_port,
2601  u32 *mapping_fib_index, u8 by_external,
2602  u8 *is_addr_only, twice_nat_type_t *twice_nat,
2603  lb_nat_type_t *lb, ip4_address_t *ext_host_addr,
2604  u8 *is_identity_nat, snat_static_mapping_t **out)
2605 {
2607  clib_bihash_8_8_t *mapping_hash;
2609  u32 rand, lo = 0, hi, mid, *tmp = 0, i;
2610  nat44_lb_addr_port_t *local;
2611  u8 backend_index;
2612 
2613  if (!by_external)
2614  {
2615  mapping_hash = &sm->static_mapping_by_local;
2616  init_nat_k (&kv, match_addr, match_port, match_fib_index,
2617  match_protocol);
2618  if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
2619  {
2620  /* Try address only mapping */
2621  init_nat_k (&kv, match_addr, 0, match_fib_index, 0);
2622  if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
2623  return 1;
2624  }
2625  }
2626  else
2627  {
2628  mapping_hash = &sm->static_mapping_by_external;
2629  init_nat_k (&kv, match_addr, match_port, 0, match_protocol);
2630  if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
2631  {
2632  /* Try address only mapping */
2633  init_nat_k (&kv, match_addr, 0, 0, 0);
2634  if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
2635  return 1;
2636  }
2637  }
2638 
2639  m = pool_elt_at_index (sm->static_mappings, value.value);
2640 
2641  if (by_external)
2642  {
2643  if (is_sm_lb (m->flags))
2644  {
2645  if (PREDICT_FALSE (lb != 0))
2646  *lb = m->affinity ? AFFINITY_LB_NAT : LB_NAT;
2648  vm, ext_host_addr[0], match_addr,
2649  match_protocol, match_port, &backend_index))
2650  {
2651  local = pool_elt_at_index (m->locals, backend_index);
2652  *mapping_addr = local->addr;
2653  *mapping_port = local->port;
2654  *mapping_fib_index = local->fib_index;
2655  goto end;
2656  }
2657  // pick locals matching this worker
2658  if (PREDICT_FALSE (sm->num_workers > 1))
2659  {
2662  {
2663  local = pool_elt_at_index (m->locals, i);
2664 
2665  ip4_header_t ip = {
2666  .src_address = local->addr,
2667  };
2668 
2670  0) == thread_index)
2671  {
2672  vec_add1 (tmp, i);
2673  }
2674  }
2675  ASSERT (vec_len (tmp) != 0);
2676  }
2677  else
2678  {
2680  {
2681  vec_add1 (tmp, i);
2682  }
2683  }
2684  hi = vec_len (tmp) - 1;
2685  local = pool_elt_at_index (m->locals, tmp[hi]);
2686  rand = 1 + (random_u32 (&sm->random_seed) % local->prefix);
2687  while (lo < hi)
2688  {
2689  mid = ((hi - lo) >> 1) + lo;
2690  local = pool_elt_at_index (m->locals, tmp[mid]);
2691  (rand > local->prefix) ? (lo = mid + 1) : (hi = mid);
2692  }
2693  local = pool_elt_at_index (m->locals, tmp[lo]);
2694  if (!(local->prefix >= rand))
2695  return 1;
2696  *mapping_addr = local->addr;
2697  *mapping_port = local->port;
2698  *mapping_fib_index = local->fib_index;
2699  if (m->affinity)
2700  {
2701  if (nat_affinity_create_and_lock (ext_host_addr[0], match_addr,
2702  match_protocol, match_port,
2703  tmp[lo], m->affinity,
2705  nat_elog_info (sm, "create affinity record failed");
2706  }
2707  vec_free (tmp);
2708  }
2709  else
2710  {
2711  if (PREDICT_FALSE (lb != 0))
2712  *lb = NO_LB_NAT;
2713  *mapping_fib_index = m->fib_index;
2714  *mapping_addr = m->local_addr;
2715  /* Address only mapping doesn't change port */
2716  *mapping_port =
2717  is_sm_addr_only (m->flags) ? match_port : m->local_port;
2718  }
2719  }
2720  else
2721  {
2722  *mapping_addr = m->external_addr;
2723  /* Address only mapping doesn't change port */
2724  *mapping_port =
2725  is_sm_addr_only (m->flags) ? match_port : m->external_port;
2726  *mapping_fib_index = sm->outside_fib_index;
2727  }
2728 
2729 end:
2730  if (PREDICT_FALSE (is_addr_only != 0))
2731  *is_addr_only = is_sm_addr_only (m->flags);
2732 
2733  if (PREDICT_FALSE (twice_nat != 0))
2734  {
2735  *twice_nat = TWICE_NAT_DISABLED;
2736 
2737  if (is_sm_twice_nat (m->flags))
2738  {
2739  *twice_nat = TWICE_NAT;
2740  }
2741  else if (is_sm_self_twice_nat (m->flags))
2742  {
2743  *twice_nat = TWICE_NAT_SELF;
2744  }
2745  }
2746 
2747  if (PREDICT_FALSE (is_identity_nat != 0))
2748  *is_identity_nat = is_sm_identity_nat (m->flags);
2749 
2750  if (out != 0)
2751  *out = m;
2752 
2753  return 0;
2754 }
2755 
2756 u32
2758  u32 rx_fib_index, u8 is_output)
2759 {
2760  snat_main_t *sm = &snat_main;
2761  u32 next_worker_index = sm->first_worker_index;
2762  u32 hash;
2763 
2764  clib_bihash_kv_16_8_t kv16, value16;
2765 
2766  u32 fib_index = rx_fib_index;
2767  if (b)
2768  {
2769  if (PREDICT_FALSE (is_output))
2770  {
2771  fib_index = sm->outside_fib_index;
2772  nat_outside_fib_t *outside_fib;
2774  fib_prefix_t pfx = {
2776  .fp_len = 32,
2777  .fp_addr = {
2778  .ip4.as_u32 = ip->dst_address.as_u32,
2779  } ,
2780  };
2781 
2782  switch (vec_len (sm->outside_fibs))
2783  {
2784  case 0:
2785  fib_index = sm->outside_fib_index;
2786  break;
2787  case 1:
2788  fib_index = sm->outside_fibs[0].fib_index;
2789  break;
2790  default:
2791  vec_foreach (outside_fib, sm->outside_fibs)
2792  {
2793  fei = fib_table_lookup (outside_fib->fib_index, &pfx);
2794  if (FIB_NODE_INDEX_INVALID != fei)
2795  {
2796  if (fib_entry_get_resolving_interface (fei) != ~0)
2797  {
2798  fib_index = outside_fib->fib_index;
2799  break;
2800  }
2801  }
2802  }
2803  break;
2804  }
2805  }
2806 
2807  if (PREDICT_FALSE (ip->protocol == IP_PROTOCOL_ICMP))
2808  {
2809  ip4_address_t lookup_saddr, lookup_daddr;
2810  u16 lookup_sport, lookup_dport;
2811  u8 lookup_protocol;
2812 
2814  b, ip, &lookup_saddr, &lookup_sport, &lookup_daddr,
2815  &lookup_dport, &lookup_protocol))
2816  {
2817  init_ed_k (&kv16, lookup_saddr, lookup_sport, lookup_daddr,
2818  lookup_dport, rx_fib_index, lookup_protocol);
2819  if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv16, &value16))
2820  {
2821  next_worker_index = ed_value_get_thread_index (&value16);
2822  vnet_buffer2 (b)->nat.cached_session_index =
2823  ed_value_get_session_index (&value16);
2824  goto out;
2825  }
2826  }
2827  }
2828 
2829  init_ed_k (&kv16, ip->src_address, vnet_buffer (b)->ip.reass.l4_src_port,
2830  ip->dst_address, vnet_buffer (b)->ip.reass.l4_dst_port,
2831  fib_index, ip->protocol);
2832 
2833  if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv16, &value16))
2834  {
2835  next_worker_index = ed_value_get_thread_index (&value16);
2836  vnet_buffer2 (b)->nat.cached_session_index =
2837  ed_value_get_session_index (&value16);
2838  goto out;
2839  }
2840 
2841  // dst NAT
2842  init_ed_k (&kv16, ip->dst_address, vnet_buffer (b)->ip.reass.l4_dst_port,
2843  ip->src_address, vnet_buffer (b)->ip.reass.l4_src_port,
2844  rx_fib_index, ip->protocol);
2845  if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv16, &value16))
2846  {
2847  next_worker_index = ed_value_get_thread_index (&value16);
2848  vnet_buffer2 (b)->nat.cached_dst_nat_session_index =
2849  ed_value_get_session_index (&value16);
2850  goto out;
2851  }
2852  }
2853 
2854  hash = ip->src_address.as_u32 + (ip->src_address.as_u32 >> 8) +
2855  (ip->src_address.as_u32 >> 16) + (ip->src_address.as_u32 >> 24);
2856 
2857  if (PREDICT_TRUE (is_pow2 (_vec_len (sm->workers))))
2858  next_worker_index += sm->workers[hash & (_vec_len (sm->workers) - 1)];
2859  else
2860  next_worker_index += sm->workers[hash % _vec_len (sm->workers)];
2861 
2862 out:
2863  if (PREDICT_TRUE (!is_output))
2864  {
2865  nat_elog_debug_handoff (sm, "HANDOFF IN2OUT", next_worker_index,
2866  rx_fib_index,
2867  clib_net_to_host_u32 (ip->src_address.as_u32),
2868  clib_net_to_host_u32 (ip->dst_address.as_u32));
2869  }
2870  else
2871  {
2872  nat_elog_debug_handoff (sm, "HANDOFF IN2OUT-OUTPUT-FEATURE",
2873  next_worker_index, rx_fib_index,
2874  clib_net_to_host_u32 (ip->src_address.as_u32),
2875  clib_net_to_host_u32 (ip->dst_address.as_u32));
2876  }
2877 
2878  return next_worker_index;
2879 }
2880 
2881 u32
2883  u32 rx_fib_index, u8 is_output)
2884 {
2885  snat_main_t *sm = &snat_main;
2887  clib_bihash_kv_16_8_t kv16, value16;
2888 
2889  u32 proto, next_worker_index = 0;
2890  u16 port;
2892  u32 hash;
2893 
2894  proto = ip_proto_to_nat_proto (ip->protocol);
2895 
2896  if (PREDICT_FALSE (proto == NAT_PROTOCOL_ICMP))
2897  {
2898  ip4_address_t lookup_saddr, lookup_daddr;
2899  u16 lookup_sport, lookup_dport;
2900  u8 lookup_protocol;
2902  b, ip, &lookup_saddr, &lookup_sport, &lookup_daddr, &lookup_dport,
2903  &lookup_protocol))
2904  {
2905  init_ed_k (&kv16, lookup_saddr, lookup_sport, lookup_daddr,
2906  lookup_dport, rx_fib_index, lookup_protocol);
2907  if (PREDICT_TRUE (
2908  !clib_bihash_search_16_8 (&sm->flow_hash, &kv16, &value16)))
2909  {
2910  next_worker_index = ed_value_get_thread_index (&value16);
2912  sm, "HANDOFF OUT2IN (session)", next_worker_index,
2913  rx_fib_index, clib_net_to_host_u32 (ip->src_address.as_u32),
2914  clib_net_to_host_u32 (ip->dst_address.as_u32));
2915  return next_worker_index;
2916  }
2917  }
2918  }
2919 
2920  init_ed_k (&kv16, ip->src_address, vnet_buffer (b)->ip.reass.l4_src_port,
2921  ip->dst_address, vnet_buffer (b)->ip.reass.l4_dst_port,
2922  rx_fib_index, ip->protocol);
2923 
2924  if (PREDICT_TRUE (
2925  !clib_bihash_search_16_8 (&sm->flow_hash, &kv16, &value16)))
2926  {
2927  vnet_buffer2 (b)->nat.cached_session_index =
2928  ed_value_get_session_index (&value16);
2929  next_worker_index = ed_value_get_thread_index (&value16);
2930  nat_elog_debug_handoff (sm, "HANDOFF OUT2IN (session)",
2931  next_worker_index, rx_fib_index,
2932  clib_net_to_host_u32 (ip->src_address.as_u32),
2933  clib_net_to_host_u32 (ip->dst_address.as_u32));
2934  return next_worker_index;
2935  }
2936 
2937  /* first try static mappings without port */
2939  {
2940  init_nat_k (&kv, ip->dst_address, 0, 0, 0);
2941  if (!clib_bihash_search_8_8
2942  (&sm->static_mapping_by_external, &kv, &value))
2943  {
2944  m = pool_elt_at_index (sm->static_mappings, value.value);
2945  next_worker_index = m->workers[0];
2946  goto done;
2947  }
2948  }
2949 
2950  /* unknown protocol */
2951  if (PREDICT_FALSE (proto == NAT_PROTOCOL_OTHER))
2952  {
2953  /* use current thread */
2954  next_worker_index = vlib_get_thread_index ();
2955  goto done;
2956  }
2957 
2958  port = vnet_buffer (b)->ip.reass.l4_dst_port;
2959 
2960  if (PREDICT_FALSE (ip->protocol == IP_PROTOCOL_ICMP))
2961  {
2962  udp_header_t *udp = ip4_next_header (ip);
2963  icmp46_header_t *icmp = (icmp46_header_t *) udp;
2964  icmp_echo_header_t *echo = (icmp_echo_header_t *) (icmp + 1);
2966  (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags))
2967  port = vnet_buffer (b)->ip.reass.l4_src_port;
2968  else
2969  {
2970  /* if error message, then it's not fragmented and we can access it */
2971  ip4_header_t *inner_ip = (ip4_header_t *) (echo + 1);
2972  proto = ip_proto_to_nat_proto (inner_ip->protocol);
2973  void *l4_header = ip4_next_header (inner_ip);
2974  switch (proto)
2975  {
2976  case NAT_PROTOCOL_ICMP:
2977  icmp = (icmp46_header_t *) l4_header;
2978  echo = (icmp_echo_header_t *) (icmp + 1);
2979  port = echo->identifier;
2980  break;
2981  case NAT_PROTOCOL_UDP:
2982  case NAT_PROTOCOL_TCP:
2983  port = ((tcp_udp_header_t *) l4_header)->src_port;
2984  break;
2985  default:
2986  next_worker_index = vlib_get_thread_index ();
2987  goto done;
2988  }
2989  }
2990  }
2991 
2992  /* try static mappings with port */
2994  {
2995  init_nat_k (&kv, ip->dst_address, port, 0, proto);
2996  if (!clib_bihash_search_8_8
2997  (&sm->static_mapping_by_external, &kv, &value))
2998  {
2999  m = pool_elt_at_index (sm->static_mappings, value.value);
3000  if (!is_sm_lb (m->flags))
3001  {
3002  next_worker_index = m->workers[0];
3003  goto done;
3004  }
3005 
3006  hash = ip->src_address.as_u32 + (ip->src_address.as_u32 >> 8) +
3007  (ip->src_address.as_u32 >> 16) + (ip->src_address.as_u32 >> 24);
3008 
3009  if (PREDICT_TRUE (is_pow2 (_vec_len (m->workers))))
3010  next_worker_index =
3011  m->workers[hash & (_vec_len (m->workers) - 1)];
3012  else
3013  next_worker_index = m->workers[hash % _vec_len (m->workers)];
3014  goto done;
3015  }
3016  }
3017 
3018  /* worker by outside port */
3019  next_worker_index = sm->first_worker_index;
3020  next_worker_index +=
3021  sm->workers[(clib_net_to_host_u16 (port) - 1024) / sm->port_per_thread];
3022 
3023 done:
3024  nat_elog_debug_handoff (sm, "HANDOFF OUT2IN", next_worker_index,
3025  rx_fib_index,
3026  clib_net_to_host_u32 (ip->src_address.as_u32),
3027  clib_net_to_host_u32 (ip->dst_address.as_u32));
3028  return next_worker_index;
3029 }
3030 
3031 u32
3033 {
3034  snat_main_t *sm = &snat_main;
3035  u32 max_limit = 0, len = 0;
3036 
3037  for (; len < vec_len (sm->max_translations_per_fib); len++)
3038  {
3039  if (max_limit < sm->max_translations_per_fib[len])
3040  max_limit = sm->max_translations_per_fib[len];
3041  }
3042  return max_limit;
3043 }
3044 
3045 int
3047 {
3048  snat_main_t *sm = &snat_main;
3049  u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
3051 
3052  if (len <= fib_index)
3053  {
3054  vec_validate (sm->max_translations_per_fib, fib_index + 1);
3055 
3056  for (; len < vec_len (sm->max_translations_per_fib); len++)
3058  }
3059 
3060  sm->max_translations_per_fib[fib_index] = session_limit;
3061  return 0;
3062 }
3063 
3064 int
3066 {
3067  snat_main_t *sm = &snat_main;
3068 
3069  if (nat44_set_session_limit (session_limit, vrf_id))
3070  return 1;
3072 
3075 
3076  sm->translation_buckets =
3078 
3080  return 0;
3081 }
3082 
3083 static void
3085  u32 translation_buckets)
3086 {
3087  dlist_elt_t *head;
3088 
3089  pool_alloc (tsm->sessions, translations);
3090  pool_alloc (tsm->lru_pool, translations);
3091 
3092  pool_get (tsm->lru_pool, head);
3093  tsm->tcp_trans_lru_head_index = head - tsm->lru_pool;
3095 
3096  pool_get (tsm->lru_pool, head);
3097  tsm->tcp_estab_lru_head_index = head - tsm->lru_pool;
3099 
3100  pool_get (tsm->lru_pool, head);
3101  tsm->udp_lru_head_index = head - tsm->lru_pool;
3103 
3104  pool_get (tsm->lru_pool, head);
3105  tsm->icmp_lru_head_index = head - tsm->lru_pool;
3107 
3108  pool_get (tsm->lru_pool, head);
3109  tsm->unk_proto_lru_head_index = head - tsm->lru_pool;
3111 }
3112 
3113 static void
3115 {
3116  snat_main_t *sm = &snat_main;
3117  // we expect 2 flows per session, so multiply translation_buckets by 2
3118  clib_bihash_init_16_8 (
3119  &sm->flow_hash, "ed-flow-hash",
3120  clib_max (1, sm->num_workers) * 2 * sm->translation_buckets, 0);
3121  clib_bihash_set_kvp_format_fn_16_8 (&sm->flow_hash, format_ed_session_kvp);
3122 }
3123 
3124 static void
3125 nat44_ed_db_init (u32 translations, u32 translation_buckets)
3126 {
3127  snat_main_t *sm = &snat_main;
3129  u32 static_mapping_buckets = 1024;
3130  u32 static_mapping_memory_size = 64 << 20;
3131 
3133 
3134  clib_bihash_init_8_8 (&sm->static_mapping_by_local,
3135  "static_mapping_by_local", static_mapping_buckets,
3136  static_mapping_memory_size);
3137  clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_local,
3139 
3140  clib_bihash_init_8_8 (&sm->static_mapping_by_external,
3141  "static_mapping_by_external", static_mapping_buckets,
3142  static_mapping_memory_size);
3143  clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_external,
3145 
3146  if (sm->pat)
3147  {
3148  vec_foreach (tsm, sm->per_thread_data)
3149  {
3151  sm->translation_buckets);
3152  }
3153  }
3154 }
3155 
3156 static void
3158 {
3159  pool_free (tsm->lru_pool);
3160  pool_free (tsm->sessions);
3162 }
3163 
3164 static void
3166 {
3167  snat_main_t *sm = &snat_main;
3169 
3170  pool_free (sm->static_mappings);
3171  clib_bihash_free_16_8 (&sm->flow_hash);
3172  clib_bihash_free_8_8 (&sm->static_mapping_by_local);
3173  clib_bihash_free_8_8 (&sm->static_mapping_by_external);
3174 
3175  if (sm->pat)
3176  {
3177  vec_foreach (tsm, sm->per_thread_data)
3178  {
3180  }
3181  }
3182 }
3183 
3184 void
3186 {
3187  snat_main_t *sm = &snat_main;
3189 
3191 
3192  if (sm->pat)
3193  {
3194  vec_foreach (tsm, sm->per_thread_data)
3195  {
3196 
3199  sm->translation_buckets);
3200  }
3201  }
3203 }
3204 
3205 static void
3208  u32 address_length, u32 if_address_index, u32 is_delete)
3209 {
3212  snat_main_t *sm = &snat_main;
3214  int i, rv = 0, match = 0;
3215 
3216  if (!sm->enabled)
3217  {
3218  return;
3219  }
3220 
3221  // find first addr_only resolve record by sw_if_index
3222  for (i = 0; i < vec_len (sm->to_resolve); i++)
3223  {
3224  rp = sm->to_resolve + i;
3225  if (rp->addr_only && rp->sw_if_index == sw_if_index)
3226  {
3227  match = 1;
3228  break;
3229  }
3230  }
3231  if (!match)
3232  {
3233  return;
3234  }
3235 
3236  init_nat_k (&kv, *address, rp->addr_only ? 0 : rp->e_port,
3237  sm->outside_fib_index, rp->addr_only ? 0 : rp->proto);
3238 
3239  if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
3240  {
3241  m = 0;
3242  }
3243  else
3244  {
3245  m = pool_elt_at_index (sm->static_mappings, value.value);
3246  }
3247 
3248  if (is_delete)
3249  {
3250  if (m)
3251  {
3253  rp->e_port, rp->proto, rp->vrf_id,
3254  ~0, rp->flags);
3255  }
3256  }
3257  else
3258  {
3259  if (!m)
3260  {
3262  rp->l_addr, address[0], rp->l_port, rp->e_port, rp->proto,
3263  rp->vrf_id, ~0, rp->flags, rp->pool_addr, rp->tag);
3264  }
3265  // else: don't trip over lease renewal, static config
3266  }
3267  if (rv)
3268  {
3269  nat_elog_notice_X1 (sm, "nat44_ed_del_static_mapping returned %d", "i4",
3270  rv);
3271  }
3272 }
3273 
3276 {
3277  u32 *i;
3279  {
3280  if (*i == sw_if_index)
3281  {
3282  return 1;
3283  }
3284  }
3285  return 0;
3286 }
3287 
3288 static void
3291  u32 address_length,
3292  u32 if_address_index, u32 is_delete)
3293 {
3294  snat_main_t *sm = &snat_main;
3296  snat_address_t *addresses = sm->addresses;
3297  u8 twice_nat = 0;
3298  int rv, i;
3299 
3300  if (!sm->enabled)
3301  {
3302  return;
3303  }
3304 
3306  sw_if_index))
3307  {
3310  {
3311  return;
3312  }
3313  else
3314  {
3315  addresses = sm->twice_nat_addresses;
3316  twice_nat = 1;
3317  }
3318  }
3319 
3320  if (!is_delete)
3321  {
3322  // don't trip over lease renewal, static config
3323  for (i = 0; i < vec_len (addresses); i++)
3324  {
3325  if (addresses[i].addr.as_u32 == address->as_u32)
3326  {
3327  return;
3328  }
3329  }
3330 
3331  (void) nat44_ed_add_address (address, ~0, twice_nat);
3332 
3333  // scan static mapping switch address resolution record vector
3334  for (i = 0; i < vec_len (sm->to_resolve); i++)
3335  {
3336  rp = sm->to_resolve + i;
3337  if (rp->addr_only)
3338  {
3339  continue;
3340  }
3341  if (rp->sw_if_index == sw_if_index)
3342  {
3344  rp->l_addr, address[0], rp->l_port, rp->e_port, rp->proto,
3345  rp->vrf_id, sw_if_index, rp->flags, rp->pool_addr, rp->tag);
3346  if (rv)
3347  {
3348  nat_elog_notice_X1 (sm, "add_static_mapping returned %d",
3349  "i4", rv);
3350  }
3351  }
3352  }
3353  }
3354  else
3355  {
3356  // remove all static mapping records
3357  (void) nat44_ed_del_address (address[0], 1, twice_nat);
3358  }
3359 }
3360 
3361 int
3363 {
3364  snat_main_t *sm = &snat_main;
3365  ip4_main_t *ip4_main = sm->ip4_main;
3366  ip4_address_t *first_int_addr;
3367  u32 *auto_add_sw_if_indices = twice_nat ?
3370  int i;
3371 
3372  for (i = 0; i < vec_len (auto_add_sw_if_indices); i++)
3373  {
3374  if (auto_add_sw_if_indices[i] == sw_if_index)
3375  {
3376  return VNET_API_ERROR_VALUE_EXIST;
3377  }
3378  }
3379 
3380  // add to the auto-address list
3381  if (twice_nat)
3382  {
3384  }
3385  else
3386  {
3388  }
3389 
3390  // if the address is already bound - or static - add it now
3391  first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index, 0);
3392  if (first_int_addr)
3393  {
3394  (void) nat44_ed_add_address (first_int_addr, ~0, twice_nat);
3395  }
3396 
3397  return 0;
3398 }
3399 
3400 int
3402 {
3403  snat_main_t *sm = &snat_main;
3404  ip4_main_t *ip4_main = sm->ip4_main;
3405  ip4_address_t *first_int_addr;
3407  u32 *indices_to_delete = 0;
3408  int i, j;
3409  u32 *auto_add_sw_if_indices;
3410 
3411  if (!sm->enabled)
3412  {
3413  return VNET_API_ERROR_UNSUPPORTED;
3414  }
3415 
3416  auto_add_sw_if_indices = twice_nat ? sm->auto_add_sw_if_indices_twice_nat :
3418 
3419  for (i = 0; i < vec_len (auto_add_sw_if_indices); i++)
3420  {
3421  if (auto_add_sw_if_indices[i] == sw_if_index)
3422  {
3423  first_int_addr =
3425  if (first_int_addr)
3426  {
3427  // remove all static mapping records
3428  (void) nat44_ed_del_address (first_int_addr[0], 1, twice_nat);
3429  }
3430  else
3431  {
3432  for (j = 0; j < vec_len (sm->to_resolve); j++)
3433  {
3434  rp = sm->to_resolve + j;
3435  if (rp->sw_if_index == sw_if_index)
3436  {
3437  vec_add1 (indices_to_delete, j);
3438  }
3439  }
3440  if (vec_len (indices_to_delete))
3441  {
3442  for (j = vec_len (indices_to_delete) - 1; j >= 0; j--)
3443  {
3444  vec_del1 (sm->to_resolve, j);
3445  }
3446  vec_free (indices_to_delete);
3447  }
3448  }
3449 
3450  if (twice_nat)
3451  {
3453  }
3454  else
3455  {
3457  }
3458  return 0;
3459  }
3460  }
3461  return VNET_API_ERROR_NO_SUCH_ENTRY;
3462 }
3463 
3464 int
3466  ip4_address_t *eh_addr, u16 eh_port, u8 proto,
3467  u32 vrf_id, int is_in)
3468 {
3469  ip4_header_t ip;
3471  u32 fib_index;
3472  snat_session_t *s;
3474 
3475  if (!sm->enabled)
3476  {
3477  return VNET_API_ERROR_UNSUPPORTED;
3478  }
3479 
3480  fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
3481  ip.dst_address.as_u32 = ip.src_address.as_u32 = addr->as_u32;
3482  if (sm->num_workers > 1)
3483  tsm = vec_elt_at_index (
3484  sm->per_thread_data,
3485  nat44_ed_get_in2out_worker_index (0, &ip, fib_index, 0));
3486  else
3487  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
3488 
3489  init_ed_k (&kv, *addr, port, *eh_addr, eh_port, fib_index, proto);
3490  if (clib_bihash_search_16_8 (&sm->flow_hash, &kv, &value))
3491  {
3492  return VNET_API_ERROR_NO_SUCH_ENTRY;
3493  }
3494 
3496  return VNET_API_ERROR_UNSPECIFIED;
3498  nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
3499  nat_ed_session_delete (sm, s, tsm - sm->per_thread_data, 1);
3500  return 0;
3501 }
3502 
3505  vlib_frame_t * frame)
3506 {
3507  return 0;
3508 }
3509 
3511  .name = "nat-default",
3512  .vector_size = sizeof (u32),
3513  .format_trace = 0,
3515  .n_errors = 0,
3516  .n_next_nodes = NAT_N_NEXT,
3517  .next_nodes = {
3518  [NAT_NEXT_DROP] = "error-drop",
3519  [NAT_NEXT_ICMP_ERROR] = "ip4-icmp-error",
3520  [NAT_NEXT_IN2OUT_ED_FAST_PATH] = "nat44-ed-in2out",
3521  [NAT_NEXT_IN2OUT_ED_SLOW_PATH] = "nat44-ed-in2out-slowpath",
3522  [NAT_NEXT_IN2OUT_ED_OUTPUT_FAST_PATH] = "nat44-ed-in2out-output",
3523  [NAT_NEXT_IN2OUT_ED_OUTPUT_SLOW_PATH] = "nat44-ed-in2out-output-slowpath",
3524  [NAT_NEXT_OUT2IN_ED_FAST_PATH] = "nat44-ed-out2in",
3525  [NAT_NEXT_OUT2IN_ED_SLOW_PATH] = "nat44-ed-out2in-slowpath",
3526  [NAT_NEXT_IN2OUT_CLASSIFY] = "nat44-in2out-worker-handoff",
3527  [NAT_NEXT_OUT2IN_CLASSIFY] = "nat44-out2in-worker-handoff",
3528  },
3529 };
3530 
3531 void
3533 {
3534  f->l3_csum_delta = 0;
3535  f->l4_csum_delta = 0;
3536  if (f->ops & NAT_FLOW_OP_SADDR_REWRITE &&
3537  f->rewrite.saddr.as_u32 != f->match.saddr.as_u32)
3538  {
3539  f->l3_csum_delta =
3540  ip_csum_add_even (f->l3_csum_delta, f->rewrite.saddr.as_u32);
3541  f->l3_csum_delta =
3542  ip_csum_sub_even (f->l3_csum_delta, f->match.saddr.as_u32);
3543  }
3544  else
3545  {
3546  f->rewrite.saddr.as_u32 = f->match.saddr.as_u32;
3547  }
3548  if (f->ops & NAT_FLOW_OP_DADDR_REWRITE &&
3549  f->rewrite.daddr.as_u32 != f->match.daddr.as_u32)
3550  {
3551  f->l3_csum_delta =
3552  ip_csum_add_even (f->l3_csum_delta, f->rewrite.daddr.as_u32);
3553  f->l3_csum_delta =
3554  ip_csum_sub_even (f->l3_csum_delta, f->match.daddr.as_u32);
3555  }
3556  else
3557  {
3558  f->rewrite.daddr.as_u32 = f->match.daddr.as_u32;
3559  }
3560  if (f->ops & NAT_FLOW_OP_SPORT_REWRITE && f->rewrite.sport != f->match.sport)
3561  {
3562  f->l4_csum_delta = ip_csum_add_even (f->l4_csum_delta, f->rewrite.sport);
3563  f->l4_csum_delta = ip_csum_sub_even (f->l4_csum_delta, f->match.sport);
3564  }
3565  else
3566  {
3567  f->rewrite.sport = f->match.sport;
3568  }
3569  if (f->ops & NAT_FLOW_OP_DPORT_REWRITE && f->rewrite.dport != f->match.dport)
3570  {
3571  f->l4_csum_delta = ip_csum_add_even (f->l4_csum_delta, f->rewrite.dport);
3572  f->l4_csum_delta = ip_csum_sub_even (f->l4_csum_delta, f->match.dport);
3573  }
3574  else
3575  {
3576  f->rewrite.dport = f->match.dport;
3577  }
3578  if (f->ops & NAT_FLOW_OP_ICMP_ID_REWRITE &&
3579  f->rewrite.icmp_id != f->match.sport)
3580  {
3581  f->l4_csum_delta =
3582  ip_csum_add_even (f->l4_csum_delta, f->rewrite.icmp_id);
3583  f->l4_csum_delta = ip_csum_sub_even (f->l4_csum_delta, f->match.sport);
3584  }
3585  else
3586  {
3587  f->rewrite.icmp_id = f->match.sport;
3588  }
3589  if (f->ops & NAT_FLOW_OP_TXFIB_REWRITE)
3590  {
3591  }
3592  else
3593  {
3594  f->rewrite.fib_index = f->match.fib_index;
3595  }
3596 }
3597 
3601 
3605  int is_icmp_inner_ip4, int skip_saddr_rewrite)
3606 {
3607  udp_header_t *udp = ip4_next_header (ip);
3608  tcp_header_t *tcp = (tcp_header_t *) udp;
3609 
3610  if ((NAT_PROTOCOL_TCP == proto || NAT_PROTOCOL_UDP == proto) &&
3611  !vnet_buffer (b)->ip.reass.is_non_first_fragment)
3612  {
3613  if (!is_icmp_inner_ip4)
3614  { // regular case
3615  ip->src_address = f->rewrite.saddr;
3616  ip->dst_address = f->rewrite.daddr;
3617  udp->src_port = f->rewrite.sport;
3618  udp->dst_port = f->rewrite.dport;
3619  }
3620  else
3621  { // icmp inner ip4 - reversed saddr/daddr
3622  ip->src_address = f->rewrite.daddr;
3623  ip->dst_address = f->rewrite.saddr;
3624  udp->src_port = f->rewrite.dport;
3625  udp->dst_port = f->rewrite.sport;
3626  }
3627 
3628  if (NAT_PROTOCOL_TCP == proto)
3629  {
3630  ip_csum_t tcp_sum = tcp->checksum;
3631  tcp_sum = ip_csum_sub_even (tcp_sum, f->l3_csum_delta);
3632  tcp_sum = ip_csum_sub_even (tcp_sum, f->l4_csum_delta);
3633  mss_clamping (sm->mss_clamping, tcp, &tcp_sum);
3634  tcp->checksum = ip_csum_fold (tcp_sum);
3635  }
3636  else if (proto == NAT_PROTOCOL_UDP && udp->checksum)
3637  {
3638  ip_csum_t udp_sum = udp->checksum;
3639  udp_sum = ip_csum_sub_even (udp_sum, f->l3_csum_delta);
3640  udp_sum = ip_csum_sub_even (udp_sum, f->l4_csum_delta);
3641  udp->checksum = ip_csum_fold (udp_sum);
3642  }
3643  }
3644  else
3645  {
3646  if (!is_icmp_inner_ip4)
3647  { // regular case
3648  if (!skip_saddr_rewrite)
3649  {
3650  ip->src_address = f->rewrite.saddr;
3651  }
3652  ip->dst_address = f->rewrite.daddr;
3653  }
3654  else
3655  { // icmp inner ip4 - reversed saddr/daddr
3656  ip->src_address = f->rewrite.daddr;
3657  ip->dst_address = f->rewrite.saddr;
3658  }
3659  }
3660 
3661  if (skip_saddr_rewrite)
3662  {
3663  ip->checksum = ip4_header_checksum (ip);
3664  }
3665  else
3666  {
3667  ip_csum_t ip_sum = ip->checksum;
3668  ip_sum = ip_csum_sub_even (ip_sum, f->l3_csum_delta);
3669  ip->checksum = ip_csum_fold (ip_sum);
3670  }
3671  if (0xffff == ip->checksum)
3672  ip->checksum = 0;
3674 }
3675 
3677 it_fits (vlib_main_t *vm, vlib_buffer_t *b, void *object, size_t size)
3678 {
3679  int result = ((u8 *) object + size <=
3682  return result;
3683 }
3684 
3688 {
3689  if (IP_PROTOCOL_ICMP != ip->protocol)
3691 
3692  icmp46_header_t *icmp = ip4_next_header (ip);
3693  icmp_echo_header_t *echo = (icmp_echo_header_t *) (icmp + 1);
3694 
3695  if ((!vnet_buffer (b)->ip.reass.is_non_first_fragment))
3696  {
3697  if (!it_fits (vm, b, icmp, sizeof (*icmp)))
3698  {
3700  }
3701 
3702  if (!icmp_type_is_error_message (icmp->type))
3703  {
3704  if ((f->ops & NAT_FLOW_OP_ICMP_ID_REWRITE) &&
3705  (f->rewrite.icmp_id != echo->identifier))
3706  {
3707  ip_csum_t sum = icmp->checksum;
3708  sum = ip_csum_update (sum, echo->identifier, f->rewrite.icmp_id,
3710  identifier /* changed member */);
3711  echo->identifier = f->rewrite.icmp_id;
3712  icmp->checksum = ip_csum_fold (sum);
3713  }
3714  }
3715  else
3716  {
3718  0, icmp,
3719  clib_net_to_host_u16 (ip->length) - ip4_header_bytes (ip));
3720  sum = (u16) ~ip_csum_fold (sum);
3721  if (sum != 0)
3722  {
3724  }
3725 
3726  // errors are not fragmented
3727  ip4_header_t *inner_ip = (ip4_header_t *) (echo + 1);
3728 
3729  if (!ip4_header_checksum_is_valid (inner_ip))
3730  {
3732  }
3733 
3734  nat_protocol_t inner_proto =
3735  ip_proto_to_nat_proto (inner_ip->protocol);
3736 
3737  ip_csum_t old_icmp_sum = icmp->checksum;
3738  ip_csum_t old_inner_ip_sum = inner_ip->checksum;
3739  ip_csum_t old_udp_sum;
3740  ip_csum_t old_tcp_sum;
3741  ip_csum_t new_icmp_sum;
3742  udp_header_t *udp;
3743  tcp_header_t *tcp;
3744 
3745  switch (inner_proto)
3746  {
3747  case NAT_PROTOCOL_UDP:
3748  udp = (udp_header_t *) (inner_ip + 1);
3749  if (!it_fits (vm, b, udp, sizeof (*udp)))
3750  {
3752  }
3753  old_udp_sum = udp->checksum;
3754  nat_6t_flow_ip4_translate (sm, b, inner_ip, f, inner_proto,
3755  1 /* is_icmp_inner_ip4 */,
3756  0 /* skip_saddr_rewrite */);
3757  new_icmp_sum = ip_csum_sub_even (old_icmp_sum, f->l3_csum_delta);
3758  new_icmp_sum = ip_csum_sub_even (new_icmp_sum, f->l4_csum_delta);
3759  new_icmp_sum =
3760  ip_csum_update (new_icmp_sum, old_inner_ip_sum,
3761  inner_ip->checksum, ip4_header_t, checksum);
3762  new_icmp_sum =
3763  ip_csum_update (new_icmp_sum, old_udp_sum, udp->checksum,
3764  udp_header_t, checksum);
3765  new_icmp_sum = ip_csum_fold (new_icmp_sum);
3766  icmp->checksum = new_icmp_sum;
3767  break;
3768  case NAT_PROTOCOL_TCP:
3769  tcp = (tcp_header_t *) (inner_ip + 1);
3770  if (!it_fits (vm, b, tcp, sizeof (*tcp)))
3771  {
3773  }
3774  old_tcp_sum = tcp->checksum;
3775  nat_6t_flow_ip4_translate (sm, b, inner_ip, f, inner_proto,
3776  1 /* is_icmp_inner_ip4 */,
3777  0 /* skip_saddr_rewrite */);
3778  new_icmp_sum = ip_csum_sub_even (old_icmp_sum, f->l3_csum_delta);
3779  new_icmp_sum = ip_csum_sub_even (new_icmp_sum, f->l4_csum_delta);
3780  new_icmp_sum =
3781  ip_csum_update (new_icmp_sum, old_inner_ip_sum,
3782  inner_ip->checksum, ip4_header_t, checksum);
3783  new_icmp_sum =
3784  ip_csum_update (new_icmp_sum, old_tcp_sum, tcp->checksum,
3785  tcp_header_t, checksum);
3786  new_icmp_sum = ip_csum_fold (new_icmp_sum);
3787  icmp->checksum = new_icmp_sum;
3788  break;
3789  case NAT_PROTOCOL_ICMP:
3790  if (f->ops & NAT_FLOW_OP_ICMP_ID_REWRITE)
3791  {
3792  icmp46_header_t *inner_icmp = ip4_next_header (inner_ip);
3793  if (!it_fits (vm, b, inner_icmp, sizeof (*inner_icmp)))
3794  {
3796  }
3797  icmp_echo_header_t *inner_echo =
3798  (icmp_echo_header_t *) (inner_icmp + 1);
3799  if (f->rewrite.icmp_id != inner_echo->identifier)
3800  {
3801  ip_csum_t sum = icmp->checksum;
3802  sum = ip_csum_update (
3803  sum, inner_echo->identifier, f->rewrite.icmp_id,
3804  icmp_echo_header_t, identifier /* changed member */);
3805  icmp->checksum = ip_csum_fold (sum);
3806  ip_csum_t inner_sum = inner_icmp->checksum;
3807  inner_sum = ip_csum_update (
3808  sum, inner_echo->identifier, f->rewrite.icmp_id,
3809  icmp_echo_header_t, identifier /* changed member */);
3810  inner_icmp->checksum = ip_csum_fold (inner_sum);
3811  inner_echo->identifier = f->rewrite.icmp_id;
3812  }
3813  }
3814  break;
3815  default:
3816  clib_warning ("unexpected NAT protocol value `%d'", inner_proto);
3818  }
3819  }
3820  }
3821 
3822  return NAT_ED_TRNSL_ERR_SUCCESS;
3823 }
3824 
3828  nat_protocol_t proto, int is_output_feature,
3829  int is_i2o)
3830 {
3831  if (!is_output_feature && f->ops & NAT_FLOW_OP_TXFIB_REWRITE)
3832  {
3833  vnet_buffer (b)->sw_if_index[VLIB_TX] = f->rewrite.fib_index;
3834  }
3835 
3836  if (NAT_PROTOCOL_ICMP == proto)
3837  {
3838  if (ip->src_address.as_u32 != f->rewrite.saddr.as_u32)
3839  {
3840  // packet is returned from a router, not from destination
3841  // skip source address rewrite if in o2i path
3843  0 /* is_icmp_inner_ip4 */,
3844  !is_i2o /* skip_saddr_rewrite */);
3845  }
3846  else
3847  {
3849  0 /* is_icmp_inner_ip4 */,
3850  0 /* skip_saddr_rewrite */);
3851  }
3852  return nat_6t_flow_icmp_translate (vm, sm, b, ip, f);
3853  }
3854 
3855  nat_6t_flow_ip4_translate (sm, b, ip, f, proto, 0 /* is_icmp_inner_ip4 */,
3856  0 /* skip_saddr_rewrite */);
3857 
3858  return NAT_ED_TRNSL_ERR_SUCCESS;
3859 }
3860 
3865  int is_output_feature)
3866 {
3867  return nat_6t_flow_buf_translate (vm, sm, b, ip, f, proto, is_output_feature,
3868  1 /* is_i2o */);
3869 }
3870 
3875  int is_output_feature)
3876 {
3877  return nat_6t_flow_buf_translate (vm, sm, b, ip, f, proto, is_output_feature,
3878  0 /* is_i2o */);
3879 }
3880 
3881 u8 *
3882 format_nat_6t (u8 *s, va_list *args)
3883 {
3884  nat_6t_t *t = va_arg (*args, nat_6t_t *);
3885 
3886  s = format (s, "saddr %U sport %u daddr %U dport %u proto %U fib_idx %u",
3888  clib_net_to_host_u16 (t->sport), format_ip4_address,
3889  t->daddr.as_u8, clib_net_to_host_u16 (t->dport),
3891  return s;
3892 }
3893 
3894 u8 *
3896 {
3898 
3899  switch (e)
3900  {
3902  s = format (s, "success");
3903  break;
3905  s = format (s, "translation-failed");
3906  break;
3908  s = format (s, "flow-mismatch");
3909  break;
3911  s = format (s, "packet-truncated");
3912  break;
3914  s = format (s, "inner-ip-corrupted");
3915  break;
3917  s = format (s, "invalid-checksum");
3918  break;
3919  }
3920  return s;
3921 }
3922 
3923 u8 *
3924 format_nat_6t_flow (u8 *s, va_list *args)
3925 {
3926  nat_6t_flow_t *f = va_arg (*args, nat_6t_flow_t *);
3927 
3928  s = format (s, "match: %U ", format_nat_6t, &f->match);
3929  int r = 0;
3930  if (f->ops & NAT_FLOW_OP_SADDR_REWRITE)
3931  {
3932  s = format (s, "rewrite: saddr %U ", format_ip4_address,
3933  f->rewrite.saddr.as_u8);
3934  r = 1;
3935  }
3936  if (f->ops & NAT_FLOW_OP_SPORT_REWRITE)
3937  {
3938  if (!r)
3939  {
3940  s = format (s, "rewrite: ");
3941  r = 1;
3942  }
3943  s = format (s, "sport %u ", clib_net_to_host_u16 (f->rewrite.sport));
3944  }
3945  if (f->ops & NAT_FLOW_OP_DADDR_REWRITE)
3946  {
3947  if (!r)
3948  {
3949  s = format (s, "rewrite: ");
3950  r = 1;
3951  }
3952  s = format (s, "daddr %U ", format_ip4_address, f->rewrite.daddr.as_u8);
3953  }
3954  if (f->ops & NAT_FLOW_OP_DPORT_REWRITE)
3955  {
3956  if (!r)
3957  {
3958  s = format (s, "rewrite: ");
3959  r = 1;
3960  }
3961  s = format (s, "dport %u ", clib_net_to_host_u16 (f->rewrite.dport));
3962  }
3963  if (f->ops & NAT_FLOW_OP_ICMP_ID_REWRITE)
3964  {
3965  if (!r)
3966  {
3967  s = format (s, "rewrite: ");
3968  r = 1;
3969  }
3970  s = format (s, "icmp-id %u ", clib_net_to_host_u16 (f->rewrite.icmp_id));
3971  }
3972  if (f->ops & NAT_FLOW_OP_TXFIB_REWRITE)
3973  {
3974  if (!r)
3975  {
3976  s = format (s, "rewrite: ");
3977  r = 1;
3978  }
3979  s = format (s, "txfib %u ", f->rewrite.fib_index);
3980  }
3981  return s;
3982 }
3983 
3984 /*
3985  * fd.io coding-style-patch-verification: ON
3986  *
3987  * Local Variables:
3988  * eval: (c-set-style "gnu")
3989  * End:
3990  */
nat44_ed_is_interface_outside
static bool nat44_ed_is_interface_outside(snat_interface_t *i)
Check if NAT interface is outside.
Definition: nat44_ed.h:808
snat_main_s::to_resolve
snat_static_map_resolve_t * to_resolve
Definition: nat44_ed.h:572
is_sm_lb
static bool is_sm_lb(u32 f)
Definition: nat44_ed.h:852
nat44_ed_worker_db_free
static void nat44_ed_worker_db_free(snat_main_per_thread_data_t *tsm)
Definition: nat44_ed.c:3157
ed_value_get_thread_index
static u32 ed_value_get_thread_index(clib_bihash_kv_16_8_t *value)
Definition: nat44_ed_inlines.h:140
tmp
u32 * tmp
Definition: interface_output.c:1096
snat_main_s::port_per_thread
u16 port_per_thread
Definition: nat44_ed.h:519
snat_is_unk_proto_session
static bool snat_is_unk_proto_session(snat_session_t *s)
Check if SNAT session for unknown protocol.
Definition: nat44_ed.h:738
snat_main_s::ip4_lookup_main
ip_lookup_main_t * ip4_lookup_main
Definition: nat44_ed.h:662
nat_6t_t::proto
u8 proto
Definition: nat44_ed.h:218
nat44_ed_sessions_clear
void nat44_ed_sessions_clear()
Definition: nat44_ed.c:3185
clib_dlist_init
static void clib_dlist_init(dlist_elt_t *pool, u32 index)
Definition: dlist.h:36
nat_value_get_thread_index
static u32 nat_value_get_thread_index(clib_bihash_kv_8_8_t *value)
Definition: nat44_ei_inlines.h:105
is_sm_switch_address
static bool is_sm_switch_address(u32 f)
Definition: nat44_ed.h:876
snat_set_workers
int snat_set_workers(uword *bitmap)
Definition: nat44_ed.c:2032
nat44_update_session_limit
int nat44_update_session_limit(u32 session_limit, u32 vrf_id)
Update NAT44 session limit flushing all data (session limit, vrf id)
Definition: nat44_ed.c:3065
im
vnet_interface_main_t * im
Definition: interface_output.c:415
snat_main_per_thread_data_t::unk_proto_lru_head_index
u32 unk_proto_lru_head_index
Definition: nat44_ed.h:482
udp_header_t::src_port
u16 src_port
Definition: udp_packet.h:48
nat_fib_t::fib_index
u32 fib_index
Definition: nat44_ed.h:369
nat_elog_debug_handoff
#define nat_elog_debug_handoff(_pm, _str, _tid, _fib, _src, _dst)
Definition: log.h:78
nat44_ed_del_static_mapping
int nat44_ed_del_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port, nat_protocol_t proto, u32 vrf_id, u32 sw_if_index, u32 flags)
Definition: nat44_ed.c:983
snat_static_mapping_t::locals
nat44_lb_addr_port_t * locals
Definition: nat44_ed.h:437
snat_main_s::in2out_output_node_index
u32 in2out_output_node_index
Definition: nat44_ed.h:584
snat_main_s::outside_vrf_id
u32 outside_vrf_id
Definition: nat44_ed.h:603
nat_affinity_get_per_service_list_head_index
u32 nat_affinity_get_per_service_list_head_index(void)
Get new affinity per service list head index.
Definition: nat44_ed_affinity.c:96
nat44_ed_add_output_interface
int nat44_ed_add_output_interface(u32 sw_if_index)
Definition: nat44_ed.c:1848
ed_value_get_session_index
static u32 ed_value_get_session_index(clib_bihash_kv_16_8_t *value)
Definition: nat44_ed_inlines.h:146
snat_main_s::static_mappings
snat_static_mapping_t * static_mappings
Definition: nat44_ed.h:531
thread_index
u32 thread_index
Definition: nat44_ei_hairpinning.c:495
snat_main_s::twice_nat_addresses
snat_address_t * twice_nat_addresses
Definition: nat44_ed.h:547
frame
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
nat44_lb_addr_port_t::addr
ip4_address_t addr
Definition: nat44_ed.h:382
split_ed_kv
static void split_ed_kv(clib_bihash_kv_16_8_t *kv, ip4_address_t *l_addr, ip4_address_t *r_addr, u8 *proto, u32 *fib_index, u16 *l_port, u16 *r_port)
Definition: nat44_ed_inlines.h:152
nat_outside_fib_t
Definition: nat44_ed.h:373
snat_main_s::total_sessions
vlib_simple_counter_main_t total_sessions
Definition: nat44_ed.h:614
snat_main_s::ip4_main
ip4_main_t * ip4_main
Definition: nat44_ed.h:661
ip4_main_t::lookup_main
ip_lookup_main_t lookup_main
Definition: ip4.h:109
LB_NAT
@ LB_NAT
Definition: nat44_ed.h:408
format_snat_key
format_function_t format_snat_key
Definition: nat44_ed.h:716
nat_elog_warn
#define nat_elog_warn(_pm, nat_elog_str)
Definition: log.h:177
format_ip4_address
format_function_t format_ip4_address
Definition: format.h:73
snat_static_mapping_t::vrf_id
u32 vrf_id
Definition: nat44_ed.h:426
snat_main_s::fib_src_hi
fib_source_t fib_src_hi
Definition: nat44_ed.h:664
fib_table_entry_delete
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:900
snat_main_s::counters
struct snat_main_s::@746 counters
nat_ip_table_add_del
static clib_error_t * nat_ip_table_add_del(vnet_main_t *vnm, u32 table_id, u32 is_add)
Definition: nat44_ed.c:2199
format_nat_6t_flow
u8 * format_nat_6t_flow(u8 *s, va_list *args)
Definition: nat44_ed.c:3924
ip4_main_t::table_bind_callbacks
ip4_table_bind_callback_t * table_bind_callbacks
Functions to call when interface to table biding changes.
Definition: ip4.h:145
ip4_main
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1104
nat_inlines.h
clib_max
#define clib_max(x, y)
Definition: clib.h:335
nat_log_err
#define nat_log_err(...)
Definition: nat44_ed.h:882
fib_table_entry_update_one_path
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:819
snat_main_s::vnet_main
vnet_main_t * vnet_main
Definition: nat44_ed.h:676
snat_main_per_thread_data_t::udp_lru_head_index
u32 udp_lru_head_index
Definition: nat44_ed.h:480
snat_main_per_thread_data_t::lru_pool
dlist_elt_t * lru_pool
Definition: nat44_ed.h:477
nat44_ed_get_outside_fib
static_always_inline nat_outside_fib_t * nat44_ed_get_outside_fib(nat_outside_fib_t *outside_fibs, u32 fib_index)
Definition: nat44_ed.c:1607
f
vlib_frame_t * f
Definition: interface_output.c:1098
nat44_ed_add_static_mapping
int nat44_ed_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port, nat_protocol_t proto, u32 vrf_id, u32 sw_if_index, u32 flags, ip4_address_t pool_addr, u8 *tag)
Definition: nat44_ed.c:783
nat_outside_fib_t::refcount
u32 refcount
Definition: nat44_ed.h:376
pool_elt_at_index
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:549
nat_validate_simple_counter
#define nat_validate_simple_counter(c, i)
Definition: nat44_ed.c:2230
NAT_NEXT_IN2OUT_CLASSIFY
@ NAT_NEXT_IN2OUT_CLASSIFY
Definition: nat44_ed.h:83
ip4_add_del_interface_address_callback_t
Definition: ip4.h:73
nat_free_session_data
void nat_free_session_data(snat_main_t *sm, snat_session_t *s, u32 thread_index, u8 is_ha)
Free NAT44 session data (lookup keys, external address port)
Definition: nat44_ed.c:231
nat_get_icmp_session_lookup_values
static_always_inline int nat_get_icmp_session_lookup_values(vlib_buffer_t *b, ip4_header_t *ip0, ip4_address_t *lookup_saddr, u16 *lookup_sport, ip4_address_t *lookup_daddr, u16 *lookup_dport, u8 *lookup_protocol)
Definition: nat44_ed_inlines.h:183
nat44_ed_is_affinity_session
static bool nat44_ed_is_affinity_session(snat_session_t *s)
Check if NAT session has affinity record.
Definition: nat44_ed.h:778
snat_free_outside_address_and_port
void snat_free_outside_address_and_port(snat_address_t *addresses, u32 thread_index, ip4_address_t *addr, u16 port, nat_protocol_t protocol)
Free outside address and port pair.
Definition: nat44_ed.c:2560
nat44_ed_del_session
int nat44_ed_del_session(snat_main_t *sm, ip4_address_t *addr, u16 port, ip4_address_t *eh_addr, u16 eh_port, u8 proto, u32 vrf_id, int is_in)
Delete NAT44 endpoint-dependent session.
Definition: nat44_ed.c:3465
tcp_header_t
struct _tcp_header tcp_header_t
ip4_header_checksum_is_valid
static uword ip4_header_checksum_is_valid(ip4_header_t *i)
Definition: ip4_packet.h:396
ip_proto_to_nat_proto
static nat_protocol_t ip_proto_to_nat_proto(u8 ip_proto)
Common NAT inline functions.
Definition: inlines.h:24
snat_main_s::translation_buckets
u32 translation_buckets
Definition: nat44_ed.h:599
nat44_api_hookup
clib_error_t * nat44_api_hookup(vlib_main_t *vm)
Definition: nat44_ed_api.c:1685
nat_6t_t::dport
u16 dport
Definition: nat44_ed.h:216
NAT_FLOW_OP_TXFIB_REWRITE
#define NAT_FLOW_OP_TXFIB_REWRITE
Definition: nat44_ed.h:233
VLIB_NODE_TYPE_INTERNAL
@ VLIB_NODE_TYPE_INTERNAL
Definition: node.h:72
vlib_log_register_class
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:339
nat_6t_flow_t
Definition: nat44_ed.h:226
node
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
nat_protocol_t
nat_protocol_t
Definition: lib.h:63
lb_nat_type_t
lb_nat_type_t
Definition: nat44_ed.h:403
snat_main_per_thread_data_t::snat_thread_index
u32 snat_thread_index
Definition: nat44_ed.h:485
snat_main_s::interfaces
snat_interface_t * interfaces
Definition: nat44_ed.h:541
nat44_ed_add_del_addr_to_fib
static void nat44_ed_add_del_addr_to_fib(ip4_address_t *addr, u8 p_len, u32 sw_if_index, int is_add)
Definition: nat44_ed.c:305
clib_bihash_kv_8_8_t::value
u64 value
the value
Definition: bihash_8_8.h:44
snat_static_map_resolve_t::l_port
u16 l_port
Definition: nat44_ed.h:454
AFFINITY_LB_NAT
@ AFFINITY_LB_NAT
Definition: nat44_ed.h:410
reinit_ed_flow_hash
static void reinit_ed_flow_hash()
Definition: nat44_ed.c:3114
ip4_address_t::as_u32
u32 as_u32
Definition: ip4_packet.h:57
clib_bihash_kv_8_8_t::key
u64 key
the key
Definition: bihash_8_8.h:43
nat44_ed_get_out2in_worker_index
u32 nat44_ed_get_out2in_worker_index(vlib_buffer_t *b, ip4_header_t *ip, u32 rx_fib_index, u8 is_output)
Definition: nat44_ed.c:2882
snat_main_s::out2in_node_index
u32 out2in_node_index
Definition: nat44_ed.h:582
probability
u8 probability
Definition: nat44_ed.api:1052
FIB_NODE_INDEX_INVALID
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:30
fib_table.h
snat_main_s::log_class
vlib_log_class_t log_class
Definition: nat44_ed.h:655
nat_6t_flow_buf_translate_o2i
nat_translation_error_e nat_6t_flow_buf_translate_o2i(vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, nat_6t_flow_t *f, nat_protocol_t proto, int is_output_feature)
Definition: nat44_ed.c:3872
ip4_fib_table_get_index_for_sw_if_index
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
Definition: pnat_test_stubs.h:21
u16
unsigned short u16
Definition: types.h:57
per_vrf_sessions_unregister_session
static_always_inline void per_vrf_sessions_unregister_session(snat_session_t *s, u32 thread_index)
Definition: nat44_ed_inlines.h:530
nat_elog_err
#define nat_elog_err(_pm, nat_elog_str)
Definition: log.h:179
pool_put
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:305
snat_static_mapping_t::tag
u8 * tag
Definition: nat44_ed.h:435
NAT_FQ_NELTS_DEFAULT
#define NAT_FQ_NELTS_DEFAULT
Definition: nat44_ei.h:41
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
snat_static_map_resolve_t::pool_addr
ip4_address_t pool_addr
Definition: nat44_ed.h:453
nat44_ed_add_del_addr_to_fib_foreach_addr
static_always_inline void nat44_ed_add_del_addr_to_fib_foreach_addr(u32 sw_if_index, u8 is_add)
Definition: nat44_ed.c:360
is_sm_out2in_only
static bool is_sm_out2in_only(u32 f)
Definition: nat44_ed.h:840
snat_main_s::workers
u32 * workers
Definition: nat44_ed.h:518
port
u16 port
Definition: lb_types.api:73
fib_table_lookup
fib_node_index_t fib_table_lookup(u32 fib_index, const fib_prefix_t *prefix)
Perfom a longest prefix match in the non-forwarding table.
Definition: fib_table.c:68
NAT_NEXT_IN2OUT_ED_SLOW_PATH
@ NAT_NEXT_IN2OUT_ED_SLOW_PATH
Definition: nat44_ed.h:78
log.h
NAT port/address allocation lib.
nat44_ed_forwarding_enable_disable
void nat44_ed_forwarding_enable_disable(u8 is_enable)
Definition: nat44_ed.c:2524
snat_static_mapping_match
int snat_static_mapping_match(vlib_main_t *vm, snat_main_t *sm, 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, twice_nat_type_t *twice_nat, lb_nat_type_t *lb, ip4_address_t *ext_host_addr, u8 *is_identity_nat, snat_static_mapping_t **out)
Match NAT44 static mapping.
Definition: nat44_ed.c:2597
nat44_ed_add_del_addr_to_fib_foreach_out_if
static void nat44_ed_add_del_addr_to_fib_foreach_out_if(ip4_address_t *addr, u8 is_add)
Definition: nat44_ed.c:338
nat44_ed_add_lb_static_mapping
int nat44_ed_add_lb_static_mapping(ip4_address_t e_addr, u16 e_port, nat_protocol_t proto, nat44_lb_addr_port_t *locals, u32 flags, u8 *tag, u32 affinity)
Definition: nat44_ed.c:1136
hi
vl_api_ip4_address_t hi
Definition: arp.api:37
snat_static_mapping_t::proto
nat_protocol_t proto
Definition: nat44_ed.h:429
vnet_buffer2
#define vnet_buffer2(b)
Definition: buffer.h:505
snat_main_s::timeouts
nat_timeouts_t timeouts
Definition: nat44_ed.h:608
nat44_lb_addr_port_t::port
u16 port
Definition: nat44_ed.h:384
snat_static_mapping_t::local_addr
ip4_address_t local_addr
Definition: nat44_ed.h:418
snat_main_s::addresses
snat_address_t * addresses
Definition: nat44_ed.h:545
FIB_ENTRY_FLAG_EXCLUSIVE
@ FIB_ENTRY_FLAG_EXCLUSIVE
Definition: fib_entry.h:116
addr
vhost_vring_addr_t addr
Definition: vhost_user.h:130
get_thread_idx_by_port
u32 get_thread_idx_by_port(u16 e_port)
Definition: nat44_ed.c:540
r
vnet_hw_if_output_node_runtime_t * r
Definition: interface_output.c:1089
vlib_frame_t
Definition: node.h:372
icmp_type_is_error_message
static_always_inline u8 icmp_type_is_error_message(u8 icmp_type)
Definition: cnat_node.h:109
snat_main_s::static_mapping_by_external
clib_bihash_8_8_t static_mapping_by_external
Definition: nat44_ed.h:528
nat_outside_fib_t::fib_index
u32 fib_index
Definition: nat44_ed.h:375
nat44_ed_get_resolve_record
int nat44_ed_get_resolve_record(ip4_address_t l_addr, u16 l_port, u16 e_port, nat_protocol_t proto, u32 vrf_id, u32 sw_if_index, u32 flags, int *out)
Definition: nat44_ed.c:698
vlib_thread_registration_::count
u32 count
Definition: threads.h:38
ip4_sv_reass_enable_disable_with_refcnt
int ip4_sv_reass_enable_disable_with_refcnt(u32 sw_if_index, int is_enable)
Definition: pnat_test_stubs.h:43
VLIB_PLUGIN_REGISTER
VLIB_PLUGIN_REGISTER()
TWICE_NAT_DISABLED
@ TWICE_NAT_DISABLED
Definition: nat44_ed.h:396
nat44_ed_add_del_static_mapping_addr_only_cb
static void nat44_ed_add_del_static_mapping_addr_only_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_ed.c:3206
nat44_ed_add_interface
int nat44_ed_add_interface(u32 sw_if_index, u8 is_inside)
Definition: nat44_ed.c:1635
snat_static_mapping_t::flags
u32 flags
Definition: nat44_ed.h:441
udp_header_t
Definition: udp_packet.h:45
ip4_header_t
Definition: ip4_packet.h:87
error
Definition: cJSON.c:88
snat_main_s::log_level
u8 log_level
Definition: nat44_ed.h:657
snat_main_s::outside_fib_index
u32 outside_fib_index
Definition: nat44_ed.h:604
snat_main_s::forwarding_enabled
u8 forwarding_enabled
Definition: nat44_ed.h:590
nat_6t_t::fib_index
u32 fib_index
Definition: nat44_ed.h:217
key
typedef key
Definition: ipsec_types.api:91
nat44_ed_del_resolve_record
int nat44_ed_del_resolve_record(ip4_address_t l_addr, u16 l_port, u16 e_port, nat_protocol_t proto, u32 vrf_id, u32 sw_if_index, u32 flags)
Definition: nat44_ed.c:748
nat_ipfix_logging_init
void nat_ipfix_logging_init(vlib_main_t *vm)
Initialize NAT plugin IPFIX logging.
Definition: ipfix_logging.c:1609
nat44_ed_add_del_interface_address_cb
static void nat44_ed_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_ed.c:3289
random_u32
static u32 random_u32(u32 *seed)
32-bit random number generator
Definition: random.h:69
vlib_frame_queue_main_init
u32 vlib_frame_queue_main_init(u32 node_index, u32 frame_queue_nelts)
Definition: threads.c:1561
snat_main_per_thread_data_t::icmp_lru_head_index
u32 icmp_lru_head_index
Definition: nat44_ed.h:481
pool_is_free_index
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:302
snat_address_t
Definition: nat44_ed.h:355
nat44_ed_reserve_port
int nat44_ed_reserve_port(ip4_address_t addr, u16 port, nat_protocol_t proto)
Definition: nat44_ed.c:598
foreach_nat_protocol
@ foreach_nat_protocol
Definition: lib.h:66
nat_init
static clib_error_t * nat_init(vlib_main_t *vm)
Definition: nat44_ed.c:2261
snat_main_s::pat
u8 pat
Definition: nat44_ed.h:668
snat_static_map_resolve_t::flags
u32 flags
Definition: nat44_ed.h:459
vlib_thread_main_t::n_vlib_mains
u32 n_vlib_mains
Definition: threads.h:262
ti
u32 ti
Definition: interface_output.c:425
is_sm_twice_nat
static bool is_sm_twice_nat(u32 f)
Definition: nat44_ed.h:870
pool_foreach
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:534
NAT_NEXT_IN2OUT_ED_OUTPUT_SLOW_PATH
@ NAT_NEXT_IN2OUT_ED_OUTPUT_SLOW_PATH
Definition: nat44_ed.h:80
NAT_SM_FLAG_LB
#define NAT_SM_FLAG_LB
Definition: nat44_ed.h:195
vec_len
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Definition: vec_bootstrap.h:142
snat_main_s::per_thread_data
snat_main_per_thread_data_t * per_thread_data
Definition: nat44_ed.h:522
nat44_ed_add_del_addr_to_fib_foreach_addr_only_sm
static_always_inline void nat44_ed_add_del_addr_to_fib_foreach_addr_only_sm(u32 sw_if_index, u8 is_add)
Definition: nat44_ed.c:372
len
u8 len
Definition: ip_types.api:103
ip4_sv_reass.h
IPv4 shallow virtual reassembly.
NAT_ED_TRNSL_ERR_INVALID_CSUM
@ NAT_ED_TRNSL_ERR_INVALID_CSUM
Definition: nat44_ed.h:1056
VLIB_NODE_FN
#define VLIB_NODE_FN(node)
Definition: node.h:202
snat_main_s::rconfig
nat44_config_t rconfig
Definition: nat44_ed.h:586
nat44_ed_del_output_interface
int nat44_ed_del_output_interface(u32 sw_if_index)
Definition: nat44_ed.c:1946
vec_add2
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:644
vec_add1
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:606
NAT_NEXT_ICMP_ERROR
@ NAT_NEXT_ICMP_ERROR
Definition: nat44_ed.h:76
snat_main_s::flow_hash
clib_bihash_16_8_t flow_hash
Definition: nat44_ed.h:538
nat_value_get_session_index
static u32 nat_value_get_session_index(clib_bihash_kv_8_8_t *value)
Definition: nat44_ei_inlines.h:111
nat44_ed_del_interface_address
int nat44_ed_del_interface_address(u32 sw_if_index, u8 twice_nat)
Definition: nat44_ed.c:3401
vnet_buffer
#define vnet_buffer(b)
Definition: buffer.h:441
vec_dup
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:444
NAT_NEXT_IN2OUT_ED_FAST_PATH
@ NAT_NEXT_IN2OUT_ED_FAST_PATH
Definition: nat44_ed.h:77
nat_6t_l3_l4_csum_calc
void nat_6t_l3_l4_csum_calc(nat_6t_flow_t *f)
Definition: nat44_ed.c:3532
vec_elt_at_index
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Definition: vec_bootstrap.h:203
snat_main_s::first_worker_index
u32 first_worker_index
Definition: nat44_ed.h:517
vnet_get_main
vnet_main_t * vnet_get_main(void)
Definition: pnat_test_stubs.h:56
nat44_lb_addr_port_t::probability
u8 probability
Definition: nat44_ed.h:386
init_nat_kv
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)
Definition: nat44_ei_inlines.h:64
expire_per_vrf_sessions
void expire_per_vrf_sessions(u32 fib_index)
Definition: nat44_ed.c:1550
nat44_ed_is_lb_session
static bool nat44_ed_is_lb_session(snat_session_t *s)
Check if NAT session is load-balancing.
Definition: nat44_ed.h:758
snat_main_per_thread_data_t::per_vrf_sessions_vec
per_vrf_sessions_t * per_vrf_sessions_vec
Definition: nat44_ed.h:490
twice_nat_type_t
twice_nat_type_t
Definition: nat44_ed.h:393
ip_table.h
fib_table_find_or_create_and_lock
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:1170
ip_incremental_checksum
static ip_csum_t ip_incremental_checksum(ip_csum_t sum, void *_data, uword n_bytes)
Definition: ip_packet.h:319
NAT_FLOW_OP_DADDR_REWRITE
#define NAT_FLOW_OP_DADDR_REWRITE
Definition: nat44_ed.h:230
PREDICT_FALSE
#define PREDICT_FALSE(x)
Definition: clib.h:124
vlib_get_thread_index
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:187
NAT_NEXT_OUT2IN_ED_FAST_PATH
@ NAT_NEXT_OUT2IN_ED_FAST_PATH
Definition: nat44_ed.h:81
NAT_INTERFACE_FLAG_IS_OUTSIDE
#define NAT_INTERFACE_FLAG_IS_OUTSIDE
Definition: nat44_ed.h:186
snat_main_s::outside_fibs
nat_outside_fib_t * outside_fibs
Definition: nat44_ed.h:569
format_session_kvp
u8 * format_session_kvp(u8 *s, va_list *args)
Definition: nat44_ed.c:186
snat_static_mapping_t::affinity_per_service_list_head_index
u32 affinity_per_service_list_head_index
Definition: nat44_ed.h:439
end
f64 end
end of the time range
Definition: mactime.api:44
is_sm_addr_only
static bool is_sm_addr_only(u32 f)
Definition: nat44_ed.h:834
vlib_object_within_buffer_data
static int vlib_object_within_buffer_data(vlib_main_t *vm, vlib_buffer_t *b, void *obj, size_t len)
Definition: ip6_packet.h:555
c
svmdb_client_t * c
Definition: vpp_get_metrics.c:48
static_always_inline
#define static_always_inline
Definition: clib.h:112
fib_node_index_t
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:29
clib_bitmap_free
#define clib_bitmap_free(v)
Free a bitmap.
Definition: bitmap.h:92
NAT_FLOW_OP_ICMP_ID_REWRITE
#define NAT_FLOW_OP_ICMP_ID_REWRITE
Definition: nat44_ed.h:232
uword
u64 uword
Definition: types.h:112
format_ip_protocol
format_function_t format_ip_protocol
Definition: format.h:45
snat_main_per_thread_data_t::thread_index
u32 thread_index
Definition: nat44_ed.h:488
fail_if_enabled
#define fail_if_enabled()
Definition: nat44_ed.c:55
tcp_udp_header_t
Definition: nat44_ei.h:94
snat_main_s::fq_in2out_output_index
u32 fq_in2out_output_index
Definition: nat44_ed.h:579
snat_main_s::fq_out2in_index
u32 fq_out2in_index
Definition: nat44_ed.h:580
TWICE_NAT_SELF
@ TWICE_NAT_SELF
Definition: nat44_ed.h:400
vlib_thread_main_t::thread_registrations_by_name
uword * thread_registrations_by_name
Definition: threads.h:251
init_ed_k
static void init_ed_k(clib_bihash_kv_16_8_t *kv, ip4_address_t l_addr, u16 l_port, ip4_address_t r_addr, u16 r_port, u32 fib_index, u8 proto)
Definition: nat44_ed_inlines.h:122
vlib_thread_registration_::first_index
u32 first_index
Definition: threads.h:44
nat_6t_flow_icmp_translate
static_always_inline int nat_6t_flow_icmp_translate(vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, nat_6t_flow_t *f)
Definition: nat44_ed.c:3686
nat44_ed_is_session_static
static bool nat44_ed_is_session_static(snat_session_t *s)
Check if SNAT session is created from static mapping.
Definition: nat44_ed.h:728
vlibapi_get_main
static api_main_t * vlibapi_get_main(void)
Definition: api_common.h:390
ipfix_logging.h
snat_main_s::fq_in2out_index
u32 fq_in2out_index
Definition: nat44_ed.h:578
is_sw_if_index_reg_for_auto_resolve
static_always_inline int is_sw_if_index_reg_for_auto_resolve(u32 *sw_if_indices, u32 sw_if_index)
Definition: nat44_ed.c:3275
snat_static_mapping_t::workers
u32 * workers
Definition: nat44_ed.h:433
format_static_mapping_kvp
u8 * format_static_mapping_kvp(u8 *s, va_list *args)
Definition: nat44_ed.c:198
nat44_ed_update_outside_fib_cb
static void nat44_ed_update_outside_fib_cb(ip4_main_t *im, uword opaque, u32 sw_if_index, u32 new_fib_index, u32 old_fib_index)
Definition: nat44_ed.c:2067
icmp_echo_header_t::identifier
u16 identifier
Definition: nat44_ei.h:90
nat_6t_t
Definition: nat44_ed.h:210
pool_get
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:255
dlist_elt_t
Definition: dlist.h:28
ip4_sv_reass_output_enable_disable_with_refcnt
int ip4_sv_reass_output_enable_disable_with_refcnt(u32 sw_if_index, int is_enable)
Definition: pnat_test_stubs.h:46
nat44_set_session_limit
int nat44_set_session_limit(u32 session_limit, u32 vrf_id)
Set NAT44 session limit (session limit, vrf id)
Definition: nat44_ed.c:3046
vec_validate
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment)
Definition: vec.h:523
nat44_lb_addr_port_t
Definition: nat44_ed.h:379
address
manual_print typedef address
Definition: ip_types.api:96
snat_static_mapping_t::external_port
u16 external_port
Definition: nat44_ed.h:424
ip4_header_t::checksum
u16 checksum
Definition: ip4_packet.h:118
nat_affinity_create_and_lock
int nat_affinity_create_and_lock(ip4_address_t client_addr, ip4_address_t service_addr, u8 proto, u16 service_port, u8 backend_index, u32 sticky_time, u32 affinity_per_service_list_head_index)
Create affinity record and take reference counting lock.
Definition: nat44_ed_affinity.c:209
snat_main_s::fib_src_low
fib_source_t fib_src_low
Definition: nat44_ed.h:665
snat_static_map_resolve_t::addr_only
int addr_only
Definition: nat44_ed.h:460
test_key_calc_split
void test_key_calc_split()
Definition: nat44_ed.c:2147
snat_static_map_resolve_t::tag
u8 * tag
Definition: nat44_ed.h:465
ip4_address_t
Definition: ip4_packet.h:50
clib_bitmap_set
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
NAT_INTERFACE_FLAG_IS_INSIDE
#define NAT_INTERFACE_FLAG_IS_INSIDE
Definition: nat44_ed.h:185
FIB_PROTOCOL_IP4
@ FIB_PROTOCOL_IP4
Definition: fib_types.h:36
fib_entry_get_resolving_interface
u32 fib_entry_get_resolving_interface(fib_node_index_t entry_index)
Definition: fib_entry.c:1474
nat44_ed_add_del_lb_static_mapping_local
int nat44_ed_add_del_lb_static_mapping_local(ip4_address_t e_addr, u16 e_port, ip4_address_t l_addr, u16 l_port, nat_protocol_t proto, u32 vrf_id, u8 probability, u8 is_add)
Definition: nat44_ed.c:1399
snat_main_s
Definition: nat44_ed.h:513
snat_main_per_thread_data_t::sessions
snat_session_t * sessions
Definition: nat44_ed.h:471
nat_6t_flow_buf_translate
static_always_inline nat_translation_error_e nat_6t_flow_buf_translate(vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, nat_6t_flow_t *f, nat_protocol_t proto, int is_output_feature, int is_i2o)
Definition: nat44_ed.c:3826
NAT_ED_TRNSL_ERR_FLOW_MISMATCH
@ NAT_ED_TRNSL_ERR_FLOW_MISMATCH
Definition: nat44_ed.h:1053
FIB_ENTRY_FLAG_LOCAL
@ FIB_ENTRY_FLAG_LOCAL
Definition: fib_entry.h:117
nat44_plugin_enable
int nat44_plugin_enable(nat44_config_t c)
Definition: nat44_ed.c:2364
nat44_ed_add_address
int nat44_ed_add_address(ip4_address_t *addr, u32 vrf_id, u8 twice_nat)
Definition: nat44_ed.c:388
vlib_node_registration_t
struct _vlib_node_registration vlib_node_registration_t
nat44_ed_set_frame_queue_nelts
int nat44_ed_set_frame_queue_nelts(u32 frame_queue_nelts)
Definition: nat44_ed.c:2058
fib_source_allocate
fib_source_t fib_source_allocate(const char *name, fib_source_priority_t prio, fib_source_behaviour_t bh)
Definition: fib_source.c:118
ip4_table_bind_callback_t
Definition: ip4.h:92
vlib_buffer_t::current_length
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:122
stat_segment.h
nat_ed_session_delete
static void nat_ed_session_delete(snat_main_t *sm, snat_session_t *ses, u32 thread_index, int lru_delete)
Definition: nat44_ed_inlines.h:358
update_per_vrf_sessions_vec
void update_per_vrf_sessions_vec(u32 fib_index, int is_del)
Definition: nat44_ed.c:1570
NAT_N_NEXT
@ NAT_N_NEXT
Definition: nat44_ed.h:85
nat44_ed_get_interface
static_always_inline snat_interface_t * nat44_ed_get_interface(snat_interface_t *interfaces, u32 sw_if_index)
Definition: nat44_ed.c:1621
plugin.h
udp_header_t::checksum
u16 checksum
Definition: udp_packet.h:55
nat44_lb_addr_port_t::fib_index
u32 fib_index
Definition: nat44_ed.h:390
FIB_SOURCE_PRIORITY_HI
#define FIB_SOURCE_PRIORITY_HI
Some priority values that plugins might use when they are not to concerned where in the list they'll ...
Definition: fib_source.h:284
snat_main_s::fibs
nat_fib_t * fibs
Definition: nat44_ed.h:566
nat_elog_notice_X1
#define nat_elog_notice_X1(_pm, nat_elog_fmt_str, nat_elog_fmt_arg, nat_elog_val1)
Definition: log.h:186
nat44_ed_is_twice_nat_session
static bool nat44_ed_is_twice_nat_session(snat_session_t *s)
Check if NAT session is twice NAT.
Definition: nat44_ed.h:748
ip4_main_t::add_del_interface_address_callbacks
ip4_add_del_interface_address_callback_t * add_del_interface_address_callbacks
Functions to call when interface address changes.
Definition: ip4.h:138
ip4_address_t::as_u8
u8 as_u8[4]
Definition: ip4_packet.h:55
nat44_lb_addr_port_t::prefix
u8 prefix
Definition: nat44_ed.h:387
nat44_ed_del_lb_static_mapping
int nat44_ed_del_lb_static_mapping(ip4_address_t e_addr, u16 e_port, nat_protocol_t proto, u32 flags)
Definition: nat44_ed.c:1279
hash_get_mem
#define hash_get_mem(h, key)
Definition: hash.h:269
is_snat_address_used_in_static_mapping
static int is_snat_address_used_in_static_mapping(snat_main_t *sm, ip4_address_t addr)
Definition: nat44_ed.c:286
ip_csum_sub_even
static ip_csum_t ip_csum_sub_even(ip_csum_t c, ip_csum_t x)
Definition: ip_packet.h:273
ip4_add_del_interface_address_callback_t::function
ip4_add_del_interface_address_function_t * function
Definition: ip4.h:75
snat_main_per_thread_data_t::tcp_trans_lru_head_index
u32 tcp_trans_lru_head_index
Definition: nat44_ed.h:478
nat44_set_node_indexes
void nat44_set_node_indexes(snat_main_t *sm, vlib_main_t *vm)
Definition: nat44_ed.c:2216
vnet_main_t
Definition: vnet.h:76
vec_free
#define vec_free(V)
Free vector's memory (no header).
Definition: vec.h:395
nat44_ed_affinity.h
NAT plugin client-IP based session affinity for load-balancing.
size
u32 size
Definition: vhost_user.h:125
vlib_get_node_by_name
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
snat_main_s::frame_queue_nelts
u32 frame_queue_nelts
Definition: nat44_ed.h:671
fail_if_disabled
#define fail_if_disabled()
Definition: nat44_ed.c:67
nat44_ed_add_resolve_record
void nat44_ed_add_resolve_record(ip4_address_t l_addr, u16 l_port, u16 e_port, nat_protocol_t proto, u32 vrf_id, u32 sw_if_index, u32 flags, ip4_address_t pool_addr, u8 *tag)
Definition: nat44_ed.c:678
icmp
icmp
Definition: map.api:387
NAT_FLOW_OP_DPORT_REWRITE
#define NAT_FLOW_OP_DPORT_REWRITE
Definition: nat44_ed.h:231
nat_affinity_init
clib_error_t * nat_affinity_init(vlib_main_t *vm)
Initialize NAT client-IP based affinity.
Definition: nat44_ed_affinity.c:74
nat44_ed_inlines.h
mss_clamping
static void mss_clamping(u16 mss_clamping, tcp_header_t *tcp, ip_csum_t *sum)
Definition: nat_inlines.h:32
snat_main_s::max_translations_per_fib
u32 * max_translations_per_fib
Definition: nat44_ed.h:601
NAT_NEXT_IN2OUT_ED_OUTPUT_FAST_PATH
@ NAT_NEXT_IN2OUT_ED_OUTPUT_FAST_PATH
Definition: nat44_ed.h:79
pool_foreach_index
#define pool_foreach_index(i, v)
Definition: pool.h:572
clib_bihash_kv_16_8_t
Definition: bihash_16_8.h:40
FIB_ENTRY_FLAG_CONNECTED
@ FIB_ENTRY_FLAG_CONNECTED
Definition: fib_entry.h:113
nat44_ed_free_port
int nat44_ed_free_port(ip4_address_t addr, u16 port, nat_protocol_t proto)
Definition: nat44_ed.c:639
nat44_config_t
Definition: nat44_ed.h:59
nat44_lb_addr_port_t::vrf_id
u32 vrf_id
Definition: nat44_ed.h:389
u64
unsigned long u64
Definition: types.h:89
nat_elog_info
#define nat_elog_info(_pm, nat_elog_str)
Definition: log.h:183
format
description fragment has unexpected format
Definition: map.api:433
ASSERT
#define ASSERT(truth)
Definition: error_bootstrap.h:69
vlib_zero_simple_counter
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
TWICE_NAT
@ TWICE_NAT
Definition: nat44_ed.h:398
nat44_ed_db_free
static void nat44_ed_db_free()
Definition: nat44_ed.c:3165
nat_reset_timeouts
static_always_inline void nat_reset_timeouts(nat_timeouts_t *timeouts)
Definition: lib.h:90
is_sm_self_twice_nat
static bool is_sm_self_twice_nat(u32 f)
Definition: nat44_ed.h:864
calc_nat_key
static u64 calc_nat_key(ip4_address_t addr, u16 port, u32 fib_index, u8 proto)
Definition: nat44_ei_inlines.h:25
nat44_ed_is_interface_inside
static bool nat44_ed_is_interface_inside(snat_interface_t *i)
Check if NAT interface is inside.
Definition: nat44_ed.h:798
fib_table_get_index_for_sw_if_index
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:1003
FIB_ROUTE_PATH_FLAG_NONE
@ FIB_ROUTE_PATH_FLAG_NONE
Definition: fib_types.h:332
fib_table_lock
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:1361
ip.h
is_sm_identity_nat
static bool is_sm_identity_nat(u32 f)
Definition: nat44_ed.h:846
u32
unsigned int u32
Definition: types.h:88
snat_static_mapping_t::fib_index
u32 fib_index
Definition: nat44_ed.h:427
VLIB_INIT_FUNCTION
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:172
nat44_get_max_session_limit
u32 nat44_get_max_session_limit()
Definition: nat44_ed.c:3032
udp_header_t::dst_port
u16 dst_port
Definition: udp_packet.h:48
STAT_DIR_TYPE_SCALAR_INDEX
@ STAT_DIR_TYPE_SCALAR_INDEX
Definition: stat_segment_shared.h:22
snat_static_mapping_t::pool_addr
ip4_address_t pool_addr
Definition: nat44_ed.h:416
vlib_thread_main_t
Definition: threads.h:243
protocol
vl_api_ip_proto_t protocol
Definition: lb_types.api:72
nat_fib_t
Definition: nat44_ed.h:367
snat_main_s::max_cfg_sessions_gauge
u32 max_cfg_sessions_gauge
Definition: nat44_ed.h:615
NAT_ED_TRNSL_ERR_PACKET_TRUNCATED
@ NAT_ED_TRNSL_ERR_PACKET_TRUNCATED
Definition: nat44_ed.h:1054
table_id
u32 table_id
Definition: wireguard.api:102
NAT_LOG_ERROR
@ NAT_LOG_ERROR
Definition: nat_types.api:29
snat_main_s::auto_add_sw_if_indices
u32 * auto_add_sw_if_indices
Definition: nat44_ed.h:550
init_ed_kv
static void init_ed_kv(clib_bihash_kv_16_8_t *kv, ip4_address_t l_addr, u16 l_port, ip4_address_t r_addr, u16 r_port, u32 fib_index, u8 proto, u32 thread_index, u32 session_index)
Definition: nat44_ed_inlines.h:131
nat_6t_t::daddr
ip4_address_t daddr
Definition: nat44_ed.h:214
snat_main_s::mss_clamping
u16 mss_clamping
Definition: nat44_ed.h:611
nat_6t_flow_buf_translate_i2o
nat_translation_error_e nat_6t_flow_buf_translate_i2o(vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, nat_6t_flow_t *f, nat_protocol_t proto, int is_output_feature)
Definition: nat44_ed.c:3862
NAT_FLOW_OP_SADDR_REWRITE
#define NAT_FLOW_OP_SADDR_REWRITE
Definition: nat44_ed.h:228
vec_foreach
#define vec_foreach(var, vec)
Vector iterator.
Definition: vec_bootstrap.h:213
snat_main_s::static_mapping_by_local
clib_bihash_8_8_t static_mapping_by_local
Definition: nat44_ed.h:525
nat44_ed.h
format_nat_6t
u8 * format_nat_6t(u8 *s, va_list *args)
Definition: nat44_ed.c:3882
clib_bihash_kv_8_8_t
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:41
nat44_ed_worker_db_init
static void nat44_ed_worker_db_init(snat_main_per_thread_data_t *tsm, u32 translations, u32 translation_buckets)
Definition: nat44_ed.c:3084
snat_main_s::max_translations_per_thread
u32 max_translations_per_thread
Definition: nat44_ed.h:600
VNET_IP_TABLE_ADD_DEL_FUNCTION
VNET_IP_TABLE_ADD_DEL_FUNCTION(nat_ip_table_add_del)
nat44_ed_db_init
static void nat44_ed_db_init(u32 translations, u32 translation_buckets)
Definition: nat44_ed.c:3125
snat_static_map_resolve_t::vrf_id
u32 vrf_id
Definition: nat44_ed.h:457
pool_elts
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:127
ip4_table_bind_callback_t::function
ip4_table_bind_function_t * function
Definition: ip4.h:94
nat44_ed_get_in2out_worker_index
u32 nat44_ed_get_in2out_worker_index(vlib_buffer_t *b, ip4_header_t *ip, u32 rx_fib_index, u8 is_output)
Definition: nat44_ed.c:2757
NAT_NEXT_DROP
@ NAT_NEXT_DROP
Definition: nat44_ed.h:75
snat_main_s::inside_vrf_id
u32 inside_vrf_id
Definition: nat44_ed.h:605
foreach_nat_counter
#define foreach_nat_counter
Definition: lib.h:42
value
u8 value
Definition: qos.api:54
bihash_16_8.h
fib_prefix_t_::fp_proto
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:211
NAT_NEXT_OUT2IN_ED_SLOW_PATH
@ NAT_NEXT_OUT2IN_ED_SLOW_PATH
Definition: nat44_ed.h:82
vnet_feature_enable_disable
int vnet_feature_enable_disable(const char *arc_name, const char *node_name, u32 sw_if_index, int enable_disable, void *feature_config, u32 n_feature_config_bytes)
Definition: pnat_test_stubs.h:50
nat_default_node
vlib_node_registration_t nat_default_node
(constructor) VLIB_REGISTER_NODE (nat_default_node)
Definition: nat44_ed.c:3510
ip4_fib.h
nat_ed_ses_i2o_flow_hash_add_del
static_always_inline int nat_ed_ses_i2o_flow_hash_add_del(snat_main_t *sm, u32 thread_idx, snat_session_t *s, int is_add)
Definition: nat44_ed_inlines.h:317
VNET_FEATURE_INIT
VNET_FEATURE_INIT(nat_pre_in2out, static)
icmp_echo_header_t
Definition: nat44_ei.h:88
ip4.h
format_ed_session_kvp
u8 * format_ed_session_kvp(u8 *s, va_list *args)
Definition: nat44_ed.c:209
snat_main_s::inside_fib_index
u32 inside_fib_index
Definition: nat44_ed.h:606
clib_bitmap_last_set
static uword clib_bitmap_last_set(uword *ai)
Return the higest numbered set bit in a bitmap.
Definition: bitmap.h:410
ip4_fib_index_from_table_id
static u32 ip4_fib_index_from_table_id(u32 table_id)
Definition: ip4_fib.h:121
clib_memset
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
vlib_main_t
Definition: main.h:102
snat_static_map_resolve_t::proto
nat_protocol_t proto
Definition: nat44_ed.h:458
snat_main
snat_main_t snat_main
Definition: nat44_ed.c:41
NAT_ED_TRNSL_ERR_INNER_IP_CORRUPT
@ NAT_ED_TRNSL_ERR_INNER_IP_CORRUPT
Definition: nat44_ed.h:1055
snat_static_map_resolve_t::sw_if_index
u32 sw_if_index
Definition: nat44_ed.h:456
ip_csum_update
#define ip_csum_update(sum, old, new, type, field)
Definition: ip_packet.h:295
nat44_ed_validate_sm_input
static_always_inline int nat44_ed_validate_sm_input(u32 flags)
Definition: nat44_ed.c:764
vlib_node_t
Definition: node.h:247
nat44_addresses_free
void nat44_addresses_free(snat_address_t **addresses)
Definition: nat44_ed.c:2442
NAT_NEXT_OUT2IN_CLASSIFY
@ NAT_NEXT_OUT2IN_CLASSIFY
Definition: nat44_ed.h:84
b
vlib_buffer_t ** b
Definition: nat44_ei_out2in.c:717
VNET_FEATURES
#define VNET_FEATURES(...)
Definition: feature.h:470
u8
unsigned char u8
Definition: types.h:56
clib_error_t
Definition: clib_error.h:21
a
a
Definition: bitmap.h:525
nat_6t_flow_ip4_translate
static_always_inline void nat_6t_flow_ip4_translate(snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, nat_6t_flow_t *f, nat_protocol_t proto, int is_icmp_inner_ip4, int skip_saddr_rewrite)
Definition: nat44_ed.c:3603
vlib_buffer_get_current
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:257
ip
vl_api_address_t ip
Definition: l2.api:558
ip4_header_checksum
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:314
snat_main_s::num_workers
u32 num_workers
Definition: nat44_ed.h:516
pool_dup
#define pool_dup(P)
Return copy of pool without alignment.
Definition: pool.h:405
snat_main_s::hairpinning
vlib_simple_counter_main_t hairpinning
Definition: nat44_ed.h:647
vlib_init_function_t
clib_error_t *() vlib_init_function_t(struct vlib_main_t *vm)
Definition: init.h:51
ip_csum_t
uword ip_csum_t
Definition: ip_packet.h:245
NO_LB_NAT
@ NO_LB_NAT
Definition: nat44_ed.h:406
split_nat_key
static void split_nat_key(u64 key, ip4_address_t *addr, u16 *port, u32 *fib_index, nat_protocol_t *proto)
Definition: nat44_ei_inlines.h:34
snat_interface_t
Definition: nat44_ed.h:444
fib_table_unlock
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:1342
FIB_SOURCE_BH_SIMPLE
@ FIB_SOURCE_BH_SIMPLE
add paths without path extensions
Definition: fib_source.h:210
snat_address_t::fib_index
u32 fib_index
Definition: nat44_ed.h:358
i
int i
Definition: flowhash_template.h:376
DPO_PROTO_IP4
@ DPO_PROTO_IP4
Definition: dpo.h:64
pool_free
#define pool_free(p)
Free a pool.
Definition: pool.h:447
snat_static_mapping_t::external_addr
ip4_address_t external_addr
Definition: nat44_ed.h:420
FIB_SOURCE_PRIORITY_LOW
#define FIB_SOURCE_PRIORITY_LOW
Definition: fib_source.h:285
NAT_FLOW_OP_SPORT_REWRITE
#define NAT_FLOW_OP_SPORT_REWRITE
Definition: nat44_ed.h:229
clib_warning
#define clib_warning(format, args...)
Definition: error.h:59
pool_alloc
#define pool_alloc(P, N)
Allocate N more free elements to pool (unspecified alignment).
Definition: pool.h:367
nat_init_simple_counter
#define nat_init_simple_counter(c, n, sn)
Definition: nat44_ed.c:2238
nat_affinity_flush_service
void nat_affinity_flush_service(u32 affinity_per_service_list_head_index)
Flush all service affinity data.
Definition: nat44_ed_affinity.c:112
nat44_plugin_disable
int nat44_plugin_disable()
Definition: nat44_ed.c:2457
nat_syslog_nat44_sdel
void nat_syslog_nat44_sdel(u32 ssubix, u32 sfibix, ip4_address_t *isaddr, u16 isport, ip4_address_t *idaddr, u16 idport, ip4_address_t *xsaddr, u16 xsport, ip4_address_t *xdaddr, u16 xdport, nat_protocol_t proto, u8 is_twicenat)
Definition: nat_syslog.c:209
ip4_header_bytes
static int ip4_header_bytes(const ip4_header_t *i)
Definition: ip4_packet.h:190
nat_calc_bihash_buckets
u32 nat_calc_bihash_buckets(u32 n_elts)
Definition: lib.h:122
it_fits
static_always_inline int it_fits(vlib_main_t *vm, vlib_buffer_t *b, void *object, size_t size)
Definition: nat44_ed.c:3677
snat_static_mapping_t
Definition: nat44_ed.h:413
rv
int __clib_unused rv
Definition: application.c:491
nat_ed_static_mapping_del_sessions
void nat_ed_static_mapping_del_sessions(snat_main_t *sm, snat_main_per_thread_data_t *tsm, ip4_address_t l_addr, u16 l_port, u8 protocol, u32 fib_index, int addr_only, ip4_address_t e_addr, u16 e_port)
Definition: nat44_ed.c:554
vrf_id
u32 vrf_id
Definition: nat44_ed.api:1053
nat_6t_t::saddr
ip4_address_t saddr
Definition: nat44_ed.h:214
nat_ipfix_logging_nat44_ses_delete
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.
Definition: ipfix_logging.c:1346
snat_static_map_resolve_t
Definition: nat44_ed.h:450
is_sm_exact_address
static bool is_sm_exact_address(u32 f)
Definition: nat44_ed.h:858
snat_address_t::addr
ip4_address_t addr
Definition: nat44_ed.h:357
ip4_interface_first_address
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:282
vnet.h
snat_main_per_thread_data_t
Definition: nat44_ed.h:468
nat_translation_error_e
nat_translation_error_e
Definition: nat44_ed.h:1049
clib_bitmap_foreach
#define clib_bitmap_foreach(i, ai)
Macro to iterate across set bits in a bitmap.
Definition: bitmap.h:361
vlib_node_runtime_t
Definition: node.h:454
vlib_thread_registration_
Definition: threads.h:27
nat_6t_t::sport
u16 sport
Definition: nat44_ed.h:215
proto
vl_api_ip_proto_t proto
Definition: acl_types.api:51
nat_validate_interface_counters
static_always_inline void nat_validate_interface_counters(snat_main_t *sm, u32 sw_if_index)
Definition: nat44_ed.c:2248
PREDICT_TRUE
#define PREDICT_TRUE(x)
Definition: clib.h:125
vlib_get_thread_main
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:56
is_pow2
static uword is_pow2(uword x)
Definition: clib.h:267
ip4_main_t
IPv4 main type.
Definition: ip4.h:107
fib_table_find
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:1111
stat_segment_set_state_counter
void stat_segment_set_state_counter(u32 index, u64 value)
Definition: stat_segment.c:962
thread_idx
#define thread_idx
Definition: tls_async.c:40
ip_csum_add_even
static ip_csum_t ip_csum_add_even(ip_csum_t c, ip_csum_t x)
Definition: ip_packet.h:256
snat_static_mapping_t::local_port
u16 local_port
Definition: nat44_ed.h:422
snat_static_mapping_t::affinity
u32 affinity
Definition: nat44_ed.h:431
snat_main_per_thread_data_t::tcp_estab_lru_head_index
u32 tcp_estab_lru_head_index
Definition: nat44_ed.h:479
snat_main_s::static_mapping_only
u8 static_mapping_only
Definition: nat44_ed.h:593
sw_if_index
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
snat_static_map_resolve_t::e_port
u16 e_port
Definition: nat44_ed.h:455
stat_segment_new_entry
u32 stat_segment_new_entry(u8 *name, stat_directory_type_t t)
Definition: stat_segment.c:393
sw_if_indices
u32 sw_if_indices[VLIB_FRAME_SIZE]
Definition: interface_output.c:1093
ip_csum_fold
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:301
nat44_ed_del_interface
int nat44_ed_del_interface(u32 sw_if_index, u8 is_inside)
Definition: nat44_ed.c:1743
NAT_ED_TRNSL_ERR_SUCCESS
@ NAT_ED_TRNSL_ERR_SUCCESS
Definition: nat44_ed.h:1051
VLIB_TX
@ VLIB_TX
Definition: defs.h:47
format_nat_ed_translation_error
u8 * format_nat_ed_translation_error(u8 *s, va_list *args)
Definition: nat44_ed.c:3895
init_nat_k
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)
Definition: nat44_ei_inlines.h:56
NAT_ED_TRNSL_ERR_TRANSLATION_FAILED
@ NAT_ED_TRNSL_ERR_TRANSLATION_FAILED
Definition: nat44_ed.h:1052
nat44_ed_add_interface_address
int nat44_ed_add_interface_address(u32 sw_if_index, u8 twice_nat)
Definition: nat44_ed.c:3362
snat_static_map_resolve_t::l_addr
ip4_address_t l_addr
Definition: nat44_ed.h:452
nat_fib_t::ref_count
u32 ref_count
Definition: nat44_ed.h:370
snat_main_s::static_mapping_connection_tracking
u8 static_mapping_connection_tracking
Definition: nat44_ed.h:594
snat_main_s::in2out_node_index
u32 in2out_node_index
Definition: nat44_ed.h:583
fib_prefix_t_
Aggregate type for a prefix.
Definition: fib_types.h:202
lo
lo
Definition: vector_altivec.h:87
type
vl_api_fib_path_type_t type
Definition: fib_types.api:123
nat44_ed_del_address
int nat44_ed_del_address(ip4_address_t addr, u8 delete_sm, u8 twice_nat)
Definition: nat44_ed.c:449
snat_main_s::auto_add_sw_if_indices_twice_nat
u32 * auto_add_sw_if_indices_twice_nat
Definition: nat44_ed.h:551
nat_affinity_unlock
void nat_affinity_unlock(ip4_address_t client_addr, ip4_address_t service_addr, u8 proto, u16 service_port)
Release a reference counting lock for affinity.
Definition: nat44_ed_affinity.c:261
ip4_header_t::protocol
u8 protocol
Definition: ip4_packet.h:115
nat_syslog.h
NAT syslog logging.
snat_main_s::api_main
api_main_t * api_main
Definition: nat44_ed.h:660
vec_del1
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:896
nat_ed_ses_o2i_flow_hash_add_del
static_always_inline int nat_ed_ses_o2i_flow_hash_add_del(snat_main_t *sm, u32 thread_idx, snat_session_t *s, int is_add)
Definition: nat44_ed_inlines.h:338
snat_main_s::enabled
u8 enabled
Definition: nat44_ed.h:674
snat_main_s::random_seed
u32 random_seed
Definition: nat44_ed.h:575
ip4_next_header
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:196
prefix
vl_api_prefix_t prefix
Definition: ip.api:175
na44_ed_is_fwd_bypass_session
static bool na44_ed_is_fwd_bypass_session(snat_session_t *s)
Check if NAT session is forwarding bypass.
Definition: nat44_ed.h:768
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111
nat_affinity_enable
void nat_affinity_enable()
NAT affinity enable.
Definition: nat44_ed_affinity.c:49
snat_main_s::output_feature_interfaces
snat_interface_t * output_feature_interfaces
Definition: nat44_ed.h:542
VLIB_REGISTER_NODE
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
nat_affinity_find_and_lock
int nat_affinity_find_and_lock(vlib_main_t *vm, ip4_address_t client_addr, ip4_address_t service_addr, u8 proto, u16 service_port, u8 *backend_index)
Find service backend index for client-IP and take a reference counting lock.
Definition: nat44_ed_affinity.c:143
flags
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105