FD.io VPP  v17.10-9-gd594711
Vector Packet Processing
nat.c
Go to the documentation of this file.
1 /*
2  * snat.c - simple nat plugin
3  *
4  * Copyright (c) 2016 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <vnet/vnet.h>
19 #include <vnet/ip/ip.h>
20 #include <vnet/ip/ip4.h>
21 #include <vnet/plugin/plugin.h>
22 #include <nat/nat.h>
23 #include <nat/nat_ipfix_logging.h>
24 #include <nat/nat_det.h>
25 #include <nat/nat64.h>
26 #include <vnet/fib/fib_table.h>
27 #include <vnet/fib/ip4_fib.h>
28 
29 #include <vpp/app/version.h>
30 
32 
33 
34 /* Hook up input features */
35 VNET_FEATURE_INIT (ip4_snat_in2out, static) = {
36  .arc_name = "ip4-unicast",
37  .node_name = "nat44-in2out",
38  .runs_before = VNET_FEATURES ("nat44-out2in"),
39 };
40 VNET_FEATURE_INIT (ip4_snat_out2in, static) = {
41  .arc_name = "ip4-unicast",
42  .node_name = "nat44-out2in",
43  .runs_before = VNET_FEATURES ("ip4-lookup"),
44 };
45 VNET_FEATURE_INIT (ip4_snat_det_in2out, static) = {
46  .arc_name = "ip4-unicast",
47  .node_name = "nat44-det-in2out",
48  .runs_before = VNET_FEATURES ("nat44-det-out2in"),
49 };
50 VNET_FEATURE_INIT (ip4_snat_det_out2in, static) = {
51  .arc_name = "ip4-unicast",
52  .node_name = "nat44-det-out2in",
53  .runs_before = VNET_FEATURES ("ip4-lookup"),
54 };
55 VNET_FEATURE_INIT (ip4_snat_in2out_worker_handoff, static) = {
56  .arc_name = "ip4-unicast",
57  .node_name = "nat44-in2out-worker-handoff",
58  .runs_before = VNET_FEATURES ("nat44-out2in-worker-handoff"),
59 };
60 VNET_FEATURE_INIT (ip4_snat_out2in_worker_handoff, static) = {
61  .arc_name = "ip4-unicast",
62  .node_name = "nat44-out2in-worker-handoff",
63  .runs_before = VNET_FEATURES ("ip4-lookup"),
64 };
65 VNET_FEATURE_INIT (ip4_snat_in2out_fast, static) = {
66  .arc_name = "ip4-unicast",
67  .node_name = "nat44-in2out-fast",
68  .runs_before = VNET_FEATURES ("nat44-out2in-fast"),
69 };
70 VNET_FEATURE_INIT (ip4_snat_out2in_fast, static) = {
71  .arc_name = "ip4-unicast",
72  .node_name = "nat44-out2in-fast",
73  .runs_before = VNET_FEATURES ("ip4-lookup"),
74 };
75 VNET_FEATURE_INIT (ip4_snat_hairpin_dst, static) = {
76  .arc_name = "ip4-unicast",
77  .node_name = "nat44-hairpin-dst",
78  .runs_before = VNET_FEATURES ("ip4-lookup"),
79 };
80 
81 /* Hook up output features */
82 VNET_FEATURE_INIT (ip4_snat_in2out_output, static) = {
83  .arc_name = "ip4-output",
84  .node_name = "nat44-in2out-output",
85  .runs_before = VNET_FEATURES ("interface-output"),
86 };
87 VNET_FEATURE_INIT (ip4_snat_in2out_output_worker_handoff, static) = {
88  .arc_name = "ip4-output",
89  .node_name = "nat44-in2out-output-worker-handoff",
90  .runs_before = VNET_FEATURES ("interface-output"),
91 };
92 VNET_FEATURE_INIT (ip4_snat_hairpin_src, static) = {
93  .arc_name = "ip4-output",
94  .node_name = "nat44-hairpin-src",
95  .runs_before = VNET_FEATURES ("interface-output"),
96 };
97 
98 
99 /* *INDENT-OFF* */
101  .version = VPP_BUILD_VER,
102  .description = "Network Address Translation",
103 };
104 /* *INDENT-ON* */
105 
106 /**
107  * @brief Add/del NAT address to FIB.
108  *
109  * Add the external NAT address to the FIB as receive entries. This ensures
110  * that VPP will reply to ARP for this address and we don't need to enable
111  * proxy ARP on the outside interface.
112  *
113  * @param addr IPv4 address.
114  * @param plen address prefix length
115  * @param sw_if_index Interface.
116  * @param is_add If 0 delete, otherwise add.
117  */
118 void
120  int is_add)
121 {
122  fib_prefix_t prefix = {
123  .fp_len = p_len,
124  .fp_proto = FIB_PROTOCOL_IP4,
125  .fp_addr = {
126  .ip4.as_u32 = addr->as_u32,
127  },
128  };
129  u32 fib_index = ip4_fib_table_get_index_for_sw_if_index(sw_if_index);
130 
131  if (is_add)
133  &prefix,
139  NULL,
140  sw_if_index,
141  ~0,
142  1,
143  NULL,
145  else
146  fib_table_entry_delete(fib_index,
147  &prefix,
149 }
150 
152 {
153  snat_address_t * ap;
156 
157  if (vrf_id != ~0)
158  sm->vrf_mode = 1;
159 
160  /* Check if address already exists */
161  vec_foreach (ap, sm->addresses)
162  {
163  if (ap->addr.as_u32 == addr->as_u32)
164  return;
165  }
166 
167  vec_add2 (sm->addresses, ap, 1);
168  ap->addr = *addr;
169  if (vrf_id != ~0)
170  ap->fib_index =
173  else
174  ap->fib_index = ~0;
175 #define _(N, i, n, s) \
176  clib_bitmap_alloc (ap->busy_##n##_port_bitmap, 65535); \
177  ap->busy_##n##_ports = 0; \
178  vec_validate_init_empty (ap->busy_##n##_ports_per_thread, tm->n_vlib_mains - 1, 0);
180 #undef _
181 
182  /* Add external address to FIB */
183  pool_foreach (i, sm->interfaces,
184  ({
185  if (i->is_inside)
186  continue;
187 
188  snat_add_del_addr_to_fib(addr, 32, i->sw_if_index, 1);
189  break;
190  }));
192  ({
193  if (i->is_inside)
194  continue;
195 
196  snat_add_del_addr_to_fib(addr, 32, i->sw_if_index, 1);
197  break;
198  }));
199 }
200 
203 {
206  ({
207  if (m->external_addr.as_u32 == addr.as_u32)
208  return 1;
209  }));
210 
211  return 0;
212 }
213 
215 {
216  u32 v;
217 
218  v = clib_net_to_host_u32(a->as_u32) + 1;
219  a->as_u32 = clib_host_to_net_u32(v);
220 }
221 
222 static void
224  ip4_address_t l_addr,
225  u16 l_port,
226  u32 sw_if_index,
227  u16 e_port,
228  u32 vrf_id,
229  snat_protocol_t proto,
230  int addr_only,
231  int is_add)
232 {
234 
235  vec_add2 (sm->to_resolve, rp, 1);
236  rp->l_addr.as_u32 = l_addr.as_u32;
237  rp->l_port = l_port;
238  rp->sw_if_index = sw_if_index;
239  rp->e_port = e_port;
240  rp->vrf_id = vrf_id;
241  rp->proto = proto;
242  rp->addr_only = addr_only;
243  rp->is_add = is_add;
244 }
245 
246 /**
247  * @brief Add static mapping.
248  *
249  * Create static mapping between local addr+port and external addr+port.
250  *
251  * @param l_addr Local IPv4 address.
252  * @param e_addr External IPv4 address.
253  * @param l_port Local port number.
254  * @param e_port External port number.
255  * @param vrf_id VRF ID.
256  * @param addr_only If 0 address port and pair mapping, otherwise address only.
257  * @param sw_if_index External port instead of specific IP address.
258  * @param is_add If 0 delete static mapping, otherwise add.
259  *
260  * @returns
261  */
263  u16 l_port, u16 e_port, u32 vrf_id, int addr_only,
264  u32 sw_if_index, snat_protocol_t proto, int is_add)
265 {
266  snat_main_t * sm = &snat_main;
268  snat_session_key_t m_key;
269  clib_bihash_kv_8_8_t kv, value;
270  snat_address_t *a = 0;
271  u32 fib_index = ~0;
272  uword * p;
273  snat_interface_t *interface;
274  int i;
275 
276  /* If the external address is a specific interface address */
277  if (sw_if_index != ~0)
278  {
279  ip4_address_t * first_int_addr;
280 
281  /* Might be already set... */
282  first_int_addr = ip4_interface_first_address
283  (sm->ip4_main, sw_if_index, 0 /* just want the address*/);
284 
285  /* DHCP resolution required? */
286  if (first_int_addr == 0)
287  {
289  (sm, l_addr, l_port, sw_if_index, e_port, vrf_id, proto,
290  addr_only, is_add);
291  return 0;
292  }
293  else
294  e_addr.as_u32 = first_int_addr->as_u32;
295  }
296 
297  m_key.addr = e_addr;
298  m_key.port = addr_only ? 0 : e_port;
299  m_key.protocol = addr_only ? 0 : proto;
300  m_key.fib_index = sm->outside_fib_index;
301  kv.key = m_key.as_u64;
302  if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
303  m = 0;
304  else
305  m = pool_elt_at_index (sm->static_mappings, value.value);
306 
307  if (is_add)
308  {
309  if (m)
310  return VNET_API_ERROR_VALUE_EXIST;
311 
312  /* Convert VRF id to FIB index */
313  if (vrf_id != ~0)
314  {
315  p = hash_get (sm->ip4_main->fib_index_by_table_id, vrf_id);
316  if (!p)
317  return VNET_API_ERROR_NO_SUCH_FIB;
318  fib_index = p[0];
319  }
320  /* If not specified use inside VRF id from SNAT plugin startup config */
321  else
322  {
323  fib_index = sm->inside_fib_index;
324  vrf_id = sm->inside_vrf_id;
325  }
326 
327  /* Find external address in allocated addresses and reserve port for
328  address and port pair mapping when dynamic translations enabled */
329  if (!addr_only && !(sm->static_mapping_only))
330  {
331  for (i = 0; i < vec_len (sm->addresses); i++)
332  {
333  if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
334  {
335  a = sm->addresses + i;
336  /* External port must be unused */
337  switch (proto)
338  {
339 #define _(N, j, n, s) \
340  case SNAT_PROTOCOL_##N: \
341  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, e_port)) \
342  return VNET_API_ERROR_INVALID_VALUE; \
343  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 1); \
344  if (e_port > 1024) \
345  { \
346  a->busy_##n##_ports++; \
347  a->busy_##n##_ports_per_thread[(e_port - 1024) / sm->port_per_thread]++; \
348  } \
349  break;
351 #undef _
352  default:
353  clib_warning("unknown_protocol");
354  return VNET_API_ERROR_INVALID_VALUE_2;
355  }
356  break;
357  }
358  }
359  /* External address must be allocated */
360  if (!a)
361  return VNET_API_ERROR_NO_SUCH_ENTRY;
362  }
363 
364  pool_get (sm->static_mappings, m);
365  memset (m, 0, sizeof (*m));
366  m->local_addr = l_addr;
367  m->external_addr = e_addr;
368  m->addr_only = addr_only;
369  m->vrf_id = vrf_id;
370  m->fib_index = fib_index;
371  if (!addr_only)
372  {
373  m->local_port = l_port;
374  m->external_port = e_port;
375  m->proto = proto;
376  }
377 
378  m_key.addr = m->local_addr;
379  m_key.port = m->local_port;
380  m_key.protocol = m->proto;
381  m_key.fib_index = m->fib_index;
382  kv.key = m_key.as_u64;
383  kv.value = m - sm->static_mappings;
384  clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 1);
385 
386  m_key.addr = m->external_addr;
387  m_key.port = m->external_port;
388  m_key.fib_index = sm->outside_fib_index;
389  kv.key = m_key.as_u64;
390  kv.value = m - sm->static_mappings;
391  clib_bihash_add_del_8_8(&sm->static_mapping_by_external, &kv, 1);
392 
393  if (sm->workers)
394  {
395  ip4_header_t ip = {
396  .src_address = m->local_addr,
397  };
398  m->worker_index = sm->worker_in2out_cb (&ip, m->fib_index);
399  }
400  }
401  else
402  {
403  if (!m)
404  return VNET_API_ERROR_NO_SUCH_ENTRY;
405 
406  /* Free external address port */
407  if (!addr_only && !(sm->static_mapping_only))
408  {
409  for (i = 0; i < vec_len (sm->addresses); i++)
410  {
411  if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
412  {
413  a = sm->addresses + i;
414  switch (proto)
415  {
416 #define _(N, j, n, s) \
417  case SNAT_PROTOCOL_##N: \
418  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 0); \
419  if (e_port > 1024) \
420  { \
421  a->busy_##n##_ports--; \
422  a->busy_##n##_ports_per_thread[(e_port - 1024) / sm->port_per_thread]--; \
423  } \
424  break;
426 #undef _
427  default:
428  clib_warning("unknown_protocol");
429  return VNET_API_ERROR_INVALID_VALUE_2;
430  }
431  break;
432  }
433  }
434  }
435 
436  m_key.addr = m->local_addr;
437  m_key.port = m->local_port;
438  m_key.protocol = m->proto;
439  m_key.fib_index = m->fib_index;
440  kv.key = m_key.as_u64;
441  clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 0);
442 
443  m_key.addr = m->external_addr;
444  m_key.port = m->external_port;
445  m_key.fib_index = sm->outside_fib_index;
446  kv.key = m_key.as_u64;
447  clib_bihash_add_del_8_8(&sm->static_mapping_by_external, &kv, 0);
448 
449  /* Delete session(s) for static mapping if exist */
450  if (!(sm->static_mapping_only) ||
452  {
453  snat_user_key_t u_key;
454  snat_user_t *u;
455  dlist_elt_t * head, * elt;
456  u32 elt_index, head_index, del_elt_index;
457  u32 ses_index;
458  u64 user_index;
459  snat_session_t * s;
461 
462  u_key.addr = m->local_addr;
463  u_key.fib_index = m->fib_index;
464  kv.key = u_key.as_u64;
465  if (sm->num_workers > 1)
467  else
469  if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
470  {
471  user_index = value.value;
472  u = pool_elt_at_index (tsm->users, user_index);
473  if (u->nstaticsessions)
474  {
475  head_index = u->sessions_per_user_list_head_index;
476  head = pool_elt_at_index (tsm->list_pool, head_index);
477  elt_index = head->next;
478  elt = pool_elt_at_index (tsm->list_pool, elt_index);
479  ses_index = elt->value;
480  while (ses_index != ~0)
481  {
482  s = pool_elt_at_index (tsm->sessions, ses_index);
483  del_elt_index = elt_index;
484  elt_index = elt->next;
485  elt = pool_elt_at_index (tsm->list_pool, elt_index);
486  ses_index = elt->value;
487 
488  if (!addr_only)
489  {
490  if ((s->out2in.addr.as_u32 != e_addr.as_u32) &&
491  (clib_net_to_host_u16 (s->out2in.port) != e_port))
492  continue;
493  }
494 
496  {
497  clib_bihash_kv_16_8_t up_kv;
498  nat_ed_ses_key_t up_key;
499  up_key.l_addr = s->in2out.addr;
500  up_key.r_addr = s->ext_host_addr;
501  up_key.fib_index = s->in2out.fib_index;
502  up_key.proto = s->in2out.port;
503  up_key.rsvd = 0;
504  up_key.l_port = 0;
505  up_kv.key[0] = up_key.as_u64[0];
506  up_kv.key[1] = up_key.as_u64[1];
507  if (clib_bihash_add_del_16_8 (&sm->in2out_ed,
508  &up_kv, 0))
509  clib_warning ("in2out key del failed");
510 
511  up_key.l_addr = s->out2in.addr;
512  up_key.fib_index = s->out2in.fib_index;
513  up_kv.key[0] = up_key.as_u64[0];
514  up_kv.key[1] = up_key.as_u64[1];
515  if (clib_bihash_add_del_16_8 (&sm->out2in_ed,
516  &up_kv, 0))
517  clib_warning ("out2in key del failed");
518 
519  goto delete;
520  }
521  /* log NAT event */
522  snat_ipfix_logging_nat44_ses_delete(s->in2out.addr.as_u32,
523  s->out2in.addr.as_u32,
524  s->in2out.protocol,
525  s->in2out.port,
526  s->out2in.port,
527  s->in2out.fib_index);
528 
529  value.key = s->in2out.as_u64;
530  if (clib_bihash_add_del_8_8 (&tsm->in2out, &value, 0))
531  clib_warning ("in2out key del failed");
532  value.key = s->out2in.as_u64;
533  if (clib_bihash_add_del_8_8 (&tsm->out2in, &value, 0))
534  clib_warning ("out2in key del failed");
535 delete:
536  pool_put (tsm->sessions, s);
537 
538  clib_dlist_remove (tsm->list_pool, del_elt_index);
539  pool_put_index (tsm->list_pool, del_elt_index);
540  u->nstaticsessions--;
541 
542  if (!addr_only)
543  break;
544  }
545  if (addr_only)
546  {
547  pool_put (tsm->users, u);
548  clib_bihash_add_del_8_8 (&tsm->user_hash, &kv, 0);
549  }
550  }
551  }
552  }
553 
554  /* Delete static mapping from pool */
555  pool_put (sm->static_mappings, m);
556  }
557 
558  if (!addr_only)
559  return 0;
560 
561  /* Add/delete external address to FIB */
562  pool_foreach (interface, sm->interfaces,
563  ({
564  if (interface->is_inside)
565  continue;
566 
567  snat_add_del_addr_to_fib(&e_addr, 32, interface->sw_if_index, is_add);
568  break;
569  }));
570  pool_foreach (interface, sm->output_feature_interfaces,
571  ({
572  if (interface->is_inside)
573  continue;
574 
575  snat_add_del_addr_to_fib(&e_addr, 32, interface->sw_if_index, is_add);
576  break;
577  }));
578 
579  return 0;
580 }
581 
583  snat_protocol_t proto, u32 vrf_id,
584  nat44_lb_addr_port_t *locals, u8 is_add)
585 {
586  snat_main_t * sm = &snat_main;
588  snat_session_key_t m_key;
589  clib_bihash_kv_8_8_t kv, value;
590  u32 fib_index;
591  snat_address_t *a = 0;
592  int i;
593  nat44_lb_addr_port_t *local;
594  u32 worker_index = 0;
596 
597  m_key.addr = e_addr;
598  m_key.port = e_port;
599  m_key.protocol = proto;
600  m_key.fib_index = sm->outside_fib_index;
601  kv.key = m_key.as_u64;
602  if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
603  m = 0;
604  else
605  m = pool_elt_at_index (sm->static_mappings, value.value);
606 
607  if (is_add)
608  {
609  if (m)
610  return VNET_API_ERROR_VALUE_EXIST;
611 
612  if (vec_len (locals) < 2)
613  return VNET_API_ERROR_INVALID_VALUE;
614 
616  vrf_id,
618 
619  /* Find external address in allocated addresses and reserve port for
620  address and port pair mapping when dynamic translations enabled */
621  if (!sm->static_mapping_only)
622  {
623  for (i = 0; i < vec_len (sm->addresses); i++)
624  {
625  if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
626  {
627  a = sm->addresses + i;
628  /* External port must be unused */
629  switch (proto)
630  {
631 #define _(N, j, n, s) \
632  case SNAT_PROTOCOL_##N: \
633  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, e_port)) \
634  return VNET_API_ERROR_INVALID_VALUE; \
635  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 1); \
636  if (e_port > 1024) \
637  { \
638  a->busy_##n##_ports++; \
639  a->busy_##n##_ports_per_thread[(e_port - 1024) / sm->port_per_thread]++; \
640  } \
641  break;
643 #undef _
644  default:
645  clib_warning("unknown_protocol");
646  return VNET_API_ERROR_INVALID_VALUE_2;
647  }
648  break;
649  }
650  }
651  /* External address must be allocated */
652  if (!a)
653  return VNET_API_ERROR_NO_SUCH_ENTRY;
654  }
655 
656  pool_get (sm->static_mappings, m);
657  memset (m, 0, sizeof (*m));
658  m->external_addr = e_addr;
659  m->addr_only = 0;
660  m->vrf_id = vrf_id;
661  m->fib_index = fib_index;
662  m->external_port = e_port;
663  m->proto = proto;
664 
665  m_key.addr = m->external_addr;
666  m_key.port = m->external_port;
667  m_key.protocol = m->proto;
668  m_key.fib_index = sm->outside_fib_index;
669  kv.key = m_key.as_u64;
670  kv.value = m - sm->static_mappings;
671  if (clib_bihash_add_del_8_8(&sm->static_mapping_by_external, &kv, 1))
672  {
673  clib_warning ("static_mapping_by_external key add failed");
674  return VNET_API_ERROR_UNSPECIFIED;
675  }
676 
677  /* Assign worker */
678  if (sm->workers)
679  {
680  worker_index = sm->first_worker_index +
681  sm->workers[sm->next_worker++ % vec_len (sm->workers)];
682  tsm = vec_elt_at_index (sm->per_thread_data, worker_index);
683  m->worker_index = worker_index;
684  }
685  else
687 
688  m_key.port = clib_host_to_net_u16 (m->external_port);
689  kv.key = m_key.as_u64;
690  kv.value = ~0ULL;
691  if (clib_bihash_add_del_8_8(&tsm->out2in, &kv, 1))
692  {
693  clib_warning ("static_mapping_by_local key add failed");
694  return VNET_API_ERROR_UNSPECIFIED;
695  }
696 
697  m_key.fib_index = m->fib_index;
698  for (i = 0; i < vec_len (locals); i++)
699  {
700  m_key.addr = locals[i].addr;
701  m_key.port = locals[i].port;
702  kv.key = m_key.as_u64;
703  kv.value = m - sm->static_mappings;
704  clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 1);
705  locals[i].prefix = (i == 0) ? locals[i].probability :\
706  (locals[i - 1].prefix + locals[i].probability);
707  vec_add1 (m->locals, locals[i]);
708 
709  m_key.port = clib_host_to_net_u16 (locals[i].port);
710  kv.key = m_key.as_u64;
711  kv.value = ~0ULL;
712  if (clib_bihash_add_del_8_8(&tsm->in2out, &kv, 1))
713  {
714  clib_warning ("in2out key add failed");
715  return VNET_API_ERROR_UNSPECIFIED;
716  }
717  }
718  }
719  else
720  {
721  if (!m)
722  return VNET_API_ERROR_NO_SUCH_ENTRY;
723 
725 
726  /* Free external address port */
727  if (!sm->static_mapping_only)
728  {
729  for (i = 0; i < vec_len (sm->addresses); i++)
730  {
731  if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
732  {
733  a = sm->addresses + i;
734  switch (proto)
735  {
736 #define _(N, j, n, s) \
737  case SNAT_PROTOCOL_##N: \
738  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 0); \
739  if (e_port > 1024) \
740  { \
741  a->busy_##n##_ports--; \
742  a->busy_##n##_ports_per_thread[(e_port - 1024) / sm->port_per_thread]--; \
743  } \
744  break;
746 #undef _
747  default:
748  clib_warning("unknown_protocol");
749  return VNET_API_ERROR_INVALID_VALUE_2;
750  }
751  break;
752  }
753  }
754  }
755 
757  m_key.addr = m->external_addr;
758  m_key.port = m->external_port;
759  m_key.protocol = m->proto;
760  m_key.fib_index = sm->outside_fib_index;
761  kv.key = m_key.as_u64;
762  if (clib_bihash_add_del_8_8(&sm->static_mapping_by_external, &kv, 0))
763  {
764  clib_warning ("static_mapping_by_external key del failed");
765  return VNET_API_ERROR_UNSPECIFIED;
766  }
767 
768  m_key.port = clib_host_to_net_u16 (m->external_port);
769  kv.key = m_key.as_u64;
770  if (clib_bihash_add_del_8_8(&tsm->out2in, &kv, 0))
771  {
772  clib_warning ("outi2in key del failed");
773  return VNET_API_ERROR_UNSPECIFIED;
774  }
775 
776  vec_foreach (local, m->locals)
777  {
778  m_key.addr = local->addr;
779  m_key.port = local->port;
780  m_key.fib_index = m->fib_index;
781  kv.key = m_key.as_u64;
782  if (clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 0))
783  {
784  clib_warning ("static_mapping_by_local key del failed");
785  return VNET_API_ERROR_UNSPECIFIED;
786  }
787 
788  m_key.port = clib_host_to_net_u16 (local->port);
789  kv.key = m_key.as_u64;
790  if (clib_bihash_add_del_8_8(&tsm->in2out, &kv, 0))
791  {
792  clib_warning ("in2out key del failed");
793  return VNET_API_ERROR_UNSPECIFIED;
794  }
795  }
796  vec_free(m->locals);
797 
798  pool_put (sm->static_mappings, m);
799  }
800 
801  return 0;
802 }
803 
805 {
806  snat_address_t *a = 0;
807  snat_session_t *ses;
808  u32 *ses_to_be_removed = 0, *ses_index;
809  clib_bihash_kv_8_8_t kv, value;
810  snat_user_key_t user_key;
811  snat_user_t *u;
814  snat_interface_t *interface;
815  int i;
816 
817  /* Find SNAT address */
818  for (i=0; i < vec_len (sm->addresses); i++)
819  {
820  if (sm->addresses[i].addr.as_u32 == addr.as_u32)
821  {
822  a = sm->addresses + i;
823  break;
824  }
825  }
826  if (!a)
827  return VNET_API_ERROR_NO_SUCH_ENTRY;
828 
829  if (delete_sm)
830  {
832  ({
833  if (m->external_addr.as_u32 == addr.as_u32)
834  (void) snat_add_static_mapping (m->local_addr, m->external_addr,
835  m->local_port, m->external_port,
836  m->vrf_id, m->addr_only, ~0,
837  m->proto, 0);
838  }));
839  }
840  else
841  {
842  /* Check if address is used in some static mapping */
844  {
845  clib_warning ("address used in static mapping");
846  return VNET_API_ERROR_UNSPECIFIED;
847  }
848  }
849 
850  if (a->fib_index != ~0)
853 
854  /* Delete sessions using address */
855  if (a->busy_tcp_ports || a->busy_udp_ports || a->busy_icmp_ports)
856  {
857  vec_foreach (tsm, sm->per_thread_data)
858  {
859  pool_foreach (ses, tsm->sessions, ({
860  if (ses->out2in.addr.as_u32 == addr.as_u32)
861  {
862  if (snat_is_unk_proto_session (ses))
863  {
864  clib_bihash_kv_16_8_t up_kv;
865  nat_ed_ses_key_t up_key;
866  up_key.l_addr = ses->in2out.addr;
867  up_key.r_addr = ses->ext_host_addr;
868  up_key.fib_index = ses->in2out.fib_index;
869  up_key.proto = ses->in2out.port;
870  up_key.rsvd = 0;
871  up_key.l_port = 0;
872  up_kv.key[0] = up_key.as_u64[0];
873  up_kv.key[1] = up_key.as_u64[1];
874  if (clib_bihash_add_del_16_8 (&sm->in2out_ed,
875  &up_kv, 0))
876  clib_warning ("in2out key del failed");
877 
878  up_key.l_addr = ses->out2in.addr;
879  up_key.fib_index = ses->out2in.fib_index;
880  up_kv.key[0] = up_key.as_u64[0];
881  up_kv.key[1] = up_key.as_u64[1];
882  if (clib_bihash_add_del_16_8 (&sm->out2in_ed,
883  &up_kv, 0))
884  clib_warning ("out2in key del failed");
885  }
886  else
887  {
888  /* log NAT event */
889  snat_ipfix_logging_nat44_ses_delete(ses->in2out.addr.as_u32,
890  ses->out2in.addr.as_u32,
891  ses->in2out.protocol,
892  ses->in2out.port,
893  ses->out2in.port,
894  ses->in2out.fib_index);
895  kv.key = ses->in2out.as_u64;
896  clib_bihash_add_del_8_8 (&tsm->in2out, &kv, 0);
897  kv.key = ses->out2in.as_u64;
898  clib_bihash_add_del_8_8 (&tsm->out2in, &kv, 0);
899  }
900  vec_add1 (ses_to_be_removed, ses - tsm->sessions);
901  clib_dlist_remove (tsm->list_pool, ses->per_user_index);
902  user_key.addr = ses->in2out.addr;
903  user_key.fib_index = ses->in2out.fib_index;
904  kv.key = user_key.as_u64;
905  if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
906  {
907  u = pool_elt_at_index (tsm->users, value.value);
908  u->nsessions--;
909  }
910  }
911  }));
912 
913  vec_foreach (ses_index, ses_to_be_removed)
914  pool_put_index (tsm->sessions, ses_index[0]);
915 
916  vec_free (ses_to_be_removed);
917  }
918  }
919 
920  vec_del1 (sm->addresses, i);
921 
922  /* Delete external address from FIB */
923  pool_foreach (interface, sm->interfaces,
924  ({
925  if (interface->is_inside)
926  continue;
927 
928  snat_add_del_addr_to_fib(&addr, 32, interface->sw_if_index, 0);
929  break;
930  }));
931  pool_foreach (interface, sm->output_feature_interfaces,
932  ({
933  if (interface->is_inside)
934  continue;
935 
936  snat_add_del_addr_to_fib(&addr, 32, interface->sw_if_index, 0);
937  break;
938  }));
939 
940  return 0;
941 }
942 
943 int snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del)
944 {
945  snat_main_t *sm = &snat_main;
947  const char * feature_name;
948  snat_address_t * ap;
950  snat_det_map_t * dm;
951 
953  feature_name = is_inside ? "nat44-in2out-fast" : "nat44-out2in-fast";
954  else
955  {
956  if (sm->num_workers > 1 && !sm->deterministic)
957  feature_name = is_inside ? "nat44-in2out-worker-handoff" : "nat44-out2in-worker-handoff";
958  else if (sm->deterministic)
959  feature_name = is_inside ? "nat44-det-in2out" : "nat44-det-out2in";
960  else
961  feature_name = is_inside ? "nat44-in2out" : "nat44-out2in";
962  }
963 
964  vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index,
965  !is_del, 0, 0);
966 
967  if (sm->fq_in2out_index == ~0 && !sm->deterministic && sm->num_workers > 1)
969 
970  if (sm->fq_out2in_index == ~0 && !sm->deterministic && sm->num_workers > 1)
972 
973  pool_foreach (i, sm->interfaces,
974  ({
975  if (i->sw_if_index == sw_if_index)
976  {
977  if (is_del)
978  pool_put (sm->interfaces, i);
979  else
980  return VNET_API_ERROR_VALUE_EXIST;
981 
982  goto fib;
983  }
984  }));
985 
986  if (is_del)
987  return VNET_API_ERROR_NO_SUCH_ENTRY;
988 
989  pool_get (sm->interfaces, i);
990  i->sw_if_index = sw_if_index;
991  i->is_inside = is_inside;
992 
993  /* Add/delete external addresses to FIB */
994 fib:
995  if (is_inside)
996  return 0;
997 
998  vec_foreach (ap, sm->addresses)
999  snat_add_del_addr_to_fib(&ap->addr, 32, sw_if_index, !is_del);
1000 
1001  pool_foreach (m, sm->static_mappings,
1002  ({
1003  if (!(m->addr_only))
1004  continue;
1005 
1006  snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
1007  }));
1008 
1009  pool_foreach (dm, sm->det_maps,
1010  ({
1011  snat_add_del_addr_to_fib(&dm->out_addr, dm->out_plen, sw_if_index, !is_del);
1012  }));
1013 
1014  return 0;
1015 }
1016 
1018  u8 is_inside,
1019  int is_del)
1020 {
1021  snat_main_t *sm = &snat_main;
1023  snat_address_t * ap;
1025 
1026  if (sm->deterministic ||
1028  return VNET_API_ERROR_UNSUPPORTED;
1029 
1030  if (is_inside)
1031  {
1032  vnet_feature_enable_disable ("ip4-unicast", "nat44-hairpin-dst",
1033  sw_if_index, !is_del, 0, 0);
1034  vnet_feature_enable_disable ("ip4-output", "nat44-hairpin-src",
1035  sw_if_index, !is_del, 0, 0);
1036  goto fq;
1037  }
1038 
1039  if (sm->num_workers > 1)
1040  {
1041  vnet_feature_enable_disable ("ip4-unicast", "nat44-out2in-worker-handoff",
1042  sw_if_index, !is_del, 0, 0);
1043  vnet_feature_enable_disable ("ip4-output",
1044  "nat44-in2out-output-worker-handoff",
1045  sw_if_index, !is_del, 0, 0);
1046  }
1047  else
1048  {
1049  vnet_feature_enable_disable ("ip4-unicast", "nat44-out2in", sw_if_index,
1050  !is_del, 0, 0);
1051  vnet_feature_enable_disable ("ip4-output", "nat44-in2out-output",
1052  sw_if_index, !is_del, 0, 0);
1053  }
1054 
1055 fq:
1056  if (sm->fq_in2out_output_index == ~0 && sm->num_workers > 1)
1059 
1060  if (sm->fq_out2in_index == ~0 && sm->num_workers > 1)
1062 
1064  ({
1065  if (i->sw_if_index == sw_if_index)
1066  {
1067  if (is_del)
1068  pool_put (sm->output_feature_interfaces, i);
1069  else
1070  return VNET_API_ERROR_VALUE_EXIST;
1071 
1072  goto fib;
1073  }
1074  }));
1075 
1076  if (is_del)
1077  return VNET_API_ERROR_NO_SUCH_ENTRY;
1078 
1079  pool_get (sm->output_feature_interfaces, i);
1080  i->sw_if_index = sw_if_index;
1081  i->is_inside = is_inside;
1082 
1083  /* Add/delete external addresses to FIB */
1084 fib:
1085  if (is_inside)
1086  return 0;
1087 
1088  vec_foreach (ap, sm->addresses)
1089  snat_add_del_addr_to_fib(&ap->addr, 32, sw_if_index, !is_del);
1090 
1091  pool_foreach (m, sm->static_mappings,
1092  ({
1093  if (!(m->addr_only))
1094  continue;
1095 
1096  snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
1097  }));
1098 
1099  return 0;
1100 }
1101 
1102 int snat_set_workers (uword * bitmap)
1103 {
1104  snat_main_t *sm = &snat_main;
1105  int i, j = 0;
1106 
1107  if (sm->num_workers < 2)
1108  return VNET_API_ERROR_FEATURE_DISABLED;
1109 
1110  if (clib_bitmap_last_set (bitmap) >= sm->num_workers)
1111  return VNET_API_ERROR_INVALID_WORKER;
1112 
1113  vec_free (sm->workers);
1114  clib_bitmap_foreach (i, bitmap,
1115  ({
1116  vec_add1(sm->workers, i);
1118  j++;
1119  }));
1120 
1121  sm->port_per_thread = (0xffff - 1024) / _vec_len (sm->workers);
1122  sm->num_snat_thread = _vec_len (sm->workers);
1123 
1124  return 0;
1125 }
1126 
1127 
1128 static void
1130  uword opaque,
1131  u32 sw_if_index,
1132  ip4_address_t * address,
1133  u32 address_length,
1134  u32 if_address_index,
1135  u32 is_delete);
1136 
1138 {
1139  snat_main_t * sm = &snat_main;
1140  clib_error_t * error = 0;
1141  ip4_main_t * im = &ip4_main;
1142  ip_lookup_main_t * lm = &im->lookup_main;
1143  uword *p;
1146  uword *bitmap = 0;
1147  u32 i;
1149 
1150  sm->vlib_main = vm;
1151  sm->vnet_main = vnet_get_main();
1152  sm->ip4_main = im;
1153  sm->ip4_lookup_main = lm;
1154  sm->api_main = &api_main;
1155  sm->first_worker_index = 0;
1156  sm->next_worker = 0;
1157  sm->num_workers = 0;
1158  sm->num_snat_thread = 1;
1159  sm->workers = 0;
1160  sm->port_per_thread = 0xffff - 1024;
1161  sm->fq_in2out_index = ~0;
1162  sm->fq_out2in_index = ~0;
1167 
1168  p = hash_get_mem (tm->thread_registrations_by_name, "workers");
1169  if (p)
1170  {
1171  tr = (vlib_thread_registration_t *) p[0];
1172  if (tr)
1173  {
1174  sm->num_workers = tr->count;
1175  sm->first_worker_index = tr->first_index;
1176  }
1177  }
1178 
1179  vec_validate (sm->per_thread_data, tm->n_vlib_mains - 1);
1180 
1181  /* Use all available workers by default */
1182  if (sm->num_workers > 1)
1183  {
1184  for (i=0; i < sm->num_workers; i++)
1185  bitmap = clib_bitmap_set (bitmap, i, 1);
1186  snat_set_workers(bitmap);
1187  clib_bitmap_free (bitmap);
1188  }
1189  else
1190  {
1192  }
1193 
1194  error = snat_api_init(vm, sm);
1195  if (error)
1196  return error;
1197 
1198  /* Set up the interface address add/del callback */
1200  cb4.function_opaque = 0;
1201 
1203 
1204  /* Init IPFIX logging */
1206 
1207  error = nat64_init(vm);
1208 
1209  return error;
1210 }
1211 
1213 
1215  u32 thread_index,
1216  snat_session_key_t * k,
1217  u32 address_index)
1218 {
1219  snat_address_t *a;
1220  u16 port_host_byte_order = clib_net_to_host_u16 (k->port);
1221 
1222  ASSERT (address_index < vec_len (sm->addresses));
1223 
1224  a = sm->addresses + address_index;
1225 
1226  switch (k->protocol)
1227  {
1228 #define _(N, i, n, s) \
1229  case SNAT_PROTOCOL_##N: \
1230  ASSERT (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, \
1231  port_host_byte_order) == 1); \
1232  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, \
1233  port_host_byte_order, 0); \
1234  a->busy_##n##_ports--; \
1235  a->busy_##n##_ports_per_thread[thread_index]--; \
1236  break;
1238 #undef _
1239  default:
1240  clib_warning("unknown_protocol");
1241  return;
1242  }
1243 }
1244 
1245 /**
1246  * @brief Match NAT44 static mapping.
1247  *
1248  * @param sm NAT main.
1249  * @param match Address and port to match.
1250  * @param mapping External or local address and port of the matched mapping.
1251  * @param by_external If 0 match by local address otherwise match by external
1252  * address.
1253  * @param is_addr_only If matched mapping is address only
1254  *
1255  * @returns 0 if match found otherwise 1.
1256  */
1258  snat_session_key_t match,
1259  snat_session_key_t * mapping,
1260  u8 by_external,
1261  u8 *is_addr_only)
1262 {
1263  clib_bihash_kv_8_8_t kv, value;
1265  snat_session_key_t m_key;
1266  clib_bihash_8_8_t *mapping_hash = &sm->static_mapping_by_local;
1267  u32 rand, lo = 0, hi, mid;
1268 
1269  if (by_external)
1270  mapping_hash = &sm->static_mapping_by_external;
1271 
1272  m_key.addr = match.addr;
1273  m_key.port = clib_net_to_host_u16 (match.port);
1274  m_key.protocol = match.protocol;
1275  m_key.fib_index = match.fib_index;
1276 
1277  kv.key = m_key.as_u64;
1278 
1279  if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
1280  {
1281  /* Try address only mapping */
1282  m_key.port = 0;
1283  m_key.protocol = 0;
1284  kv.key = m_key.as_u64;
1285  if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
1286  return 1;
1287  }
1288 
1289  m = pool_elt_at_index (sm->static_mappings, value.value);
1290 
1291  if (by_external)
1292  {
1293  if (vec_len (m->locals))
1294  {
1295  hi = vec_len (m->locals) - 1;
1296  rand = 1 + (random_u32 (&sm->random_seed) % m->locals[hi].prefix);
1297  while (lo < hi)
1298  {
1299  mid = ((hi - lo) >> 1) + lo;
1300  (rand > m->locals[mid].prefix) ? (lo = mid + 1) : (hi = mid);
1301  }
1302  if (!(m->locals[lo].prefix >= rand))
1303  return 1;
1304  mapping->addr = m->locals[lo].addr;
1305  mapping->port = clib_host_to_net_u16 (m->locals[lo].port);
1306  }
1307  else
1308  {
1309  mapping->addr = m->local_addr;
1310  /* Address only mapping doesn't change port */
1311  mapping->port = m->addr_only ? match.port
1312  : clib_host_to_net_u16 (m->local_port);
1313  }
1314  mapping->fib_index = m->fib_index;
1315  mapping->protocol = m->proto;
1316  }
1317  else
1318  {
1319  mapping->addr = m->external_addr;
1320  /* Address only mapping doesn't change port */
1321  mapping->port = m->addr_only ? match.port
1322  : clib_host_to_net_u16 (m->external_port);
1323  mapping->fib_index = sm->outside_fib_index;
1324  }
1325 
1326  if (PREDICT_FALSE(is_addr_only != 0))
1327  *is_addr_only = m->addr_only;
1328 
1329  return 0;
1330 }
1331 
1334 {
1335  return min + random_u32 (&sm->random_seed) /
1336  (random_u32_max() / (max - min + 1) + 1);
1337 }
1338 
1340  u32 fib_index,
1341  u32 thread_index,
1342  snat_session_key_t * k,
1343  u32 * address_indexp)
1344 {
1345  int i;
1346  snat_address_t *a;
1347  u32 portnum;
1348 
1349  for (i = 0; i < vec_len (sm->addresses); i++)
1350  {
1351  a = sm->addresses + i;
1352  if (sm->vrf_mode && a->fib_index != ~0 && a->fib_index != fib_index)
1353  continue;
1354  switch (k->protocol)
1355  {
1356 #define _(N, j, n, s) \
1357  case SNAT_PROTOCOL_##N: \
1358  if (a->busy_##n##_ports_per_thread[thread_index] < sm->port_per_thread) \
1359  { \
1360  while (1) \
1361  { \
1362  portnum = (sm->port_per_thread * \
1363  sm->per_thread_data[thread_index].snat_thread_index) + \
1364  snat_random_port(sm, 1, sm->port_per_thread) + 1024; \
1365  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \
1366  continue; \
1367  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \
1368  a->busy_##n##_ports_per_thread[thread_index]++; \
1369  a->busy_##n##_ports++; \
1370  k->addr = a->addr; \
1371  k->port = clib_host_to_net_u16(portnum); \
1372  *address_indexp = i; \
1373  return 0; \
1374  } \
1375  } \
1376  break;
1378 #undef _
1379  default:
1380  clib_warning("unknown protocol");
1381  return 1;
1382  }
1383 
1384  }
1385  /* Totally out of translations to use... */
1387  return 1;
1388 }
1389 
1390 
1391 static clib_error_t *
1393  unformat_input_t * input,
1394  vlib_cli_command_t * cmd)
1395 {
1396  unformat_input_t _line_input, *line_input = &_line_input;
1397  snat_main_t * sm = &snat_main;
1398  ip4_address_t start_addr, end_addr, this_addr;
1399  u32 start_host_order, end_host_order;
1400  u32 vrf_id = ~0;
1401  int i, count;
1402  int is_add = 1;
1403  int rv = 0;
1404  clib_error_t *error = 0;
1405 
1406  /* Get a line of input. */
1407  if (!unformat_user (input, unformat_line_input, line_input))
1408  return 0;
1409 
1410  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1411  {
1412  if (unformat (line_input, "%U - %U",
1413  unformat_ip4_address, &start_addr,
1414  unformat_ip4_address, &end_addr))
1415  ;
1416  else if (unformat (line_input, "tenant-vrf %u", &vrf_id))
1417  ;
1418  else if (unformat (line_input, "%U", unformat_ip4_address, &start_addr))
1419  end_addr = start_addr;
1420  else if (unformat (line_input, "del"))
1421  is_add = 0;
1422  else
1423  {
1424  error = clib_error_return (0, "unknown input '%U'",
1425  format_unformat_error, line_input);
1426  goto done;
1427  }
1428  }
1429 
1430  if (sm->static_mapping_only)
1431  {
1432  error = clib_error_return (0, "static mapping only mode");
1433  goto done;
1434  }
1435 
1436  start_host_order = clib_host_to_net_u32 (start_addr.as_u32);
1437  end_host_order = clib_host_to_net_u32 (end_addr.as_u32);
1438 
1439  if (end_host_order < start_host_order)
1440  {
1441  error = clib_error_return (0, "end address less than start address");
1442  goto done;
1443  }
1444 
1445  count = (end_host_order - start_host_order) + 1;
1446 
1447  if (count > 1024)
1448  clib_warning ("%U - %U, %d addresses...",
1449  format_ip4_address, &start_addr,
1450  format_ip4_address, &end_addr,
1451  count);
1452 
1453  this_addr = start_addr;
1454 
1455  for (i = 0; i < count; i++)
1456  {
1457  if (is_add)
1458  snat_add_address (sm, &this_addr, vrf_id);
1459  else
1460  rv = snat_del_address (sm, this_addr, 0);
1461 
1462  switch (rv)
1463  {
1464  case VNET_API_ERROR_NO_SUCH_ENTRY:
1465  error = clib_error_return (0, "S-NAT address not exist.");
1466  goto done;
1467  case VNET_API_ERROR_UNSPECIFIED:
1468  error = clib_error_return (0, "S-NAT address used in static mapping.");
1469  goto done;
1470  default:
1471  break;
1472  }
1473 
1474  increment_v4_address (&this_addr);
1475  }
1476 
1477 done:
1478  unformat_free (line_input);
1479 
1480  return error;
1481 }
1482 
1483 VLIB_CLI_COMMAND (add_address_command, static) = {
1484  .path = "nat44 add address",
1485  .short_help = "nat44 add address <ip4-range-start> [- <ip4-range-end>] "
1486  "[tenant-vrf <vrf-id>] [del]",
1487  .function = add_address_command_fn,
1488 };
1489 
1490 static clib_error_t *
1492  unformat_input_t * input,
1493  vlib_cli_command_t * cmd)
1494 {
1495  unformat_input_t _line_input, *line_input = &_line_input;
1496  vnet_main_t * vnm = vnet_get_main();
1497  clib_error_t * error = 0;
1498  u32 sw_if_index;
1499  u32 * inside_sw_if_indices = 0;
1500  u32 * outside_sw_if_indices = 0;
1501  u8 is_output_feature = 0;
1502  int is_del = 0;
1503  int i;
1504 
1505  sw_if_index = ~0;
1506 
1507  /* Get a line of input. */
1508  if (!unformat_user (input, unformat_line_input, line_input))
1509  return 0;
1510 
1511  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1512  {
1513  if (unformat (line_input, "in %U", unformat_vnet_sw_interface,
1514  vnm, &sw_if_index))
1515  vec_add1 (inside_sw_if_indices, sw_if_index);
1516  else if (unformat (line_input, "out %U", unformat_vnet_sw_interface,
1517  vnm, &sw_if_index))
1518  vec_add1 (outside_sw_if_indices, sw_if_index);
1519  else if (unformat (line_input, "output-feature"))
1520  is_output_feature = 1;
1521  else if (unformat (line_input, "del"))
1522  is_del = 1;
1523  else
1524  {
1525  error = clib_error_return (0, "unknown input '%U'",
1526  format_unformat_error, line_input);
1527  goto done;
1528  }
1529  }
1530 
1531  if (vec_len (inside_sw_if_indices))
1532  {
1533  for (i = 0; i < vec_len(inside_sw_if_indices); i++)
1534  {
1535  sw_if_index = inside_sw_if_indices[i];
1536  if (is_output_feature)
1537  {
1538  if (snat_interface_add_del_output_feature (sw_if_index, 1, is_del))
1539  {
1540  error = clib_error_return (0, "%s %U failed",
1541  is_del ? "del" : "add",
1543  vnet_get_sw_interface (vnm,
1544  sw_if_index));
1545  goto done;
1546  }
1547  }
1548  else
1549  {
1550  if (snat_interface_add_del (sw_if_index, 1, is_del))
1551  {
1552  error = clib_error_return (0, "%s %U failed",
1553  is_del ? "del" : "add",
1555  vnet_get_sw_interface (vnm,
1556  sw_if_index));
1557  goto done;
1558  }
1559  }
1560  }
1561  }
1562 
1563  if (vec_len (outside_sw_if_indices))
1564  {
1565  for (i = 0; i < vec_len(outside_sw_if_indices); i++)
1566  {
1567  sw_if_index = outside_sw_if_indices[i];
1568  if (is_output_feature)
1569  {
1570  if (snat_interface_add_del_output_feature (sw_if_index, 0, is_del))
1571  {
1572  error = clib_error_return (0, "%s %U failed",
1573  is_del ? "del" : "add",
1575  vnet_get_sw_interface (vnm,
1576  sw_if_index));
1577  goto done;
1578  }
1579  }
1580  else
1581  {
1582  if (snat_interface_add_del (sw_if_index, 0, is_del))
1583  {
1584  error = clib_error_return (0, "%s %U failed",
1585  is_del ? "del" : "add",
1587  vnet_get_sw_interface (vnm,
1588  sw_if_index));
1589  goto done;
1590  }
1591  }
1592  }
1593  }
1594 
1595 done:
1596  unformat_free (line_input);
1597  vec_free (inside_sw_if_indices);
1598  vec_free (outside_sw_if_indices);
1599 
1600  return error;
1601 }
1602 
1603 VLIB_CLI_COMMAND (set_interface_snat_command, static) = {
1604  .path = "set interface nat44",
1605  .function = snat_feature_command_fn,
1606  .short_help = "set interface nat44 in <intfc> out <intfc> [output-feature] "
1607  "[del]",
1608 };
1609 
1610 uword
1611 unformat_snat_protocol (unformat_input_t * input, va_list * args)
1612 {
1613  u32 *r = va_arg (*args, u32 *);
1614 
1615  if (0);
1616 #define _(N, i, n, s) else if (unformat (input, s)) *r = SNAT_PROTOCOL_##N;
1618 #undef _
1619  else
1620  return 0;
1621  return 1;
1622 }
1623 
1624 u8 *
1625 format_snat_protocol (u8 * s, va_list * args)
1626 {
1627  u32 i = va_arg (*args, u32);
1628  u8 *t = 0;
1629 
1630  switch (i)
1631  {
1632 #define _(N, j, n, str) case SNAT_PROTOCOL_##N: t = (u8 *) str; break;
1634 #undef _
1635  default:
1636  s = format (s, "unknown");
1637  return s;
1638  }
1639  s = format (s, "%s", t);
1640  return s;
1641 }
1642 
1643 static clib_error_t *
1645  unformat_input_t * input,
1646  vlib_cli_command_t * cmd)
1647 {
1648  unformat_input_t _line_input, *line_input = &_line_input;
1649  clib_error_t * error = 0;
1650  ip4_address_t l_addr, e_addr;
1651  u32 l_port = 0, e_port = 0, vrf_id = ~0;
1652  int is_add = 1;
1653  int addr_only = 1;
1654  u32 sw_if_index = ~0;
1655  vnet_main_t * vnm = vnet_get_main();
1656  int rv;
1657  snat_protocol_t proto;
1658  u8 proto_set = 0;
1659 
1660  /* Get a line of input. */
1661  if (!unformat_user (input, unformat_line_input, line_input))
1662  return 0;
1663 
1664  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1665  {
1666  if (unformat (line_input, "local %U %u", unformat_ip4_address, &l_addr,
1667  &l_port))
1668  addr_only = 0;
1669  else if (unformat (line_input, "local %U", unformat_ip4_address, &l_addr))
1670  ;
1671  else if (unformat (line_input, "external %U %u", unformat_ip4_address,
1672  &e_addr, &e_port))
1673  addr_only = 0;
1674  else if (unformat (line_input, "external %U", unformat_ip4_address,
1675  &e_addr))
1676  ;
1677  else if (unformat (line_input, "external %U %u",
1678  unformat_vnet_sw_interface, vnm, &sw_if_index,
1679  &e_port))
1680  addr_only = 0;
1681 
1682  else if (unformat (line_input, "external %U",
1683  unformat_vnet_sw_interface, vnm, &sw_if_index))
1684  ;
1685  else if (unformat (line_input, "vrf %u", &vrf_id))
1686  ;
1687  else if (unformat (line_input, "%U", unformat_snat_protocol, &proto))
1688  proto_set = 1;
1689  else if (unformat (line_input, "del"))
1690  is_add = 0;
1691  else
1692  {
1693  error = clib_error_return (0, "unknown input: '%U'",
1694  format_unformat_error, line_input);
1695  goto done;
1696  }
1697  }
1698 
1699  if (!addr_only && !proto_set)
1700  {
1701  error = clib_error_return (0, "missing protocol");
1702  goto done;
1703  }
1704 
1705  rv = snat_add_static_mapping(l_addr, e_addr, (u16) l_port, (u16) e_port,
1706  vrf_id, addr_only, sw_if_index, proto, is_add);
1707 
1708  switch (rv)
1709  {
1710  case VNET_API_ERROR_INVALID_VALUE:
1711  error = clib_error_return (0, "External port already in use.");
1712  goto done;
1713  case VNET_API_ERROR_NO_SUCH_ENTRY:
1714  if (is_add)
1715  error = clib_error_return (0, "External addres must be allocated.");
1716  else
1717  error = clib_error_return (0, "Mapping not exist.");
1718  goto done;
1719  case VNET_API_ERROR_NO_SUCH_FIB:
1720  error = clib_error_return (0, "No such VRF id.");
1721  goto done;
1722  case VNET_API_ERROR_VALUE_EXIST:
1723  error = clib_error_return (0, "Mapping already exist.");
1724  goto done;
1725  default:
1726  break;
1727  }
1728 
1729 done:
1730  unformat_free (line_input);
1731 
1732  return error;
1733 }
1734 
1735 /*?
1736  * @cliexpar
1737  * @cliexstart{snat add static mapping}
1738  * Static mapping allows hosts on the external network to initiate connection
1739  * to to the local network host.
1740  * To create static mapping between local host address 10.0.0.3 port 6303 and
1741  * external address 4.4.4.4 port 3606 for TCP protocol use:
1742  * vpp# nat44 add static mapping tcp local 10.0.0.3 6303 external 4.4.4.4 3606
1743  * If not runnig "static mapping only" NAT plugin mode use before:
1744  * vpp# nat44 add address 4.4.4.4
1745  * To create static mapping between local and external address use:
1746  * vpp# nat44 add static mapping local 10.0.0.3 external 4.4.4.4
1747  * @cliexend
1748 ?*/
1749 VLIB_CLI_COMMAND (add_static_mapping_command, static) = {
1750  .path = "nat44 add static mapping",
1751  .function = add_static_mapping_command_fn,
1752  .short_help =
1753  "nat44 add static mapping tcp|udp|icmp local <addr> [<port>] external <addr> [<port>] [vrf <table-id>] [del]",
1754 };
1755 
1756 static clib_error_t *
1758  unformat_input_t * input,
1759  vlib_cli_command_t * cmd)
1760 {
1761  unformat_input_t _line_input, *line_input = &_line_input;
1762  clib_error_t * error = 0;
1763  ip4_address_t l_addr, e_addr;
1764  u32 l_port = 0, e_port = 0, vrf_id = 0, probability = 0;
1765  int is_add = 1;
1766  int rv;
1767  snat_protocol_t proto;
1768  u8 proto_set = 0;
1769  nat44_lb_addr_port_t *locals = 0, local;
1770 
1771  /* Get a line of input. */
1772  if (!unformat_user (input, unformat_line_input, line_input))
1773  return 0;
1774 
1775  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1776  {
1777  if (unformat (line_input, "local %U:%u probability %u",
1778  unformat_ip4_address, &l_addr, &l_port, &probability))
1779  {
1780  memset (&local, 0, sizeof (local));
1781  local.addr = l_addr;
1782  local.port = (u16) l_port;
1783  local.probability = (u8) probability;
1784  vec_add1 (locals, local);
1785  }
1786  else if (unformat (line_input, "external %U:%u", unformat_ip4_address,
1787  &e_addr, &e_port))
1788  ;
1789  else if (unformat (line_input, "vrf %u", &vrf_id))
1790  ;
1791  else if (unformat (line_input, "protocol %U", unformat_snat_protocol,
1792  &proto))
1793  proto_set = 1;
1794  else if (unformat (line_input, "del"))
1795  is_add = 0;
1796  else
1797  {
1798  error = clib_error_return (0, "unknown input: '%U'",
1799  format_unformat_error, line_input);
1800  goto done;
1801  }
1802  }
1803 
1804  if (vec_len (locals) < 2)
1805  {
1806  error = clib_error_return (0, "at least two local must be set");
1807  goto done;
1808  }
1809 
1810  if (!proto_set)
1811  {
1812  error = clib_error_return (0, "missing protocol");
1813  goto done;
1814  }
1815 
1816  rv = nat44_add_del_lb_static_mapping (e_addr, (u16) e_port, proto, vrf_id,
1817  locals, is_add);
1818 
1819  switch (rv)
1820  {
1821  case VNET_API_ERROR_INVALID_VALUE:
1822  error = clib_error_return (0, "External port already in use.");
1823  goto done;
1824  case VNET_API_ERROR_NO_SUCH_ENTRY:
1825  if (is_add)
1826  error = clib_error_return (0, "External addres must be allocated.");
1827  else
1828  error = clib_error_return (0, "Mapping not exist.");
1829  goto done;
1830  case VNET_API_ERROR_VALUE_EXIST:
1831  error = clib_error_return (0, "Mapping already exist.");
1832  goto done;
1833  default:
1834  break;
1835  }
1836 
1837 done:
1838  unformat_free (line_input);
1839  vec_free (locals);
1840 
1841  return error;
1842 }
1843 
1844 VLIB_CLI_COMMAND (add_lb_static_mapping_command, static) = {
1845  .path = "nat44 add load-balancing static mapping",
1847  .short_help =
1848  "nat44 add load-balancing static mapping protocol tcp|udp external <addr>:<port> local <addr>:<port> probability <n> [vrf <table-id>] [del]",
1849 };
1850 
1851 static clib_error_t *
1853  unformat_input_t * input,
1854  vlib_cli_command_t * cmd)
1855 {
1856  unformat_input_t _line_input, *line_input = &_line_input;
1857  uword *bitmap = 0;
1858  int rv = 0;
1859  clib_error_t *error = 0;
1860 
1861  /* Get a line of input. */
1862  if (!unformat_user (input, unformat_line_input, line_input))
1863  return 0;
1864 
1865  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1866  {
1867  if (unformat (line_input, "%U", unformat_bitmap_list, &bitmap))
1868  ;
1869  else
1870  {
1871  error = clib_error_return (0, "unknown input '%U'",
1872  format_unformat_error, line_input);
1873  goto done;
1874  }
1875  }
1876 
1877  if (bitmap == 0)
1878  {
1879  error = clib_error_return (0, "List of workers must be specified.");
1880  goto done;
1881  }
1882 
1883  rv = snat_set_workers(bitmap);
1884 
1885  clib_bitmap_free (bitmap);
1886 
1887  switch (rv)
1888  {
1889  case VNET_API_ERROR_INVALID_WORKER:
1890  error = clib_error_return (0, "Invalid worker(s).");
1891  goto done;
1892  case VNET_API_ERROR_FEATURE_DISABLED:
1893  error = clib_error_return (0,
1894  "Supported only if 2 or more workes available.");
1895  goto done;
1896  default:
1897  break;
1898  }
1899 
1900 done:
1901  unformat_free (line_input);
1902 
1903  return error;
1904 }
1905 
1906 /*?
1907  * @cliexpar
1908  * @cliexstart{set snat workers}
1909  * Set NAT workers if 2 or more workers available, use:
1910  * vpp# set snat workers 0-2,5
1911  * @cliexend
1912 ?*/
1913 VLIB_CLI_COMMAND (set_workers_command, static) = {
1914  .path = "set nat workers",
1915  .function = set_workers_command_fn,
1916  .short_help =
1917  "set nat workers <workers-list>",
1918 };
1919 
1920 static clib_error_t *
1922  unformat_input_t * input,
1923  vlib_cli_command_t * cmd)
1924 {
1925  unformat_input_t _line_input, *line_input = &_line_input;
1926  u32 domain_id = 0;
1927  u32 src_port = 0;
1928  u8 enable = 1;
1929  int rv = 0;
1930  clib_error_t *error = 0;
1931 
1932  /* Get a line of input. */
1933  if (!unformat_user (input, unformat_line_input, line_input))
1934  return 0;
1935 
1936  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1937  {
1938  if (unformat (line_input, "domain %d", &domain_id))
1939  ;
1940  else if (unformat (line_input, "src-port %d", &src_port))
1941  ;
1942  else if (unformat (line_input, "disable"))
1943  enable = 0;
1944  else
1945  {
1946  error = clib_error_return (0, "unknown input '%U'",
1947  format_unformat_error, line_input);
1948  goto done;
1949  }
1950  }
1951 
1952  rv = snat_ipfix_logging_enable_disable (enable, domain_id, (u16) src_port);
1953 
1954  if (rv)
1955  {
1956  error = clib_error_return (0, "ipfix logging enable failed");
1957  goto done;
1958  }
1959 
1960 done:
1961  unformat_free (line_input);
1962 
1963  return error;
1964 }
1965 
1966 /*?
1967  * @cliexpar
1968  * @cliexstart{snat ipfix logging}
1969  * To enable NAT IPFIX logging use:
1970  * vpp# nat ipfix logging
1971  * To set IPFIX exporter use:
1972  * vpp# set ipfix exporter collector 10.10.10.3 src 10.10.10.1
1973  * @cliexend
1974 ?*/
1975 VLIB_CLI_COMMAND (snat_ipfix_logging_enable_disable_command, static) = {
1976  .path = "nat ipfix logging",
1978  .short_help = "nat ipfix logging [domain <domain-id>] [src-port <port>] [disable]",
1979 };
1980 
1981 static u32
1983 {
1984  snat_main_t *sm = &snat_main;
1985  u32 next_worker_index = 0;
1986  u32 hash;
1987 
1988  next_worker_index = sm->first_worker_index;
1989  hash = ip0->src_address.as_u32 + (ip0->src_address.as_u32 >> 8) +
1990  (ip0->src_address.as_u32 >> 16) + (ip0->src_address.as_u32 >>24);
1991 
1992  if (PREDICT_TRUE (is_pow2 (_vec_len (sm->workers))))
1993  next_worker_index += sm->workers[hash & (_vec_len (sm->workers) - 1)];
1994  else
1995  next_worker_index += sm->workers[hash % _vec_len (sm->workers)];
1996 
1997  return next_worker_index;
1998 }
1999 
2000 static u32
2002 {
2003  snat_main_t *sm = &snat_main;
2004  udp_header_t *udp;
2005  u16 port;
2006  snat_session_key_t m_key;
2007  clib_bihash_kv_8_8_t kv, value;
2009  nat_ed_ses_key_t key;
2010  clib_bihash_kv_16_8_t s_kv, s_value;
2012  snat_session_t *s;
2013  int i;
2014  u32 proto;
2015 
2016  /* first try static mappings without port */
2018  {
2019  m_key.addr = ip0->dst_address;
2020  m_key.port = 0;
2021  m_key.protocol = 0;
2022  m_key.fib_index = rx_fib_index0;
2023  kv.key = m_key.as_u64;
2024  if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
2025  {
2026  m = pool_elt_at_index (sm->static_mappings, value.value);
2027  return m->worker_index;
2028  }
2029  }
2030 
2031  proto = ip_proto_to_snat_proto (ip0->protocol);
2032  udp = ip4_next_header (ip0);
2033  port = udp->dst_port;
2034 
2035  /* unknown protocol */
2036  if (PREDICT_FALSE (proto == ~0))
2037  {
2038  key.l_addr = ip0->dst_address;
2039  key.r_addr = ip0->src_address;
2040  key.fib_index = rx_fib_index0;
2041  key.proto = ip0->protocol;
2042  key.rsvd = 0;
2043  key.l_port = 0;
2044  s_kv.key[0] = key.as_u64[0];
2045  s_kv.key[1] = key.as_u64[1];
2046 
2047  if (!clib_bihash_search_16_8 (&sm->out2in_ed, &s_kv, &s_value))
2048  {
2049  for (i = 0; i < _vec_len (sm->per_thread_data); i++)
2050  {
2051  tsm = vec_elt_at_index (sm->per_thread_data, i);
2052  if (!pool_is_free_index(tsm->sessions, s_value.value))
2053  {
2054  s = pool_elt_at_index (tsm->sessions, s_value.value);
2055  if (s->out2in.addr.as_u32 == ip0->dst_address.as_u32 &&
2056  s->out2in.port == ip0->protocol &&
2058  return i;
2059  }
2060  }
2061  }
2062 
2063  /* if no session use current thread */
2064  return vlib_get_thread_index ();
2065  }
2066 
2067  if (PREDICT_FALSE (ip0->protocol == IP_PROTOCOL_ICMP))
2068  {
2069  icmp46_header_t * icmp = (icmp46_header_t *) udp;
2070  icmp_echo_header_t *echo = (icmp_echo_header_t *)(icmp + 1);
2071  if (!icmp_is_error_message (icmp))
2072  port = echo->identifier;
2073  else
2074  {
2075  ip4_header_t *inner_ip = (ip4_header_t *)(echo + 1);
2076  proto = ip_proto_to_snat_proto (inner_ip->protocol);
2077  void *l4_header = ip4_next_header (inner_ip);
2078  switch (proto)
2079  {
2080  case SNAT_PROTOCOL_ICMP:
2081  icmp = (icmp46_header_t*)l4_header;
2082  echo = (icmp_echo_header_t *)(icmp + 1);
2083  port = echo->identifier;
2084  break;
2085  case SNAT_PROTOCOL_UDP:
2086  case SNAT_PROTOCOL_TCP:
2087  port = ((tcp_udp_header_t*)l4_header)->src_port;
2088  break;
2089  default:
2090  return vlib_get_thread_index ();
2091  }
2092  }
2093  }
2094 
2095  /* try static mappings with port */
2096  if (PREDICT_FALSE (pool_elts (sm->static_mappings)))
2097  {
2098  m_key.addr = ip0->dst_address;
2099  m_key.port = clib_net_to_host_u16 (port);
2100  m_key.protocol = proto;
2101  m_key.fib_index = rx_fib_index0;
2102  kv.key = m_key.as_u64;
2103  if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
2104  {
2105  m = pool_elt_at_index (sm->static_mappings, value.value);
2106  return m->worker_index;
2107  }
2108  }
2109 
2110  /* worker by outside port */
2111  return (u32) ((clib_net_to_host_u16 (port) - 1024) / sm->port_per_thread);
2112 }
2113 
2114 static clib_error_t *
2116 {
2117  snat_main_t * sm = &snat_main;
2118  u32 translation_buckets = 1024;
2119  u32 translation_memory_size = 128<<20;
2120  u32 user_buckets = 128;
2121  u32 user_memory_size = 64<<20;
2122  u32 max_translations_per_user = 100;
2123  u32 outside_vrf_id = 0;
2124  u32 inside_vrf_id = 0;
2125  u32 static_mapping_buckets = 1024;
2126  u32 static_mapping_memory_size = 64<<20;
2127  u8 static_mapping_only = 0;
2128  u8 static_mapping_connection_tracking = 0;
2130 
2131  sm->deterministic = 0;
2132 
2133  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2134  {
2135  if (unformat (input, "translation hash buckets %d", &translation_buckets))
2136  ;
2137  else if (unformat (input, "translation hash memory %d",
2138  &translation_memory_size));
2139  else if (unformat (input, "user hash buckets %d", &user_buckets))
2140  ;
2141  else if (unformat (input, "user hash memory %d",
2142  &user_memory_size))
2143  ;
2144  else if (unformat (input, "max translations per user %d",
2145  &max_translations_per_user))
2146  ;
2147  else if (unformat (input, "outside VRF id %d",
2148  &outside_vrf_id))
2149  ;
2150  else if (unformat (input, "inside VRF id %d",
2151  &inside_vrf_id))
2152  ;
2153  else if (unformat (input, "static mapping only"))
2154  {
2155  static_mapping_only = 1;
2156  if (unformat (input, "connection tracking"))
2157  static_mapping_connection_tracking = 1;
2158  }
2159  else if (unformat (input, "deterministic"))
2160  sm->deterministic = 1;
2161  else
2162  return clib_error_return (0, "unknown input '%U'",
2163  format_unformat_error, input);
2164  }
2165 
2166  /* for show commands, etc. */
2167  sm->translation_buckets = translation_buckets;
2168  sm->translation_memory_size = translation_memory_size;
2169  /* do not exceed load factor 10 */
2170  sm->max_translations = 10 * translation_buckets;
2171  sm->user_buckets = user_buckets;
2172  sm->user_memory_size = user_memory_size;
2173  sm->max_translations_per_user = max_translations_per_user;
2174  sm->outside_vrf_id = outside_vrf_id;
2176  outside_vrf_id,
2178  sm->inside_vrf_id = inside_vrf_id;
2180  inside_vrf_id,
2182  sm->static_mapping_only = static_mapping_only;
2183  sm->static_mapping_connection_tracking = static_mapping_connection_tracking;
2184 
2185  if (sm->deterministic)
2186  {
2188  sm->in2out_output_node_index = ~0;
2192  }
2193  else
2194  {
2197  sm->in2out_node_index = snat_in2out_node.index;
2199  sm->out2in_node_index = snat_out2in_node.index;
2200  if (!static_mapping_only ||
2201  (static_mapping_only && static_mapping_connection_tracking))
2202  {
2205 
2206  vec_foreach (tsm, sm->per_thread_data)
2207  {
2208  clib_bihash_init_8_8 (&tsm->in2out, "in2out", translation_buckets,
2209  translation_memory_size);
2210 
2211  clib_bihash_init_8_8 (&tsm->out2in, "out2in", translation_buckets,
2212  translation_memory_size);
2213 
2214  clib_bihash_init_8_8 (&tsm->user_hash, "users", user_buckets,
2215  user_memory_size);
2216  }
2217 
2218  clib_bihash_init_16_8 (&sm->in2out_ed, "in2out-ed",
2219  translation_buckets, translation_memory_size);
2220 
2221  clib_bihash_init_16_8 (&sm->out2in_ed, "out2in-ed",
2222  translation_buckets, translation_memory_size);
2223  }
2224  else
2225  {
2228  }
2229  clib_bihash_init_8_8 (&sm->static_mapping_by_local,
2230  "static_mapping_by_local", static_mapping_buckets,
2231  static_mapping_memory_size);
2232 
2233  clib_bihash_init_8_8 (&sm->static_mapping_by_external,
2234  "static_mapping_by_external", static_mapping_buckets,
2235  static_mapping_memory_size);
2236  }
2237 
2238  return 0;
2239 }
2240 
2242 
2243 u8 * format_snat_session_state (u8 * s, va_list * args)
2244 {
2245  u32 i = va_arg (*args, u32);
2246  u8 *t = 0;
2247 
2248  switch (i)
2249  {
2250 #define _(v, N, str) case SNAT_SESSION_##N: t = (u8 *) str; break;
2252 #undef _
2253  default:
2254  t = format (t, "unknown");
2255  }
2256  s = format (s, "%s", t);
2257  return s;
2258 }
2259 
2260 u8 * format_snat_key (u8 * s, va_list * args)
2261 {
2262  snat_session_key_t * key = va_arg (*args, snat_session_key_t *);
2263 
2264  s = format (s, "%U proto %U port %d fib %d",
2265  format_ip4_address, &key->addr,
2267  clib_net_to_host_u16 (key->port), key->fib_index);
2268  return s;
2269 }
2270 
2271 u8 * format_snat_session (u8 * s, va_list * args)
2272 {
2273  snat_main_t * sm __attribute__((unused)) = va_arg (*args, snat_main_t *);
2274  snat_session_t * sess = va_arg (*args, snat_session_t *);
2275 
2276  if (snat_is_unk_proto_session (sess))
2277  {
2278  s = format (s, " i2o %U proto %u fib %u\n",
2279  format_ip4_address, &sess->in2out.addr, sess->in2out.port,
2280  sess->in2out.fib_index);
2281  s = format (s, " o2i %U proto %u fib %u\n",
2282  format_ip4_address, &sess->out2in.addr, sess->out2in.port,
2283  sess->out2in.fib_index);
2284  }
2285  else
2286  {
2287  s = format (s, " i2o %U\n", format_snat_key, &sess->in2out);
2288  s = format (s, " o2i %U\n", format_snat_key, &sess->out2in);
2289  }
2290  if (sess->ext_host_addr.as_u32)
2291  s = format (s, " external host %U\n",
2292  format_ip4_address, &sess->ext_host_addr);
2293  s = format (s, " last heard %.2f\n", sess->last_heard);
2294  s = format (s, " total pkts %d, total bytes %lld\n",
2295  sess->total_pkts, sess->total_bytes);
2296  if (snat_is_session_static (sess))
2297  s = format (s, " static translation\n");
2298  else
2299  s = format (s, " dynamic translation\n");
2300  if (sess->flags & SNAT_SESSION_FLAG_LOAD_BALANCING)
2301  s = format (s, " load-balancing\n");
2302 
2303  return s;
2304 }
2305 
2306 u8 * format_snat_user (u8 * s, va_list * args)
2307 {
2309  snat_user_t * u = va_arg (*args, snat_user_t *);
2310  int verbose = va_arg (*args, int);
2311  dlist_elt_t * head, * elt;
2312  u32 elt_index, head_index;
2313  u32 session_index;
2314  snat_session_t * sess;
2315 
2316  s = format (s, "%U: %d dynamic translations, %d static translations\n",
2318 
2319  if (verbose == 0)
2320  return s;
2321 
2322  if (u->nsessions || u->nstaticsessions)
2323  {
2324  head_index = u->sessions_per_user_list_head_index;
2325  head = pool_elt_at_index (sm->list_pool, head_index);
2326 
2327  elt_index = head->next;
2328  elt = pool_elt_at_index (sm->list_pool, elt_index);
2329  session_index = elt->value;
2330 
2331  while (session_index != ~0)
2332  {
2333  sess = pool_elt_at_index (sm->sessions, session_index);
2334 
2335  s = format (s, " %U\n", format_snat_session, sm, sess);
2336 
2337  elt_index = elt->next;
2338  elt = pool_elt_at_index (sm->list_pool, elt_index);
2339  session_index = elt->value;
2340  }
2341  }
2342 
2343  return s;
2344 }
2345 
2346 u8 * format_snat_static_mapping (u8 * s, va_list * args)
2347 {
2348  snat_static_mapping_t *m = va_arg (*args, snat_static_mapping_t *);
2349  nat44_lb_addr_port_t *local;
2350 
2351  if (m->addr_only)
2352  s = format (s, "local %U external %U vrf %d",
2355  m->vrf_id);
2356  else
2357  {
2358  if (vec_len (m->locals))
2359  {
2360  s = format (s, "%U vrf %d external %U:%d",
2362  m->vrf_id,
2364  vec_foreach (local, m->locals)
2365  s = format (s, "\n local %U:%d probability %d\%",
2366  format_ip4_address, &local->addr, local->port,
2367  local->probability);
2368  }
2369  else
2370  s = format (s, "%U local %U:%d external %U:%d vrf %d",
2374  m->vrf_id);
2375  }
2376  return s;
2377 }
2378 
2379 u8 * format_snat_static_map_to_resolve (u8 * s, va_list * args)
2380 {
2382  vnet_main_t *vnm = vnet_get_main();
2383 
2384  if (m->addr_only)
2385  s = format (s, "local %U external %U vrf %d",
2389  m->vrf_id);
2390  else
2391  s = format (s, "%U local %U:%d external %U:%d vrf %d",
2393  format_ip4_address, &m->l_addr, m->l_port,
2396  m->vrf_id);
2397 
2398  return s;
2399 }
2400 
2401 u8 * format_det_map_ses (u8 * s, va_list * args)
2402 {
2403  snat_det_map_t * det_map = va_arg (*args, snat_det_map_t *);
2404  ip4_address_t in_addr, out_addr;
2405  u32 in_offset, out_offset;
2406  snat_det_session_t * ses = va_arg (*args, snat_det_session_t *);
2407  u32 * i = va_arg (*args, u32 *);
2408 
2409  u32 user_index = *i / SNAT_DET_SES_PER_USER;
2410  in_addr.as_u32 = clib_host_to_net_u32 (
2411  clib_net_to_host_u32(det_map->in_addr.as_u32) + user_index);
2412  in_offset = clib_net_to_host_u32(in_addr.as_u32) -
2413  clib_net_to_host_u32(det_map->in_addr.as_u32);
2414  out_offset = in_offset / det_map->sharing_ratio;
2415  out_addr.as_u32 = clib_host_to_net_u32(
2416  clib_net_to_host_u32(det_map->out_addr.as_u32) + out_offset);
2417  s = format (s, "in %U:%d out %U:%d external host %U:%d state: %U expire: %d\n",
2418  format_ip4_address, &in_addr,
2419  clib_net_to_host_u16 (ses->in_port),
2420  format_ip4_address, &out_addr,
2421  clib_net_to_host_u16 (ses->out.out_port),
2423  clib_net_to_host_u16 (ses->out.ext_host_port),
2425  ses->expire);
2426 
2427  return s;
2428 }
2429 
2430 static clib_error_t *
2432  unformat_input_t * input,
2433  vlib_cli_command_t * cmd)
2434 {
2435  int verbose = 0;
2436  snat_main_t * sm = &snat_main;
2437  snat_user_t * u;
2440  snat_address_t * ap;
2441  vnet_main_t *vnm = vnet_get_main();
2443  u32 users_num = 0, sessions_num = 0, *worker, *sw_if_index;
2444  uword j = 0;
2446  snat_det_map_t * dm;
2447  snat_det_session_t * ses;
2448 
2449  if (unformat (input, "detail"))
2450  verbose = 1;
2451  else if (unformat (input, "verbose"))
2452  verbose = 2;
2453 
2454  if (sm->static_mapping_only)
2455  {
2457  vlib_cli_output (vm, "NAT plugin mode: static mapping only connection "
2458  "tracking");
2459  else
2460  vlib_cli_output (vm, "NAT plugin mode: static mapping only");
2461  }
2462  else if (sm->deterministic)
2463  {
2464  vlib_cli_output (vm, "NAT plugin mode: deterministic mapping");
2465  }
2466  else
2467  {
2468  vlib_cli_output (vm, "NAT plugin mode: dynamic translations enabled");
2469  }
2470 
2471  if (verbose > 0)
2472  {
2473  pool_foreach (i, sm->interfaces,
2474  ({
2475  vlib_cli_output (vm, "%U %s", format_vnet_sw_interface_name, vnm,
2476  vnet_get_sw_interface (vnm, i->sw_if_index),
2477  i->is_inside ? "in" : "out");
2478  }));
2479 
2481  ({
2482  vlib_cli_output (vm, "%U output-feature %s",
2483  format_vnet_sw_interface_name, vnm,
2484  vnet_get_sw_interface (vnm, i->sw_if_index),
2485  i->is_inside ? "in" : "out");
2486  }));
2487 
2488  if (vec_len (sm->auto_add_sw_if_indices))
2489  {
2490  vlib_cli_output (vm, "NAT44 pool addresses interfaces:");
2491  vec_foreach (sw_if_index, sm->auto_add_sw_if_indices)
2492  {
2494  vnet_get_sw_interface (vnm, *sw_if_index));
2495  }
2496  }
2497 
2498  vec_foreach (ap, sm->addresses)
2499  {
2500  vlib_cli_output (vm, "%U", format_ip4_address, &ap->addr);
2501  if (ap->fib_index != ~0)
2502  vlib_cli_output (vm, " tenant VRF: %u",
2504  else
2505  vlib_cli_output (vm, " tenant VRF independent");
2506 #define _(N, i, n, s) \
2507  vlib_cli_output (vm, " %d busy %s ports", ap->busy_##n##_ports, s);
2509 #undef _
2510  }
2511  }
2512 
2513  if (sm->num_workers > 1)
2514  {
2515  vlib_cli_output (vm, "%d workers", vec_len (sm->workers));
2516  if (verbose > 0)
2517  {
2518  vec_foreach (worker, sm->workers)
2519  {
2521  vlib_worker_threads + *worker + sm->first_worker_index;
2522  vlib_cli_output (vm, " %s", w->name);
2523  }
2524  }
2525  }
2526 
2527  if (sm->deterministic)
2528  {
2529  vlib_cli_output (vm, "udp timeout: %dsec", sm->udp_timeout);
2530  vlib_cli_output (vm, "tcp-established timeout: %dsec",
2532  vlib_cli_output (vm, "tcp-transitory timeout: %dsec",
2534  vlib_cli_output (vm, "icmp timeout: %dsec", sm->icmp_timeout);
2535  vlib_cli_output (vm, "%d deterministic mappings",
2536  pool_elts (sm->det_maps));
2537  if (verbose > 0)
2538  {
2539  pool_foreach (dm, sm->det_maps,
2540  ({
2541  vlib_cli_output (vm, "in %U/%d out %U/%d\n",
2542  format_ip4_address, &dm->in_addr, dm->in_plen,
2543  format_ip4_address, &dm->out_addr, dm->out_plen);
2544  vlib_cli_output (vm, " outside address sharing ratio: %d\n",
2545  dm->sharing_ratio);
2546  vlib_cli_output (vm, " number of ports per inside host: %d\n",
2547  dm->ports_per_host);
2548  vlib_cli_output (vm, " sessions number: %d\n", dm->ses_num);
2549  if (verbose > 1)
2550  {
2551  vec_foreach_index (j, dm->sessions)
2552  {
2553  ses = vec_elt_at_index (dm->sessions, j);
2554  if (ses->in_port)
2555  vlib_cli_output (vm, " %U", format_det_map_ses, dm, ses,
2556  &j);
2557  }
2558  }
2559  }));
2560  }
2561  }
2562  else
2563  {
2564  if (sm->static_mapping_only && !(sm->static_mapping_connection_tracking))
2565  {
2566  vlib_cli_output (vm, "%d static mappings",
2567  pool_elts (sm->static_mappings));
2568 
2569  if (verbose > 0)
2570  {
2571  pool_foreach (m, sm->static_mappings,
2572  ({
2573  vlib_cli_output (vm, "%U", format_snat_static_mapping, m);
2574  }));
2575  }
2576  }
2577  else
2578  {
2579  vec_foreach (tsm, sm->per_thread_data)
2580  {
2581  users_num += pool_elts (tsm->users);
2582  sessions_num += pool_elts (tsm->sessions);
2583  }
2584 
2585  vlib_cli_output (vm, "%d users, %d outside addresses, %d active sessions,"
2586  " %d static mappings",
2587  users_num,
2588  vec_len (sm->addresses),
2589  sessions_num,
2590  pool_elts (sm->static_mappings));
2591 
2592  if (verbose > 0)
2593  {
2594  vlib_cli_output (vm, "%U", format_bihash_16_8, &sm->in2out_ed,
2595  verbose - 1);
2596  vlib_cli_output (vm, "%U", format_bihash_16_8, &sm->out2in_ed,
2597  verbose - 1);
2598  vec_foreach_index (j, sm->per_thread_data)
2599  {
2600  tsm = vec_elt_at_index (sm->per_thread_data, j);
2601 
2602  if (pool_elts (tsm->users) == 0)
2603  continue;
2604 
2606  vlib_cli_output (vm, "Thread %d (%s at lcore %u):", j, w->name,
2607  w->lcore_id);
2608  vlib_cli_output (vm, " %U", format_bihash_8_8, &tsm->in2out,
2609  verbose - 1);
2610  vlib_cli_output (vm, " %U", format_bihash_8_8, &tsm->out2in,
2611  verbose - 1);
2612  vlib_cli_output (vm, " %d list pool elements",
2613  pool_elts (tsm->list_pool));
2614 
2615  pool_foreach (u, tsm->users,
2616  ({
2617  vlib_cli_output (vm, " %U", format_snat_user, tsm, u,
2618  verbose - 1);
2619  }));
2620  }
2621 
2622  if (pool_elts (sm->static_mappings))
2623  {
2624  vlib_cli_output (vm, "static mappings:");
2625  pool_foreach (m, sm->static_mappings,
2626  ({
2627  vlib_cli_output (vm, "%U", format_snat_static_mapping, m);
2628  }));
2629  for (j = 0; j < vec_len (sm->to_resolve); j++)
2630  {
2631  rp = sm->to_resolve + j;
2632  vlib_cli_output (vm, "%U",
2634  }
2635  }
2636  }
2637  }
2638  }
2639  return 0;
2640 }
2641 
2642 VLIB_CLI_COMMAND (show_snat_command, static) = {
2643  .path = "show nat44",
2644  .short_help = "show nat44",
2645  .function = show_snat_command_fn,
2646 };
2647 
2648 
2649 static void
2651  uword opaque,
2652  u32 sw_if_index,
2653  ip4_address_t * address,
2654  u32 address_length,
2655  u32 if_address_index,
2656  u32 is_delete)
2657 {
2658  snat_main_t *sm = &snat_main;
2660  u32 *indices_to_delete = 0;
2661  int i, j;
2662  int rv;
2663 
2664  for (i = 0; i < vec_len(sm->auto_add_sw_if_indices); i++)
2665  {
2666  if (sw_if_index == sm->auto_add_sw_if_indices[i])
2667  {
2668  if (!is_delete)
2669  {
2670  /* Don't trip over lease renewal, static config */
2671  for (j = 0; j < vec_len(sm->addresses); j++)
2672  if (sm->addresses[j].addr.as_u32 == address->as_u32)
2673  return;
2674 
2675  snat_add_address (sm, address, ~0);
2676  /* Scan static map resolution vector */
2677  for (j = 0; j < vec_len (sm->to_resolve); j++)
2678  {
2679  rp = sm->to_resolve + j;
2680  /* On this interface? */
2681  if (rp->sw_if_index == sw_if_index)
2682  {
2683  /* Add the static mapping */
2684  rv = snat_add_static_mapping (rp->l_addr,
2685  address[0],
2686  rp->l_port,
2687  rp->e_port,
2688  rp->vrf_id,
2689  rp->addr_only,
2690  ~0 /* sw_if_index */,
2691  rp->proto,
2692  rp->is_add);
2693  if (rv)
2694  clib_warning ("snat_add_static_mapping returned %d",
2695  rv);
2696  vec_add1 (indices_to_delete, j);
2697  }
2698  }
2699  /* If we resolved any of the outstanding static mappings */
2700  if (vec_len(indices_to_delete))
2701  {
2702  /* Delete them */
2703  for (j = vec_len(indices_to_delete)-1; j >= 0; j--)
2704  vec_delete(sm->to_resolve, 1, j);
2705  vec_free(indices_to_delete);
2706  }
2707  return;
2708  }
2709  else
2710  {
2711  (void) snat_del_address(sm, address[0], 1);
2712  return;
2713  }
2714  }
2715  }
2716 }
2717 
2718 
2719 int snat_add_interface_address (snat_main_t *sm, u32 sw_if_index, int is_del)
2720 {
2721  ip4_main_t * ip4_main = sm->ip4_main;
2722  ip4_address_t * first_int_addr;
2724  u32 *indices_to_delete = 0;
2725  int i, j;
2726 
2727  first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index,
2728  0 /* just want the address*/);
2729 
2730  for (i = 0; i < vec_len(sm->auto_add_sw_if_indices); i++)
2731  {
2732  if (sm->auto_add_sw_if_indices[i] == sw_if_index)
2733  {
2734  if (is_del)
2735  {
2736  /* if have address remove it */
2737  if (first_int_addr)
2738  (void) snat_del_address (sm, first_int_addr[0], 1);
2739  else
2740  {
2741  for (j = 0; j < vec_len (sm->to_resolve); j++)
2742  {
2743  rp = sm->to_resolve + j;
2744  if (rp->sw_if_index == sw_if_index)
2745  vec_add1 (indices_to_delete, j);
2746  }
2747  if (vec_len(indices_to_delete))
2748  {
2749  for (j = vec_len(indices_to_delete)-1; j >= 0; j--)
2750  vec_del1(sm->to_resolve, j);
2751  vec_free(indices_to_delete);
2752  }
2753  }
2755  }
2756  else
2757  return VNET_API_ERROR_VALUE_EXIST;
2758 
2759  return 0;
2760  }
2761  }
2762 
2763  if (is_del)
2764  return VNET_API_ERROR_NO_SUCH_ENTRY;
2765 
2766  /* add to the auto-address list */
2767  vec_add1(sm->auto_add_sw_if_indices, sw_if_index);
2768 
2769  /* If the address is already bound - or static - add it now */
2770  if (first_int_addr)
2771  snat_add_address (sm, first_int_addr, ~0);
2772 
2773  return 0;
2774 }
2775 
2776 static clib_error_t *
2778  unformat_input_t * input,
2779  vlib_cli_command_t * cmd)
2780 {
2781  snat_main_t *sm = &snat_main;
2782  unformat_input_t _line_input, *line_input = &_line_input;
2783  u32 sw_if_index;
2784  int rv;
2785  int is_del = 0;
2786  clib_error_t *error = 0;
2787 
2788  /* Get a line of input. */
2789  if (!unformat_user (input, unformat_line_input, line_input))
2790  return 0;
2791 
2792  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2793  {
2794  if (unformat (line_input, "%U", unformat_vnet_sw_interface,
2795  sm->vnet_main, &sw_if_index))
2796  ;
2797  else if (unformat (line_input, "del"))
2798  is_del = 1;
2799  else
2800  {
2801  error = clib_error_return (0, "unknown input '%U'",
2802  format_unformat_error, line_input);
2803  goto done;
2804  }
2805  }
2806 
2807  rv = snat_add_interface_address (sm, sw_if_index, is_del);
2808 
2809  switch (rv)
2810  {
2811  case 0:
2812  break;
2813 
2814  default:
2815  error = clib_error_return (0, "snat_add_interface_address returned %d",
2816  rv);
2817  goto done;
2818  }
2819 
2820 done:
2821  unformat_free (line_input);
2822 
2823  return error;
2824 }
2825 
2826 VLIB_CLI_COMMAND (snat_add_interface_address_command, static) = {
2827  .path = "nat44 add interface address",
2828  .short_help = "nat44 add interface address <interface> [del]",
2830 };
2831 
2832 static clib_error_t *
2834  unformat_input_t * input,
2835  vlib_cli_command_t * cmd)
2836 {
2837  snat_main_t *sm = &snat_main;
2838  unformat_input_t _line_input, *line_input = &_line_input;
2839  ip4_address_t in_addr, out_addr;
2840  u32 in_plen, out_plen;
2841  int is_add = 1, rv;
2842  clib_error_t *error = 0;
2843 
2844  /* Get a line of input. */
2845  if (!unformat_user (input, unformat_line_input, line_input))
2846  return 0;
2847 
2848  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2849  {
2850  if (unformat (line_input, "in %U/%u", unformat_ip4_address, &in_addr, &in_plen))
2851  ;
2852  else if (unformat (line_input, "out %U/%u", unformat_ip4_address, &out_addr, &out_plen))
2853  ;
2854  else if (unformat (line_input, "del"))
2855  is_add = 0;
2856  else
2857  {
2858  error = clib_error_return (0, "unknown input '%U'",
2859  format_unformat_error, line_input);
2860  goto done;
2861  }
2862  }
2863 
2864  unformat_free (line_input);
2865 
2866  rv = snat_det_add_map(sm, &in_addr, (u8) in_plen, &out_addr, (u8)out_plen,
2867  is_add);
2868 
2869  if (rv)
2870  {
2871  error = clib_error_return (0, "snat_det_add_map return %d", rv);
2872  goto done;
2873  }
2874 
2875 done:
2876  unformat_free (line_input);
2877 
2878  return error;
2879 }
2880 
2881 /*?
2882  * @cliexpar
2883  * @cliexstart{snat deterministic add}
2884  * Create bijective mapping of inside address to outside address and port range
2885  * pairs, with the purpose of enabling deterministic NAT to reduce logging in
2886  * CGN deployments.
2887  * To create deterministic mapping between inside network 10.0.0.0/18 and
2888  * outside network 1.1.1.0/30 use:
2889  * # vpp# nat44 deterministic add in 10.0.0.0/18 out 1.1.1.0/30
2890  * @cliexend
2891 ?*/
2892 VLIB_CLI_COMMAND (snat_det_map_command, static) = {
2893  .path = "nat44 deterministic add",
2894  .short_help = "nat44 deterministic add in <addr>/<plen> out <addr>/<plen> [del]",
2895  .function = snat_det_map_command_fn,
2896 };
2897 
2898 static clib_error_t *
2900  unformat_input_t * input,
2901  vlib_cli_command_t * cmd)
2902 {
2903  snat_main_t *sm = &snat_main;
2904  unformat_input_t _line_input, *line_input = &_line_input;
2905  ip4_address_t in_addr, out_addr;
2906  u16 lo_port;
2907  snat_det_map_t * dm;
2908  clib_error_t *error = 0;
2909 
2910  /* Get a line of input. */
2911  if (!unformat_user (input, unformat_line_input, line_input))
2912  return 0;
2913 
2914  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2915  {
2916  if (unformat (line_input, "%U", unformat_ip4_address, &in_addr))
2917  ;
2918  else
2919  {
2920  error = clib_error_return (0, "unknown input '%U'",
2921  format_unformat_error, line_input);
2922  goto done;
2923  }
2924  }
2925 
2926  unformat_free (line_input);
2927 
2928  dm = snat_det_map_by_user(sm, &in_addr);
2929  if (!dm)
2930  vlib_cli_output (vm, "no match");
2931  else
2932  {
2933  snat_det_forward (dm, &in_addr, &out_addr, &lo_port);
2934  vlib_cli_output (vm, "%U:<%d-%d>", format_ip4_address, &out_addr,
2935  lo_port, lo_port + dm->ports_per_host - 1);
2936  }
2937 
2938 done:
2939  unformat_free (line_input);
2940 
2941  return error;
2942 }
2943 
2944 /*?
2945  * @cliexpar
2946  * @cliexstart{snat deterministic forward}
2947  * Return outside address and port range from inside address for deterministic
2948  * NAT.
2949  * To obtain outside address and port of inside host use:
2950  * vpp# nat44 deterministic forward 10.0.0.2
2951  * 1.1.1.0:<1054-1068>
2952  * @cliexend
2953 ?*/
2954 VLIB_CLI_COMMAND (snat_det_forward_command, static) = {
2955  .path = "nat44 deterministic forward",
2956  .short_help = "nat44 deterministic forward <addr>",
2957  .function = snat_det_forward_command_fn,
2958 };
2959 
2960 static clib_error_t *
2962  unformat_input_t * input,
2963  vlib_cli_command_t * cmd)
2964 {
2965  snat_main_t *sm = &snat_main;
2966  unformat_input_t _line_input, *line_input = &_line_input;
2967  ip4_address_t in_addr, out_addr;
2968  u32 out_port;
2969  snat_det_map_t * dm;
2970  clib_error_t *error = 0;
2971 
2972  /* Get a line of input. */
2973  if (!unformat_user (input, unformat_line_input, line_input))
2974  return 0;
2975 
2976  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2977  {
2978  if (unformat (line_input, "%U:%d", unformat_ip4_address, &out_addr, &out_port))
2979  ;
2980  else
2981  {
2982  error = clib_error_return (0, "unknown input '%U'",
2983  format_unformat_error, line_input);
2984  }
2985  }
2986 
2987  unformat_free (line_input);
2988 
2989  if (out_port < 1024 || out_port > 65535)
2990  {
2991  error = clib_error_return (0, "wrong port, must be <1024-65535>");
2992  goto done;
2993  }
2994 
2995  dm = snat_det_map_by_out(sm, &out_addr);
2996  if (!dm)
2997  vlib_cli_output (vm, "no match");
2998  else
2999  {
3000  snat_det_reverse (dm, &out_addr, (u16) out_port, &in_addr);
3001  vlib_cli_output (vm, "%U", format_ip4_address, &in_addr);
3002  }
3003 
3004 done:
3005  unformat_free (line_input);
3006 
3007  return error;
3008 }
3009 
3010 /*?
3011  * @cliexpar
3012  * @cliexstart{snat deterministic reverse}
3013  * Return inside address from outside address and port for deterministic NAT.
3014  * To obtain inside host address from outside address and port use:
3015  * #vpp nat44 deterministic reverse 1.1.1.1:1276
3016  * 10.0.16.16
3017  * @cliexend
3018 ?*/
3019 VLIB_CLI_COMMAND (snat_det_reverse_command, static) = {
3020  .path = "nat44 deterministic reverse",
3021  .short_help = "nat44 deterministic reverse <addr>:<port>",
3022  .function = snat_det_reverse_command_fn,
3023 };
3024 
3025 static clib_error_t *
3027  unformat_input_t * input,
3028  vlib_cli_command_t * cmd)
3029 {
3030  snat_main_t *sm = &snat_main;
3031  unformat_input_t _line_input, *line_input = &_line_input;
3032  clib_error_t *error = 0;
3033 
3034  /* Get a line of input. */
3035  if (!unformat_user (input, unformat_line_input, line_input))
3036  return 0;
3037 
3038  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
3039  {
3040  if (unformat (line_input, "udp %u", &sm->udp_timeout))
3041  ;
3042  else if (unformat (line_input, "tcp-established %u",
3044  ;
3045  else if (unformat (line_input, "tcp-transitory %u",
3046  &sm->tcp_transitory_timeout))
3047  ;
3048  else if (unformat (line_input, "icmp %u", &sm->icmp_timeout))
3049  ;
3050  else if (unformat (line_input, "reset"))
3051  {
3056  }
3057  else
3058  {
3059  error = clib_error_return (0, "unknown input '%U'",
3060  format_unformat_error, line_input);
3061  goto done;
3062  }
3063  }
3064 
3065  unformat_free (line_input);
3066 
3067 done:
3068  unformat_free (line_input);
3069 
3070  return error;
3071 }
3072 
3073 /*?
3074  * @cliexpar
3075  * @cliexstart{set snat deterministic timeout}
3076  * Set values of timeouts for deterministic NAT (in seconds), use:
3077  * vpp# set nat44 deterministic timeout udp 120 tcp-established 7500
3078  * tcp-transitory 250 icmp 90
3079  * To reset default values use:
3080  * vpp# set nat44 deterministic timeout reset
3081  * @cliexend
3082 ?*/
3083 VLIB_CLI_COMMAND (set_timeout_command, static) = {
3084  .path = "set nat44 deterministic timeout",
3085  .function = set_timeout_command_fn,
3086  .short_help =
3087  "set nat44 deterministic timeout [udp <sec> | tcp-established <sec> "
3088  "tcp-transitory <sec> | icmp <sec> | reset]",
3089 };
3090 
3091 static clib_error_t *
3093  unformat_input_t * input,
3094  vlib_cli_command_t * cmd)
3095 {
3096  snat_main_t *sm = &snat_main;
3097  unformat_input_t _line_input, *line_input = &_line_input;
3098  ip4_address_t out_addr, ext_addr, in_addr;
3099  u32 out_port, ext_port;
3100  snat_det_map_t * dm;
3101  snat_det_session_t * ses;
3102  snat_det_out_key_t key;
3103  clib_error_t *error = 0;
3104 
3105  /* Get a line of input. */
3106  if (!unformat_user (input, unformat_line_input, line_input))
3107  return 0;
3108 
3109  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
3110  {
3111  if (unformat (line_input, "%U:%d %U:%d",
3112  unformat_ip4_address, &out_addr, &out_port,
3113  unformat_ip4_address, &ext_addr, &ext_port))
3114  ;
3115  else
3116  {
3117  error = clib_error_return (0, "unknown input '%U'",
3118  format_unformat_error, line_input);
3119  goto done;
3120  }
3121  }
3122 
3123  unformat_free (line_input);
3124 
3125  dm = snat_det_map_by_out(sm, &out_addr);
3126  if (!dm)
3127  vlib_cli_output (vm, "no match");
3128  else
3129  {
3130  snat_det_reverse(dm, &ext_addr, (u16)out_port, &in_addr);
3131  key.ext_host_addr = out_addr;
3132  key.ext_host_port = ntohs((u16)ext_port);
3133  key.out_port = ntohs((u16)out_port);
3134  ses = snat_det_get_ses_by_out(dm, &out_addr, key.as_u64);
3135  if (!ses)
3136  vlib_cli_output (vm, "no match");
3137  else
3138  snat_det_ses_close(dm, ses);
3139  }
3140 
3141 done:
3142  unformat_free (line_input);
3143 
3144  return error;
3145 }
3146 
3147 /*?
3148  * @cliexpar
3149  * @cliexstart{snat deterministic close session out}
3150  * Close session using outside ip address and port
3151  * and external ip address and port, use:
3152  * vpp# nat44 deterministic close session out 1.1.1.1:1276 2.2.2.2:2387
3153  * @cliexend
3154 ?*/
3155 VLIB_CLI_COMMAND (snat_det_close_sesion_out_command, static) = {
3156  .path = "nat44 deterministic close session out",
3157  .short_help = "nat44 deterministic close session out "
3158  "<out_addr>:<out_port> <ext_addr>:<ext_port>",
3159  .function = snat_det_close_session_out_fn,
3160 };
3161 
3162 static clib_error_t *
3164  unformat_input_t * input,
3165  vlib_cli_command_t * cmd)
3166 {
3167  snat_main_t *sm = &snat_main;
3168  unformat_input_t _line_input, *line_input = &_line_input;
3169  ip4_address_t in_addr, ext_addr;
3170  u32 in_port, ext_port;
3171  snat_det_map_t * dm;
3172  snat_det_session_t * ses;
3173  snat_det_out_key_t key;
3174  clib_error_t *error = 0;
3175 
3176  /* Get a line of input. */
3177  if (!unformat_user (input, unformat_line_input, line_input))
3178  return 0;
3179 
3180  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
3181  {
3182  if (unformat (line_input, "%U:%d %U:%d",
3183  unformat_ip4_address, &in_addr, &in_port,
3184  unformat_ip4_address, &ext_addr, &ext_port))
3185  ;
3186  else
3187  {
3188  error = clib_error_return (0, "unknown input '%U'",
3189  format_unformat_error, line_input);
3190  goto done;
3191  }
3192  }
3193 
3194  unformat_free (line_input);
3195 
3196  dm = snat_det_map_by_user (sm, &in_addr);
3197  if (!dm)
3198  vlib_cli_output (vm, "no match");
3199  else
3200  {
3201  key.ext_host_addr = ext_addr;
3202  key.ext_host_port = ntohs ((u16)ext_port);
3203  ses = snat_det_find_ses_by_in (dm, &in_addr, ntohs((u16)in_port), key);
3204  if (!ses)
3205  vlib_cli_output (vm, "no match");
3206  else
3207  snat_det_ses_close(dm, ses);
3208  }
3209 
3210 done:
3211  unformat_free(line_input);
3212 
3213  return error;
3214 }
3215 
3216 /*?
3217  * @cliexpar
3218  * @cliexstart{snat deterministic close_session_in}
3219  * Close session using inside ip address and port
3220  * and external ip address and port, use:
3221  * vpp# nat44 deterministic close session in 3.3.3.3:3487 2.2.2.2:2387
3222  * @cliexend
3223 ?*/
3224 VLIB_CLI_COMMAND (snat_det_close_session_in_command, static) = {
3225  .path = "nat44 deterministic close session in",
3226  .short_help = "nat44 deterministic close session in "
3227  "<in_addr>:<in_port> <ext_addr>:<ext_port>",
3228  .function = snat_det_close_session_in_fn,
3229 };
ip4_address_t external_addr
Definition: nat.h:207
u32 user_memory_size
Definition: nat.h:335
int snat_add_interface_address(snat_main_t *sm, u32 sw_if_index, int is_del)
Definition: nat.c:2719
u8 * format_snat_user(u8 *s, va_list *args)
Definition: nat.c:2306
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:432
clib_error_t * snat_api_init(vlib_main_t *vm, snat_main_t *sm)
Definition: nat_api.c:3367
u32 next
Definition: dlist.h:30
vmrglw vmrglh hi
#define vec_foreach_index(var, v)
Iterate over vector indices.
#define snat_is_session_static(s)
Check if SNAT session is created from static mapping.
Definition: nat.h:409
u32 sessions_per_user_list_head_index
Definition: nat.h:163
clib_bihash_16_8_t out2in_ed
Definition: nat.h:271
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
u16 ext_host_port
Definition: nat.h:79
u16 out_port
Definition: nat.h:80
ip4_add_del_interface_address_callback_t * add_del_interface_address_callbacks
Functions to call when interface address changes.
Definition: ip4.h:129
a
Definition: bitmap.h:516
u8 * format_snat_protocol(u8 *s, va_list *args)
Definition: nat.c:1625
u32 icmp_timeout
Definition: nat.h:349
ip4_address_t src_address
Definition: ip4_packet.h:164
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
u32 fq_in2out_output_index
Definition: nat.h:316
#define SNAT_TCP_ESTABLISHED_TIMEOUT
Definition: nat.h:36
#define PREDICT_TRUE(x)
Definition: clib.h:98
u32 nsessions
Definition: nat.h:164
ip4_address_t addr
Definition: nat.h:199
#define NULL
Definition: clib.h:55
snat_protocol_t proto
Definition: nat.h:213
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:684
void snat_free_outside_address_and_port(snat_main_t *sm, u32 thread_index, snat_session_key_t *k, u32 address_index)
Definition: nat.c:1214
u16 port_per_thread
Definition: nat.h:283
u32 vlib_frame_queue_main_init(u32 node_index, u32 frame_queue_nelts)
Definition: threads.c:1745
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:518
static clib_error_t * snat_det_map_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: nat.c:2833
u32 nstaticsessions
Definition: nat.h:165
static void snat_det_ses_close(snat_det_map_t *dm, snat_det_session_t *ses)
Definition: nat_det.h:179
u32 icmp_match_out2in_slow(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation and create session if needed...
Definition: out2in.c:299
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:557
static snat_det_session_t * snat_det_find_ses_by_in(snat_det_map_t *dm, ip4_address_t *in_addr, u16 in_port, snat_det_out_key_t out_key)
Definition: nat_det.h:129
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
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, 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:754
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:983
static void snat_det_forward(snat_det_map_t *dm, ip4_address_t *in_addr, ip4_address_t *out_addr, u16 *lo_port)
Definition: nat_det.h:75
ip_lookup_main_t lookup_main
Definition: ip4.h:97
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
vlib_node_registration_t snat_det_out2in_node
(constructor) VLIB_REGISTER_NODE (snat_det_out2in_node)
Definition: out2in.c:2001
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
unformat_function_t unformat_vnet_sw_interface
static_always_inline u16 snat_random_port(snat_main_t *sm, u16 min, u16 max)
Definition: nat.c:1333
clib_bihash_16_8_t in2out_ed
Definition: nat.h:272
void snat_add_del_addr_to_fib(ip4_address_t *addr, u8 p_len, u32 sw_if_index, int is_add)
Add/del NAT address to FIB.
Definition: nat.c:119
snat_det_map_t * det_maps
Definition: nat.h:325
u8 vrf_mode
Definition: nat.h:343
static clib_error_t * snat_add_interface_address_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: nat.c:2777
static void snat_ip4_add_del_interface_address_cb(ip4_main_t *im, uword opaque, u32 sw_if_index, ip4_address_t *address, u32 address_length, u32 if_address_index, u32 is_delete)
Definition: nat.c:2650
u32 num_snat_thread
Definition: nat.h:284
static clib_error_t * snat_det_close_session_in_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: nat.c:3163
int snat_static_mapping_match(snat_main_t *sm, snat_session_key_t match, snat_session_key_t *mapping, u8 by_external, u8 *is_addr_only)
Match NAT44 static mapping.
Definition: nat.c:1257
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:225
dlist_elt_t * list_pool
Definition: nat.h:249
static void snat_det_reverse(snat_det_map_t *dm, ip4_address_t *out_addr, u16 out_port, ip4_address_t *in_addr)
Definition: nat_det.h:90
#define snat_is_unk_proto_session(s)
Check if SNAT session for unknown protocol.
Definition: nat.h:415
u8 * format_snat_static_mapping(u8 *s, va_list *args)
Definition: nat.c:2346
u32 icmp_match_in2out_fast(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation.
Definition: in2out.c:618
u8 deterministic
Definition: nat.h:330
int snat_interface_add_del(u32 sw_if_index, u8 is_inside, int is_del)
Definition: nat.c:943
u16 l_port
Definition: nat.h:65
nat44_lb_addr_port_t * locals
Definition: nat.h:215
u32 user_buckets
Definition: nat.h:334
clib_bihash_8_8_t user_hash
Definition: nat.h:240
u16 identifier
Definition: nat.h:424
u32 max_translations_per_user
Definition: nat.h:336
clib_bihash_8_8_t in2out
Definition: nat.h:237
static clib_error_t * snat_feature_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: nat.c:1491
u32 in2out_output_node_index
Definition: nat.h:321
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
Definition: ip4_fib.c:223
format_function_t format_ip4_address
Definition: format.h:79
#define static_always_inline
Definition: clib.h:85
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:437
unformat_function_t unformat_ip4_address
Definition: format.h:76
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
vlib_node_registration_t snat_out2in_node
(constructor) VLIB_REGISTER_NODE (snat_out2in_node)
Definition: out2in.c:1514
u32 table_id
Definition: ip4_fib.h:51
ip4_address_t ext_host_addr
Definition: nat.h:78
ip4_address_t dst_address
Definition: ip4_packet.h:164
static u32 snat_get_worker_in2out_cb(ip4_header_t *ip0, u32 rx_fib_index0)
Definition: nat.c:1982
u32 translation_buckets
Definition: nat.h:331
ip4_address_t addr
Definition: nat.h:161
#define SNAT_DET_SES_PER_USER
Definition: nat_det.h:30
A high priority source a plugin can use.
Definition: fib_entry.h:58
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Aggregrate type for a prefix.
Definition: fib_types.h:160
#define clib_error_return(e, args...)
Definition: error.h:99
int snat_ipfix_logging_enable_disable(int enable, u32 domain_id, u16 src_port)
Enable/disable NAT plugin IPFIX logging.
void snat_ipfix_logging_init(vlib_main_t *vm)
Initialize NAT plugin IPFIX logging.
u8 * format_snat_key(u8 *s, va_list *args)
Definition: nat.c:2260
ip4_main_t * ip4_main
Definition: nat.h:357
unsigned long u64
Definition: types.h:89
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:233
static clib_error_t * add_address_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: nat.c:1392
u16 fp_len
The mask length.
Definition: fib_types.h:164
ip4_address_t local_addr
Definition: nat.h:206
u64 as_u64[2]
Definition: nat.h:69
snat_protocol_t proto
Definition: nat.h:229
u32 icmp_match_out2in_det(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation and create session if needed...
Definition: out2in.c:2038
unformat_function_t unformat_line_input
Definition: format.h:281
VNET_FEATURE_INIT(ip4_snat_in2out, static)
u32 max_translations
Definition: nat.h:333
Definition: fib_entry.h:233
u32 fib_index
Definition: nat.h:64
vlib_worker_thread_t * vlib_worker_threads
Definition: threads.c:35
#define hash_get(h, key)
Definition: hash.h:248
format_function_t format_vnet_sw_interface_name
Definition: fib_entry.h:232
#define clib_bitmap_foreach(i, ai, body)
Macro to iterate across set bits in a bitmap.
Definition: bitmap.h:361
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:458
static clib_error_t * snat_det_forward_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: nat.c:2899
uword * fib_index_by_table_id
Hash table mapping table id to fib index.
Definition: ip4.h:121
static uword clib_bitmap_last_set(uword *ai)
Return the higest numbered set bit in a bitmap.
Definition: bitmap.h:402
u64 key
the key
Definition: bihash_8_8.h:35
static snat_det_map_t * snat_det_map_by_out(snat_main_t *sm, ip4_address_t *out_addr)
Definition: nat_det.h:60
vlib_main_t * vlib_main
Definition: nat.h:355
#define v
Definition: acl.c:323
static clib_error_t * show_snat_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: nat.c:2431
struct _unformat_input_t unformat_input_t
u16 protocol
Definition: nat.h:50
#define SNAT_UDP_TIMEOUT
Definition: nat.h:33
snat_static_mapping_t * static_mappings
Definition: nat.h:296
u32 inside_fib_index
Definition: nat.h:340
void snat_ipfix_logging_nat44_ses_delete(u32 src_ip, u32 nat_src_ip, snat_protocol_t snat_proto, u16 src_port, u16 nat_src_port, u32 vrf_id)
Generate NAT44 session delete event.
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:270
u32 udp_timeout
Definition: nat.h:346
u8 static_mapping_only
Definition: nat.h:328
#define PREDICT_FALSE(x)
Definition: clib.h:97
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:119
static clib_error_t * set_workers_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: nat.c:1852
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:801
clib_bihash_8_8_t static_mapping_by_external
Definition: nat.h:293
api_main_t * api_main
Definition: nat.h:359
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:1177
vnet_main_t * vnet_main
Definition: nat.h:356
u32 inside_vrf_id
Definition: nat.h:339
static clib_error_t * add_lb_static_mapping_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: nat.c:1757
u32 fq_out2in_index
Definition: nat.h:317
snat_interface_t * output_feature_interfaces
Definition: nat.h:300
snat_main_t snat_main
Definition: nat.c:31
u64 value
the value
Definition: bihash_8_8.h:36
snat_user_t * users
Definition: nat.h:243
u32 random_seed
Definition: nat.h:312
api_main_t api_main
Definition: api_shared.c:35
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
clib_bihash_8_8_t out2in
Definition: nat.h:236
static u32 random_u32_max(void)
Maximum value returned by random_u32()
Definition: random.h:80
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:221
vlib_main_t * vm
Definition: buffer.c:283
u32 outside_vrf_id
Definition: nat.h:337
vlib_node_registration_t snat_in2out_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_node)
Definition: in2out.c:86
ip4_address_t l_addr
Definition: nat.h:62
u8 static_mapping_connection_tracking
Definition: nat.h:329
snat_get_worker_function_t * worker_in2out_cb
Definition: nat.h:281
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:336
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:835
ip4_add_del_interface_address_function_t * function
Definition: ip4.h:72
static ip4_fib_t * ip4_fib_get(u32 index)
Get the FIB at the given index.
Definition: ip4_fib.h:105
deterministic NAT definitions
#define clib_warning(format, args...)
Definition: error.h:59
VLIB_PLUGIN_REGISTER()
int snat_interface_add_del_output_feature(u32 sw_if_index, u8 is_inside, int is_del)
Definition: nat.c:1017
u32 sharing_ratio
Definition: nat.h:191
ip4_address_t out_addr
Definition: nat.h:189
u32 outside_fib_index
Definition: nat.h:338
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:267
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:33
ip4_address_t addr
Definition: nat.h:48
int snat_del_address(snat_main_t *sm, ip4_address_t addr, u8 delete_sm)
Definition: nat.c:804
u32 icmp_match_in2out_slow(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation and create session if needed...
Definition: in2out.c:525
u32 tcp_transitory_timeout
Definition: nat.h:348
ip4_address_t r_addr
Definition: nat.h:63
int snat_det_add_map(snat_main_t *sm, ip4_address_t *in_addr, u8 in_plen, ip4_address_t *out_addr, u8 out_plen, int is_add)
Add/delete deterministic NAT mapping.
Definition: nat_det.c:40
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
u32 * auto_add_sw_if_indices
Definition: nat.h:306
int nat44_add_del_lb_static_mapping(ip4_address_t e_addr, u16 e_port, snat_protocol_t proto, u32 vrf_id, nat44_lb_addr_port_t *locals, u8 is_add)
Definition: nat.c:582
static snat_det_map_t * snat_det_map_by_user(snat_main_t *sm, ip4_address_t *user_addr)
Definition: nat_det.h:45
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:293
#define ASSERT(truth)
u8 * format_snat_static_map_to_resolve(u8 *s, va_list *args)
Definition: nat.c:2379
u32 num_workers
Definition: nat.h:277
unsigned int u32
Definition: types.h:88
u32 first_worker_index
Definition: nat.h:278
#define vec_delete(V, N, M)
Delete N elements starting at element M.
Definition: vec.h:781
snat_get_worker_function_t * worker_out2in_cb
Definition: nat.h:282
ip4_address_t l_addr
Definition: nat.h:224
static u32 ip_proto_to_snat_proto(u8 ip_proto)
Definition: nat.h:429
snat_icmp_match_function_t * icmp_match_out2in_cb
Definition: nat.h:275
IPv4 main type.
Definition: ip4.h:95
u64 as_u64
Definition: nat.h:94
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:1084
ip4_address_t addr
Definition: nat.h:91
ip4_address_t in_addr
Definition: nat.h:187
#define clib_bitmap_free(v)
Free a bitmap.
Definition: bitmap.h:92
u32 fq_in2out_index
Definition: nat.h:315
size_t count
Definition: vapi.c:40
uword * thread_registrations_by_name
Definition: threads.h:297
static void clib_dlist_remove(dlist_elt_t *pool, u32 index)
Definition: dlist.h:99
u32 out2in_node_index
Definition: nat.h:322
ip4_address_t addr
Definition: nat.h:169
#define VNET_FEATURES(...)
Definition: feature.h:368
static clib_error_t * snat_init(vlib_main_t *vm)
Definition: nat.c:1137
static uword is_pow2(uword x)
Definition: clib.h:272
u32 value
Definition: dlist.h:32
u64 uword
Definition: types.h:112
vlib_node_registration_t snat_det_in2out_node
(constructor) VLIB_REGISTER_NODE (snat_det_in2out_node)
Definition: in2out.c:90
u32 icmp_match_out2in_fast(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation.
Definition: out2in.c:409
clib_error_t * nat64_init(vlib_main_t *vm)
Initialize NAT64.
Definition: nat64.c:51
NAT64 global declarations.
void increment_v4_address(ip4_address_t *a)
Definition: nat.c:214
unsigned short u16
Definition: types.h:57
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static clib_error_t * set_timeout_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: nat.c:3026
unsigned char u8
Definition: types.h:56
u16 ports_per_host
Definition: nat.h:192
Definition: fib_entry.h:229
static void snat_add_static_mapping_when_resolved(snat_main_t *sm, ip4_address_t l_addr, u16 l_port, u32 sw_if_index, u16 e_port, u32 vrf_id, snat_protocol_t proto, int addr_only, int is_add)
Definition: nat.c:223
static uword unformat_bitmap_list(unformat_input_t *input, va_list *va)
unformat a list of bit ranges into a bitmap (eg "0-3,5-7,11" )
Definition: bitmap.h:693
void snat_ipfix_logging_addresses_exhausted(u32 pool_id)
Generate NAT addresses exhausted event.
u32 * workers
Definition: nat.h:280
snat_main_per_thread_data_t * per_thread_data
Definition: nat.h:287
static void unformat_free(unformat_input_t *i)
Definition: format.h:161
snat_protocol_t
Definition: nat.h:104
snat_det_out_key_t out
Definition: nat.h:181
static clib_error_t * snat_det_reverse_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: nat.c:2961
u32 fib_index
Definition: nat.h:92
snat_address_t * addresses
Definition: nat.h:303
u32 icmp_match_in2out_det(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation and create session if needed...
Definition: in2out.c:2914
u8 * format_snat_session(u8 *s, va_list *args)
Definition: nat.c:2271
#define hash_get_mem(h, key)
Definition: hash.h:268
u8 * format_det_map_ses(u8 *s, va_list *args)
Definition: nat.c:2401
u32 in2out_node_index
Definition: nat.h:320
#define SNAT_ICMP_TIMEOUT
Definition: nat.h:38
uword unformat_snat_protocol(unformat_input_t *input, va_list *args)
Definition: nat.c:1611
static snat_det_session_t * snat_det_get_ses_by_out(snat_det_map_t *dm, ip4_address_t *in_addr, u64 out_key)
Definition: nat_det.h:112
snat_static_map_resolve_t * to_resolve
Definition: nat.h:309
static u32 random_u32(u32 *seed)
32-bit random number generator
Definition: random.h:69
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1175
static clib_error_t * snat_ipfix_logging_enable_disable_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: nat.c:1921
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
u32 translation_memory_size
Definition: nat.h:332
#define vec_foreach(var, vec)
Vector iterator.
vlib_node_registration_t snat_in2out_output_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_output_node)
Definition: in2out.c:91
static clib_error_t * snat_det_close_session_out_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: nat.c:3092
u32 next_worker
Definition: nat.h:279
int snat_set_workers(uword *bitmap)
Definition: nat.c:1102
static clib_error_t * add_static_mapping_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: nat.c:1644
int snat_alloc_outside_address_and_port(snat_main_t *sm, u32 fib_index, u32 thread_index, snat_session_key_t *k, u32 *address_indexp)
Definition: nat.c:1339
vhost_vring_addr_t addr
Definition: vhost-user.h:83
static clib_error_t * snat_config(vlib_main_t *vm, unformat_input_t *input)
Definition: nat.c:2115
void snat_add_address(snat_main_t *sm, ip4_address_t *addr, u32 vrf_id)
Definition: nat.c:151
int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port, u32 vrf_id, int addr_only, u32 sw_if_index, snat_protocol_t proto, int is_add)
Add static mapping.
Definition: nat.c:262
#define SNAT_TCP_TRANSITORY_TIMEOUT
Definition: nat.h:35
ip_lookup_main_t * ip4_lookup_main
Definition: nat.h:358
static int is_snat_address_used_in_static_mapping(snat_main_t *sm, ip4_address_t addr)
Definition: nat.c:201
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:680
snat_session_t * sessions
Definition: nat.h:246
u8 * format_snat_session_state(u8 *s, va_list *args)
Definition: nat.c:2243
snat_icmp_match_function_t * icmp_match_in2out_cb
Definition: nat.h:274
#define SNAT_SESSION_FLAG_LOAD_BALANCING
Definition: nat.h:130
clib_bihash_8_8_t static_mapping_by_local
Definition: nat.h:290
static u32 snat_get_worker_out2in_cb(ip4_header_t *ip0, u32 rx_fib_index0)
Definition: nat.c:2001
u32 fib_index
Definition: nat.h:170
snat_interface_t * interfaces
Definition: nat.h:299
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
u16 fib_index
Definition: nat.h:50
int vnet_feature_enable_disable(const char *arc_name, const char *node_name, u32 sw_if_index, int enable_disable, void *feature_config, u32 n_feature_config_bytes)
Definition: feature.c:229
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
static_always_inline u8 icmp_is_error_message(icmp46_header_t *icmp)
Definition: nat.h:506
u32 tcp_established_timeout
Definition: nat.h:347
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128