FD.io VPP  v16.09
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/plugin/plugin.h>
20 #include <vlibapi/api.h>
21 #include <snat/snat.h>
22 
23 #include <vlibapi/api.h>
24 #include <vlibmemory/api.h>
25 #include <vlibsocket/api.h>
26 
28 
29 /* define message IDs */
30 #include <snat/snat_msg_enum.h>
31 
32 /* define message structures */
33 #define vl_typedefs
34 #include <snat/snat_all_api_h.h>
35 #undef vl_typedefs
36 
37 /* define generated endian-swappers */
38 #define vl_endianfun
39 #include <snat/snat_all_api_h.h>
40 #undef vl_endianfun
41 
42 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
43 
44 /* Get the API version number */
45 #define vl_api_version(n,v) static u32 api_version=(v);
46 #include <snat/snat_all_api_h.h>
47 #undef vl_api_version
48 
49 /* Macro to finish up custom dump fns */
50 #define FINISH \
51  vec_add1 (s, 0); \
52  vl_print (handle, (char *)s); \
53  vec_free (s); \
54  return handle;
55 
56 /*
57  * A handy macro to set up a message reply.
58  * Assumes that the following variables are available:
59  * mp - pointer to request message
60  * rmp - pointer to reply message type
61  * rv - return value
62  */
63 
64 #define REPLY_MACRO(t) \
65 do { \
66  unix_shared_memory_queue_t * q = \
67  vl_api_client_index_to_input_queue (mp->client_index); \
68  if (!q) \
69  return; \
70  \
71  rmp = vl_msg_api_alloc (sizeof (*rmp)); \
72  rmp->_vl_msg_id = ntohs((t)+sm->msg_id_base); \
73  rmp->context = mp->context; \
74  rmp->retval = ntohl(rv); \
75  \
76  vl_msg_api_send_shmem (q, (u8 *)&rmp); \
77 } while(0);
78 
79 
80 /* Hook up input features */
81 VNET_IP4_UNICAST_FEATURE_INIT (ip4_snat_in2out, static) = {
82  .node_name = "snat-in2out",
83  .runs_before = {"snat-out2in", 0},
84  .feature_index = &snat_main.rx_feature_in2out,
85 };
86 VNET_IP4_UNICAST_FEATURE_INIT (ip4_snat_out2in, static) = {
87  .node_name = "snat-out2in",
88  .runs_before = {"ip4-lookup", 0},
89  .feature_index = &snat_main.rx_feature_out2in,
90 };
91 
92 /*
93  * This routine exists to convince the vlib plugin framework that
94  * we haven't accidentally copied a random .dll into the plugin directory.
95  *
96  * Also collects global variable pointers passed from the vpp engine
97  */
98 
99 clib_error_t *
101  int from_early_init)
102 {
103  snat_main_t * sm = &snat_main;
104  clib_error_t * error = 0;
105 
106  sm->vlib_main = vm;
107  sm->vnet_main = h->vnet_main;
108  sm->ethernet_main = h->ethernet_main;
109 
110  return error;
111 }
112 
113 /*$$$$$ move to an installed header file */
114 #if (1 || CLIB_DEBUG > 0) /* "trust, but verify" */
115 
116 #define VALIDATE_SW_IF_INDEX(mp) \
117  do { u32 __sw_if_index = ntohl(mp->sw_if_index); \
118  vnet_main_t *__vnm = vnet_get_main(); \
119  if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \
120  __sw_if_index)) { \
121  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; \
122  goto bad_sw_if_index; \
123  } \
124 } while(0);
125 
126 #define BAD_SW_IF_INDEX_LABEL \
127 do { \
128 bad_sw_if_index: \
129  ; \
130 } while (0);
131 
132 #define VALIDATE_RX_SW_IF_INDEX(mp) \
133  do { u32 __rx_sw_if_index = ntohl(mp->rx_sw_if_index); \
134  vnet_main_t *__vnm = vnet_get_main(); \
135  if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \
136  __rx_sw_if_index)) { \
137  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; \
138  goto bad_rx_sw_if_index; \
139  } \
140 } while(0);
141 
142 #define BAD_RX_SW_IF_INDEX_LABEL \
143 do { \
144 bad_rx_sw_if_index: \
145  ; \
146 } while (0);
147 
148 #define VALIDATE_TX_SW_IF_INDEX(mp) \
149  do { u32 __tx_sw_if_index = ntohl(mp->tx_sw_if_index); \
150  vnet_main_t *__vnm = vnet_get_main(); \
151  if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \
152  __tx_sw_if_index)) { \
153  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; \
154  goto bad_tx_sw_if_index; \
155  } \
156 } while(0);
157 
158 #define BAD_TX_SW_IF_INDEX_LABEL \
159 do { \
160 bad_tx_sw_if_index: \
161  ; \
162 } while (0);
163 
164 #else
165 
166 #define VALIDATE_SW_IF_INDEX(mp)
167 #define BAD_SW_IF_INDEX_LABEL
168 #define VALIDATE_RX_SW_IF_INDEX(mp)
169 #define BAD_RX_SW_IF_INDEX_LABEL
170 #define VALIDATE_TX_SW_IF_INDEX(mp)
171 #define BAD_TX_SW_IF_INDEX_LABEL
172 
173 #endif /* CLIB_DEBUG > 0 */
174 
176 {
177  snat_address_t * ap;
178 
179  vec_add2 (sm->addresses, ap, 1);
180  ap->addr = *addr;
181 
182 }
183 
185 {
186  u32 v;
187 
188  v = clib_net_to_host_u32(a->as_u32) + 1;
189  a->as_u32 = clib_host_to_net_u32(v);
190 }
191 
192 static void
195 {
196  snat_main_t * sm = &snat_main;
198  ip4_address_t this_addr;
199  u32 start_host_order, end_host_order;
200  int i, count;
201  int rv = 0;
202  u32 * tmp;
203 
204  if (mp->is_ip4 != 1)
205  {
206  rv = VNET_API_ERROR_UNIMPLEMENTED;
207  goto send_reply;
208  }
209 
210  tmp = (u32 *) mp->first_ip_address;
211  start_host_order = clib_host_to_net_u32 (tmp[0]);
212  tmp = (u32 *) mp->last_ip_address;
213  end_host_order = clib_host_to_net_u32 (tmp[0]);
214 
215  count = (end_host_order - start_host_order) + 1;
216 
217  if (count > 1024)
218  clib_warning ("%U - %U, %d addresses...",
221  count);
222 
223  memcpy (&this_addr.as_u8, mp->first_ip_address, 4);
224 
225  for (i = 0; i < count; i++)
226  {
227  snat_add_address (sm, &this_addr);
228  increment_v4_address (&this_addr);
229  }
230 
231  send_reply:
232  REPLY_MACRO (VL_API_SNAT_ADD_ADDRESS_RANGE_REPLY);
233 }
234 
237 {
238  u8 * s;
239 
240  s = format (0, "SCRIPT: snat_add_address_range ");
241  s = format (s, "%U ", format_ip4_address, mp->first_ip_address);
242  if (memcmp (mp->first_ip_address, mp->last_ip_address, 4))
243  {
244  s = format (s, " - %U ", format_ip4_address, mp->last_ip_address);
245  }
246  FINISH;
247 }
248 
249 static void
252 {
253  snat_main_t * sm = &snat_main;
255  u8 is_del = mp->is_add == 0;
256  u32 sw_if_index = ntohl(mp->sw_if_index);
257  u32 ci;
258  ip4_main_t * im = &ip4_main;
259  ip_lookup_main_t * lm = &im->lookup_main;
261  u32 feature_index;
262  int rv = 0;
263 
265 
266  feature_index = mp->is_inside ? sm->rx_feature_in2out
267  : sm->rx_feature_out2in;
268 
269  ci = rx_cm->config_index_by_sw_if_index[sw_if_index];
270  ci = (is_del
273  (sm->vlib_main, &rx_cm->config_main,
274  ci,
275  feature_index,
276  0 /* config struct */,
277  0 /* sizeof config struct*/);
278  rx_cm->config_index_by_sw_if_index[sw_if_index] = ci;
279 
281 
282  REPLY_MACRO(VL_API_SNAT_INTERFACE_ADD_DEL_FEATURE_REPLY);
283 }
284 
287 {
288  u8 * s;
289 
290  s = format (0, "SCRIPT: snat_interface_add_del_feature ");
291  s = format (s, "sw_if_index %d %s %s",
292  clib_host_to_net_u32(mp->sw_if_index),
293  mp->is_inside ? "in":"out",
294  mp->is_add ? "" : "del");
295 
296  FINISH;
297 }
298 
299 /* List of message types that this plugin understands */
300 #define foreach_snat_plugin_api_msg \
301 _(SNAT_ADD_ADDRESS_RANGE, snat_add_address_range) \
302 _(SNAT_INTERFACE_ADD_DEL_FEATURE, snat_interface_add_del_feature)
303 
304 /* Set up the API message handling tables */
305 static clib_error_t *
307 {
308  snat_main_t * sm __attribute__ ((unused)) = &snat_main;
309 #define _(N,n) \
310  vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base), \
311  #n, \
312  vl_api_##n##_t_handler, \
313  vl_noop_handler, \
314  vl_api_##n##_t_endian, \
315  vl_api_##n##_t_print, \
316  sizeof(vl_api_##n##_t), 1);
318 #undef _
319 
320  return 0;
321 }
322 
324 {
325 #define _(n,f) sm->api_main->msg_print_handlers \
326  [VL_API_##n + sm->msg_id_base] \
327  = (void *) vl_api_##f##_t_print;
329 #undef _
330 }
331 
333 {
334  snat_main_t * sm = &snat_main;
335  clib_error_t * error = 0;
336  ip4_main_t * im = &ip4_main;
337  ip_lookup_main_t * lm = &im->lookup_main;
338  u8 * name;
339 
340  name = format (0, "snat_%08x%c", api_version, 0);
341 
342  /* Ask for a correctly-sized block of API message decode slots */
344  ((char *) name, VL_MSG_FIRST_AVAILABLE);
345 
346  sm->vlib_main = vm;
347  sm->vnet_main = vnet_get_main();
348  sm->ip4_main = im;
349  sm->ip4_lookup_main = lm;
350  sm->api_main = &api_main;
351 
352  error = snat_plugin_api_hookup (vm);
354  vec_free(name);
355 
356  return error;
357 }
358 
360 
362  snat_session_key_t * k,
363  u32 address_index)
364 {
365  snat_address_t *a;
366  u16 port_host_byte_order = clib_net_to_host_u16 (k->port);
367 
368  ASSERT (address_index < vec_len (sm->addresses));
369 
370  a = sm->addresses + address_index;
371 
372  ASSERT (clib_bitmap_get (a->busy_port_bitmap, port_host_byte_order) == 1);
373 
375  port_host_byte_order, 0);
376  a->busy_ports--;
377 }
378 
380  snat_session_key_t * k,
381  u32 * address_indexp)
382 {
383  int i;
384  snat_address_t *a;
385  u32 portnum;
386 
387  for (i = 0; i < vec_len (sm->addresses); i++)
388  {
389  if (sm->addresses[i].busy_ports < (65535-1024))
390  {
391  a = sm->addresses + i;
392 
393  while (1)
394  {
395  portnum = random_u32 (&sm->random_seed);
396  portnum &= 0xFFFF;
397  if (portnum < 1024)
398  continue;
399  if (clib_bitmap_get (a->busy_port_bitmap, portnum))
400  continue;
402  portnum, 1);
403  a->busy_ports++;
404  /* Caller sets protocol and fib index */
405  k->addr = a->addr;
406  k->port = clib_host_to_net_u16(portnum);
407  *address_indexp = i;
408  return 0;
409  }
410  }
411  }
412  /* Totally out of translations to use... */
413  return 1;
414 }
415 
416 
417 static clib_error_t *
419  unformat_input_t * input,
420  vlib_cli_command_t * cmd)
421 {
422  snat_main_t * sm = &snat_main;
423  ip4_address_t start_addr, end_addr, this_addr;
424  u32 start_host_order, end_host_order;
425  int i, count;
426 
427  if (unformat (input, "%U - %U",
428  unformat_ip4_address, &start_addr,
429  unformat_ip4_address, &end_addr))
430  ;
431  else if (unformat (input, "%U", unformat_ip4_address, &start_addr))
432  end_addr = start_addr;
433 
434  start_host_order = clib_host_to_net_u32 (start_addr.as_u32);
435  end_host_order = clib_host_to_net_u32 (end_addr.as_u32);
436 
437  if (end_host_order < start_host_order)
438  return clib_error_return (0, "end address less than start address");
439 
440  count = (end_host_order - start_host_order) + 1;
441 
442  if (count > 1024)
443  clib_warning ("%U - %U, %d addresses...",
444  format_ip4_address, &start_addr,
445  format_ip4_address, &end_addr,
446  count);
447 
448  this_addr = start_addr;
449 
450  for (i = 0; i < count; i++)
451  {
452  snat_add_address (sm, &this_addr);
453  increment_v4_address (&this_addr);
454  }
455 
456  return 0;
457 }
458 
459 VLIB_CLI_COMMAND (add_address_command, static) = {
460  .path = "snat add address",
461  .short_help = "snat add addresses <ip4-range-start> [- <ip4-range-end>]",
462  .function = add_address_command_fn,
463 };
464 
465 static clib_error_t *
467  unformat_input_t * input,
468  vlib_cli_command_t * cmd)
469 {
470  vnet_main_t * vnm = vnet_get_main();
471  snat_main_t * sm = &snat_main;
472  ip4_main_t * im = &ip4_main;
473  ip_lookup_main_t * lm = &im->lookup_main;
475  clib_error_t * error = 0;
476  u32 sw_if_index, ci;
477  u32 feature_index;
478  u32 * inside_sw_if_indices = 0;
479  u32 * outside_sw_if_indices = 0;
480  int is_del = 0;
481  int i;
482 
483  sw_if_index = ~0;
484 
486  {
487  if (unformat (input, "in %U", unformat_vnet_sw_interface,
488  vnm, &sw_if_index))
489  vec_add1 (inside_sw_if_indices, sw_if_index);
490  else if (unformat (input, "out %U", unformat_vnet_sw_interface,
491  vnm, &sw_if_index))
492  vec_add1 (outside_sw_if_indices, sw_if_index);
493  else if (unformat (input, "del"))
494  is_del = 1;
495  else
496  break;
497  }
498 
499  if (vec_len (inside_sw_if_indices))
500  {
501  feature_index = sm->rx_feature_in2out;
502 
503  for (i = 0; i < vec_len(inside_sw_if_indices); i++)
504  {
505  sw_if_index = inside_sw_if_indices[i];
506  ci = rx_cm->config_index_by_sw_if_index[sw_if_index];
507  ci = (is_del
510  (vm, &rx_cm->config_main,
511  ci,
512  feature_index,
513  0 /* config struct */,
514  0 /* sizeof config struct*/);
515  rx_cm->config_index_by_sw_if_index[sw_if_index] = ci;
516  }
517  }
518 
519  if (vec_len (outside_sw_if_indices))
520  {
521  feature_index = sm->rx_feature_out2in;
522 
523  for (i = 0; i < vec_len(outside_sw_if_indices); i++)
524  {
525  sw_if_index = outside_sw_if_indices[i];
526  ci = rx_cm->config_index_by_sw_if_index[sw_if_index];
527  ci = (is_del
530  (vm, &rx_cm->config_main,
531  ci,
532  feature_index,
533  0 /* config struct */,
534  0 /* sizeof config struct*/);
535  rx_cm->config_index_by_sw_if_index[sw_if_index] = ci;
536  }
537  }
538 
539  vec_free (inside_sw_if_indices);
540  vec_free (outside_sw_if_indices);
541 
542  return error;
543 }
544 
545 VLIB_CLI_COMMAND (set_interface_snat_command, static) = {
546  .path = "set interface snat",
547  .function = snat_feature_command_fn,
548  .short_help = "set interface snat in <intfc> out <intfc> [del]",
549 };
550 
551 static clib_error_t *
553 {
554  snat_main_t * sm = &snat_main;
555  u32 translation_buckets = 1024;
556  u32 translation_memory_size = 128<<20;
557  u32 user_buckets = 128;
558  u32 user_memory_size = 64<<20;
559  u32 max_translations_per_user = 100;
560  u32 outside_vrf_id = 0;
561 
563  {
564  if (unformat (input, "translation hash buckets %d", &translation_buckets))
565  ;
566  else if (unformat (input, "translation hash memory %d",
567  &translation_memory_size));
568  else if (unformat (input, "user hash buckets %d", &user_buckets))
569  ;
570  else if (unformat (input, "user hash memory %d",
571  &user_memory_size))
572  ;
573  else if (unformat (input, "max translations per user %d",
574  &max_translations_per_user))
575  ;
576  else if (unformat (input, "outside VRF id %d",
577  &outside_vrf_id))
578  ;
579  else
580  return clib_error_return (0, "unknown input `%U'",
581  format_unformat_error, input);
582  }
583 
584  /* for show commands, etc. */
585  sm->translation_buckets = translation_buckets;
586  sm->translation_memory_size = translation_memory_size;
587  sm->user_buckets = user_buckets;
588  sm->user_memory_size = user_memory_size;
589  sm->max_translations_per_user = max_translations_per_user;
590  sm->outside_vrf_id = outside_vrf_id;
591 
592  clib_bihash_init_8_8 (&sm->in2out, "in2out", translation_buckets,
593  translation_memory_size);
594 
595  clib_bihash_init_8_8 (&sm->out2in, "out2in", translation_buckets,
596  translation_memory_size);
597 
598  clib_bihash_init_8_8 (&sm->user_hash, "users", user_buckets,
599  user_memory_size);
600  return 0;
601 }
602 
604 
605 u8 * format_snat_key (u8 * s, va_list * args)
606 {
607  snat_session_key_t * key = va_arg (*args, snat_session_key_t *);
608  char * protocol_string = "unknown";
609  static char *protocol_strings[] = {
610  "UDP",
611  "TCP",
612  "ICMP",
613  };
614 
615  if (key->protocol < ARRAY_LEN(protocol_strings))
616  protocol_string = protocol_strings[key->protocol];
617 
618  s = format (s, "%U proto %s port %d fib %d",
619  format_ip4_address, &key->addr, protocol_string,
620  key->port, key->fib_index);
621  return s;
622 }
623 
624 u8 * format_snat_session (u8 * s, va_list * args)
625 {
626  snat_main_t * sm __attribute__((unused)) = va_arg (*args, snat_main_t *);
627  snat_session_t * sess = va_arg (*args, snat_session_t *);
628 
629  s = format (s, " i2o %U\n", format_snat_key, &sess->in2out);
630  s = format (s, " o2i %U\n", format_snat_key, &sess->out2in);
631  s = format (s, " last heard %.2f\n", sess->last_heard);
632  s = format (s, " total pkts %d, total bytes %lld\n",
633  sess->total_pkts, sess->total_bytes);
634 
635  return s;
636 }
637 
638 u8 * format_snat_user (u8 * s, va_list * args)
639 {
640  snat_main_t * sm = va_arg (*args, snat_main_t *);
641  snat_user_t * u = va_arg (*args, snat_user_t *);
642  int verbose = va_arg (*args, int);
643  dlist_elt_t * head, * elt;
644  u32 elt_index, head_index;
645  u32 session_index;
646  snat_session_t * sess;
647 
648  s = format (s, "%U: %d translations\n",
650 
651  if (verbose == 0)
652  return s;
653 
654  head_index = u->sessions_per_user_list_head_index;
655  head = pool_elt_at_index (sm->list_pool, head_index);
656 
657  elt_index = head->next;
658  elt = pool_elt_at_index (sm->list_pool, elt_index);
659  session_index = elt->value;
660 
661  while (session_index != ~0)
662  {
663  sess = pool_elt_at_index (sm->sessions, session_index);
664 
665  s = format (s, " %U\n", format_snat_session, sm, sess);
666 
667  elt_index = elt->next;
668  elt = pool_elt_at_index (sm->list_pool, elt_index);
669  session_index = elt->value;
670  }
671 
672  return s;
673 }
674 
675 static clib_error_t *
677  unformat_input_t * input,
678  vlib_cli_command_t * cmd)
679 {
680  int verbose = 0;
681  snat_main_t * sm = &snat_main;
682  snat_user_t * u;
683 
684  if (unformat (input, "detail"))
685  verbose = 1;
686  else if (unformat (input, "verbose"))
687  verbose = 2;
688 
689  vlib_cli_output (vm, "%d users, %d outside addresses, %d active sessions",
690  pool_elts (sm->users),
691  vec_len (sm->addresses),
692  pool_elts (sm->sessions));
693 
694  if (verbose > 0)
695  {
696  vlib_cli_output (vm, "%U", format_bihash_8_8, &sm->in2out,
697  verbose - 1);
698  vlib_cli_output (vm, "%U", format_bihash_8_8, &sm->out2in,
699  verbose - 1);
700  vlib_cli_output (vm, "%d list pool elements",
701  pool_elts (sm->list_pool));
702 
703  pool_foreach (u, sm->users,
704  ({
705  vlib_cli_output (vm, "%U", format_snat_user, sm, u, verbose - 1);
706  }));
707  }
708 
709  return 0;
710 }
711 
712 VLIB_CLI_COMMAND (show_snat_command, static) = {
713  .path = "show snat",
714  .short_help = "show snat",
715  .function = show_snat_command_fn,
716 };
u32 translation_memory_size
Definition: snat.h:133
u32 next
Definition: dlist.h:30
u32 sessions_per_user_list_head_index
Definition: snat.h:94
u32 max_translations_per_user
Definition: snat.h:136
static void vl_api_snat_interface_add_del_feature_t_handler(vl_api_snat_interface_add_del_feature_t *mp)
Definition: snat.c:251
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
u32 * config_index_by_sw_if_index
Definition: lookup.h:369
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
vlib_main_t * vlib_main
Definition: snat.h:144
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:286
u32 busy_ports
Definition: snat.h:100
u32 nsessions
Definition: snat.h:95
static void vl_api_snat_add_address_range_t_handler(vl_api_snat_add_address_range_t *mp)
Definition: snat.c:194
clib_bihash_8_8_t out2in
Definition: snat.h:106
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
u32 vnet_config_del_feature(vlib_main_t *vm, vnet_config_main_t *cm, u32 config_string_heap_index, u32 feature_index, void *feature_config, u32 n_feature_config_bytes)
Definition: config.c:300
ip_lookup_main_t * ip4_lookup_main
Definition: snat.h:147
ip_config_main_t rx_config_mains[VNET_N_CAST]
rx/tx interface/feature configuration.
Definition: lookup.h:452
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:482
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:521
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap. ...
Definition: bitmap.h:167
ip_lookup_main_t lookup_main
Definition: ip4.h:115
void snat_add_address(snat_main_t *sm, ip4_address_t *addr)
Definition: snat.c:175
unformat_function_t unformat_vnet_sw_interface
snat_main_t snat_main
Definition: snat.c:27
format_function_t format_ip4_address
Definition: format.h:71
u32 rx_feature_in2out
Definition: snat.h:128
static clib_error_t * snat_init(vlib_main_t *vm)
Definition: snat.c:332
static clib_error_t * add_address_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: snat.c:418
ethernet_main_t * ethernet_main
Definition: plugin.h:27
api_main_t api_main
Definition: api.h:185
u32 random_seed
Definition: snat.h:125
u8 * format_snat_key(u8 *s, va_list *args)
Definition: snat.c:605
vnet_main_t * vnet_get_main(void)
Definition: misc.c:45
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:348
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
u8 * format_snat_user(u8 *s, va_list *args)
Definition: snat.c:638
ip4_address_t addr
Definition: snat.h:93
#define foreach_snat_plugin_api_msg
Definition: snat.c:300
ip4_main_t * ip4_main
Definition: snat.h:146
#define VALIDATE_SW_IF_INDEX(mp)
Definition: snat.c:116
#define clib_warning(format, args...)
Definition: error.h:59
static clib_error_t * snat_plugin_api_hookup(vlib_main_t *vm)
Definition: snat.c:306
snat_user_t * users
Definition: snat.h:113
unformat_function_t unformat_ip4_address
Definition: format.h:68
#define REPLY_MACRO(t)
Definition: snat.c:64
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:369
VNET_IP4_UNICAST_FEATURE_INIT(ip4_snat_in2out, static)
u32 translation_buckets
Definition: snat.h:132
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:118
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:575
static void increment_v4_address(ip4_address_t *a)
Definition: snat.c:184
u8 * format_snat_session(u8 *s, va_list *args)
Definition: snat.c:624
api_main_t * api_main
Definition: snat.h:149
static clib_error_t * show_snat_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: snat.c:676
clib_bihash_8_8_t user_hash
Definition: snat.h:110
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
snat_address_t * addresses
Definition: snat.h:119
u16 msg_id_base
Definition: snat.h:141
int snat_alloc_outside_address_and_port(snat_main_t *sm, snat_session_key_t *k, u32 *address_indexp)
Definition: snat.c:379
#define FINISH
Definition: snat.c:50
clib_error_t * vlib_plugin_register(vlib_main_t *vm, vnet_plugin_handoff_t *h, int from_early_init)
Definition: snat.c:100
static clib_error_t * snat_config(vlib_main_t *vm, unformat_input_t *input)
Definition: snat.c:552
#define ARRAY_LEN(x)
Definition: clib.h:59
ip4_address_t addr
Definition: snat.h:37
static uword clib_bitmap_get(uword *ai, uword i)
Gets the ith bit value from a bitmap.
Definition: bitmap.h:197
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:418
dlist_elt_t * list_pool
Definition: snat.h:122
IPv4 main type.
Definition: ip4.h:114
clib_bihash_8_8_t in2out
Definition: snat.h:107
u32 vnet_config_add_feature(vlib_main_t *vm, vnet_config_main_t *cm, u32 config_string_heap_index, u32 feature_index, void *feature_config, u32 n_feature_config_bytes)
Definition: config.c:239
#define BAD_SW_IF_INDEX_LABEL
Definition: snat.c:126
ip4_address_t addr
Definition: snat.h:99
snat_session_t * sessions
Definition: snat.h:116
u32 value
Definition: dlist.h:32
u32 user_buckets
Definition: snat.h:134
unsigned short u16
Definition: types.h:57
VLIB_CLI_COMMAND(set_interface_ip_source_and_port_range_check_command, static)
vnet_main_t * vnet_main
Definition: snat.h:145
uword * busy_port_bitmap
Definition: snat.h:101
static void * vl_api_snat_add_address_range_t_print(vl_api_snat_add_address_range_t *mp, void *handle)
Definition: snat.c:236
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
u32 user_memory_size
Definition: snat.h:135
void snat_free_outside_address_and_port(snat_main_t *sm, snat_session_key_t *k, u32 address_index)
Definition: snat.c:361
vnet_main_t * vnet_main
Definition: plugin.h:26
u32 rx_feature_out2in
Definition: snat.h:129
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
static u32 random_u32(u32 *seed)
32-bit random number generator
Definition: random.h:69
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1578
static void plugin_custom_dump_configure(snat_main_t *sm)
Definition: snat.c:323
u16 vl_msg_api_get_msg_ids(char *name, int n)
Definition: api_shared.c:1269
vhost_vring_addr_t addr
Definition: vhost-user.h:82
#define clib_error_return(e, args...)
Definition: error.h:111
struct _unformat_input_t unformat_input_t
ethernet_main_t * ethernet_main
Definition: snat.h:148
static clib_error_t * snat_feature_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: snat.c:466
vnet_config_main_t config_main
Definition: lookup.h:367
u32 outside_vrf_id
Definition: snat.h:137
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109