FD.io VPP  v17.04.2-2-ga8f93f8
Vector Packet Processing
snat.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 <snat/snat.h>
24 #include <snat/snat_det.h>
25 #include <vnet/fib/fib_table.h>
26 #include <vnet/fib/ip4_fib.h>
27 
28 #include <vlibapi/api.h>
29 #include <vlibmemory/api.h>
30 #include <vlibsocket/api.h>
31 #include <vpp/app/version.h>
32 
34 
35 /* define message IDs */
36 #include <snat/snat_msg_enum.h>
37 
38 /* define message structures */
39 #define vl_typedefs
40 #include <snat/snat_all_api_h.h>
41 #undef vl_typedefs
42 
43 /* define generated endian-swappers */
44 #define vl_endianfun
45 #include <snat/snat_all_api_h.h>
46 #undef vl_endianfun
47 
48 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
49 
50 #define REPLY_MSG_ID_BASE sm->msg_id_base
52 
53 /* Get the API version number */
54 #define vl_api_version(n,v) static u32 api_version=(v);
55 #include <snat/snat_all_api_h.h>
56 #undef vl_api_version
57 
58 /* Macro to finish up custom dump fns */
59 #define FINISH \
60  vec_add1 (s, 0); \
61  vl_print (handle, (char *)s); \
62  vec_free (s); \
63  return handle;
64 
65 /* Hook up input features */
66 VNET_FEATURE_INIT (ip4_snat_in2out, static) = {
67  .arc_name = "ip4-unicast",
68  .node_name = "snat-in2out",
69  .runs_before = VNET_FEATURES ("snat-out2in"),
70 };
71 VNET_FEATURE_INIT (ip4_snat_out2in, static) = {
72  .arc_name = "ip4-unicast",
73  .node_name = "snat-out2in",
74  .runs_before = VNET_FEATURES ("ip4-lookup"),
75 };
76 VNET_FEATURE_INIT (ip4_snat_det_in2out, static) = {
77  .arc_name = "ip4-unicast",
78  .node_name = "snat-det-in2out",
79  .runs_before = VNET_FEATURES ("snat-det-out2in"),
80 };
81 VNET_FEATURE_INIT (ip4_snat_det_out2in, static) = {
82  .arc_name = "ip4-unicast",
83  .node_name = "snat-det-out2in",
84  .runs_before = VNET_FEATURES ("ip4-lookup"),
85 };
86 VNET_FEATURE_INIT (ip4_snat_in2out_worker_handoff, static) = {
87  .arc_name = "ip4-unicast",
88  .node_name = "snat-in2out-worker-handoff",
89  .runs_before = VNET_FEATURES ("snat-out2in-worker-handoff"),
90 };
91 VNET_FEATURE_INIT (ip4_snat_out2in_worker_handoff, static) = {
92  .arc_name = "ip4-unicast",
93  .node_name = "snat-out2in-worker-handoff",
94  .runs_before = VNET_FEATURES ("ip4-lookup"),
95 };
96 VNET_FEATURE_INIT (ip4_snat_in2out_fast, static) = {
97  .arc_name = "ip4-unicast",
98  .node_name = "snat-in2out-fast",
99  .runs_before = VNET_FEATURES ("snat-out2in-fast"),
100 };
101 VNET_FEATURE_INIT (ip4_snat_out2in_fast, static) = {
102  .arc_name = "ip4-unicast",
103  .node_name = "snat-out2in-fast",
104  .runs_before = VNET_FEATURES ("ip4-lookup"),
105 };
106 
107 /* *INDENT-OFF* */
109  .version = VPP_BUILD_VER,
110  .description = "Network Address Translation",
111 };
112 /* *INDENT-ON* */
113 
114 /**
115  * @brief Add/del NAT address to FIB.
116  *
117  * Add the external NAT address to the FIB as receive entries. This ensures
118  * that VPP will reply to ARP for this address and we don't need to enable
119  * proxy ARP on the outside interface.
120  *
121  * @param addr IPv4 address.
122  * @param plen address prefix length
123  * @param sw_if_index Interface.
124  * @param is_add If 0 delete, otherwise add.
125  */
126 void
128  int is_add)
129 {
130  fib_prefix_t prefix = {
131  .fp_len = p_len,
132  .fp_proto = FIB_PROTOCOL_IP4,
133  .fp_addr = {
134  .ip4.as_u32 = addr->as_u32,
135  },
136  };
137  u32 fib_index = ip4_fib_table_get_index_for_sw_if_index(sw_if_index);
138 
139  if (is_add)
141  &prefix,
147  NULL,
148  sw_if_index,
149  ~0,
150  1,
151  NULL,
153  else
154  fib_table_entry_delete(fib_index,
155  &prefix,
157 }
158 
160 {
161  snat_address_t * ap;
163 
164  if (vrf_id != ~0)
165  sm->vrf_mode = 1;
166 
167  /* Check if address already exists */
168  vec_foreach (ap, sm->addresses)
169  {
170  if (ap->addr.as_u32 == addr->as_u32)
171  return;
172  }
173 
174  vec_add2 (sm->addresses, ap, 1);
175  ap->addr = *addr;
177 #define _(N, i, n, s) \
178  clib_bitmap_alloc (ap->busy_##n##_port_bitmap, 65535);
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  }));
191 }
192 
195 {
197  pool_foreach (m, sm->static_mappings,
198  ({
199  if (m->external_addr.as_u32 == addr.as_u32)
200  return 1;
201  }));
202 
203  return 0;
204 }
205 
207 {
208  u32 v;
209 
210  v = clib_net_to_host_u32(a->as_u32) + 1;
211  a->as_u32 = clib_host_to_net_u32(v);
212 }
213 
214 static void
216  ip4_address_t l_addr,
217  u16 l_port,
218  u32 sw_if_index,
219  u16 e_port,
220  u32 vrf_id,
221  snat_protocol_t proto,
222  int addr_only,
223  int is_add)
224 {
226 
227  vec_add2 (sm->to_resolve, rp, 1);
228  rp->l_addr.as_u32 = l_addr.as_u32;
229  rp->l_port = l_port;
230  rp->sw_if_index = sw_if_index;
231  rp->e_port = e_port;
232  rp->vrf_id = vrf_id;
233  rp->proto = proto;
234  rp->addr_only = addr_only;
235  rp->is_add = is_add;
236 }
237 
238 /**
239  * @brief Add static mapping.
240  *
241  * Create static mapping between local addr+port and external addr+port.
242  *
243  * @param l_addr Local IPv4 address.
244  * @param e_addr External IPv4 address.
245  * @param l_port Local port number.
246  * @param e_port External port number.
247  * @param vrf_id VRF ID.
248  * @param addr_only If 0 address port and pair mapping, otherwise address only.
249  * @param sw_if_index External port instead of specific IP address.
250  * @param is_add If 0 delete static mapping, otherwise add.
251  *
252  * @returns
253  */
255  u16 l_port, u16 e_port, u32 vrf_id, int addr_only,
256  u32 sw_if_index, snat_protocol_t proto, int is_add)
257 {
258  snat_main_t * sm = &snat_main;
260  snat_session_key_t m_key;
261  clib_bihash_kv_8_8_t kv, value;
262  snat_address_t *a = 0;
263  u32 fib_index = ~0;
264  uword * p;
265  snat_interface_t *interface;
266  int i;
267 
268  /* If the external address is a specific interface address */
269  if (sw_if_index != ~0)
270  {
271  ip4_address_t * first_int_addr;
272 
273  /* Might be already set... */
274  first_int_addr = ip4_interface_first_address
275  (sm->ip4_main, sw_if_index, 0 /* just want the address*/);
276 
277  /* DHCP resolution required? */
278  if (first_int_addr == 0)
279  {
281  (sm, l_addr, l_port, sw_if_index, e_port, vrf_id, proto,
282  addr_only, is_add);
283  return 0;
284  }
285  else
286  e_addr.as_u32 = first_int_addr->as_u32;
287  }
288 
289  m_key.addr = e_addr;
290  m_key.port = addr_only ? 0 : e_port;
291  m_key.protocol = addr_only ? 0 : proto;
292  m_key.fib_index = sm->outside_fib_index;
293  kv.key = m_key.as_u64;
294  if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
295  m = 0;
296  else
297  m = pool_elt_at_index (sm->static_mappings, value.value);
298 
299  if (is_add)
300  {
301  if (m)
302  return VNET_API_ERROR_VALUE_EXIST;
303 
304  /* Convert VRF id to FIB index */
305  if (vrf_id != ~0)
306  {
307  p = hash_get (sm->ip4_main->fib_index_by_table_id, vrf_id);
308  if (!p)
309  return VNET_API_ERROR_NO_SUCH_FIB;
310  fib_index = p[0];
311  }
312  /* If not specified use inside VRF id from SNAT plugin startup config */
313  else
314  {
315  fib_index = sm->inside_fib_index;
316  vrf_id = sm->inside_vrf_id;
317  }
318 
319  /* Find external address in allocated addresses and reserve port for
320  address and port pair mapping when dynamic translations enabled */
321  if (!addr_only && !(sm->static_mapping_only))
322  {
323  for (i = 0; i < vec_len (sm->addresses); i++)
324  {
325  if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
326  {
327  a = sm->addresses + i;
328  /* External port must be unused */
329  switch (proto)
330  {
331 #define _(N, j, n, s) \
332  case SNAT_PROTOCOL_##N: \
333  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, e_port)) \
334  return VNET_API_ERROR_INVALID_VALUE; \
335  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 1); \
336  if (e_port > 1024) \
337  a->busy_##n##_ports++; \
338  break;
340 #undef _
341  default:
342  clib_warning("unknown_protocol");
343  return VNET_API_ERROR_INVALID_VALUE_2;
344  }
345  break;
346  }
347  }
348  /* External address must be allocated */
349  if (!a)
350  return VNET_API_ERROR_NO_SUCH_ENTRY;
351  }
352 
353  pool_get (sm->static_mappings, m);
354  memset (m, 0, sizeof (*m));
355  m->local_addr = l_addr;
356  m->external_addr = e_addr;
357  m->addr_only = addr_only;
358  m->vrf_id = vrf_id;
359  m->fib_index = fib_index;
360  if (!addr_only)
361  {
362  m->local_port = l_port;
363  m->external_port = e_port;
364  m->proto = proto;
365  }
366 
367  m_key.addr = m->local_addr;
368  m_key.port = m->local_port;
369  m_key.protocol = m->proto;
370  m_key.fib_index = m->fib_index;
371  kv.key = m_key.as_u64;
372  kv.value = m - sm->static_mappings;
373  clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 1);
374 
375  m_key.addr = m->external_addr;
376  m_key.port = m->external_port;
377  m_key.fib_index = sm->outside_fib_index;
378  kv.key = m_key.as_u64;
379  kv.value = m - sm->static_mappings;
380  clib_bihash_add_del_8_8(&sm->static_mapping_by_external, &kv, 1);
381 
382  /* Assign worker */
383  if (sm->workers)
384  {
385  snat_user_key_t w_key0;
386  snat_worker_key_t w_key1;
387 
388  w_key0.addr = m->local_addr;
389  w_key0.fib_index = m->fib_index;
390  kv.key = w_key0.as_u64;
391 
392  if (clib_bihash_search_8_8 (&sm->worker_by_in, &kv, &value))
393  {
394  kv.value = sm->first_worker_index +
395  sm->workers[sm->next_worker++ % vec_len (sm->workers)];
396 
397  clib_bihash_add_del_8_8 (&sm->worker_by_in, &kv, 1);
398  }
399  else
400  {
401  kv.value = value.value;
402  }
403 
404  w_key1.addr = m->external_addr;
405  w_key1.port = clib_host_to_net_u16 (m->external_port);
406  w_key1.fib_index = sm->outside_fib_index;
407  kv.key = w_key1.as_u64;
408  clib_bihash_add_del_8_8 (&sm->worker_by_out, &kv, 1);
409  }
410  }
411  else
412  {
413  if (!m)
414  return VNET_API_ERROR_NO_SUCH_ENTRY;
415 
416  /* Free external address port */
417  if (!addr_only && !(sm->static_mapping_only))
418  {
419  for (i = 0; i < vec_len (sm->addresses); i++)
420  {
421  if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
422  {
423  a = sm->addresses + i;
424  switch (proto)
425  {
426 #define _(N, j, n, s) \
427  case SNAT_PROTOCOL_##N: \
428  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 0); \
429  if (e_port > 1024) \
430  a->busy_##n##_ports--; \
431  break;
433 #undef _
434  default:
435  clib_warning("unknown_protocol");
436  return VNET_API_ERROR_INVALID_VALUE_2;
437  }
438  break;
439  }
440  }
441  }
442 
443  m_key.addr = m->local_addr;
444  m_key.port = m->local_port;
445  m_key.protocol = m->proto;
446  m_key.fib_index = m->fib_index;
447  kv.key = m_key.as_u64;
448  clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 0);
449 
450  m_key.addr = m->external_addr;
451  m_key.port = m->external_port;
452  m_key.fib_index = sm->outside_fib_index;
453  kv.key = m_key.as_u64;
454  clib_bihash_add_del_8_8(&sm->static_mapping_by_external, &kv, 0);
455 
456  /* Delete session(s) for static mapping if exist */
457  if (!(sm->static_mapping_only) ||
458  (sm->static_mapping_only && sm->static_mapping_connection_tracking))
459  {
460  snat_user_key_t u_key;
461  snat_user_t *u;
462  dlist_elt_t * head, * elt;
463  u32 elt_index, head_index, del_elt_index;
464  u32 ses_index;
465  u64 user_index;
466  snat_session_t * s;
468 
469  u_key.addr = m->local_addr;
470  u_key.fib_index = m->fib_index;
471  kv.key = u_key.as_u64;
472  if (!clib_bihash_search_8_8 (&sm->user_hash, &kv, &value))
473  {
474  user_index = value.value;
475  if (!clib_bihash_search_8_8 (&sm->worker_by_in, &kv, &value))
476  tsm = vec_elt_at_index (sm->per_thread_data, value.value);
477  else
478  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
479  u = pool_elt_at_index (tsm->users, user_index);
480  if (u->nstaticsessions)
481  {
482  head_index = u->sessions_per_user_list_head_index;
483  head = pool_elt_at_index (tsm->list_pool, head_index);
484  elt_index = head->next;
485  elt = pool_elt_at_index (tsm->list_pool, elt_index);
486  ses_index = elt->value;
487  while (ses_index != ~0)
488  {
489  s = pool_elt_at_index (tsm->sessions, ses_index);
490  del_elt_index = elt_index;
491  elt_index = elt->next;
492  elt = pool_elt_at_index (tsm->list_pool, elt_index);
493  ses_index = elt->value;
494 
495  if (!addr_only)
496  {
497  if ((s->out2in.addr.as_u32 != e_addr.as_u32) &&
498  (clib_net_to_host_u16 (s->out2in.port) != e_port))
499  continue;
500  }
501 
502  /* log NAT event */
503  snat_ipfix_logging_nat44_ses_delete(s->in2out.addr.as_u32,
504  s->out2in.addr.as_u32,
505  s->in2out.protocol,
506  s->in2out.port,
507  s->out2in.port,
508  s->in2out.fib_index);
509 
510  value.key = s->in2out.as_u64;
511  clib_bihash_add_del_8_8 (&sm->in2out, &value, 0);
512  value.key = s->out2in.as_u64;
513  clib_bihash_add_del_8_8 (&sm->out2in, &value, 0);
514  pool_put (tsm->sessions, s);
515 
516  clib_dlist_remove (tsm->list_pool, del_elt_index);
517  pool_put_index (tsm->list_pool, del_elt_index);
518  u->nstaticsessions--;
519 
520  if (!addr_only)
521  break;
522  }
523  if (addr_only)
524  {
525  pool_put (tsm->users, u);
526  clib_bihash_add_del_8_8 (&sm->user_hash, &kv, 0);
527  }
528  }
529  }
530  }
531 
532  /* Delete static mapping from pool */
533  pool_put (sm->static_mappings, m);
534  }
535 
536  if (!addr_only)
537  return 0;
538 
539  /* Add/delete external address to FIB */
540  pool_foreach (interface, sm->interfaces,
541  ({
542  if (interface->is_inside)
543  continue;
544 
545  snat_add_del_addr_to_fib(&e_addr, 32, interface->sw_if_index, is_add);
546  break;
547  }));
548 
549  return 0;
550 }
551 
553 {
554  snat_address_t *a = 0;
555  snat_session_t *ses;
556  u32 *ses_to_be_removed = 0, *ses_index;
557  clib_bihash_kv_8_8_t kv, value;
558  snat_user_key_t user_key;
559  snat_user_t *u;
562  snat_interface_t *interface;
563  int i;
564 
565  /* Find SNAT address */
566  for (i=0; i < vec_len (sm->addresses); i++)
567  {
568  if (sm->addresses[i].addr.as_u32 == addr.as_u32)
569  {
570  a = sm->addresses + i;
571  break;
572  }
573  }
574  if (!a)
575  return VNET_API_ERROR_NO_SUCH_ENTRY;
576 
577  if (delete_sm)
578  {
579  pool_foreach (m, sm->static_mappings,
580  ({
581  if (m->external_addr.as_u32 == addr.as_u32)
582  (void) snat_add_static_mapping (m->local_addr, m->external_addr,
583  m->local_port, m->external_port,
584  m->vrf_id, m->addr_only, ~0,
585  m->proto, 0);
586  }));
587  }
588  else
589  {
590  /* Check if address is used in some static mapping */
592  {
593  clib_warning ("address used in static mapping");
594  return VNET_API_ERROR_UNSPECIFIED;
595  }
596  }
597 
598  /* Delete sessions using address */
599  if (a->busy_tcp_ports || a->busy_udp_ports || a->busy_icmp_ports)
600  {
601  vec_foreach (tsm, sm->per_thread_data)
602  {
603  pool_foreach (ses, tsm->sessions, ({
604  if (ses->out2in.addr.as_u32 == addr.as_u32)
605  {
606  /* log NAT event */
607  snat_ipfix_logging_nat44_ses_delete(ses->in2out.addr.as_u32,
608  ses->out2in.addr.as_u32,
609  ses->in2out.protocol,
610  ses->in2out.port,
611  ses->out2in.port,
612  ses->in2out.fib_index);
613  vec_add1 (ses_to_be_removed, ses - tsm->sessions);
614  kv.key = ses->in2out.as_u64;
615  clib_bihash_add_del_8_8 (&sm->in2out, &kv, 0);
616  kv.key = ses->out2in.as_u64;
617  clib_bihash_add_del_8_8 (&sm->out2in, &kv, 0);
618  clib_dlist_remove (tsm->list_pool, ses->per_user_index);
619  user_key.addr = ses->in2out.addr;
620  user_key.fib_index = ses->in2out.fib_index;
621  kv.key = user_key.as_u64;
622  if (!clib_bihash_search_8_8 (&sm->user_hash, &kv, &value))
623  {
624  u = pool_elt_at_index (tsm->users, value.value);
625  u->nsessions--;
626  }
627  }
628  }));
629 
630  vec_foreach (ses_index, ses_to_be_removed)
631  pool_put_index (tsm->sessions, ses_index[0]);
632 
633  vec_free (ses_to_be_removed);
634  }
635  }
636 
637  vec_del1 (sm->addresses, i);
638 
639  /* Delete external address from FIB */
640  pool_foreach (interface, sm->interfaces,
641  ({
642  if (interface->is_inside)
643  continue;
644 
645  snat_add_del_addr_to_fib(&addr, 32, interface->sw_if_index, 0);
646  break;
647  }));
648 
649  return 0;
650 }
651 
652 static int snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del)
653 {
654  snat_main_t *sm = &snat_main;
656  const char * feature_name;
657  snat_address_t * ap;
659  snat_det_map_t * dm;
660 
661  if (sm->static_mapping_only && !(sm->static_mapping_connection_tracking))
662  feature_name = is_inside ? "snat-in2out-fast" : "snat-out2in-fast";
663  else
664  {
665  if (sm->num_workers > 1 && !sm->deterministic)
666  feature_name = is_inside ? "snat-in2out-worker-handoff" : "snat-out2in-worker-handoff";
667  else if (sm->deterministic)
668  feature_name = is_inside ? "snat-det-in2out" : "snat-det-out2in";
669  else
670  feature_name = is_inside ? "snat-in2out" : "snat-out2in";
671  }
672 
673  vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index,
674  !is_del, 0, 0);
675 
676  if (sm->fq_in2out_index == ~0 && !sm->deterministic && sm->num_workers > 1)
677  sm->fq_in2out_index = vlib_frame_queue_main_init (sm->in2out_node_index, 0);
678 
679  if (sm->fq_out2in_index == ~0 && !sm->deterministic && sm->num_workers > 1)
680  sm->fq_out2in_index = vlib_frame_queue_main_init (sm->out2in_node_index, 0);
681 
682  pool_foreach (i, sm->interfaces,
683  ({
684  if (i->sw_if_index == sw_if_index)
685  {
686  if (is_del)
687  pool_put (sm->interfaces, i);
688  else
689  return VNET_API_ERROR_VALUE_EXIST;
690 
691  goto fib;
692  }
693  }));
694 
695  if (is_del)
696  return VNET_API_ERROR_NO_SUCH_ENTRY;
697 
698  pool_get (sm->interfaces, i);
699  i->sw_if_index = sw_if_index;
700  i->is_inside = is_inside;
701 
702  /* Add/delete external addresses to FIB */
703 fib:
704  if (is_inside)
705  return 0;
706 
707  vec_foreach (ap, sm->addresses)
708  snat_add_del_addr_to_fib(&ap->addr, 32, sw_if_index, !is_del);
709 
710  pool_foreach (m, sm->static_mappings,
711  ({
712  if (!(m->addr_only))
713  continue;
714 
715  snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
716  }));
717 
718  pool_foreach (dm, sm->det_maps,
719  ({
720  snat_add_del_addr_to_fib(&dm->out_addr, dm->out_plen, sw_if_index, !is_del);
721  }));
722 
723  return 0;
724 }
725 
726 static int snat_set_workers (uword * bitmap)
727 {
728  snat_main_t *sm = &snat_main;
729  int i;
730 
731  if (sm->num_workers < 2)
732  return VNET_API_ERROR_FEATURE_DISABLED;
733 
734  if (clib_bitmap_last_set (bitmap) >= sm->num_workers)
735  return VNET_API_ERROR_INVALID_WORKER;
736 
737  vec_free (sm->workers);
738  clib_bitmap_foreach (i, bitmap,
739  ({
740  vec_add1(sm->workers, i);
741  }));
742 
743  return 0;
744 }
745 
746 static void
749 {
750  snat_main_t * sm = &snat_main;
752  ip4_address_t this_addr;
753  u32 start_host_order, end_host_order;
754  u32 vrf_id;
755  int i, count;
756  int rv = 0;
757  u32 * tmp;
758 
759  if (mp->is_ip4 != 1)
760  {
761  rv = VNET_API_ERROR_UNIMPLEMENTED;
762  goto send_reply;
763  }
764 
765  if (sm->static_mapping_only)
766  {
767  rv = VNET_API_ERROR_FEATURE_DISABLED;
768  goto send_reply;
769  }
770 
771  tmp = (u32 *) mp->first_ip_address;
772  start_host_order = clib_host_to_net_u32 (tmp[0]);
773  tmp = (u32 *) mp->last_ip_address;
774  end_host_order = clib_host_to_net_u32 (tmp[0]);
775 
776  count = (end_host_order - start_host_order) + 1;
777 
778  vrf_id = clib_host_to_net_u32 (mp->vrf_id);
779 
780  if (count > 1024)
781  clib_warning ("%U - %U, %d addresses...",
784  count);
785 
786  memcpy (&this_addr.as_u8, mp->first_ip_address, 4);
787 
788  for (i = 0; i < count; i++)
789  {
790  if (mp->is_add)
791  snat_add_address (sm, &this_addr, vrf_id);
792  else
793  rv = snat_del_address (sm, this_addr, 0);
794 
795  if (rv)
796  goto send_reply;
797 
798  increment_v4_address (&this_addr);
799  }
800 
801  send_reply:
802  REPLY_MACRO (VL_API_SNAT_ADD_ADDRESS_RANGE_REPLY);
803 }
804 
807 {
808  u8 * s;
809 
810  s = format (0, "SCRIPT: snat_add_address_range ");
811  s = format (s, "%U ", format_ip4_address, mp->first_ip_address);
812  if (memcmp (mp->first_ip_address, mp->last_ip_address, 4))
813  {
814  s = format (s, " - %U ", format_ip4_address, mp->last_ip_address);
815  }
816  FINISH;
817 }
818 
819 static void
822 {
824  snat_main_t * sm = &snat_main;
825 
826  rmp = vl_msg_api_alloc (sizeof (*rmp));
827  memset (rmp, 0, sizeof (*rmp));
828  rmp->_vl_msg_id = ntohs (VL_API_SNAT_ADDRESS_DETAILS+sm->msg_id_base);
829  rmp->is_ip4 = 1;
830  clib_memcpy (rmp->ip_address, &(a->addr), 4);
831  if (a->fib_index != ~0)
832  rmp->vrf_id = ntohl(ip4_fib_get(a->fib_index)->table_id);
833  else
834  rmp->vrf_id = ~0;
835  rmp->context = context;
836 
837  vl_msg_api_send_shmem (q, (u8 *) & rmp);
838 }
839 
840 static void
843 {
845  snat_main_t * sm = &snat_main;
846  snat_address_t * a;
847 
849  if (q == 0)
850  return;
851 
852  vec_foreach (a, sm->addresses)
854 }
855 
857 (vl_api_snat_address_dump_t *mp, void * handle)
858 {
859  u8 *s;
860 
861  s = format (0, "SCRIPT: snat_address_dump ");
862 
863  FINISH;
864 }
865 
866 static void
869 {
870  snat_main_t * sm = &snat_main;
872  u8 is_del = mp->is_add == 0;
873  u32 sw_if_index = ntohl(mp->sw_if_index);
874  int rv = 0;
875 
877 
878  rv = snat_interface_add_del (sw_if_index, mp->is_inside, is_del);
879 
881 
882  REPLY_MACRO(VL_API_SNAT_INTERFACE_ADD_DEL_FEATURE_REPLY);
883 }
884 
887 {
888  u8 * s;
889 
890  s = format (0, "SCRIPT: snat_interface_add_del_feature ");
891  s = format (s, "sw_if_index %d %s %s",
892  clib_host_to_net_u32(mp->sw_if_index),
893  mp->is_inside ? "in":"out",
894  mp->is_add ? "" : "del");
895 
896  FINISH;
897 }
898 
899 static void
902 {
904  snat_main_t * sm = &snat_main;
905 
906  rmp = vl_msg_api_alloc (sizeof (*rmp));
907  memset (rmp, 0, sizeof (*rmp));
908  rmp->_vl_msg_id = ntohs (VL_API_SNAT_INTERFACE_DETAILS+sm->msg_id_base);
909  rmp->sw_if_index = ntohl (i->sw_if_index);
910  rmp->is_inside = i->is_inside;
911  rmp->context = context;
912 
913  vl_msg_api_send_shmem (q, (u8 *) & rmp);
914 }
915 
916 static void
919 {
921  snat_main_t * sm = &snat_main;
923 
925  if (q == 0)
926  return;
927 
928  pool_foreach (i, sm->interfaces,
929  ({
930  send_snat_interface_details(i, q, mp->context);
931  }));
932 }
933 
935 (vl_api_snat_interface_dump_t *mp, void * handle)
936 {
937  u8 *s;
938 
939  s = format (0, "SCRIPT: snat_interface_dump ");
940 
941  FINISH;
942 }static void
943 
946 {
947  snat_main_t * sm = &snat_main;
949  ip4_address_t local_addr, external_addr;
950  u16 local_port = 0, external_port = 0;
951  u32 vrf_id, external_sw_if_index;
952  int rv = 0;
953  snat_protocol_t proto;
954 
955  if (mp->is_ip4 != 1)
956  {
957  rv = VNET_API_ERROR_UNIMPLEMENTED;
958  goto send_reply;
959  }
960 
961  memcpy (&local_addr.as_u8, mp->local_ip_address, 4);
962  memcpy (&external_addr.as_u8, mp->external_ip_address, 4);
963  if (mp->addr_only == 0)
964  {
965  local_port = clib_net_to_host_u16 (mp->local_port);
966  external_port = clib_net_to_host_u16 (mp->external_port);
967  }
968  vrf_id = clib_net_to_host_u32 (mp->vrf_id);
969  external_sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index);
970  proto = ip_proto_to_snat_proto (mp->protocol);
971 
972  rv = snat_add_static_mapping(local_addr, external_addr, local_port,
973  external_port, vrf_id, mp->addr_only,
974  external_sw_if_index, proto, mp->is_add);
975 
976  send_reply:
977  REPLY_MACRO (VL_API_SNAT_ADD_ADDRESS_RANGE_REPLY);
978 }
979 
982 {
983  u8 * s;
984 
985  s = format (0, "SCRIPT: snat_add_static_mapping ");
986  s = format (s, "protocol %d local_addr %U external_addr %U ",
987  mp->protocol,
990 
991  if (mp->addr_only == 0)
992  s = format (s, "local_port %d external_port %d ",
993  clib_net_to_host_u16 (mp->local_port),
994  clib_net_to_host_u16 (mp->external_port));
995 
996  if (mp->vrf_id != ~0)
997  s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
998 
999  if (mp->external_sw_if_index != ~0)
1000  s = format (s, "external_sw_if_index %d",
1001  clib_net_to_host_u32 (mp->external_sw_if_index));
1002  FINISH;
1003 }
1004 
1005 static void
1008 {
1010  snat_main_t * sm = &snat_main;
1011 
1012  rmp = vl_msg_api_alloc (sizeof (*rmp));
1013  memset (rmp, 0, sizeof (*rmp));
1014  rmp->_vl_msg_id = ntohs (VL_API_SNAT_STATIC_MAPPING_DETAILS+sm->msg_id_base);
1015  rmp->is_ip4 = 1;
1016  rmp->addr_only = m->addr_only;
1017  clib_memcpy (rmp->local_ip_address, &(m->local_addr), 4);
1019  rmp->local_port = htons (m->local_port);
1020  rmp->external_port = htons (m->external_port);
1021  rmp->external_sw_if_index = ~0;
1022  rmp->vrf_id = htonl (m->vrf_id);
1024  rmp->context = context;
1025 
1026  vl_msg_api_send_shmem (q, (u8 *) & rmp);
1027 }
1028 
1029 static void
1032 {
1034  snat_main_t * sm = &snat_main;
1035 
1036  rmp = vl_msg_api_alloc (sizeof (*rmp));
1037  memset (rmp, 0, sizeof (*rmp));
1038  rmp->_vl_msg_id = ntohs (VL_API_SNAT_STATIC_MAPPING_DETAILS+sm->msg_id_base);
1039  rmp->is_ip4 = 1;
1040  rmp->addr_only = m->addr_only;
1041  clib_memcpy (rmp->local_ip_address, &(m->l_addr), 4);
1042  rmp->local_port = htons (m->l_port);
1043  rmp->external_port = htons (m->e_port);
1044  rmp->external_sw_if_index = htonl (m->sw_if_index);
1045  rmp->vrf_id = htonl (m->vrf_id);
1047  rmp->context = context;
1048 
1049  vl_msg_api_send_shmem (q, (u8 *) & rmp);
1050 }
1051 
1052 static void
1055 {
1057  snat_main_t * sm = &snat_main;
1060  int j;
1061 
1063  if (q == 0)
1064  return;
1065 
1066  pool_foreach (m, sm->static_mappings,
1067  ({
1068  send_snat_static_mapping_details (m, q, mp->context);
1069  }));
1070 
1071  for (j = 0; j < vec_len (sm->to_resolve); j++)
1072  {
1073  rp = sm->to_resolve + j;
1075  }
1076 }
1077 
1080 {
1081  u8 *s;
1082 
1083  s = format (0, "SCRIPT: snat_static_mapping_dump ");
1084 
1085  FINISH;
1086 }
1087 
1088 static void
1091 {
1093  snat_main_t * sm = &snat_main;
1094  int rv = 0;
1095 
1096  REPLY_MACRO2(VL_API_SNAT_CONTROL_PING_REPLY,
1097  ({
1098  rmp->vpe_pid = ntohl (getpid());
1099  }));
1100 }
1101 
1103 (vl_api_snat_control_ping_t *mp, void * handle)
1104 {
1105  u8 *s;
1106 
1107  s = format (0, "SCRIPT: snat_control_ping ");
1108 
1109  FINISH;
1110 }
1111 
1112 static void
1115 {
1117  snat_main_t * sm = &snat_main;
1118  int rv = 0;
1119 
1120  REPLY_MACRO2(VL_API_SNAT_SHOW_CONFIG_REPLY,
1121  ({
1122  rmp->translation_buckets = htonl (sm->translation_buckets);
1123  rmp->translation_memory_size = htonl (sm->translation_memory_size);
1124  rmp->user_buckets = htonl (sm->user_buckets);
1125  rmp->user_memory_size = htonl (sm->user_memory_size);
1126  rmp->max_translations_per_user = htonl (sm->max_translations_per_user);
1127  rmp->outside_vrf_id = htonl (sm->outside_vrf_id);
1128  rmp->inside_vrf_id = htonl (sm->inside_vrf_id);
1129  rmp->static_mapping_only = sm->static_mapping_only;
1131  sm->static_mapping_connection_tracking;
1132  rmp->deterministic = sm->deterministic;
1133  }));
1134 }
1135 
1137 (vl_api_snat_show_config_t *mp, void * handle)
1138 {
1139  u8 *s;
1140 
1141  s = format (0, "SCRIPT: snat_show_config ");
1142 
1143  FINISH;
1144 }
1145 
1146 static void
1149 {
1150  snat_main_t * sm = &snat_main;
1152  int rv = 0;
1153  uword *bitmap = 0;
1154  u64 mask = clib_net_to_host_u64 (mp->worker_mask);
1155 
1156  if (sm->num_workers < 2)
1157  {
1158  rv = VNET_API_ERROR_FEATURE_DISABLED;
1159  goto send_reply;
1160  }
1161 
1162  bitmap = clib_bitmap_set_multiple (bitmap, 0, mask, BITS (mask));
1163  rv = snat_set_workers(bitmap);
1164  clib_bitmap_free (bitmap);
1165 
1166  send_reply:
1167  REPLY_MACRO (VL_API_SNAT_SET_WORKERS_REPLY);
1168 }
1169 
1171 (vl_api_snat_set_workers_t *mp, void * handle)
1172 {
1173  u8 * s;
1174  uword *bitmap = 0;
1175  u8 first = 1;
1176  int i;
1177  u64 mask = clib_net_to_host_u64 (mp->worker_mask);
1178 
1179  s = format (0, "SCRIPT: snat_set_workers ");
1180  bitmap = clib_bitmap_set_multiple (bitmap, 0, mask, BITS (mask));
1181  clib_bitmap_foreach (i, bitmap,
1182  ({
1183  if (first)
1184  s = format (s, "%d", i);
1185  else
1186  s = format (s, ",%d", i);
1187  first = 0;
1188  }));
1189  clib_bitmap_free (bitmap);
1190  FINISH;
1191 }
1192 
1193 static void
1195 (u32 worker_index, unix_shared_memory_queue_t * q, u32 context)
1196 {
1198  snat_main_t * sm = &snat_main;
1200  vlib_worker_threads + worker_index + sm->first_worker_index;
1201 
1202  rmp = vl_msg_api_alloc (sizeof (*rmp));
1203  memset (rmp, 0, sizeof (*rmp));
1204  rmp->_vl_msg_id = ntohs (VL_API_SNAT_WORKER_DETAILS+sm->msg_id_base);
1205  rmp->context = context;
1206  rmp->worker_index = htonl (worker_index);
1207  rmp->lcore_id = htonl (w->lcore_id);
1208  strncpy ((char *) rmp->name, (char *) w->name, ARRAY_LEN (rmp->name) - 1);
1209 
1210  vl_msg_api_send_shmem (q, (u8 *) & rmp);
1211 }
1212 
1213 static void
1216 {
1218  snat_main_t * sm = &snat_main;
1219  u32 * worker_index;
1220 
1222  if (q == 0)
1223  return;
1224 
1225  vec_foreach (worker_index, sm->workers)
1226  {
1227  send_snat_worker_details(*worker_index, q, mp->context);
1228  }
1229 }
1230 
1232 (vl_api_snat_worker_dump_t *mp, void * handle)
1233 {
1234  u8 *s;
1235 
1236  s = format (0, "SCRIPT: snat_worker_dump ");
1237 
1238  FINISH;
1239 }
1240 
1242  u32 sw_if_index,
1243  int is_del);
1244 
1245 static void
1248 {
1249  snat_main_t * sm = &snat_main;
1251  u8 is_del = mp->is_add == 0;
1252  u32 sw_if_index = ntohl(mp->sw_if_index);
1253  int rv = 0;
1254 
1256 
1257  rv = snat_add_interface_address (sm, sw_if_index, is_del);
1258 
1260 
1261  REPLY_MACRO(VL_API_SNAT_ADD_DEL_INTERFACE_ADDR_REPLY);
1262 }
1263 
1266 {
1267  u8 * s;
1268 
1269  s = format (0, "SCRIPT: snat_add_del_interface_addr ");
1270  s = format (s, "sw_if_index %d %s",
1271  clib_host_to_net_u32(mp->sw_if_index),
1272  mp->is_add ? "" : "del");
1273 
1274  FINISH;
1275 }
1276 
1277 static void
1279 (u32 sw_if_index, unix_shared_memory_queue_t * q, u32 context)
1280 {
1282  snat_main_t * sm = &snat_main;
1283 
1284  rmp = vl_msg_api_alloc (sizeof (*rmp));
1285  memset (rmp, 0, sizeof (*rmp));
1286  rmp->_vl_msg_id = ntohs (VL_API_SNAT_INTERFACE_ADDR_DETAILS+sm->msg_id_base);
1287  rmp->sw_if_index = ntohl (sw_if_index);
1288  rmp->context = context;
1289 
1290  vl_msg_api_send_shmem (q, (u8 *) & rmp);
1291 }
1292 
1293 static void
1296 {
1298  snat_main_t * sm = &snat_main;
1299  u32 * i;
1300 
1302  if (q == 0)
1303  return;
1304 
1305  vec_foreach (i, sm->auto_add_sw_if_indices)
1307 }
1308 
1311 {
1312  u8 *s;
1313 
1314  s = format (0, "SCRIPT: snat_interface_addr_dump ");
1315 
1316  FINISH;
1317 }
1318 
1319 static void
1322 {
1323  snat_main_t * sm = &snat_main;
1325  int rv = 0;
1326 
1328  clib_host_to_net_u32 (mp->domain_id),
1329  clib_host_to_net_u16 (mp->src_port));
1330 
1331  REPLY_MACRO (VL_API_SNAT_IPFIX_ENABLE_DISABLE_REPLY);
1332 }
1333 
1336 {
1337  u8 * s;
1338 
1339  s = format (0, "SCRIPT: snat_ipfix_enable_disable ");
1340  if (mp->domain_id)
1341  s = format (s, "domain %d ", clib_net_to_host_u32 (mp->domain_id));
1342  if (mp->src_port)
1343  s = format (s, "src_port %d ", clib_net_to_host_u16 (mp->src_port));
1344  if (!mp->enable)
1345  s = format (s, "disable ");
1346 
1347  FINISH;
1348 }
1349 
1350 static void
1353 {
1355  snat_main_t * sm = &snat_main;
1356  ip4_fib_t * fib_table;
1357 
1358  rmp = vl_msg_api_alloc (sizeof (*rmp));
1359  memset (rmp, 0, sizeof (*rmp));
1360  rmp->_vl_msg_id = ntohs (VL_API_SNAT_USER_DETAILS+sm->msg_id_base);
1361 
1362  fib_table = ip4_fib_get(u->fib_index);
1363  rmp->vrf_id = ntohl (fib_table->table_id);
1364 
1365  rmp->is_ip4 = 1;
1366  clib_memcpy(rmp->ip_address, &(u->addr), 4);
1367  rmp->nsessions = ntohl (u->nsessions);
1368  rmp->nstaticsessions = ntohl (u->nstaticsessions);
1369  rmp->context = context;
1370 
1371  vl_msg_api_send_shmem (q, (u8 *) & rmp);
1372 }
1373 
1374 static void
1377 {
1379  snat_main_t * sm = &snat_main;
1381  snat_user_t * u;
1382 
1384  if (q == 0)
1385  return;
1386 
1387  vec_foreach (tsm, sm->per_thread_data)
1388  vec_foreach (u, tsm->users)
1389  send_snat_user_details (u, q, mp->context);
1390 }
1391 
1392 static void *vl_api_snat_user_dump_t_print
1393 (vl_api_snat_user_dump_t *mp, void * handle)
1394 {
1395  u8 *s;
1396 
1397  s = format (0, "SCRIPT: snat_user_dump ");
1398 
1399  FINISH;
1400 }
1401 
1402 static void
1404 (snat_session_t * s, unix_shared_memory_queue_t * q, u32 context)
1405 {
1407  snat_main_t * sm = &snat_main;
1408 
1409  rmp = vl_msg_api_alloc (sizeof(*rmp));
1410  memset (rmp, 0, sizeof (*rmp));
1411  rmp->_vl_msg_id = ntohs (VL_API_SNAT_USER_SESSION_DETAILS+sm->msg_id_base);
1412  rmp->is_ip4 = 1;
1413  clib_memcpy(rmp->outside_ip_address, (&s->out2in.addr), 4);
1414  rmp->outside_port = s->out2in.port;
1415  clib_memcpy(rmp->inside_ip_address, (&s->in2out.addr), 4);
1416  rmp->inside_port = s->in2out.port;
1417  rmp->protocol = ntohs(snat_proto_to_ip_proto(s->in2out.protocol));
1418  rmp->is_static = s->flags & SNAT_SESSION_FLAG_STATIC_MAPPING ? 1 : 0;
1419  rmp->last_heard = clib_host_to_net_u64((u64)s->last_heard);
1420  rmp->total_bytes = clib_host_to_net_u64(s->total_bytes);
1421  rmp->total_pkts = ntohl(s->total_pkts);
1422  rmp->context = context;
1423 
1424  vl_msg_api_send_shmem (q, (u8 *) & rmp);
1425 }
1426 
1427 static void
1430 {
1432  snat_main_t * sm = &snat_main;
1434  snat_session_t * s;
1435  clib_bihash_kv_8_8_t key, value;
1436  snat_user_key_t ukey;
1437  snat_user_t * u;
1438  u32 session_index, head_index, elt_index;
1439  dlist_elt_t * head, * elt;
1440 
1442  if (q == 0)
1443  return;
1444  if (!mp->is_ip4)
1445  return;
1446 
1447  clib_memcpy (&ukey.addr, mp->ip_address, 4);
1448  ukey.fib_index = ip4_fib_index_from_table_id (ntohl(mp->vrf_id));
1449  key.key = ukey.as_u64;
1450  if (!clib_bihash_search_8_8 (&sm->worker_by_in, &key, &value))
1451  tsm = vec_elt_at_index (sm->per_thread_data, value.value);
1452  else
1453  tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1454  if (clib_bihash_search_8_8 (&sm->user_hash, &key, &value))
1455  return;
1456  u = pool_elt_at_index (tsm->users, value.value);
1457  if (!u->nsessions && !u->nstaticsessions)
1458  return;
1459 
1460  head_index = u->sessions_per_user_list_head_index;
1461  head = pool_elt_at_index (tsm->list_pool, head_index);
1462  elt_index = head->next;
1463  elt = pool_elt_at_index (tsm->list_pool, elt_index);
1464  session_index = elt->value;
1465  while (session_index != ~0)
1466  {
1467  s = pool_elt_at_index (tsm->sessions, session_index);
1468 
1470 
1471  elt_index = elt->next;
1472  elt = pool_elt_at_index (tsm->list_pool, elt_index);
1473  session_index = elt->value;
1474  }
1475 }
1476 
1479 {
1480  u8 *s;
1481 
1482  s = format (0, "SCRIPT: snat_user_session_dump ");
1483  s = format (s, "ip_address %U vrf_id %d\n",
1485  clib_net_to_host_u32 (mp->vrf_id));
1486 
1487  FINISH;
1488 }
1489 
1490 static void
1493 {
1494  snat_main_t * sm = &snat_main;
1496  int rv = 0;
1497  ip4_address_t in_addr, out_addr;
1498 
1499  clib_memcpy(&in_addr, mp->in_addr, 4);
1500  clib_memcpy(&out_addr, mp->out_addr, 4);
1501  rv = snat_det_add_map(sm, &in_addr, mp->in_plen, &out_addr,
1502  mp->out_plen, mp->is_add);
1503 
1504  REPLY_MACRO (VL_API_SNAT_ADD_DET_MAP_REPLY);
1505 }
1506 
1508 (vl_api_snat_add_det_map_t *mp, void * handle)
1509 {
1510  u8 * s;
1511 
1512  s = format (0, "SCRIPT: snat_add_det_map ");
1513  s = format (s, "inside address %U/%d outside address %U/%d\n",
1516 
1517  FINISH;
1518 }
1519 
1520 static void
1523 {
1524  snat_main_t * sm = &snat_main;
1526  int rv = 0;
1527  u16 lo_port = 0, hi_port = 0;
1528  snat_det_map_t * dm;
1529  ip4_address_t in_addr, out_addr;
1530 
1531  out_addr.as_u32 = 0;
1532  clib_memcpy(&in_addr, mp->in_addr, 4);
1533  dm = snat_det_map_by_user(sm, &in_addr);
1534  if (!dm)
1535  {
1536  rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1537  goto send_reply;
1538  }
1539 
1540  snat_det_forward(dm, &in_addr, &out_addr, &lo_port);
1541  hi_port = lo_port + dm->ports_per_host - 1;
1542 
1543 send_reply:
1544  REPLY_MACRO2(VL_API_SNAT_DET_FORWARD_REPLY,
1545  ({
1546  rmp->out_port_lo = ntohs(lo_port);
1547  rmp->out_port_hi = ntohs(hi_port);
1548  rmp->is_ip4 = 1;
1549  memset(rmp->out_addr, 0, 16);
1550  clib_memcpy(rmp->out_addr, &out_addr, 4);
1551  }))
1552 }
1553 
1555 (vl_api_snat_det_forward_t * mp, void * handle)
1556 {
1557  u8 * s;
1558 
1559  s = format (0, "SCRIPT: smat_det_forward_t");
1560  s = format (s, "inside ip address %U\n",
1562 
1563  FINISH;
1564 }
1565 
1566 static void
1569 {
1570  snat_main_t * sm = &snat_main;
1572  int rv = 0;
1573  ip4_address_t out_addr, in_addr;
1574  snat_det_map_t * dm;
1575 
1576  in_addr.as_u32 = 0;
1577  clib_memcpy(&out_addr, mp->out_addr, 4);
1578  dm = snat_det_map_by_out(sm, &out_addr);
1579  if (!dm)
1580  {
1581  rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1582  goto send_reply;
1583  }
1584 
1585  snat_det_reverse(dm, &out_addr, htons(mp->out_port), &in_addr);
1586 
1587  send_reply:
1588  REPLY_MACRO2(VL_API_SNAT_DET_REVERSE_REPLY,
1589  ({
1590  rmp->is_ip4 = 1;
1591  memset(rmp->in_addr, 0, 16);
1592  clib_memcpy(rmp->in_addr, &in_addr, 4);
1593  }))
1594 }
1595 
1597 (vl_api_snat_det_reverse_t * mp, void * handle)
1598 {
1599  u8 * s;
1600 
1601  s = format(0, "SCRIPT: smat_det_reverse_t");
1602  s = format(s, "outside ip address %U outside port %d",
1603  format_ip4_address, mp->out_addr, ntohs(mp->out_port));
1604 
1605  FINISH;
1606 }
1607 
1608 static void
1611 {
1613  snat_main_t * sm = &snat_main;
1614 
1615  rmp = vl_msg_api_alloc (sizeof (*rmp));
1616  memset (rmp, 0, sizeof (*rmp));
1617  rmp->_vl_msg_id = ntohs (VL_API_SNAT_DET_MAP_DETAILS+sm->msg_id_base);
1618  rmp->is_ip4 = 1;
1619  clib_memcpy (rmp->in_addr, &m->in_addr, 4);
1620  rmp->in_plen = m->in_plen;
1621  clib_memcpy (rmp->out_addr, &m->out_addr, 4);
1622  rmp->out_plen = m->out_plen;
1623  rmp->sharing_ratio = htonl (m->sharing_ratio);
1624  rmp->ports_per_host = htons (m->ports_per_host);
1625  rmp->ses_num = htonl (m->ses_num);
1626  rmp->context = context;
1627 
1628  vl_msg_api_send_shmem (q, (u8 *) & rmp);
1629 }
1630 
1631 static void
1634 {
1636  snat_main_t * sm = &snat_main;
1637  snat_det_map_t * m;
1638 
1640  if (q == 0)
1641  return;
1642 
1643  vec_foreach(m, sm->det_maps)
1645 }
1646 
1648 (vl_api_snat_det_map_dump_t *mp, void * handle)
1649 {
1650  u8 * s;
1651 
1652  s = format (0, "SCRIPT: snat_det_map_dump ");
1653 
1654  FINISH;
1655 }
1656 
1657 /* List of message types that this plugin understands */
1658 #define foreach_snat_plugin_api_msg \
1659 _(SNAT_ADD_ADDRESS_RANGE, snat_add_address_range) \
1660 _(SNAT_INTERFACE_ADD_DEL_FEATURE, snat_interface_add_del_feature) \
1661 _(SNAT_ADD_STATIC_MAPPING, snat_add_static_mapping) \
1662 _(SNAT_CONTROL_PING, snat_control_ping) \
1663 _(SNAT_STATIC_MAPPING_DUMP, snat_static_mapping_dump) \
1664 _(SNAT_SHOW_CONFIG, snat_show_config) \
1665 _(SNAT_ADDRESS_DUMP, snat_address_dump) \
1666 _(SNAT_INTERFACE_DUMP, snat_interface_dump) \
1667 _(SNAT_SET_WORKERS, snat_set_workers) \
1668 _(SNAT_WORKER_DUMP, snat_worker_dump) \
1669 _(SNAT_ADD_DEL_INTERFACE_ADDR, snat_add_del_interface_addr) \
1670 _(SNAT_INTERFACE_ADDR_DUMP, snat_interface_addr_dump) \
1671 _(SNAT_IPFIX_ENABLE_DISABLE, snat_ipfix_enable_disable) \
1672 _(SNAT_USER_DUMP, snat_user_dump) \
1673 _(SNAT_USER_SESSION_DUMP, snat_user_session_dump) \
1674 _(SNAT_ADD_DET_MAP, snat_add_det_map) \
1675 _(SNAT_DET_FORWARD, snat_det_forward) \
1676 _(SNAT_DET_REVERSE, snat_det_reverse) \
1677 _(SNAT_DET_MAP_DUMP, snat_det_map_dump)
1678 
1679 /* Set up the API message handling tables */
1680 static clib_error_t *
1682 {
1683  snat_main_t * sm __attribute__ ((unused)) = &snat_main;
1684 #define _(N,n) \
1685  vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base), \
1686  #n, \
1687  vl_api_##n##_t_handler, \
1688  vl_noop_handler, \
1689  vl_api_##n##_t_endian, \
1690  vl_api_##n##_t_print, \
1691  sizeof(vl_api_##n##_t), 1);
1693 #undef _
1694 
1695  return 0;
1696 }
1697 
1698 #define vl_msg_name_crc_list
1699 #include <snat/snat_all_api_h.h>
1700 #undef vl_msg_name_crc_list
1701 
1702 static void
1704 {
1705 #define _(id,n,crc) \
1706  vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + sm->msg_id_base);
1707  foreach_vl_msg_name_crc_snat;
1708 #undef _
1709 }
1710 
1712 {
1713 #define _(n,f) sm->api_main->msg_print_handlers \
1714  [VL_API_##n + sm->msg_id_base] \
1715  = (void *) vl_api_##f##_t_print;
1717 #undef _
1718 }
1719 
1720 
1721 static void
1723  uword opaque,
1724  u32 sw_if_index,
1725  ip4_address_t * address,
1726  u32 address_length,
1727  u32 if_address_index,
1728  u32 is_delete);
1729 
1731 {
1732  snat_main_t * sm = &snat_main;
1733  clib_error_t * error = 0;
1734  ip4_main_t * im = &ip4_main;
1735  ip_lookup_main_t * lm = &im->lookup_main;
1736  u8 * name;
1737  uword *p;
1740  uword *bitmap = 0;
1741  u32 i;
1743 
1744  name = format (0, "snat_%08x%c", api_version, 0);
1745 
1746  /* Ask for a correctly-sized block of API message decode slots */
1747  sm->msg_id_base = vl_msg_api_get_msg_ids
1748  ((char *) name, VL_MSG_FIRST_AVAILABLE);
1749 
1750  sm->vlib_main = vm;
1751  sm->vnet_main = vnet_get_main();
1752  sm->ip4_main = im;
1753  sm->ip4_lookup_main = lm;
1754  sm->api_main = &api_main;
1755  sm->first_worker_index = 0;
1756  sm->next_worker = 0;
1757  sm->num_workers = 0;
1758  sm->workers = 0;
1759  sm->fq_in2out_index = ~0;
1760  sm->fq_out2in_index = ~0;
1761 
1762  p = hash_get_mem (tm->thread_registrations_by_name, "workers");
1763  if (p)
1764  {
1765  tr = (vlib_thread_registration_t *) p[0];
1766  if (tr)
1767  {
1768  sm->num_workers = tr->count;
1769  sm->first_worker_index = tr->first_index;
1770  }
1771  }
1772 
1773  /* Use all available workers by default */
1774  if (sm->num_workers > 1)
1775  {
1776  for (i=0; i < sm->num_workers; i++)
1777  bitmap = clib_bitmap_set (bitmap, i, 1);
1778  snat_set_workers(bitmap);
1779  clib_bitmap_free (bitmap);
1780  }
1781 
1782  error = snat_plugin_api_hookup (vm);
1783 
1784  /* Add our API messages to the global name_crc hash table */
1786 
1788  vec_free(name);
1789 
1790  /* Set up the interface address add/del callback */
1792  cb4.function_opaque = 0;
1793 
1795 
1796  /* Init IPFIX logging */
1798 
1799  return error;
1800 }
1801 
1803 
1805  snat_session_key_t * k,
1806  u32 address_index)
1807 {
1808  snat_address_t *a;
1809  u16 port_host_byte_order = clib_net_to_host_u16 (k->port);
1810 
1811  ASSERT (address_index < vec_len (sm->addresses));
1812 
1813  a = sm->addresses + address_index;
1814 
1815  switch (k->protocol)
1816  {
1817 #define _(N, i, n, s) \
1818  case SNAT_PROTOCOL_##N: \
1819  ASSERT (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, \
1820  port_host_byte_order) == 1); \
1821  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, \
1822  port_host_byte_order, 0); \
1823  a->busy_##n##_ports--; \
1824  break;
1826 #undef _
1827  default:
1828  clib_warning("unknown_protocol");
1829  return;
1830  }
1831 }
1832 
1833 /**
1834  * @brief Match SNAT static mapping.
1835  *
1836  * @param sm SNAT main.
1837  * @param match Address and port to match.
1838  * @param mapping External or local address and port of the matched mapping.
1839  * @param by_external If 0 match by local address otherwise match by external
1840  * address.
1841  * @param is_addr_only If matched mapping is address only
1842  *
1843  * @returns 0 if match found otherwise 1.
1844  */
1846  snat_session_key_t match,
1847  snat_session_key_t * mapping,
1848  u8 by_external,
1849  u8 *is_addr_only)
1850 {
1851  clib_bihash_kv_8_8_t kv, value;
1853  snat_session_key_t m_key;
1854  clib_bihash_8_8_t *mapping_hash = &sm->static_mapping_by_local;
1855 
1856  if (by_external)
1857  mapping_hash = &sm->static_mapping_by_external;
1858 
1859  m_key.addr = match.addr;
1860  m_key.port = clib_net_to_host_u16 (match.port);
1861  m_key.protocol = match.protocol;
1862  m_key.fib_index = match.fib_index;
1863 
1864  kv.key = m_key.as_u64;
1865 
1866  if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
1867  {
1868  /* Try address only mapping */
1869  m_key.port = 0;
1870  m_key.protocol = 0;
1871  kv.key = m_key.as_u64;
1872  if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
1873  return 1;
1874  }
1875 
1876  m = pool_elt_at_index (sm->static_mappings, value.value);
1877 
1878  if (by_external)
1879  {
1880  mapping->addr = m->local_addr;
1881  /* Address only mapping doesn't change port */
1882  mapping->port = m->addr_only ? match.port
1883  : clib_host_to_net_u16 (m->local_port);
1884  mapping->fib_index = m->fib_index;
1885  }
1886  else
1887  {
1888  mapping->addr = m->external_addr;
1889  /* Address only mapping doesn't change port */
1890  mapping->port = m->addr_only ? match.port
1891  : clib_host_to_net_u16 (m->external_port);
1892  mapping->fib_index = sm->outside_fib_index;
1893  }
1894 
1895  if (PREDICT_FALSE(is_addr_only != 0))
1896  *is_addr_only = m->addr_only;
1897 
1898  return 0;
1899 }
1900 
1902  u32 fib_index,
1903  snat_session_key_t * k,
1904  u32 * address_indexp)
1905 {
1906  int i;
1907  snat_address_t *a;
1908  u32 portnum;
1909 
1910  for (i = 0; i < vec_len (sm->addresses); i++)
1911  {
1912  a = sm->addresses + i;
1913  if (sm->vrf_mode && a->fib_index != ~0 && a->fib_index != fib_index)
1914  continue;
1915  switch (k->protocol)
1916  {
1917 #define _(N, j, n, s) \
1918  case SNAT_PROTOCOL_##N: \
1919  if (a->busy_##n##_ports < (65535-1024)) \
1920  { \
1921  while (1) \
1922  { \
1923  portnum = random_u32 (&sm->random_seed); \
1924  portnum &= 0xFFFF; \
1925  if (portnum < 1024) \
1926  continue; \
1927  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \
1928  continue; \
1929  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \
1930  a->busy_##n##_ports++; \
1931  k->addr = a->addr; \
1932  k->port = clib_host_to_net_u16(portnum); \
1933  *address_indexp = i; \
1934  return 0; \
1935  } \
1936  } \
1937  break;
1939 #undef _
1940  default:
1941  clib_warning("unknown protocol");
1942  return 1;
1943  }
1944 
1945  }
1946  /* Totally out of translations to use... */
1948  return 1;
1949 }
1950 
1951 
1952 static clib_error_t *
1954  unformat_input_t * input,
1955  vlib_cli_command_t * cmd)
1956 {
1957  unformat_input_t _line_input, *line_input = &_line_input;
1958  snat_main_t * sm = &snat_main;
1959  ip4_address_t start_addr, end_addr, this_addr;
1960  u32 start_host_order, end_host_order;
1961  u32 vrf_id = ~0;
1962  int i, count;
1963  int is_add = 1;
1964  int rv = 0;
1965  clib_error_t *error = 0;
1966 
1967  /* Get a line of input. */
1968  if (!unformat_user (input, unformat_line_input, line_input))
1969  return 0;
1970 
1971  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1972  {
1973  if (unformat (line_input, "%U - %U",
1974  unformat_ip4_address, &start_addr,
1975  unformat_ip4_address, &end_addr))
1976  ;
1977  else if (unformat (line_input, "tenant-vrf %u", &vrf_id))
1978  ;
1979  else if (unformat (line_input, "%U", unformat_ip4_address, &start_addr))
1980  end_addr = start_addr;
1981  else if (unformat (line_input, "del"))
1982  is_add = 0;
1983  else
1984  {
1985  error = clib_error_return (0, "unknown input '%U'",
1986  format_unformat_error, line_input);
1987  goto done;
1988  }
1989  }
1990 
1991  if (sm->static_mapping_only)
1992  {
1993  error = clib_error_return (0, "static mapping only mode");
1994  goto done;
1995  }
1996 
1997  start_host_order = clib_host_to_net_u32 (start_addr.as_u32);
1998  end_host_order = clib_host_to_net_u32 (end_addr.as_u32);
1999 
2000  if (end_host_order < start_host_order)
2001  {
2002  error = clib_error_return (0, "end address less than start address");
2003  goto done;
2004  }
2005 
2006  count = (end_host_order - start_host_order) + 1;
2007 
2008  if (count > 1024)
2009  clib_warning ("%U - %U, %d addresses...",
2010  format_ip4_address, &start_addr,
2011  format_ip4_address, &end_addr,
2012  count);
2013 
2014  this_addr = start_addr;
2015 
2016  for (i = 0; i < count; i++)
2017  {
2018  if (is_add)
2019  snat_add_address (sm, &this_addr, vrf_id);
2020  else
2021  rv = snat_del_address (sm, this_addr, 0);
2022 
2023  switch (rv)
2024  {
2025  case VNET_API_ERROR_NO_SUCH_ENTRY:
2026  error = clib_error_return (0, "S-NAT address not exist.");
2027  goto done;
2028  case VNET_API_ERROR_UNSPECIFIED:
2029  error = clib_error_return (0, "S-NAT address used in static mapping.");
2030  goto done;
2031  default:
2032  break;
2033  }
2034 
2035  increment_v4_address (&this_addr);
2036  }
2037 
2038 done:
2039  unformat_free (line_input);
2040 
2041  return error;
2042 }
2043 
2045  .path = "snat add address",
2046  .short_help = "snat add addresses <ip4-range-start> [- <ip4-range-end>] "
2047  "[tenant-vrf <vrf-id>] [del]",
2048  .function = add_address_command_fn,
2049 };
2050 
2051 static clib_error_t *
2053  unformat_input_t * input,
2054  vlib_cli_command_t * cmd)
2055 {
2056  unformat_input_t _line_input, *line_input = &_line_input;
2057  vnet_main_t * vnm = vnet_get_main();
2058  clib_error_t * error = 0;
2059  u32 sw_if_index;
2060  u32 * inside_sw_if_indices = 0;
2061  u32 * outside_sw_if_indices = 0;
2062  int is_del = 0;
2063  int i;
2064 
2065  sw_if_index = ~0;
2066 
2067  /* Get a line of input. */
2068  if (!unformat_user (input, unformat_line_input, line_input))
2069  return 0;
2070 
2071  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2072  {
2073  if (unformat (line_input, "in %U", unformat_vnet_sw_interface,
2074  vnm, &sw_if_index))
2075  vec_add1 (inside_sw_if_indices, sw_if_index);
2076  else if (unformat (line_input, "out %U", unformat_vnet_sw_interface,
2077  vnm, &sw_if_index))
2078  vec_add1 (outside_sw_if_indices, sw_if_index);
2079  else if (unformat (line_input, "del"))
2080  is_del = 1;
2081  else
2082  {
2083  error = clib_error_return (0, "unknown input '%U'",
2084  format_unformat_error, line_input);
2085  goto done;
2086  }
2087  }
2088 
2089  if (vec_len (inside_sw_if_indices))
2090  {
2091  for (i = 0; i < vec_len(inside_sw_if_indices); i++)
2092  {
2093  sw_if_index = inside_sw_if_indices[i];
2094  snat_interface_add_del (sw_if_index, 1, is_del);
2095  }
2096  }
2097 
2098  if (vec_len (outside_sw_if_indices))
2099  {
2100  for (i = 0; i < vec_len(outside_sw_if_indices); i++)
2101  {
2102  sw_if_index = outside_sw_if_indices[i];
2103  snat_interface_add_del (sw_if_index, 0, is_del);
2104  }
2105  }
2106 
2107 done:
2108  unformat_free (line_input);
2109  vec_free (inside_sw_if_indices);
2110  vec_free (outside_sw_if_indices);
2111 
2112  return error;
2113 }
2114 
2116  .path = "set interface snat",
2117  .function = snat_feature_command_fn,
2118  .short_help = "set interface snat in <intfc> out <intfc> [del]",
2119 };
2120 
2121 uword
2122 unformat_snat_protocol (unformat_input_t * input, va_list * args)
2123 {
2124  u32 *r = va_arg (*args, u32 *);
2125 
2126  if (0);
2127 #define _(N, i, n, s) else if (unformat (input, s)) *r = SNAT_PROTOCOL_##N;
2129 #undef _
2130  else
2131  return 0;
2132  return 1;
2133 }
2134 
2135 u8 *
2136 format_snat_protocol (u8 * s, va_list * args)
2137 {
2138  u32 i = va_arg (*args, u32);
2139  u8 *t = 0;
2140 
2141  switch (i)
2142  {
2143 #define _(N, j, n, str) case SNAT_PROTOCOL_##N: t = (u8 *) str; break;
2145 #undef _
2146  default:
2147  s = format (s, "unknown");
2148  }
2149  s = format (s, "%s", t);
2150  return s;
2151 }
2152 
2153 static clib_error_t *
2155  unformat_input_t * input,
2156  vlib_cli_command_t * cmd)
2157 {
2158  unformat_input_t _line_input, *line_input = &_line_input;
2159  clib_error_t * error = 0;
2160  ip4_address_t l_addr, e_addr;
2161  u32 l_port = 0, e_port = 0, vrf_id = ~0;
2162  int is_add = 1;
2163  int addr_only = 1;
2164  u32 sw_if_index = ~0;
2165  vnet_main_t * vnm = vnet_get_main();
2166  int rv;
2167  snat_protocol_t proto;
2168  u8 proto_set = 0;
2169 
2170  /* Get a line of input. */
2171  if (!unformat_user (input, unformat_line_input, line_input))
2172  return 0;
2173 
2174  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2175  {
2176  if (unformat (line_input, "local %U %u", unformat_ip4_address, &l_addr,
2177  &l_port))
2178  addr_only = 0;
2179  else if (unformat (line_input, "local %U", unformat_ip4_address, &l_addr))
2180  ;
2181  else if (unformat (line_input, "external %U %u", unformat_ip4_address,
2182  &e_addr, &e_port))
2183  addr_only = 0;
2184  else if (unformat (line_input, "external %U", unformat_ip4_address,
2185  &e_addr))
2186  ;
2187  else if (unformat (line_input, "external %U %u",
2188  unformat_vnet_sw_interface, vnm, &sw_if_index,
2189  &e_port))
2190  addr_only = 0;
2191 
2192  else if (unformat (line_input, "external %U",
2193  unformat_vnet_sw_interface, vnm, &sw_if_index))
2194  ;
2195  else if (unformat (line_input, "vrf %u", &vrf_id))
2196  ;
2197  else if (unformat (line_input, "%U", unformat_snat_protocol, &proto))
2198  proto_set = 1;
2199  else if (unformat (line_input, "del"))
2200  is_add = 0;
2201  else
2202  {
2203  error = clib_error_return (0, "unknown input: '%U'",
2204  format_unformat_error, line_input);
2205  goto done;
2206  }
2207  }
2208 
2209  if (!addr_only && !proto_set)
2210  {
2211  error = clib_error_return (0, "missing protocol");
2212  goto done;
2213  }
2214 
2215  rv = snat_add_static_mapping(l_addr, e_addr, (u16) l_port, (u16) e_port,
2216  vrf_id, addr_only, sw_if_index, proto, is_add);
2217 
2218  switch (rv)
2219  {
2220  case VNET_API_ERROR_INVALID_VALUE:
2221  error = clib_error_return (0, "External port already in use.");
2222  goto done;
2223  case VNET_API_ERROR_NO_SUCH_ENTRY:
2224  if (is_add)
2225  error = clib_error_return (0, "External addres must be allocated.");
2226  else
2227  error = clib_error_return (0, "Mapping not exist.");
2228  goto done;
2229  case VNET_API_ERROR_NO_SUCH_FIB:
2230  error = clib_error_return (0, "No such VRF id.");
2231  goto done;
2232  case VNET_API_ERROR_VALUE_EXIST:
2233  error = clib_error_return (0, "Mapping already exist.");
2234  goto done;
2235  default:
2236  break;
2237  }
2238 
2239 done:
2240  unformat_free (line_input);
2241 
2242  return error;
2243 }
2244 
2245 /*?
2246  * @cliexpar
2247  * @cliexstart{snat add static mapping}
2248  * Static mapping allows hosts on the external network to initiate connection
2249  * to to the local network host.
2250  * To create static mapping between local host address 10.0.0.3 port 6303 and
2251  * external address 4.4.4.4 port 3606 for TCP protocol use:
2252  * vpp# snat add static mapping local tcp 10.0.0.3 6303 external 4.4.4.4 3606
2253  * If not runnig "static mapping only" S-NAT plugin mode use before:
2254  * vpp# snat add address 4.4.4.4
2255  * To create static mapping between local and external address use:
2256  * vpp# snat add static mapping local 10.0.0.3 external 4.4.4.4
2257  * @cliexend
2258 ?*/
2260  .path = "snat add static mapping",
2261  .function = add_static_mapping_command_fn,
2262  .short_help =
2263  "snat add static mapping local tcp|udp|icmp <addr> [<port>] external <addr> [<port>] [vrf <table-id>] [del]",
2264 };
2265 
2266 static clib_error_t *
2268  unformat_input_t * input,
2269  vlib_cli_command_t * cmd)
2270 {
2271  unformat_input_t _line_input, *line_input = &_line_input;
2272  uword *bitmap = 0;
2273  int rv = 0;
2274  clib_error_t *error = 0;
2275 
2276  /* Get a line of input. */
2277  if (!unformat_user (input, unformat_line_input, line_input))
2278  return 0;
2279 
2280  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2281  {
2282  if (unformat (line_input, "%U", unformat_bitmap_list, &bitmap))
2283  ;
2284  else
2285  {
2286  error = clib_error_return (0, "unknown input '%U'",
2287  format_unformat_error, line_input);
2288  goto done;
2289  }
2290  }
2291 
2292  if (bitmap == 0)
2293  {
2294  error = clib_error_return (0, "List of workers must be specified.");
2295  goto done;
2296  }
2297 
2298  rv = snat_set_workers(bitmap);
2299 
2300  clib_bitmap_free (bitmap);
2301 
2302  switch (rv)
2303  {
2304  case VNET_API_ERROR_INVALID_WORKER:
2305  error = clib_error_return (0, "Invalid worker(s).");
2306  goto done;
2307  case VNET_API_ERROR_FEATURE_DISABLED:
2308  error = clib_error_return (0,
2309  "Supported only if 2 or more workes available.");
2310  goto done;
2311  default:
2312  break;
2313  }
2314 
2315 done:
2316  unformat_free (line_input);
2317 
2318  return error;
2319 }
2320 
2321 /*?
2322  * @cliexpar
2323  * @cliexstart{set snat workers}
2324  * Set SNAT workers if 2 or more workers available, use:
2325  * vpp# set snat workers 0-2,5
2326  * @cliexend
2327 ?*/
2329  .path = "set snat workers",
2330  .function = set_workers_command_fn,
2331  .short_help =
2332  "set snat workers <workers-list>",
2333 };
2334 
2335 static clib_error_t *
2337  unformat_input_t * input,
2338  vlib_cli_command_t * cmd)
2339 {
2340  unformat_input_t _line_input, *line_input = &_line_input;
2341  u32 domain_id = 0;
2342  u32 src_port = 0;
2343  u8 enable = 1;
2344  int rv = 0;
2345  clib_error_t *error = 0;
2346 
2347  /* Get a line of input. */
2348  if (!unformat_user (input, unformat_line_input, line_input))
2349  return 0;
2350 
2351  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2352  {
2353  if (unformat (line_input, "domain %d", &domain_id))
2354  ;
2355  else if (unformat (line_input, "src-port %d", &src_port))
2356  ;
2357  else if (unformat (line_input, "disable"))
2358  enable = 0;
2359  else
2360  {
2361  error = clib_error_return (0, "unknown input '%U'",
2362  format_unformat_error, line_input);
2363  goto done;
2364  }
2365  }
2366 
2367  rv = snat_ipfix_logging_enable_disable (enable, domain_id, (u16) src_port);
2368 
2369  if (rv)
2370  {
2371  error = clib_error_return (0, "ipfix logging enable failed");
2372  goto done;
2373  }
2374 
2375 done:
2376  unformat_free (line_input);
2377 
2378  return error;
2379 }
2380 
2381 /*?
2382  * @cliexpar
2383  * @cliexstart{snat ipfix logging}
2384  * To enable SNAT IPFIX logging use:
2385  * vpp# snat ipfix logging
2386  * To set IPFIX exporter use:
2387  * vpp# set ipfix exporter collector 10.10.10.3 src 10.10.10.1
2388  * @cliexend
2389 ?*/
2391  .path = "snat ipfix logging",
2393  .short_help = "snat ipfix logging [domain <domain-id>] [src-port <port>] [disable]",
2394 };
2395 
2396 static u32
2398 {
2399  snat_main_t *sm = &snat_main;
2400  snat_user_key_t key0;
2401  clib_bihash_kv_8_8_t kv0, value0;
2402  u32 next_worker_index = 0;
2403 
2404  key0.addr = ip0->src_address;
2405  key0.fib_index = rx_fib_index0;
2406 
2407  kv0.key = key0.as_u64;
2408 
2409  /* Ever heard of of the "user" before? */
2410  if (clib_bihash_search_8_8 (&sm->worker_by_in, &kv0, &value0))
2411  {
2412  /* No, assign next available worker (RR) */
2413  next_worker_index = sm->first_worker_index;
2414  if (vec_len (sm->workers))
2415  {
2416  next_worker_index +=
2417  sm->workers[sm->next_worker++ % _vec_len (sm->workers)];
2418  }
2419 
2420  /* add non-traslated packets worker lookup */
2421  kv0.value = next_worker_index;
2422  clib_bihash_add_del_8_8 (&sm->worker_by_in, &kv0, 1);
2423  }
2424  else
2425  next_worker_index = value0.value;
2426 
2427  return next_worker_index;
2428 }
2429 
2430 static u32
2432 {
2433  snat_main_t *sm = &snat_main;
2434  snat_worker_key_t key0;
2435  clib_bihash_kv_8_8_t kv0, value0;
2436  udp_header_t * udp0;
2437  u32 next_worker_index = 0;
2438 
2439  udp0 = ip4_next_header (ip0);
2440 
2441  key0.addr = ip0->dst_address;
2442  key0.port = udp0->dst_port;
2443  key0.fib_index = rx_fib_index0;
2444 
2445  if (PREDICT_FALSE(ip0->protocol == IP_PROTOCOL_ICMP))
2446  {
2447  icmp46_header_t * icmp0 = (icmp46_header_t *) udp0;
2448  icmp_echo_header_t *echo0 = (icmp_echo_header_t *)(icmp0+1);
2449  key0.port = echo0->identifier;
2450  }
2451 
2452  kv0.key = key0.as_u64;
2453 
2454  /* Ever heard of of the "user" before? */
2455  if (clib_bihash_search_8_8 (&sm->worker_by_out, &kv0, &value0))
2456  {
2457  key0.port = 0;
2458  kv0.key = key0.as_u64;
2459 
2460  if (clib_bihash_search_8_8 (&sm->worker_by_out, &kv0, &value0))
2461  {
2462  /* No, assign next available worker (RR) */
2463  next_worker_index = sm->first_worker_index;
2464  if (vec_len (sm->workers))
2465  {
2466  next_worker_index +=
2467  sm->workers[sm->next_worker++ % _vec_len (sm->workers)];
2468  }
2469  }
2470  else
2471  {
2472  /* Static mapping without port */
2473  next_worker_index = value0.value;
2474  }
2475 
2476  /* Add to translated packets worker lookup */
2477  kv0.value = next_worker_index;
2478  clib_bihash_add_del_8_8 (&sm->worker_by_out, &kv0, 1);
2479  }
2480  else
2481  next_worker_index = value0.value;
2482 
2483  return next_worker_index;
2484 }
2485 
2486 static clib_error_t *
2488 {
2489  snat_main_t * sm = &snat_main;
2490  u32 translation_buckets = 1024;
2491  u32 translation_memory_size = 128<<20;
2492  u32 user_buckets = 128;
2493  u32 user_memory_size = 64<<20;
2494  u32 max_translations_per_user = 100;
2495  u32 outside_vrf_id = 0;
2496  u32 inside_vrf_id = 0;
2497  u32 static_mapping_buckets = 1024;
2498  u32 static_mapping_memory_size = 64<<20;
2499  u8 static_mapping_only = 0;
2500  u8 static_mapping_connection_tracking = 0;
2502 
2503  sm->deterministic = 0;
2504 
2505  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2506  {
2507  if (unformat (input, "translation hash buckets %d", &translation_buckets))
2508  ;
2509  else if (unformat (input, "translation hash memory %d",
2510  &translation_memory_size));
2511  else if (unformat (input, "user hash buckets %d", &user_buckets))
2512  ;
2513  else if (unformat (input, "user hash memory %d",
2514  &user_memory_size))
2515  ;
2516  else if (unformat (input, "max translations per user %d",
2517  &max_translations_per_user))
2518  ;
2519  else if (unformat (input, "outside VRF id %d",
2520  &outside_vrf_id))
2521  ;
2522  else if (unformat (input, "inside VRF id %d",
2523  &inside_vrf_id))
2524  ;
2525  else if (unformat (input, "static mapping only"))
2526  {
2527  static_mapping_only = 1;
2528  if (unformat (input, "connection tracking"))
2529  static_mapping_connection_tracking = 1;
2530  }
2531  else if (unformat (input, "deterministic"))
2532  sm->deterministic = 1;
2533  else
2534  return clib_error_return (0, "unknown input '%U'",
2535  format_unformat_error, input);
2536  }
2537 
2538  /* for show commands, etc. */
2539  sm->translation_buckets = translation_buckets;
2540  sm->translation_memory_size = translation_memory_size;
2541  sm->user_buckets = user_buckets;
2542  sm->user_memory_size = user_memory_size;
2543  sm->max_translations_per_user = max_translations_per_user;
2544  sm->outside_vrf_id = outside_vrf_id;
2545  sm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
2546  outside_vrf_id);
2547  sm->inside_vrf_id = inside_vrf_id;
2548  sm->inside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
2549  inside_vrf_id);
2550  sm->static_mapping_only = static_mapping_only;
2551  sm->static_mapping_connection_tracking = static_mapping_connection_tracking;
2552 
2553  if (sm->deterministic)
2554  {
2555  sm->in2out_node_index = snat_det_in2out_node.index;
2556  sm->out2in_node_index = snat_det_out2in_node.index;
2557  }
2558  else
2559  {
2560  sm->worker_in2out_cb = snat_get_worker_in2out_cb;
2561  sm->worker_out2in_cb = snat_get_worker_out2in_cb;
2562  sm->in2out_node_index = snat_in2out_node.index;
2563  sm->out2in_node_index = snat_out2in_node.index;
2564  if (!static_mapping_only ||
2565  (static_mapping_only && static_mapping_connection_tracking))
2566  {
2567  sm->icmp_match_in2out_cb = icmp_match_in2out_slow;
2568  sm->icmp_match_out2in_cb = icmp_match_out2in_slow;
2569 
2570  clib_bihash_init_8_8 (&sm->worker_by_in, "worker-by-in", user_buckets,
2571  user_memory_size);
2572 
2573  clib_bihash_init_8_8 (&sm->worker_by_out, "worker-by-out", user_buckets,
2574  user_memory_size);
2575 
2576  vec_validate (sm->per_thread_data, tm->n_vlib_mains - 1);
2577 
2578  clib_bihash_init_8_8 (&sm->in2out, "in2out", translation_buckets,
2579  translation_memory_size);
2580 
2581  clib_bihash_init_8_8 (&sm->out2in, "out2in", translation_buckets,
2582  translation_memory_size);
2583 
2584  clib_bihash_init_8_8 (&sm->user_hash, "users", user_buckets,
2585  user_memory_size);
2586  }
2587  else
2588  {
2589  sm->icmp_match_in2out_cb = icmp_match_in2out_fast;
2590  sm->icmp_match_out2in_cb = icmp_match_out2in_fast;
2591  }
2592  clib_bihash_init_8_8 (&sm->static_mapping_by_local,
2593  "static_mapping_by_local", static_mapping_buckets,
2594  static_mapping_memory_size);
2595 
2596  clib_bihash_init_8_8 (&sm->static_mapping_by_external,
2597  "static_mapping_by_external", static_mapping_buckets,
2598  static_mapping_memory_size);
2599  }
2600 
2601  return 0;
2602 }
2603 
2605 
2606 u8 * format_snat_session_state (u8 * s, va_list * args)
2607 {
2608  u32 i = va_arg (*args, u32);
2609  u8 *t = 0;
2610 
2611  switch (i)
2612  {
2613 #define _(v, N, str) case SNAT_SESSION_##N: t = (u8 *) str; break;
2615 #undef _
2616  default:
2617  t = format (t, "unknown");
2618  }
2619  s = format (s, "%s", t);
2620  return s;
2621 }
2622 
2623 u8 * format_snat_key (u8 * s, va_list * args)
2624 {
2625  snat_session_key_t * key = va_arg (*args, snat_session_key_t *);
2626  char * protocol_string = "unknown";
2627  static char *protocol_strings[] = {
2628  "UDP",
2629  "TCP",
2630  "ICMP",
2631  };
2632 
2633  if (key->protocol < ARRAY_LEN(protocol_strings))
2634  protocol_string = protocol_strings[key->protocol];
2635 
2636  s = format (s, "%U proto %s port %d fib %d",
2637  format_ip4_address, &key->addr, protocol_string,
2638  clib_net_to_host_u16 (key->port), key->fib_index);
2639  return s;
2640 }
2641 
2642 u8 * format_snat_session (u8 * s, va_list * args)
2643 {
2644  snat_main_t * sm __attribute__((unused)) = va_arg (*args, snat_main_t *);
2645  snat_session_t * sess = va_arg (*args, snat_session_t *);
2646 
2647  s = format (s, " i2o %U\n", format_snat_key, &sess->in2out);
2648  s = format (s, " o2i %U\n", format_snat_key, &sess->out2in);
2649  s = format (s, " last heard %.2f\n", sess->last_heard);
2650  s = format (s, " total pkts %d, total bytes %lld\n",
2651  sess->total_pkts, sess->total_bytes);
2652  if (snat_is_session_static (sess))
2653  s = format (s, " static translation\n");
2654  else
2655  s = format (s, " dynamic translation\n");
2656 
2657  return s;
2658 }
2659 
2660 u8 * format_snat_user (u8 * s, va_list * args)
2661 {
2663  snat_user_t * u = va_arg (*args, snat_user_t *);
2664  int verbose = va_arg (*args, int);
2665  dlist_elt_t * head, * elt;
2666  u32 elt_index, head_index;
2667  u32 session_index;
2668  snat_session_t * sess;
2669 
2670  s = format (s, "%U: %d dynamic translations, %d static translations\n",
2672 
2673  if (verbose == 0)
2674  return s;
2675 
2676  if (u->nsessions || u->nstaticsessions)
2677  {
2678  head_index = u->sessions_per_user_list_head_index;
2679  head = pool_elt_at_index (sm->list_pool, head_index);
2680 
2681  elt_index = head->next;
2682  elt = pool_elt_at_index (sm->list_pool, elt_index);
2683  session_index = elt->value;
2684 
2685  while (session_index != ~0)
2686  {
2687  sess = pool_elt_at_index (sm->sessions, session_index);
2688 
2689  s = format (s, " %U\n", format_snat_session, sm, sess);
2690 
2691  elt_index = elt->next;
2692  elt = pool_elt_at_index (sm->list_pool, elt_index);
2693  session_index = elt->value;
2694  }
2695  }
2696 
2697  return s;
2698 }
2699 
2700 u8 * format_snat_static_mapping (u8 * s, va_list * args)
2701 {
2702  snat_static_mapping_t *m = va_arg (*args, snat_static_mapping_t *);
2703 
2704  if (m->addr_only)
2705  s = format (s, "local %U external %U vrf %d",
2708  m->vrf_id);
2709  else
2710  s = format (s, "%U local %U:%d external %U:%d vrf %d",
2714  m->vrf_id);
2715 
2716  return s;
2717 }
2718 
2719 u8 * format_snat_static_map_to_resolve (u8 * s, va_list * args)
2720 {
2722  vnet_main_t *vnm = vnet_get_main();
2723 
2724  if (m->addr_only)
2725  s = format (s, "local %U external %U vrf %d",
2729  m->vrf_id);
2730  else
2731  s = format (s, "%U local %U:%d external %U:%d vrf %d",
2733  format_ip4_address, &m->l_addr, m->l_port,
2736  m->vrf_id);
2737 
2738  return s;
2739 }
2740 
2741 u8 * format_det_map_ses (u8 * s, va_list * args)
2742 {
2743  snat_det_map_t * det_map = va_arg (*args, snat_det_map_t *);
2744  ip4_address_t in_addr, out_addr;
2745  u32 in_offset, out_offset;
2746  snat_det_session_t * ses = va_arg (*args, snat_det_session_t *);
2747  u32 * i = va_arg (*args, u32 *);
2748 
2749  u32 user_index = *i / SNAT_DET_SES_PER_USER;
2750  in_addr.as_u32 = clib_host_to_net_u32 (
2751  clib_net_to_host_u32(det_map->in_addr.as_u32) + user_index);
2752  in_offset = clib_net_to_host_u32(in_addr.as_u32) -
2753  clib_net_to_host_u32(det_map->in_addr.as_u32);
2754  out_offset = in_offset / det_map->sharing_ratio;
2755  out_addr.as_u32 = clib_host_to_net_u32(
2756  clib_net_to_host_u32(det_map->out_addr.as_u32) + out_offset);
2757  s = format (s, "in %U:%d out %U:%d external host %U:%d state: %U expire: %d\n",
2758  format_ip4_address, &in_addr,
2759  clib_net_to_host_u16 (ses->in_port),
2760  format_ip4_address, &out_addr,
2761  clib_net_to_host_u16 (ses->out.out_port),
2763  clib_net_to_host_u16 (ses->out.ext_host_port),
2765  ses->expire);
2766 
2767  return s;
2768 }
2769 
2770 static clib_error_t *
2772  unformat_input_t * input,
2773  vlib_cli_command_t * cmd)
2774 {
2775  int verbose = 0;
2776  snat_main_t * sm = &snat_main;
2777  snat_user_t * u;
2780  snat_address_t * ap;
2781  vnet_main_t *vnm = vnet_get_main();
2783  u32 users_num = 0, sessions_num = 0, *worker, *sw_if_index;
2784  uword j = 0;
2786  snat_det_map_t * dm;
2787  snat_det_session_t * ses;
2788 
2789  if (unformat (input, "detail"))
2790  verbose = 1;
2791  else if (unformat (input, "verbose"))
2792  verbose = 2;
2793 
2794  if (sm->static_mapping_only)
2795  {
2796  if (sm->static_mapping_connection_tracking)
2797  vlib_cli_output (vm, "SNAT mode: static mapping only connection "
2798  "tracking");
2799  else
2800  vlib_cli_output (vm, "SNAT mode: static mapping only");
2801  }
2802  else if (sm->deterministic)
2803  {
2804  vlib_cli_output (vm, "SNAT mode: deterministic mapping");
2805  }
2806  else
2807  {
2808  vlib_cli_output (vm, "SNAT mode: dynamic translations enabled");
2809  }
2810 
2811  if (verbose > 0)
2812  {
2813  pool_foreach (i, sm->interfaces,
2814  ({
2815  vlib_cli_output (vm, "%U %s", format_vnet_sw_interface_name, vnm,
2816  vnet_get_sw_interface (vnm, i->sw_if_index),
2817  i->is_inside ? "in" : "out");
2818  }));
2819 
2820  if (vec_len (sm->auto_add_sw_if_indices))
2821  {
2822  vlib_cli_output (vm, "SNAT pool addresses interfaces:");
2823  vec_foreach (sw_if_index, sm->auto_add_sw_if_indices)
2824  {
2826  vnet_get_sw_interface (vnm, *sw_if_index));
2827  }
2828  }
2829 
2830  vec_foreach (ap, sm->addresses)
2831  {
2832  vlib_cli_output (vm, "%U", format_ip4_address, &ap->addr);
2833  if (ap->fib_index != ~0)
2834  vlib_cli_output (vm, " tenant VRF: %u",
2836  else
2837  vlib_cli_output (vm, " tenant VRF independent");
2838 #define _(N, i, n, s) \
2839  vlib_cli_output (vm, " %d busy %s ports", ap->busy_##n##_ports, s);
2841 #undef _
2842  }
2843  }
2844 
2845  if (sm->num_workers > 1)
2846  {
2847  vlib_cli_output (vm, "%d workers", vec_len (sm->workers));
2848  if (verbose > 0)
2849  {
2850  vec_foreach (worker, sm->workers)
2851  {
2853  vlib_worker_threads + *worker + sm->first_worker_index;
2854  vlib_cli_output (vm, " %s", w->name);
2855  }
2856  }
2857  }
2858 
2859  if (sm->deterministic)
2860  {
2861  vlib_cli_output (vm, "%d deterministic mappings",
2862  pool_elts (sm->det_maps));
2863  if (verbose > 0)
2864  {
2865  pool_foreach (dm, sm->det_maps,
2866  ({
2867  vlib_cli_output (vm, "in %U/%d out %U/%d\n",
2868  format_ip4_address, &dm->in_addr, dm->in_plen,
2869  format_ip4_address, &dm->out_addr, dm->out_plen);
2870  vlib_cli_output (vm, " outside address sharing ratio: %d\n",
2871  dm->sharing_ratio);
2872  vlib_cli_output (vm, " number of ports per inside host: %d\n",
2873  dm->ports_per_host);
2874  vlib_cli_output (vm, " sessions number: %d\n", dm->ses_num);
2875  if (verbose > 1)
2876  {
2877  vec_foreach_index (j, dm->sessions)
2878  {
2879  ses = vec_elt_at_index (dm->sessions, j);
2880  if (ses->in_port)
2881  vlib_cli_output (vm, " %U", format_det_map_ses, dm, ses,
2882  &j);
2883  }
2884  }
2885  }));
2886  }
2887  }
2888  else
2889  {
2890  if (sm->static_mapping_only && !(sm->static_mapping_connection_tracking))
2891  {
2892  vlib_cli_output (vm, "%d static mappings",
2893  pool_elts (sm->static_mappings));
2894 
2895  if (verbose > 0)
2896  {
2897  pool_foreach (m, sm->static_mappings,
2898  ({
2899  vlib_cli_output (vm, "%U", format_snat_static_mapping, m);
2900  }));
2901  }
2902  }
2903  else
2904  {
2905  vec_foreach (tsm, sm->per_thread_data)
2906  {
2907  users_num += pool_elts (tsm->users);
2908  sessions_num += pool_elts (tsm->sessions);
2909  }
2910 
2911  vlib_cli_output (vm, "%d users, %d outside addresses, %d active sessions,"
2912  " %d static mappings",
2913  users_num,
2914  vec_len (sm->addresses),
2915  sessions_num,
2916  pool_elts (sm->static_mappings));
2917 
2918  if (verbose > 0)
2919  {
2920  vlib_cli_output (vm, "%U", format_bihash_8_8, &sm->in2out,
2921  verbose - 1);
2922  vlib_cli_output (vm, "%U", format_bihash_8_8, &sm->out2in,
2923  verbose - 1);
2924  vlib_cli_output (vm, "%U", format_bihash_8_8, &sm->worker_by_in,
2925  verbose - 1);
2926  vlib_cli_output (vm, "%U", format_bihash_8_8, &sm->worker_by_out,
2927  verbose - 1);
2928  vec_foreach_index (j, sm->per_thread_data)
2929  {
2930  tsm = vec_elt_at_index (sm->per_thread_data, j);
2931 
2932  if (pool_elts (tsm->users) == 0)
2933  continue;
2934 
2936  vlib_cli_output (vm, "Thread %d (%s at lcore %u):", j, w->name,
2937  w->lcore_id);
2938  vlib_cli_output (vm, " %d list pool elements",
2939  pool_elts (tsm->list_pool));
2940 
2941  pool_foreach (u, tsm->users,
2942  ({
2943  vlib_cli_output (vm, " %U", format_snat_user, tsm, u,
2944  verbose - 1);
2945  }));
2946  }
2947 
2948  if (pool_elts (sm->static_mappings))
2949  {
2950  vlib_cli_output (vm, "static mappings:");
2951  pool_foreach (m, sm->static_mappings,
2952  ({
2953  vlib_cli_output (vm, "%U", format_snat_static_mapping, m);
2954  }));
2955  for (j = 0; j < vec_len (sm->to_resolve); j++)
2956  {
2957  rp = sm->to_resolve + j;
2958  vlib_cli_output (vm, "%U",
2960  }
2961  }
2962  }
2963  }
2964  }
2965  return 0;
2966 }
2967 
2969  .path = "show snat",
2970  .short_help = "show snat",
2971  .function = show_snat_command_fn,
2972 };
2973 
2974 
2975 static void
2977  uword opaque,
2978  u32 sw_if_index,
2979  ip4_address_t * address,
2980  u32 address_length,
2981  u32 if_address_index,
2982  u32 is_delete)
2983 {
2984  snat_main_t *sm = &snat_main;
2986  u32 *indices_to_delete = 0;
2987  int i, j;
2988  int rv;
2989 
2990  for (i = 0; i < vec_len(sm->auto_add_sw_if_indices); i++)
2991  {
2992  if (sw_if_index == sm->auto_add_sw_if_indices[i])
2993  {
2994  if (!is_delete)
2995  {
2996  /* Don't trip over lease renewal, static config */
2997  for (j = 0; j < vec_len(sm->addresses); j++)
2998  if (sm->addresses[j].addr.as_u32 == address->as_u32)
2999  return;
3000 
3001  snat_add_address (sm, address, ~0);
3002  /* Scan static map resolution vector */
3003  for (j = 0; j < vec_len (sm->to_resolve); j++)
3004  {
3005  rp = sm->to_resolve + j;
3006  /* On this interface? */
3007  if (rp->sw_if_index == sw_if_index)
3008  {
3009  /* Add the static mapping */
3010  rv = snat_add_static_mapping (rp->l_addr,
3011  address[0],
3012  rp->l_port,
3013  rp->e_port,
3014  rp->vrf_id,
3015  rp->addr_only,
3016  ~0 /* sw_if_index */,
3017  rp->proto,
3018  rp->is_add);
3019  if (rv)
3020  clib_warning ("snat_add_static_mapping returned %d",
3021  rv);
3022  vec_add1 (indices_to_delete, j);
3023  }
3024  }
3025  /* If we resolved any of the outstanding static mappings */
3026  if (vec_len(indices_to_delete))
3027  {
3028  /* Delete them */
3029  for (j = vec_len(indices_to_delete)-1; j >= 0; j--)
3030  vec_delete(sm->to_resolve, 1, j);
3031  vec_free(indices_to_delete);
3032  }
3033  return;
3034  }
3035  else
3036  {
3037  (void) snat_del_address(sm, address[0], 1);
3038  return;
3039  }
3040  }
3041  }
3042 }
3043 
3044 
3046  u32 sw_if_index,
3047  int is_del)
3048 {
3049  ip4_main_t * ip4_main = sm->ip4_main;
3050  ip4_address_t * first_int_addr;
3052  u32 *indices_to_delete = 0;
3053  int i, j;
3054 
3055  first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index,
3056  0 /* just want the address*/);
3057 
3058  for (i = 0; i < vec_len(sm->auto_add_sw_if_indices); i++)
3059  {
3060  if (sm->auto_add_sw_if_indices[i] == sw_if_index)
3061  {
3062  if (is_del)
3063  {
3064  /* if have address remove it */
3065  if (first_int_addr)
3066  (void) snat_del_address (sm, first_int_addr[0], 1);
3067  else
3068  {
3069  for (j = 0; j < vec_len (sm->to_resolve); j++)
3070  {
3071  rp = sm->to_resolve + j;
3072  if (rp->sw_if_index == sw_if_index)
3073  vec_add1 (indices_to_delete, j);
3074  }
3075  if (vec_len(indices_to_delete))
3076  {
3077  for (j = vec_len(indices_to_delete)-1; j >= 0; j--)
3078  vec_del1(sm->to_resolve, j);
3079  vec_free(indices_to_delete);
3080  }
3081  }
3082  vec_del1(sm->auto_add_sw_if_indices, i);
3083  }
3084  else
3085  return VNET_API_ERROR_VALUE_EXIST;
3086 
3087  return 0;
3088  }
3089  }
3090 
3091  if (is_del)
3092  return VNET_API_ERROR_NO_SUCH_ENTRY;
3093 
3094  /* add to the auto-address list */
3095  vec_add1(sm->auto_add_sw_if_indices, sw_if_index);
3096 
3097  /* If the address is already bound - or static - add it now */
3098  if (first_int_addr)
3099  snat_add_address (sm, first_int_addr, ~0);
3100 
3101  return 0;
3102 }
3103 
3104 static clib_error_t *
3106  unformat_input_t * input,
3107  vlib_cli_command_t * cmd)
3108 {
3109  snat_main_t *sm = &snat_main;
3110  unformat_input_t _line_input, *line_input = &_line_input;
3111  u32 sw_if_index;
3112  int rv;
3113  int is_del = 0;
3114  clib_error_t *error = 0;
3115 
3116  /* Get a line of input. */
3117  if (!unformat_user (input, unformat_line_input, line_input))
3118  return 0;
3119 
3120  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
3121  {
3122  if (unformat (line_input, "%U", unformat_vnet_sw_interface,
3123  sm->vnet_main, &sw_if_index))
3124  ;
3125  else if (unformat (line_input, "del"))
3126  is_del = 1;
3127  else
3128  {
3129  error = clib_error_return (0, "unknown input '%U'",
3130  format_unformat_error, line_input);
3131  goto done;
3132  }
3133  }
3134 
3135  rv = snat_add_interface_address (sm, sw_if_index, is_del);
3136 
3137  switch (rv)
3138  {
3139  case 0:
3140  break;
3141 
3142  default:
3143  error = clib_error_return (0, "snat_add_interface_address returned %d",
3144  rv);
3145  goto done;
3146  }
3147 
3148 done:
3149  unformat_free (line_input);
3150 
3151  return error;
3152 }
3153 
3155  .path = "snat add interface address",
3156  .short_help = "snat add interface address <interface> [del]",
3158 };
3159 
3160 static clib_error_t *
3162  unformat_input_t * input,
3163  vlib_cli_command_t * cmd)
3164 {
3165  snat_main_t *sm = &snat_main;
3166  unformat_input_t _line_input, *line_input = &_line_input;
3167  ip4_address_t in_addr, out_addr;
3168  u32 in_plen, out_plen;
3169  int is_add = 1, rv;
3170  clib_error_t *error = 0;
3171 
3172  /* Get a line of input. */
3173  if (!unformat_user (input, unformat_line_input, line_input))
3174  return 0;
3175 
3176  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
3177  {
3178  if (unformat (line_input, "in %U/%u", unformat_ip4_address, &in_addr, &in_plen))
3179  ;
3180  else if (unformat (line_input, "out %U/%u", unformat_ip4_address, &out_addr, &out_plen))
3181  ;
3182  else if (unformat (line_input, "del"))
3183  is_add = 0;
3184  else
3185  {
3186  error = clib_error_return (0, "unknown input '%U'",
3187  format_unformat_error, line_input);
3188  goto done;
3189  }
3190  }
3191 
3192  unformat_free (line_input);
3193 
3194  rv = snat_det_add_map(sm, &in_addr, (u8) in_plen, &out_addr, (u8)out_plen,
3195  is_add);
3196 
3197  if (rv)
3198  {
3199  error = clib_error_return (0, "snat_det_add_map return %d", rv);
3200  goto done;
3201  }
3202 
3203 done:
3204  unformat_free (line_input);
3205 
3206  return error;
3207 }
3208 
3209 /*?
3210  * @cliexpar
3211  * @cliexstart{snat deterministic add}
3212  * Create bijective mapping of inside address to outside address and port range
3213  * pairs, with the purpose of enabling deterministic NAT to reduce logging in
3214  * CGN deployments.
3215  * To create deterministic mapping between inside network 10.0.0.0/18 and
3216  * outside network 1.1.1.0/30 use:
3217  * # vpp# snat deterministic add in 10.0.0.0/18 out 1.1.1.0/30
3218  * @cliexend
3219 ?*/
3221  .path = "snat deterministic add",
3222  .short_help = "snat deterministic add in <addr>/<plen> out <addr>/<plen> [del]",
3223  .function = snat_det_map_command_fn,
3224 };
3225 
3226 static clib_error_t *
3228  unformat_input_t * input,
3229  vlib_cli_command_t * cmd)
3230 {
3231  snat_main_t *sm = &snat_main;
3232  unformat_input_t _line_input, *line_input = &_line_input;
3233  ip4_address_t in_addr, out_addr;
3234  u16 lo_port;
3235  snat_det_map_t * dm;
3236  clib_error_t *error = 0;
3237 
3238  /* Get a line of input. */
3239  if (!unformat_user (input, unformat_line_input, line_input))
3240  return 0;
3241 
3242  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
3243  {
3244  if (unformat (line_input, "%U", unformat_ip4_address, &in_addr))
3245  ;
3246  else
3247  {
3248  error = clib_error_return (0, "unknown input '%U'",
3249  format_unformat_error, line_input);
3250  goto done;
3251  }
3252  }
3253 
3254  unformat_free (line_input);
3255 
3256  dm = snat_det_map_by_user(sm, &in_addr);
3257  if (!dm)
3258  vlib_cli_output (vm, "no match");
3259  else
3260  {
3261  snat_det_forward (dm, &in_addr, &out_addr, &lo_port);
3262  vlib_cli_output (vm, "%U:<%d-%d>", format_ip4_address, &out_addr,
3263  lo_port, lo_port + dm->ports_per_host - 1);
3264  }
3265 
3266 done:
3267  unformat_free (line_input);
3268 
3269  return error;
3270 }
3271 
3272 /*?
3273  * @cliexpar
3274  * @cliexstart{snat deterministic forward}
3275  * Return outside address and port range from inside address for deterministic
3276  * NAT.
3277  * To obtain outside address and port of inside host use:
3278  * vpp# snat deterministic forward 10.0.0.2
3279  * 1.1.1.0:<1054-1068>
3280  * @cliexend
3281 ?*/
3283  .path = "snat deterministic forward",
3284  .short_help = "snat deterministic forward <addr>",
3285  .function = snat_det_forward_command_fn,
3286 };
3287 
3288 static clib_error_t *
3290  unformat_input_t * input,
3291  vlib_cli_command_t * cmd)
3292 {
3293  snat_main_t *sm = &snat_main;
3294  unformat_input_t _line_input, *line_input = &_line_input;
3295  ip4_address_t in_addr, out_addr;
3296  u32 out_port;
3297  snat_det_map_t * dm;
3298  clib_error_t *error = 0;
3299 
3300  /* Get a line of input. */
3301  if (!unformat_user (input, unformat_line_input, line_input))
3302  return 0;
3303 
3304  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
3305  {
3306  if (unformat (line_input, "%U:%d", unformat_ip4_address, &out_addr, &out_port))
3307  ;
3308  else
3309  {
3310  error = clib_error_return (0, "unknown input '%U'",
3311  format_unformat_error, line_input);
3312  }
3313  }
3314 
3315  unformat_free (line_input);
3316 
3317  if (out_port < 1024 || out_port > 65535)
3318  {
3319  error = clib_error_return (0, "wrong port, must be <1024-65535>");
3320  goto done;
3321  }
3322 
3323  dm = snat_det_map_by_out(sm, &out_addr);
3324  if (!dm)
3325  vlib_cli_output (vm, "no match");
3326  else
3327  {
3328  snat_det_reverse (dm, &out_addr, (u16) out_port, &in_addr);
3329  vlib_cli_output (vm, "%U", format_ip4_address, &in_addr);
3330  }
3331 
3332 done:
3333  unformat_free (line_input);
3334 
3335  return error;
3336 }
3337 
3338 /*?
3339  * @cliexpar
3340  * @cliexstart{snat deterministic reverse}
3341  * Return inside address from outside address and port for deterministic NAT.
3342  * To obtain inside host address from outside address and port use:
3343  * #vpp snat deterministic reverse 1.1.1.1:1276
3344  * 10.0.16.16
3345  * @cliexend
3346 ?*/
3348  .path = "snat deterministic reverse",
3349  .short_help = "snat deterministic reverse <addr>:<port>",
3350  .function = snat_det_reverse_command_fn,
3351 };
ip4_address_t external_addr
Definition: snat.h:184
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:436
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, fib_protocol_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:716
static void vl_api_snat_add_det_map_t_handler(vl_api_snat_add_det_map_t *mp)
Definition: snat.c:1492
u32 next
Definition: dlist.h:30
static void vl_api_snat_add_del_interface_addr_t_handler(vl_api_snat_add_del_interface_addr_t *mp)
Definition: snat.c:1247
static void send_snat_user_session_details(snat_session_t *s, unix_shared_memory_queue_t *q, u32 context)
Definition: snat.c:1404
static void * vl_api_snat_worker_dump_t_print(vl_api_snat_worker_dump_t *mp, void *handle)
Definition: snat.c:1232
Add/del S-NAT address range.
Definition: snat.api:32
static vlib_cli_command_t set_interface_snat_command
(constructor) VLIB_CLI_COMMAND (set_interface_snat_command)
Definition: snat.c:2115
#define vec_foreach_index(var, v)
Iterate over vector indices.
u32 sessions_per_user_list_head_index
Definition: snat.h:148
static void vl_api_snat_interface_add_del_feature_t_handler(vl_api_snat_interface_add_del_feature_t *mp)
Definition: snat.c:868
void snat_add_address(snat_main_t *sm, ip4_address_t *addr, u32 vrf_id)
Definition: snat.c:159
static void * vl_api_snat_add_det_map_t_print(vl_api_snat_add_det_map_t *mp, void *handle)
Definition: snat.c:1508
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
static void * vl_api_snat_add_static_mapping_t_print(vl_api_snat_add_static_mapping_t *mp, void *handle)
Definition: snat.c:981
static void sent_snat_det_map_details(snat_det_map_t *m, unix_shared_memory_queue_t *q, u32 context)
Definition: snat.c:1610
u16 ext_host_port
Definition: snat.h:57
Add/delete S-NAT pool address from specific interfce.
Definition: snat.api:302
ip4_add_del_interface_address_callback_t * add_del_interface_address_callbacks
Functions to call when interface address changes.
Definition: ip4.h:138
Set S-NAT workers reply.
Definition: snat.api:269
u8 * format_snat_session_state(u8 *s, va_list *args)
Definition: snat.c:2606
a
Definition: bitmap.h:516
static void * vl_api_snat_interface_add_del_feature_t_print(vl_api_snat_interface_add_del_feature_t *mp, void *handle)
Definition: snat.c:886
static void vl_api_snat_user_dump_t_handler(vl_api_snat_user_dump_t *mp)
Definition: snat.c:1376
void vl_msg_api_send_shmem(unix_shared_memory_queue_t *q, u8 *elem)
ip4_address_t src_address
Definition: ip4_packet.h:163
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
u16 fib_index
Definition: snat.h:83
u32 table_id
Definition: ip4.h:57
u32 nsessions
Definition: snat.h:149
int snat_alloc_outside_address_and_port(snat_main_t *sm, u32 fib_index, snat_session_key_t *k, u32 *address_indexp)
Definition: snat.c:1901
static void vl_api_snat_add_address_range_t_handler(vl_api_snat_add_address_range_t *mp)
Definition: snat.c:748
#define REPLY_MACRO2(t, body)
#define NULL
Definition: clib.h:55
snat_protocol_t proto
Definition: snat.h:190
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:710
static void snat_det_reverse(snat_det_map_t *dm, ip4_address_t *out_addr, u16 out_port, ip4_address_t *in_addr)
Definition: snat_det.h:89
Add/delete S-NAT deterministic mapping.
Definition: snat.api:439
u32 vlib_frame_queue_main_init(u32 node_index, u32 frame_queue_nelts)
Definition: threads.c:1423
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
Dump S-NAT deterministic mappings.
Definition: snat.api:522
static snat_det_map_t * snat_det_map_by_out(snat_main_t *sm, ip4_address_t *out_addr)
Definition: snat_det.h:59
u32 nstaticsessions
Definition: snat.h:150
unix_shared_memory_queue_t * vl_api_client_index_to_input_queue(u32 index)
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:561
static void send_snat_worker_details(u32 worker_index, unix_shared_memory_queue_t *q, u32 context)
Definition: snat.c:1195
static void send_snat_user_details(snat_user_t *u, unix_shared_memory_queue_t *q, u32 context)
Definition: snat.c:1352
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap. ...
Definition: bitmap.h:167
u8 * format_snat_static_map_to_resolve(u8 *s, va_list *args)
Definition: snat.c:2719
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:982
Enable/disable S-NAT IPFIX logging.
Definition: snat.api:344
ip_lookup_main_t lookup_main
Definition: ip4.h:109
static void snat_det_forward(snat_det_map_t *dm, ip4_address_t *in_addr, ip4_address_t *out_addr, u16 *lo_port)
Definition: snat_det.h:74
void snat_ipfix_logging_init(vlib_main_t *vm)
Initialize SNAT IPFIX logging.
static vlib_cli_command_t snat_add_interface_address_command
(constructor) VLIB_CLI_COMMAND (snat_add_interface_address_command)
Definition: snat.c:3154
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
int snat_ipfix_logging_enable_disable(int enable, u32 domain_id, u16 src_port)
Enable/disable SNAT IPFIX logging.
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
static void vl_api_snat_det_forward_t_handler(vl_api_snat_det_forward_t *mp)
Definition: snat.c:1522
unformat_function_t unformat_vnet_sw_interface
u32 fib_index
Definition: snat.h:147
static u32 snat_get_worker_in2out_cb(ip4_header_t *ip0, u32 rx_fib_index0)
Definition: snat.c:2397
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.
snat_main_t snat_main
Definition: snat.c:33
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
u8 in_plen
Definition: snat.h:172
dlist_elt_t * list_pool
Definition: snat.h:217
static clib_error_t * snat_init(vlib_main_t *vm)
Definition: snat.c:1730
static clib_error_t * add_address_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: snat.c:1953
static void vl_api_snat_add_static_mapping_t_handler(vl_api_snat_add_static_mapping_t *mp)
Definition: snat.c:945
static void * vl_api_snat_det_reverse_t_print(vl_api_snat_det_reverse_t *mp, void *handle)
Definition: snat.c:1597
static void vl_api_snat_control_ping_t_handler(vl_api_snat_control_ping_t *mp)
Definition: snat.c:1090
api_main_t api_main
Definition: api_shared.c:35
static int snat_interface_add_del(u32 sw_if_index, u8 is_inside, int is_del)
Definition: snat.c:652
S-NAT user&#39;s sessions response.
Definition: snat.api:415
u8 * format_snat_key(u8 *s, va_list *args)
Definition: snat.c:2623
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
Definition: ip4_fib.c:211
format_function_t format_ip4_address
Definition: format.h:79
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: snat.c:215
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:376
unformat_function_t unformat_ip4_address
Definition: format.h:76
vlib_node_registration_t snat_det_out2in_node
(constructor) VLIB_REGISTER_NODE (snat_det_out2in_node)
Definition: out2in.c:84
static void * vl_api_snat_control_ping_t_print(vl_api_snat_control_ping_t *mp, void *handle)
Definition: snat.c:1103
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
ip4_address_t ext_host_addr
Definition: snat.h:56
Get outside address and port range from inside address.
Definition: snat.api:481
ip4_address_t dst_address
Definition: ip4_packet.h:163
u8 * format_snat_user(u8 *s, va_list *args)
Definition: snat.c:2660
ip4_address_t addr
Definition: snat.h:146
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: snat.c:2976
A high priority source a plugin can use.
Definition: fib_entry.h:54
#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 foreach_snat_plugin_api_msg
Definition: snat.c:1658
#define clib_error_return(e, args...)
Definition: error.h:111
unsigned long u64
Definition: types.h:89
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:232
static clib_error_t * snat_det_forward_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: snat.c:3227
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: snat.c:2336
static clib_error_t * snat_plugin_api_hookup(vlib_main_t *vm)
Definition: snat.c:1681
S-NAT user&#39;s sessions.
Definition: snat.api:394
static void * vl_api_snat_ipfix_enable_disable_t_print(vl_api_snat_ipfix_enable_disable_t *mp, void *handle)
Definition: snat.c:1335
u16 fp_len
The mask length.
Definition: fib_types.h:164
ip4_address_t local_addr
Definition: snat.h:183
Control ping from the client to the server response.
Definition: snat.api:206
Add/delete S-NAT deterministic mapping reply.
Definition: snat.api:455
static void * vl_api_snat_user_session_dump_t_print(vl_api_snat_user_session_dump_t *mp, void *handle)
Definition: snat.c:1478
uword unformat_snat_protocol(unformat_input_t *input, va_list *args)
Definition: snat.c:2122
static void vl_api_snat_interface_addr_dump_t_handler(vl_api_snat_interface_addr_dump_t *mp)
Definition: snat.c:1295
snat_protocol_t proto
Definition: snat.h:204
unformat_function_t unformat_line_input
Definition: format.h:281
u32 icmp_match_out2in_fast(snat_main_t *sm, vlib_node_runtime_t *node, u32 cpu_index, vlib_buffer_t *b0, snat_session_key_t *p_key, snat_session_key_t *p_value, u8 *p_dont_translate, void *d)
Get address and port values to be used for packet SNAT translation.
Definition: out2in.c:420
static heap_elt_t * first(heap_header_t *h)
Definition: heap.c:59
static vlib_cli_command_t snat_ipfix_logging_enable_disable_command
(constructor) VLIB_CLI_COMMAND (snat_ipfix_logging_enable_disable_command)
Definition: snat.c:2390
Definition: fib_entry.h:232
S-NAT static mapping details response.
Definition: snat.api:177
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:231
#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:397
Dump S-NAT workers.
Definition: snat.api:278
deterministic NAT definitions
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 u32 snat_get_worker_out2in_cb(ip4_header_t *ip0, u32 rx_fib_index0)
Definition: snat.c:2431
u32 icmp_match_in2out_slow(snat_main_t *sm, vlib_node_runtime_t *node, u32 cpu_index, vlib_buffer_t *b0, snat_session_key_t *p_key, snat_session_key_t *p_value, u8 *p_dont_translate, void *d)
Get address and port values to be used for packet SNAT translation and create session if needed...
Definition: in2out.c:477
#define v
Definition: acl.c:246
struct _unformat_input_t unformat_input_t
static void send_snat_static_mapping_details(snat_static_mapping_t *m, unix_shared_memory_queue_t *q, u32 context)
Definition: snat.c:1007
static int is_snat_address_used_in_static_mapping(snat_main_t *sm, ip4_address_t addr)
Definition: snat.c:193
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:241
S-NAT pool addresses interfaces details response.
Definition: snat.api:332
Set S-NAT workers.
Definition: snat.api:259
u32 icmp_match_out2in_slow(snat_main_t *sm, vlib_node_runtime_t *node, u32 cpu_index, vlib_buffer_t *b0, snat_session_key_t *p_key, snat_session_key_t *p_value, u8 *p_dont_translate, void *d)
Get address and port values to be used for packet SNAT translation and create session if needed...
Definition: out2in.c:312
#define PREDICT_FALSE(x)
Definition: clib.h:97
Enable/disable S-NAT feature on the interface reply.
Definition: snat.api:92
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:119
#define REPLY_MACRO(t)
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:805
S-NAT users response.
Definition: snat.api:538
int snat_del_address(snat_main_t *sm, ip4_address_t addr, u8 delete_sm)
Definition: snat.c:552
vlib_node_registration_t snat_out2in_node
(constructor) VLIB_REGISTER_NODE (snat_out2in_node)
Definition: out2in.c:81
static void * vl_api_snat_address_dump_t_print(vl_api_snat_address_dump_t *mp, void *handle)
Definition: snat.c:857
static void vl_api_snat_det_map_dump_t_handler(vl_api_snat_det_map_dump_t *mp)
Definition: snat.c:1633
u8 out_plen
Definition: snat.h:174
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 SNAT static mapping.
Definition: snat.c:1845
static void increment_v4_address(ip4_address_t *a)
Definition: snat.c:206
ip4_address_t addr
Definition: snat.h:81
static void * vl_api_snat_det_map_dump_t_print(vl_api_snat_det_map_dump_t *mp, void *handle)
Definition: snat.c:1648
static clib_error_t * snat_add_interface_address_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: snat.c:3105
u8 * format_snat_session(u8 *s, va_list *args)
Definition: snat.c:2642
#define SNAT_DET_SES_PER_USER
Definition: snat_det.h:29
Dump S-NAT static mappings.
Definition: snat.api:160
VNET_FEATURE_INIT(ip4_snat_in2out, static)
static void * vl_api_snat_set_workers_t_print(vl_api_snat_set_workers_t *mp, void *handle)
Definition: snat.c:1171
u64 value
the value
Definition: bihash_8_8.h:36
#define BAD_SW_IF_INDEX_LABEL
snat_user_t * users
Definition: snat.h:211
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
void * vl_msg_api_alloc(int nbytes)
static void send_snat_static_map_resolve_details(snat_static_map_resolve_t *m, unix_shared_memory_queue_t *q, u32 context)
Definition: snat.c:1031
static void send_snat_interface_addr_details(u32 sw_if_index, unix_shared_memory_queue_t *q, u32 context)
Definition: snat.c:1279
static clib_error_t * show_snat_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: snat.c:2771
vlib_main_t * vm
Definition: buffer.c:276
static void * vl_api_snat_static_mapping_dump_t_print(vl_api_snat_static_mapping_dump_t *mp, void *handle)
Definition: snat.c:1079
vlib_node_registration_t snat_in2out_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_node)
Definition: in2out.c:86
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:340
static clib_error_t * add_static_mapping_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: snat.c:2154
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:798
ip4_add_del_interface_address_function_t * function
Definition: ip4.h:94
static ip4_fib_t * ip4_fib_get(u32 index)
Get the FIB at the given index.
Definition: ip4_fib.h:80
Get outside address and port range from inside address.
Definition: snat.api:466
Definition: ip4.h:48
Dump interfaces with S-NAT feature.
Definition: snat.api:101
u8 * format_snat_protocol(u8 *s, va_list *args)
Definition: snat.c:2136
#define clib_warning(format, args...)
Definition: error.h:59
#define FINISH
Definition: snat.c:59
#define clib_memcpy(a, b, c)
Definition: string.h:69
u32 sharing_ratio
Definition: snat.h:175
ip4_address_t out_addr
Definition: snat.h:173
static void send_snat_interface_details(snat_interface_t *i, unix_shared_memory_queue_t *q, u32 context)
Definition: snat.c:901
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: snat.c:254
static uword * clib_bitmap_set_multiple(uword *bitmap, uword i, uword value, uword n_bits)
sets the ith through ith + n_bits bits in a bitmap
Definition: bitmap.h:275
static clib_error_t * snat_config(vlib_main_t *vm, unformat_input_t *input)
Definition: snat.c:2487
static u32 ip4_fib_index_from_table_id(u32 table_id)
Definition: ip4_fib.h:110
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:33
#define ARRAY_LEN(x)
Definition: clib.h:59
Enable/disable S-NAT IPFIX logging reply.
Definition: snat.api:356
ip4_address_t addr
Definition: snat.h:42
u32 sw_if_index
Definition: snat.h:194
static void vl_api_snat_user_session_dump_t_handler(vl_api_snat_user_session_dump_t *mp)
Definition: snat.c:1429
static u8 snat_proto_to_ip_proto(snat_protocol_t snat_proto)
Definition: snat.h:390
S-NAT address details response.
Definition: snat.api:66
Add S-NAT address range reply.
Definition: snat.api:46
Add/delete S-NAT static mapping.
Definition: snat.api:132
Enable/disable S-NAT feature on the interface.
Definition: snat.api:80
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
snat_protocol_t
Definition: snat.h:95
void snat_ipfix_logging_addresses_exhausted(u32 pool_id)
Generate NAT addresses exhausted event.
static void vl_api_snat_ipfix_enable_disable_t_handler(vl_api_snat_ipfix_enable_disable_t *mp)
Definition: snat.c:1321
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:255
#define ASSERT(truth)
Dump S-NAT addresses.
Definition: snat.api:55
unsigned int u32
Definition: types.h:88
static clib_error_t * snat_det_map_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: snat.c:3161
#define vec_delete(V, N, M)
Delete N elements starting at element M.
Definition: vec.h:785
ip4_address_t l_addr
Definition: snat.h:199
static void vl_api_snat_set_workers_t_handler(vl_api_snat_set_workers_t *mp)
Definition: snat.c:1148
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: snat.c:127
static snat_protocol_t ip_proto_to_snat_proto(u8 ip_proto)
Definition: snat.h:378
IPv4 main type.
Definition: ip4.h:107
u8 * format_snat_static_mapping(u8 *s, va_list *args)
Definition: snat.c:2700
u64 as_u64
Definition: snat.h:72
static vlib_cli_command_t snat_det_map_command
(constructor) VLIB_CLI_COMMAND (snat_det_map_command)
Definition: snat.c:3220
static void vl_api_snat_show_config_t_handler(vl_api_snat_show_config_t *mp)
Definition: snat.c:1114
ip4_address_t addr
Definition: snat.h:69
u32 fib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:954
ip4_address_t in_addr
Definition: snat.h:171
#define clib_bitmap_free(v)
Free a bitmap.
Definition: bitmap.h:92
static void vl_api_snat_det_reverse_t_handler(vl_api_snat_det_reverse_t *mp)
Definition: snat.c:1568
static void * vl_api_snat_user_dump_t_print(vl_api_snat_user_dump_t *mp, void *handle)
Definition: snat.c:1393
uword * thread_registrations_by_name
Definition: threads.h:276
static void clib_dlist_remove(dlist_elt_t *pool, u32 index)
Definition: dlist.h:99
u8 * format_det_map_ses(u8 *s, va_list *args)
Definition: snat.c:2741
ip4_address_t addr
Definition: snat.h:154
#define VNET_FEATURES(...)
Definition: feature.h:368
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: snat_det.c:40
static vlib_cli_command_t show_snat_command
(constructor) VLIB_CLI_COMMAND (show_snat_command)
Definition: snat.c:2968
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
static void vl_api_snat_static_mapping_dump_t_handler(vl_api_snat_static_mapping_dump_t *mp)
Definition: snat.c:1054
static void * vl_api_snat_add_del_interface_addr_t_print(vl_api_snat_add_del_interface_addr_t *mp, void *handle)
Definition: snat.c:1265
S-NAT workers details response.
Definition: snat.api:289
unsigned short u16
Definition: types.h:57
S-NAT users response.
Definition: snat.api:378
static void vl_api_snat_interface_dump_t_handler(vl_api_snat_interface_dump_t *mp)
Definition: snat.c:918
static vlib_cli_command_t snat_det_reverse_command
(constructor) VLIB_CLI_COMMAND (snat_det_reverse_command)
Definition: snat.c:3347
static void * vl_api_snat_det_forward_t_print(vl_api_snat_det_forward_t *mp, void *handle)
Definition: snat.c:1555
static void * vl_api_snat_add_address_range_t_print(vl_api_snat_add_address_range_t *mp, void *handle)
Definition: snat.c:806
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
static snat_det_map_t * snat_det_map_by_user(snat_main_t *sm, ip4_address_t *user_addr)
Definition: snat_det.h:44
static int snat_add_interface_address(snat_main_t *sm, u32 sw_if_index, int is_del)
Definition: snat.c:3045
u16 ports_per_host
Definition: snat.h:176
Definition: fib_entry.h:228
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
static vlib_cli_command_t add_address_command
(constructor) VLIB_CLI_COMMAND (add_address_command)
Definition: snat.c:2044
static void unformat_free(unformat_input_t *i)
Definition: format.h:161
static void * vl_api_snat_show_config_t_print(vl_api_snat_show_config_t *mp, void *handle)
Definition: snat.c:1137
snat_det_out_key_t out
Definition: snat.h:165
u32 fib_index
Definition: snat.h:70
void snat_free_outside_address_and_port(snat_main_t *sm, snat_session_key_t *k, u32 address_index)
Definition: snat.c:1804
static vlib_cli_command_t add_static_mapping_command
(constructor) VLIB_CLI_COMMAND (add_static_mapping_command)
Definition: snat.c:2259
S-NAT interface details response.
Definition: snat.api:111
#define hash_get_mem(h, key)
Definition: hash.h:268
Dump S-NAT pool addresses interfaces.
Definition: snat.api:323
static void send_snat_address_details(snat_address_t *a, unix_shared_memory_queue_t *q, u32 context)
Definition: snat.c:821
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
Show S-NAT plugin startup config reply.
Definition: snat.api:238
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1117
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
Control ping from client to api server request.
Definition: snat.api:194
static void vl_api_snat_worker_dump_t_handler(vl_api_snat_worker_dump_t *mp)
Definition: snat.c:1215
Get inside address from outside address and port reply.
Definition: snat.api:511
#define vec_foreach(var, vec)
Vector iterator.
VLIB_PLUGIN_REGISTER()
u32 ses_num
Definition: snat.h:177
static void vl_api_snat_address_dump_t_handler(vl_api_snat_address_dump_t *mp)
Definition: snat.c:842
static vlib_cli_command_t snat_det_forward_command
(constructor) VLIB_CLI_COMMAND (snat_det_forward_command)
Definition: snat.c:3282
static void plugin_custom_dump_configure(snat_main_t *sm)
Definition: snat.c:1711
u16 vl_msg_api_get_msg_ids(char *name, int n)
Definition: api_shared.c:831
u32 icmp_match_in2out_fast(snat_main_t *sm, vlib_node_runtime_t *node, u32 cpu_index, vlib_buffer_t *b0, snat_session_key_t *p_key, snat_session_key_t *p_value, u8 *p_dont_translate, void *d)
Get address and port values to be used for packet SNAT translation.
Definition: in2out.c:571
#define SNAT_SESSION_FLAG_STATIC_MAPPING
Definition: snat.h:118
vhost_vring_addr_t addr
Definition: vhost-user.h:84
Add/delete S-NAT static mapping reply.
Definition: snat.api:151
static vlib_cli_command_t set_workers_command
(constructor) VLIB_CLI_COMMAND (set_workers_command)
Definition: snat.c:2328
static void * vl_api_snat_interface_dump_t_print(vl_api_snat_interface_dump_t *mp, void *handle)
Definition: snat.c:935
#define BITS(x)
Definition: clib.h:58
Show S-NAT plugin startup config.
Definition: snat.api:218
static clib_error_t * snat_det_reverse_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: snat.c:3289
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:577
snat_session_t * sessions
Definition: snat.h:214
static clib_error_t * snat_feature_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: snat.c:2052
#define snat_is_session_static(s)
Check if SNAT session is created from static mapping.
Definition: snat.h:364
static void setup_message_id_table(snat_main_t *sm, api_main_t *am)
Definition: snat.c:1703
static clib_error_t * set_workers_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: snat.c:2267
u32 fib_index
Definition: snat.h:155
Get inside address from outside address and port.
Definition: snat.api:497
Add/delete S-NAT pool address from specific interfce reply.
Definition: snat.api:314
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:971
Dump S-NAT users.
Definition: snat.api:365
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:225
static void * vl_api_snat_interface_addr_dump_t_print(vl_api_snat_interface_addr_dump_t *mp, void *handle)
Definition: snat.c:1310
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
#define VALIDATE_SW_IF_INDEX(mp)
static int snat_set_workers(uword *bitmap)
Definition: snat.c:726
struct _unix_shared_memory_queue unix_shared_memory_queue_t
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109