FD.io VPP  v16.12-rc0-308-g931be3a
Vector Packet Processing
cnat_cli_handler.c
Go to the documentation of this file.
1 /* *------------------------------------------------------------------
2  * cnat_cli_handler.c - CLI handler definitions
3  *
4  * Copyright (c) 2007-2015 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 
19 #include <vlib/vlib.h>
20 #include <vnet/vnet.h>
21 #include <vppinfra/vec.h>
22 #include <vppinfra/bitmap.h>
23 #include <vppinfra/hash.h>
24 #include <vppinfra/pool.h>
25 #include <vppinfra/clib.h>
26 #include <vppinfra/error.h>
27 
28 #include "cnat_db.h"
29 #include "cnat_config.h"
30 #include "cnat_global.h"
31 #include "cnat_cli.h"
32 #include "cnat_logging.h"
33 #include "cnat_syslog.h"
34 #include "cnat_config_api.h"
35 #include "cnat_show_api.h"
36 #include "cnat_show_response.h"
37 
38 #include <arpa/inet.h>
39 
40 #if DPDK
41 #include <vnet/devices/dpdk/dpdk.h>
42 #endif
43 
45 
46 u32
48 {
49  cnat_nfv9_logging_info_t *my_nfv9_logging_info = 0;
50  u32 logging_index = EMPTY;
51 
52  /*
53  * Start with global logging index if available
54  */
57 
58  pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({
59  if (my_nfv9_logging_info->i_vrf_id == i_vrf_id) {
60  logging_index = my_nfv9_logging_info -
61  cnat_nfv9_logging_info_pool;
62  break;
63  }
64  }));
65  }
66  return (logging_index);
67 }
68 
69 u32
71 {
72  cnat_syslog_logging_info_t *my_syslog_info = NULL;
73  u32 logging_index = EMPTY;
74 
75  /*
76  * Start with global logging index if available
77  */
79 
80  pool_foreach (my_syslog_info, cnat_syslog_logging_info_pool, ({
81  if (my_syslog_info->i_vrf_id == i_vrf_id) {
82  logging_index = my_syslog_info -
83  cnat_syslog_logging_info_pool;
84  break;
85  }
86  }));
87  }
88  return (logging_index);
89 }
90 
91 void
93 {
94 
95  my_vrfmap->status = S_WAO;
96 
97  my_vrfmap->i_vrf = i_vrf;
98  my_vrfmap->i_vrf_id = i_vrf_id;
99 
100  my_vrfmap->o_vrf = INVALID_UIDX;
101  my_vrfmap->o_vrf_id = INVALID_VRFID;
102 
103 #ifndef NO_BULK_LOGGING
105 #endif /* #ifndef NO_BULK_LOGGING */
108  my_vrfmap->port_limit = V4_DEF_VRF_MAX_PORTS;
109  my_vrfmap->nfv9_logging_index =
111  my_vrfmap->syslog_logging_index =
113 
114  /* Copy logging policy from nfv9 info. */
115  if(my_vrfmap->nfv9_logging_index != EMPTY) {
116  cnat_nfv9_logging_info_t *nfv9_logging_info =
118  my_vrfmap->nf_logging_policy = nfv9_logging_info->logging_policy;
119  }
120  if(my_vrfmap->syslog_logging_index != EMPTY) {
121  cnat_syslog_logging_info_t *syslog_logging_info =
123  my_vrfmap->syslog_logging_policy = syslog_logging_info->logging_policy;
124  }
125  #if 0
126  printf("Initializing params in cnat_set_vrf_params_with_default\n"
127  "my_vrfmap->status = %u\n"
128  "my_vrfmap->tcp_mss = %u\n"
129  "my_vrfmap->i_vrf = %u\n"
130  "my_vrfmap->i_vrf_id = %u\n"
131  "my_vrfmap->o_vrf = %u\n"
132  "my_vrfmap->o_vrf_id = %u\n"
133  "my_vrfmap->bulk_size = %u\n"
134  "my_vrfmap->nfv9_logging_index = %u\n"
135  "my_vrfmap->syslog_logging_index = %u\n"
136  "my_vrfmap->frag_tout = %u\n"
137  "my_vrfmap->port_limit = %u\n"
138  "my_vrfmap->nf_logging_policy = %u\n"
139  "my_vrfmap->syslog_logging_policy = %u\n",
140  my_vrfmap->status,
141  my_vrfmap->tcp_mss,
142  my_vrfmap->i_vrf,
143  my_vrfmap->i_vrf_id,
144  my_vrfmap->o_vrf,
145  my_vrfmap->o_vrf_id,
146  my_vrfmap->bulk_size,
147  my_vrfmap->nfv9_logging_index,
148  my_vrfmap->syslog_logging_index,
149  my_vrfmap->frag_tout,
150  my_vrfmap->port_limit,
151  my_vrfmap->nf_logging_policy,
152  my_vrfmap->syslog_logging_policy);
153  #endif /* if 0 */
154 }
155 
156 /* config command handlers */
158  vlib_main_t *vm)
159 {
160  void cnat_table_entry_fill_map(u32 start_addr, u32 end_addr,
161  cnat_portmap_v2_t **port_map_holder);
162  u32 start_addr, end_addr;
163  u32 pm_len __attribute__((unused));
164  cnat_vrfmap_t *my_vrfmap = 0;
165  cnat_portmap_v2_t *pm = 0;
166  u16 i_vrf, o_vrf;
167  u32 ivrf_id, ovrf_id;
168  u16 my_vrfmap_index;
169  u8 i = 0;
170 
171  start_addr = mp->start_addr[0];
172  end_addr = mp->end_addr[0];
173  i_vrf = mp->i_vrf;
174  o_vrf = mp->o_vrf;
175  ovrf_id = mp->o_vrf_id;
176  ivrf_id = mp->i_vrf_id;
177 
178 #if DEBUG_NOT_COMMENTED
179  vlib_cli_output(vm, "%s: saddr[0x%x], eaddr[0x%x], i_vrf[0x%x], o_vrf[0x%x], "
180  "ovrf_id[0x%x], ivrf_id[0x%x]\n", __func__, start_addr, end_addr,
181  i_vrf, o_vrf, ovrf_id, ivrf_id);
182 #endif
183  if (start_addr > end_addr) {
184  vlib_cli_output(vm, "Add VRF Map failed start addr 0x%x > end addr 0x%x\n",
185  start_addr, end_addr);
186  return;
187  }
188  if ((end_addr - start_addr) > CNAT_MAX_ADDR_POOL_SIZE) {
189  vlib_cli_output(vm, "Add VRF Map failed start addr 0x%x - end addr "
190  "0x%x range > 65536\n", start_addr, end_addr);
191  return;
192  }
193  my_vrfmap_index = vrf_map_array[i_vrf];
194 
195  if (my_vrfmap_index != VRF_MAP_ENTRY_EMPTY) {
196 
197  my_vrfmap = cnat_map_by_vrf + my_vrfmap_index;
198 
199  my_vrfmap->o_vrf = o_vrf;
200  my_vrfmap->i_vrf_id = ivrf_id;
201  my_vrfmap->o_vrf_id = ovrf_id;
202  } else {
203  /*
204  * first time add
205  */
206  pool_get(cnat_map_by_vrf, my_vrfmap);
207  memset(my_vrfmap, 0, sizeof(*my_vrfmap));
208  /* waiting for outside vrf */
209  cnat_set_vrf_params_with_default(my_vrfmap, i_vrf, ivrf_id);
210  my_vrfmap->i_vrf = i_vrf;
211  my_vrfmap->o_vrf = o_vrf;
212  my_vrfmap->i_vrf_id = ivrf_id;
213  my_vrfmap->o_vrf_id = ovrf_id;
214 #ifndef NO_BULK_LOGGING
216 #endif /* #ifndef NO_BULK_LOGGING */
217 
219  my_vrfmap->status = S_WA;
220  my_vrfmap->frag_tout = 0; /* currently setting it to 0 */
221  my_vrfmap->port_limit = V4_DEF_VRF_MAX_PORTS;
222  vrf_map_array[i_vrf] = (my_vrfmap - cnat_map_by_vrf);
223  }
224  pm = my_vrfmap->portmap_list;
225  pm_len = vec_len(pm);
226  for(i=0; i < 1 ; i++) {
227  start_addr = mp->start_addr[i];
228  end_addr = mp->end_addr[i];
229  if((start_addr == 0) || (end_addr == 0))
230  break;
231 
232  cnat_table_entry_fill_map(start_addr, end_addr,
233  &(my_vrfmap->portmap_list));
234  }
235  my_vrfmap->status = S_RUN;
236  vlib_cli_output(vm, "Address Pool Config Successful !!\n");
237  return;
238 }
239 
241  u16 init, u8 *proto, u8 reset, vlib_main_t *vm)
242 {
243  if (!strncmp((char *) proto, "tcp", 3)) {
244  tcp_initial_setup_timeout = (reset) ? V4_DEF_TCP_IS_TO : init;
245  tcp_active_timeout = (reset) ? V4_DEF_TCP_AS_TO : active;
246 
247  } else if (!strncmp((char *) proto, "udp", 3)) {
248  udp_init_session_timeout = (reset) ? V4_DEF_UDP_IS_TO : init;
249  udp_act_session_timeout = (reset) ? V4_DEF_UDP_AS_TO : active;
250 
251  } else if (!strncmp((char *) proto, "icmp", 4)) {
252  icmp_session_timeout = (reset) ? V4_DEF_ICMP_S_TO : active;
253 
254  } else {
255  vlib_cli_output(vm, "Error !! Unsupported protocol %s\n", proto);
256  }
257  return;
258 }
259 
260 
261 
262 
263 /* Show command handlers */
265 {
266  pool_header_t *h;
267  u32 used, free;
268  cnat_vrfmap_t *my_vrfmap =0;
269  cnat_portmap_v2_t *pm =0, *my_pm = 0;
270  u32 i, pm_len;
271  struct in_addr ip;
273  (vlib_main_t *vm, cnat_nfv9_logging_info_t *my_nfv9_logging_info);
274 
275  /* active translations */
277  free = vec_len(h->free_indices);
278  used = vec_len(cnat_main_db) - free;
279 
280  vlib_cli_output(vm, "vCGN NAT44 Statistics :\n");
281  vlib_cli_output(vm, "\tActive Translations : %u\n",
282  NAT44_COMMON_STATS.active_translations);
283  vlib_cli_output(vm, "\tTotal free translation entries : %u\n", free);
284  vlib_cli_output(vm, "\tTotal used translation entries : %u\n", used);
285  vlib_cli_output(vm, "\ti2o drops due to port limit exceeded : %lu\n",
287  vlib_cli_output(vm, "\ti2o drops due to system limit reached : %lu\n",
289  vlib_cli_output(vm, "\ti2o drops due to resource depletion : %lu\n",
291  vlib_cli_output(vm, "\to2i drops due to no translations : %lu\n",
292  NAT44_COMMON_STATS.no_translation_entry_drops);
293 
294  vlib_cli_output(vm, "\tPool address usage:\n");
295  vlib_cli_output(vm, "\t-------------------------------------------------\n");
296  vlib_cli_output(vm, "\tExternal Address \tPorts Used\n");
297  vlib_cli_output(vm, "\t-------------------------------------------------\n");
298 
299  used = 0;
300  pool_foreach (my_vrfmap, cnat_map_by_vrf, ({
301  pm = my_vrfmap->portmap_list;
302  pm_len = vec_len(pm);
303  for (i = 0; i < pm_len; i++) {
304  my_pm = pm + i;
305  if (my_pm->inuse) {
306  used++;
307  /* maximum of 200 addresses to be returned */
308  if (used <= 200) {
309  ip.s_addr = ntohl(my_pm->ipv4_address);
310  vlib_cli_output(vm, "\t%s \t\t%u\n", inet_ntoa(ip), my_pm->inuse);
311  }
312  }
313  }
314  }));
315  return;
316 }
317 
319 {
320  cnat_vrfmap_t * my_vrfmap;
321  cnat_portmap_v2_t *pm = 0;
322  cnat_portmap_v2_t *my_pm = 0;
323  u32 pm_len;
324  struct in_addr ip_addr;
325  u8 status_str[20];
326  cnat_nfv9_logging_info_t *my_nfv9_logging_info,
327  *global_nfv9_logging_info = 0;
328 
329  vnet_hw_interface_t * hw;
330  vnet_main_t * vnm = vnet_get_main();
331 
333  (vlib_main_t *vm, cnat_nfv9_logging_info_t *my_nfv9_logging_info);
334 
335  vlib_cli_output(vm, "vCGN NAT44 Config:\n");
336  vlib_cli_output(vm, "\tPort Limit : %u\n", cnat_main_db_max_ports_per_user);
337  vlib_cli_output(vm, "\ttotal address pool : %u\n", total_address_pool_allocated);
338  vlib_cli_output(vm, "\tdynamic port start range : %u\n", cnat_static_port_range);
339 
340  pool_foreach(my_vrfmap, cnat_map_by_vrf, ({
341  hw = vnet_get_hw_interface (vnm, my_vrfmap->i_vrf);
342  vlib_cli_output(vm, "\tInside Interface : %v\n", hw->name);
343  hw = vnet_get_hw_interface (vnm, my_vrfmap->o_vrf);
344  vlib_cli_output(vm, "\tOutside Interface : %v\n", hw->name);
345 
346  memset(status_str, 0x00, sizeof(status_str));
347  switch(my_vrfmap->status) {
348  case S_WAO: clib_memcpy(status_str, "S_WAO", 5); break;
349  case S_WA: clib_memcpy(status_str, "S_WA", 4); break;
350  case S_WO: clib_memcpy(status_str, "S_WO", 4); break;
351  case S_RUN: clib_memcpy(status_str, "ONLINE", 6); break;
352  case S_DEL: clib_memcpy(status_str, "S_DEL", 5); break;
353  default: clib_memcpy(status_str, "Invalid state", 13);
354 
355  }
356  vlib_cli_output(vm,
357  "\tAddress pool map table status : %s\n", status_str);
358 
359  pm = my_vrfmap->portmap_list;
360  pm_len = vec_len(pm);
361  my_pm = pm;
362  ip_addr.s_addr = clib_net_to_host_u32(my_pm->ipv4_address);
363  vlib_cli_output(vm,
364  "\tStart Address : %s\n", inet_ntoa(ip_addr));
365  my_pm = pm + (pm_len - 1);
366  ip_addr.s_addr = clib_net_to_host_u32(my_pm->ipv4_address);
367  vlib_cli_output(vm,
368  "\tEnd Address : %s\n", inet_ntoa(ip_addr));
369 
370  }));
371  vlib_cli_output(vm,
372  "\ttcp init timeout : %u sec\n", tcp_initial_setup_timeout);
373  vlib_cli_output(vm,
374  "\ttcp active timeout : %u sec\n", tcp_active_timeout);
375  vlib_cli_output(vm,
376  "\tudp init timeout : %u sec\n", udp_init_session_timeout);
377  vlib_cli_output(vm,
378  "\tudp active timeout : %u sec\n", udp_act_session_timeout);
379  vlib_cli_output(vm,
380  "\ticmp session timeout: %u sec\n", icmp_session_timeout);
381 
382 #if 0
384  vlib_cli_output(vm,"\nGloabal NFV9 Collector :");
385  global_nfv9_logging_info = cnat_nfv9_logging_info_pool +
387  cnat_nfv9_show_collector(vm, global_nfv9_logging_info);
388  }
389 #endif
390 
391  vlib_cli_output(vm, "\nNFV9 Collector :");
393  pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({
394  if (my_nfv9_logging_info != global_nfv9_logging_info) {
395  cnat_nfv9_show_collector(vm, my_nfv9_logging_info);
396  vlib_cli_output(vm, "\n");
397  }
398  }));
399  } else {
400  vlib_cli_output(vm, "\n");
401  }
402 
403  return;
404 }
405 
406 /*
407  * Check if the request flag matches the entry flags and
408  * if so return "1"
409  *
410  * entry_flag_ptr is an output parameter - it returns the flags
411  * corresponding to the translation entry
412  */
414  u16 request_flag,
416  u16 *entry_flag_ptr)
417 {
418  u8 display_entry = 0;
419 
420  /*
421  * This should never happen
422  */
423  if (!entry_flag_ptr) {
424  return (display_entry);
425  }
426 
427  *entry_flag_ptr = 0;
428 
429  if ((db->flags & CNAT_DB_FLAG_STATIC_PORT)
430  &&(db->flags & CNAT_DB_FLAG_ALG_ENTRY)) {
431  *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_STATIC;
432  *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_ALG;
433  } else if (db->flags & CNAT_DB_FLAG_STATIC_PORT) {
434  *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_STATIC;
435  } else if ((db->flags & CNAT_DB_FLAG_ALG_ENTRY) ||
437  *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_ALG;
438  } else if (db->flags & CNAT_DB_FLAG_PCPI) {
439  *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_PCPI_DYNAMIC;
440  } else if (db->flags & CNAT_DB_FLAG_PCPE) {
441  *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_PCPE_DYNAMIC;
442  } else {
443  *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_DYNAMIC;
444  }
445 
446  if (request_flag == CNAT_TRANSLATION_ENTRY_ALL) {
447  display_entry = 1;
448  } else {
449  /*
450  * Check if the request_flag is STATIC or ALG
451  * and the entry is STATIC or ALG as well
452  */
453  if ((request_flag & CNAT_TRANSLATION_ENTRY_STATIC) &&
454  (*entry_flag_ptr & CNAT_TRANSLATION_ENTRY_STATIC)) {
455  display_entry = 1;
456  }
457 
458  if ((request_flag & CNAT_TRANSLATION_ENTRY_ALG) &&
459  (*entry_flag_ptr & CNAT_TRANSLATION_ENTRY_ALG)) {
460  display_entry = 1;
461  }
462 
463  if ((request_flag & CNAT_TRANSLATION_ENTRY_PCPI_DYNAMIC) &&
464  (*entry_flag_ptr & CNAT_TRANSLATION_ENTRY_PCPI_DYNAMIC)) {
465  display_entry = 1;
466  }
467 
468  if ((request_flag & CNAT_TRANSLATION_ENTRY_PCPE_DYNAMIC) &&
469  (*entry_flag_ptr & CNAT_TRANSLATION_ENTRY_PCPE_DYNAMIC)) {
470  display_entry = 1;
471  }
472 
473  /*
474  * For dynamic entry case, check if flags field is 0
475  */
476  if ((request_flag & CNAT_TRANSLATION_ENTRY_DYNAMIC) &&
477  (*entry_flag_ptr & CNAT_TRANSLATION_ENTRY_DYNAMIC)) {
478  display_entry = 1;
479  }
480  }
481 
482  if (PREDICT_FALSE(show_debug_level > 2)) {
483  PLATFORM_DEBUG_PRINT("Entry (0x%x, %d) -> (0x%x, %d) request_flag 0x%x, entry_flag 0x%x, display_entry %d\n", db->in2out_key.k.ipv4, db->in2out_key.k.port, db->out2in_key.k.ipv4, db->out2in_key.k.port, request_flag, *entry_flag_ptr, display_entry);
484  }
485 
486  return (display_entry);
487 }
490 {
491  cnat_user_db_entry_t *udb = NULL;
493  cnat_db_key_bucket_t u_ki, ki;
494  u64 a, b, c;
495  u32 index;
496  u16 start_port, end_port, port;
497  u16 request_flag = 0;
498  u16 entry_flag = 0;
499  u8 num_entries = 0;
500  u8 proto, all;
501  u8 done = 0;
502  cnat_v4_show_translation_entry *entry_list;
504  u8 display_entry;
505  u8 flag_str[11];
506  vnet_hw_interface_t * hw;
507  vnet_main_t * vnm = vnet_get_main();
508 
509  ki.k.k.ipv4 = mp->ipv4_addr;
510  ki.k.k.vrf = mp->vrf_id;
511  start_port = mp->start_port;
512  end_port = mp->end_port;
513 #if DEBUG
514  vlib_cli_output(vm, "## proto %d, inside-addr 0x%x, start_port %u, "
515  "end_port %u, vrf 0x%x, flag 0x%x\n",
516  mp->protocol,
517  mp->ipv4_addr,
518  mp->start_port,
519  mp->end_port,
520  mp->vrf_id,
521  mp->flags);
522 #endif
523 
524  proto = mp->protocol;
525  ki.k.k.vrf |= ((u16)proto << CNAT_PRO_SHIFT);
526 
527  all = mp->all_entries; /* for no port range case */
528  request_flag = mp->flags; /* for all, alg, static entries case */
529  entry_list = entry;
530 
531  /*
532  * check if the address is belonging to this core
533  */
534 
535 
536  /*
537  * first we check if the user exists in the udb, if he is not then
538  * it does not make sense to check the main db for translations
539  */
540  u_ki.k.k.vrf = ki.k.k.vrf & CNAT_VRF_MASK;
541  u_ki.k.k.ipv4 = ki.k.k.ipv4;
542  u_ki.k.k.port = 0;
543 
544  if (PREDICT_FALSE(show_debug_level > 0)) {
545  vlib_cli_output(vm, "\nI_TRANS_CORE %d: IPv4 0x%x, VRF 0x%x, "
546  "start_port %d, end_port %d",
547  my_instance_number, ki.k.k.ipv4,
548  ki.k.k.vrf, start_port, end_port);
549  }
550 
551  udb = cnat_user_db_lookup_entry(&u_ki);
552  if (!udb) {
553  if (PREDICT_FALSE(show_debug_level > 0)) {
554  vlib_cli_output(vm, "\nReturning %d entries",
555  num_entries);
556  }
557  return;
558  }
559 
560  if (all) {
561  #if 0
562  if (PREDICT_FALSE(show_debug_level > 0)) {
563  PLATFORM_DEBUG_PRINT("\nI_TRANS: Printing ALL\n");
564  }
565 
566  /*
567  * get the head of list of translation entries for that user
568  * from the user db
569  */
570  head = udb->translation_list_head_index;
571  db = cnat_main_db + head;
572 
573  while (num_entries < PLATFORM_MAX_TRANSLATION_ENTRIES) {
574 
575  if (((db->in2out_key.k.vrf & CNAT_PRO_MASK) >> CNAT_PRO_SHIFT)
576  != proto) {
577  goto next_entry;
578  }
579 
580  display_entry =
581  spp_api_cnat_v4_show_verify_display_entry(request_flag, db,
582  &entry_flag);
583 
584  if (display_entry) {
585  entry_list->ipv4_addr =
586  spp_host_to_net_byte_order_32(db->out2in_key.k.ipv4);
587  entry_list->cnat_port =
588  spp_host_to_net_byte_order_16(db->out2in_key.k.port);
589  entry_list->src_port =
590  spp_host_to_net_byte_order_16(db->in2out_key.k.port);
591 
592  entry_list->protocol = proto;
593 
594  /* incase of gre - in2out is not accounted */
595  if(proto != CNAT_PPTP) {
596 
597  entry_list->in2out_packets =
598  spp_host_to_net_byte_order_32(db->in2out_pkts);
599  } else {
600  entry_list->in2out_packets = 0;
601  }
602  entry_list->out2in_packets =
603  spp_host_to_net_byte_order_32(db->out2in_pkts);
604 
605  entry_list->flags =
606  spp_host_to_net_byte_order_16(entry_flag);
607 
608  num_entries++;
609  entry_list = entry_list + 1;
610  }
611 next_entry:
612  db = cnat_main_db + db->user_ports.next;
613  /*
614  * its a circular list, so if we have reached the head again
615  * all the entries for that user have been read
616  */
617  if (db == (cnat_main_db + head)) {
618  break;
619  }
620  }
621  resp->num_entries = num_entries;
622  #endif /* if 0 */
623  } else {
624  if (PREDICT_FALSE(show_debug_level > 0)) {
625  vlib_cli_output(vm, "\nI_TRANS: Printing range %d .. %d\n",
626  start_port, end_port);
627  }
628  /*
629  * port range is specified so for each port calculate the hash and
630  * check if the entry is present in main db
631  */
632  port = start_port;
633  done = 0;
634  while ((!done) && (num_entries < PLATFORM_MAX_TRANSLATION_ENTRIES)) {
635 
636  ki.k.k.port = port;
637  if (port >= end_port) {
638  done = 1;
639  } else {
640  port++;
641  }
643  ki.bucket,
645  index = cnat_in2out_hash[ki.bucket].next;
646  if (PREDICT_TRUE(index == EMPTY)) {
647  continue;
648  }
649 
650  do {
651  db = cnat_main_db + index;
652  if (db->in2out_key.key64 == ki.k.key64) {
653  break;
654  }
655  index = db->in2out_hash.next;
656  } while (index != EMPTY);
657 
658  if (index == EMPTY) {
659  continue;
660  } else {
661 
662  display_entry =
663  cnat_v4_show_verify_display_entry(request_flag, db,
664  &entry_flag);
665  if (display_entry) {
666 
667  entry_list->ipv4_addr =
668  clib_host_to_net_u32(db->out2in_key.k.ipv4);
669  entry_list->cnat_port =
670  clib_host_to_net_u16(db->out2in_key.k.port);
671  entry_list->src_port =
672  clib_host_to_net_u16(db->in2out_key.k.port);
673 
674  entry_list->protocol = proto;
675  entry_list->nsessions = db->nsessions;
676  entry_list->flags = ((db->flags & CNAT_DB_FLAG_TCP_ACTIVE) ||
677  (db->flags & CNAT_DB_FLAG_UDP_ACTIVE)) ? 1:0;
678  /* incase of gre - in2out is not accounted */
679  if(proto != CNAT_PPTP) {
680  entry_list->in2out_packets =
681  clib_host_to_net_u32(db->in2out_pkts);
682  } else {
683  entry_list->in2out_packets = 0;
684  }
685 
686  entry_list->out2in_packets =
687  clib_host_to_net_u32(db->out2in_pkts);
688 
689  if (PREDICT_FALSE(show_debug_level > 3)) {
690  vlib_cli_output(vm, "\n1. Entry: Addr 0x%x, port %d, num_entries %d",
691  clib_net_to_host_u32(entry_list->ipv4_addr),
692  clib_net_to_host_u16(entry_list->cnat_port),
693  num_entries);
694  }
695 
696  entry_list = entry_list + 1;
697  num_entries++;
698  }
699  } /* if (index == EMPTY) */
700  } /* while() */
701  }
702 
703  if (PREDICT_FALSE(show_debug_level > 0)) {
704  if (num_entries) {
705  vlib_cli_output(vm, "\nReturning %d entries\n",
706  num_entries);
707  }
708  }
709 
710  entry_list = entry;
711  u8 i = 0;
712  struct in_addr ip;
713  u8 proto_str[10];
714  u8 transl_str[10];
715  memset(proto_str, 0x00, 10);
716  memset(transl_str, 0x00, 10);
717 
718  if (proto == 1) strncpy((char *)proto_str, "udp", 3);
719  else if (proto == 2) strncpy((char *)proto_str, "tcp", 3);
720  else if (proto == 3) strncpy((char *)proto_str, "icmp", 4);
721  else strncpy((char *)proto_str, "unknown", 7);
722 
723  if (request_flag == 0x04) strncpy((char *)transl_str, "Dynamic", 7);
724  else strncpy((char *)transl_str, "Unknown", 7); /* currently we are not supporting static/alg entries */
725 
726  ip.s_addr = clib_net_to_host_u32(u_ki.k.k.ipv4);
727  hw = vnet_get_hw_interface (vnm, u_ki.k.k.vrf);
728 
729  vlib_cli_output (vm, "Inside-translation details\n");
730  vlib_cli_output (vm, "--------------------------\n");
731 
732  vlib_cli_output (vm, "Inside interface : %s\n", hw->name);
733  vlib_cli_output (vm, "Inside address : %s\n", inet_ntoa(ip));
734  vlib_cli_output (vm, "Start port : %u\n", start_port);
735  vlib_cli_output (vm, "End port : %u\n", end_port);
736 
737  vlib_cli_output (vm, "--------------------------------------------------------------------------------------"
738  "-----------------------\n");
739  vlib_cli_output (vm, "Outside Protocol Inside Outside Translation"
740  " I2O O2I Flag Num\n");
741  vlib_cli_output (vm, "Address Src Port Src Port Type "
742  " Pkts Pkts Sessions\n");
743  vlib_cli_output (vm, "--------------------------------------------------------------------------------------"
744  "-----------------------\n");
745 
746  while ((num_entries) && (entry_list) && (i < 50)) {
747 
748  ip.s_addr = entry_list->ipv4_addr;
749  memset(flag_str,0x00,11);
750  if((proto == 1) || (proto == 2)) {
751  if(entry_list->flags == 1) {
752  strncpy((char *)flag_str,"Active",6);
753  }
754  else {
755  strncpy((char *) flag_str,"Non Active",10);
756  }
757  } else {
758  strncpy((char *) flag_str, "NA", 2);
759  }
760  vlib_cli_output(vm, "%s %10s %11u %12u %13s %10u %10u %14s %6u\n",
761  inet_ntoa(ip), proto_str,
762  clib_net_to_host_u16(entry_list->src_port),
763  clib_net_to_host_u16(entry_list->cnat_port),
764  transl_str,
765  clib_net_to_host_u32(entry_list->in2out_packets),
766  clib_net_to_host_u32(entry_list->out2in_packets),
767  flag_str,
768  entry_list->nsessions);
769  entry_list++;
770  num_entries--; i++;
771  }
772 
773  return;
774 }
775 
778 {
781  u64 a, b, c;
782  u32 index;
783  u16 start_port, end_port, port;
784  u16 request_flag = 0;
785  u16 entry_flag = 0;
786  u8 num_entries = 0;
787  u8 proto;
788  cnat_v4_show_translation_entry *entry_list;
790  u8 done = 0;
791  u8 display_entry;
792  u8 flag_str[11];
793  vnet_hw_interface_t * hw;
794  vnet_main_t * vnm = vnet_get_main();
795 
796  ko.k.k.ipv4 = mp->ipv4_addr;
797  ko.k.k.vrf = mp->vrf_id;
798  start_port = mp->start_port;
799  end_port = mp->end_port;
800 
801  proto = mp->protocol;
802  request_flag = mp->flags;
803 
804  ko.k.k.vrf |= ((u16)proto << CNAT_PRO_SHIFT);
805 
806  entry_list = entry;
807 
808  if (PREDICT_FALSE(show_debug_level > 0)) {
809  vlib_cli_output(vm, "\nO_TRANS_CORE %d: IPv4 0x%x, VRF 0x%x, "
810  "start_port %d, end_port %d", my_instance_number,
811  ko.k.k.ipv4, ko.k.k.vrf, start_port, end_port);
812  }
813 
814  /*
815  * for each ip and port combination we need to scan the main db
816  * and check if the entry is present in main db
817  */
818  port = start_port;
819  done = 0;
820  while ((!done) && (num_entries < PLATFORM_MAX_TRANSLATION_ENTRIES)) {
821  ko.k.k.port = port;
822 
823  /*
824  * If we have reached the end_port, we are DONE
825  */
826  if (port >= end_port) {
827  done = 1;
828  } else {
829  port++;
830  }
831 
833  ko.bucket,
835 
836  index = cnat_out2in_hash[ko.bucket].next;
837  if (PREDICT_TRUE(index == EMPTY)) {
838  continue;
839  }
840 
841  do {
842  db = cnat_main_db + index;
843  if (db->out2in_key.key64 == ko.k.key64) {
844  break;
845  }
846  index = db->out2in_hash.next;
847  } while (index != EMPTY);
848 
849  if (index == EMPTY) {
850  continue;
851  } else {
852  display_entry =
853  cnat_v4_show_verify_display_entry(request_flag, db,
854  &entry_flag);
855 
856  if (display_entry) {
857  entry_list->ipv4_addr =
858  clib_host_to_net_u32(db->in2out_key.k.ipv4);
859  entry_list->cnat_port =
860  clib_host_to_net_u16(db->out2in_key.k.port);
861  entry_list->src_port =
862  clib_host_to_net_u16(db->in2out_key.k.port);
863  entry_list->protocol = proto;
864  entry_list->nsessions = db->nsessions;
865  entry_list->flags = ((db->flags & CNAT_DB_FLAG_TCP_ACTIVE) ||
866  (db->flags & CNAT_DB_FLAG_UDP_ACTIVE)) ? 1:0;
867  /* incase of gre - in2out is not accounted */
868  if(proto != CNAT_PPTP) {
869  entry_list->in2out_packets =
870  clib_host_to_net_u32(db->in2out_pkts);
871  } else {
872  entry_list->in2out_packets = 0 ;
873  }
874  entry_list->out2in_packets =
875  clib_host_to_net_u32(db->out2in_pkts);
876  #if 0
877  entry_list->flags =
878  clib_host_to_net_u16(entry_flag);
879  #endif
880  entry_list = entry_list + 1;
881  num_entries++;
882  }
883  }
884  }
885 
886  if (num_entries == 0) {
887  /* No point proceeding further */
888  return;
889  }
890 
891  if (PREDICT_FALSE(show_debug_level > 0)) {
892  if (num_entries) {
893  vlib_cli_output(vm, "\nO_TRANS: Core %d returning %d entries",
894  num_entries);
895  }
896  }
897 
898  entry_list = entry;
899  u8 i = 0;
900  struct in_addr ip;
901  u8 proto_str[10];
902  u8 transl_str[10];
903  memset(proto_str, 0x00, 10);
904  memset(transl_str, 0x00, 10);
905 
906  if (proto == 1) strncpy((char *) proto_str, "udp", 3);
907  else if (proto == 2) strncpy((char *) proto_str, "tcp", 3);
908  else if (proto == 3) strncpy((char *) proto_str, "icmp", 4);
909  else strncpy((char *) proto_str, "unknown", 7);
910 
911  if (request_flag == 0x04) strncpy((char *) transl_str, "Dynamic", 7);
912  else strncpy((char *)transl_str, "Unknown", 7); /* currently we are not supporting static/alg entries */
913 
914  ip.s_addr = clib_net_to_host_u32(ko.k.k.ipv4);
915  hw = vnet_get_hw_interface (vnm, (ko.k.k.vrf & CNAT_VRF_MASK));
916 
917  vlib_cli_output (vm, "Outside-translation details\n");
918  vlib_cli_output (vm, "--------------------------\n");
919 
920  vlib_cli_output (vm, "Outside interface : %s\n", hw->name);
921  vlib_cli_output (vm, "Outside address : %s\n", inet_ntoa(ip));
922  vlib_cli_output (vm, "Start port : %u\n", start_port);
923  vlib_cli_output (vm, "End port : %u\n", end_port);
924 
925  vlib_cli_output (vm, "--------------------------------------------------------------------------------------"
926  "-----------------------\n");
927  vlib_cli_output (vm, "Inside Protocol Outside Inside Translation"
928  " I2O O2I Flag Num\n");
929  vlib_cli_output (vm, "Address Dst Port Dst Port Type "
930  " Pkts Pkts Sessions\n");
931  vlib_cli_output (vm, "--------------------------------------------------------------------------------------"
932  "-----------------------\n");
933 
934  while ((num_entries) && (entry_list) && (i < 50)) {
935  ip.s_addr = entry_list->ipv4_addr;
936  memset(flag_str,0x00,11);
937  if((proto == 1) || (proto == 2)) {
938  if(entry_list->flags == 1) {
939  strncpy((char *) flag_str,"Active",6);
940  }
941  else {
942  strncpy((char *) flag_str,"Non Active",10);
943  }
944  } else {
945  strncpy((char *) flag_str, "NA", 2);
946  }
947  vlib_cli_output(vm, "%s %10s %11u %12u %13s %10u %10u %14s %6u\n",
948  inet_ntoa(ip), proto_str,
949  clib_net_to_host_u16(entry_list->cnat_port),
950  clib_net_to_host_u16(entry_list->src_port),
951  transl_str,
952  clib_net_to_host_u32(entry_list->in2out_packets),
953  clib_net_to_host_u32(entry_list->out2in_packets),
954  flag_str,
955  entry_list->nsessions);
956  entry_list++;
957  num_entries--; i++;
958 
959  }
960  return;
961 }
cnat_nfv9_global_info_t cnat_nfv9_global_info
Definition: cnat_logging.c:63
#define S_DEL
Definition: cnat_db.h:417
u16 flags
Definition: cnat_db.h:159
cnat_main_db_entry_t * cnat_main_db
Definition: cnat_db_v2.c:201
u32 i_vrf_id
Definition: cnat_db.h:428
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
#define S_WA
Definition: cnat_db.h:414
u32 total_address_pool_allocated
Definition: cnat_show.c:43
a
Definition: bitmap.h:516
#define PREDICT_TRUE(x)
Definition: clib.h:98
Fixed length block allocator.
#define CNAT_PRO_SHIFT
Definition: cnat_db.h:98
#define NULL
Definition: clib.h:55
cnat_syslog_global_info_t cnat_syslog_global_info
Definition: cnat_syslog.c:37
u32 * free_indices
Vector of free indices.
Definition: pool.h:58
#define V4_DEF_TCP_AS_TO
Definition: cnat_config.h:33
#define CNAT_DB_FLAG_PCPE
Definition: cnat_db.h:178
u64 key64
Definition: cnat_db.h:109
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
u16 cnat_static_port_range
Definition: cnat_config.c:53
#define V4_DEF_UDP_IS_TO
Definition: cnat_config.h:30
Definition: cnat_db.h:153
#define CNAT_TRANSLATION_ENTRY_ALG
index_slist_t in2out_hash
Definition: cnat_db.h:156
#define V4_DEF_VRF_MAX_PORTS
Definition: cnat_config.h:42
#define CNAT_DB_FLAG_STATIC_PORT
Definition: cnat_db.h:164
u16 udp_init_session_timeout
Definition: cnat_config.c:28
u32 ipv4_addr
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
#define CNAT_TRANSLATION_ENTRY_STATIC
#define CNAT_VRF_MASK
Definition: cnat_db.h:96
u32 o_vrf_id
Definition: cnat_db.h:429
u32 cnat_get_vrfmap_nfv9_logging_index(u32 i_vrf_id)
cnat_portmap_v2_t * portmap_list
Definition: cnat_db.h:430
static u8 cnat_v4_show_verify_display_entry(u16 request_flag, cnat_main_db_entry_t *db, u16 *entry_flag_ptr)
void cnat_nat44_add_vrf_map_t_handler(spp_api_cnat_v4_add_vrf_map_t *mp, vlib_main_t *vm)
u16 cnat_main_db_max_ports_per_user
Definition: cnat_config.c:48
index_slist_t out2in_hash
Definition: cnat_db.h:155
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
void cnat_v4_show_inside_entry_req_t_handler(spp_api_cnat_v4_show_inside_entry_req_t *mp, vlib_main_t *vm)
index_slist_t * cnat_in2out_hash
Definition: cnat_db_v2.c:196
#define CNAT_DB_FLAG_PPTP_GRE_ENTRY
Definition: cnat_db.h:174
#define PLATFORM_DEBUG_PRINT(...)
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:348
#define V4_DEF_UDP_AS_TO
Definition: cnat_config.h:31
u64 in2out_drops_system_limit_reached
Definition: cnat_db_v2.c:229
#define CNAT_TRANSLATION_ENTRY_PCPE_DYNAMIC
u32 out2in_packets
cnat_key_t k
Definition: cnat_db.h:113
unsigned long u64
Definition: types.h:89
void cnat_nat44_set_protocol_timeout_value(u16 active, u16 init, u8 *proto, u8 reset, vlib_main_t *vm)
#define INVALID_VRFID
Definition: cnat_db.h:420
#define CNAT_PRO_MASK
Definition: cnat_db.h:97
#define V4_DEF_TCP_IS_TO
Definition: cnat_config.h:32
u64 in2out_drops_port_limit_exceeded
Definition: cnat_db_v2.c:228
u16 port_limit
Definition: cnat_db.h:444
u32 in2out_packets
#define CNAT_DB_FLAG_ALG_ENTRY
Definition: cnat_db.h:166
u32 show_debug_level
u32 syslog_logging_index
Definition: cnat_db.h:432
static pool_header_t * pool_header(void *v)
Get pool header from user pool pointer.
Definition: pool.h:67
#define S_WO
Definition: cnat_db.h:415
u8 nf_logging_policy
Definition: cnat_db.h:440
u16 nsessions
u32 nfv9_logging_index
Definition: cnat_db.h:431
#define S_RUN
Definition: cnat_db.h:416
#define PREDICT_FALSE(x)
Definition: clib.h:97
u16 icmp_session_timeout
Definition: cnat_config.c:30
u16 vrf_map_array[CNAT_MAX_VRFMAP_ENTRIES]
Definition: cnat_db_v2.c:225
void cnat_nfv9_show_collector(vlib_main_t *vm, cnat_nfv9_logging_info_t *my_nfv9_logging_info)
Definition: cnat_show.c:502
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:575
#define CNAT_IPV4_FRAG_TIMEOUT_DEF
Definition: cnat_config.h:58
u32 translation_list_head_index
Definition: cnat_db.h:303
#define CNAT_DB_FLAG_PCPI
Definition: cnat_db.h:177
svmdb_client_t * c
#define V4_TCP_MSS_NOT_CONFIGURED_VALUE
Definition: cnat_config.h:53
#define INVALID_UIDX
Definition: cnat_db.h:419
#define clib_memcpy(a, b, c)
Definition: string.h:64
struct _spp_api_cnat_v4_show_outside_entry_req spp_api_cnat_v4_show_outside_entry_req_t
u32 cnat_get_vrfmap_syslog_logging_index(u32 i_vrf_id)
struct _spp_api_cnat_v4_add_vrf_map spp_api_cnat_v4_add_vrf_map_t
bulk_alloc_size_t bulk_size
Definition: cnat_db.h:435
u8 my_instance_number
Definition: cnat_ports.c:51
void cnat_nat44_handle_show_config(vlib_main_t *vm)
cnat_db_key_t k
Definition: cnat_db.h:108
#define CNAT_PPTP
Definition: cnat_db.h:92
#define BULKSIZE_FROM_VRFMAP(vrfmap)
#define CNAT_TRANSLATION_ENTRY_PCPI_DYNAMIC
#define CNAT_DB_FLAG_TCP_ACTIVE
Definition: cnat_db.h:161
u16 tcp_initial_setup_timeout
Definition: cnat_config.c:26
Definition: cnat_db.h:285
unsigned int u32
Definition: types.h:88
u16 tcp_active_timeout
Definition: cnat_config.c:27
void cnat_nat44_handle_show_stats(vlib_main_t *vm)
index_dlist_t user_ports
Definition: cnat_db.h:204
cnat_key_t out2in_key
Definition: cnat_db.h:198
u16 cnat_port
index_slist_t * cnat_out2in_hash
Definition: cnat_db_v2.c:195
Bitmaps built as vectors of machine words.
struct _spp_api_cnat_v4_show_inside_entry_req spp_api_cnat_v4_show_inside_entry_req_t
void cnat_v4_show_outside_entry_req_t_handler(spp_api_cnat_v4_show_outside_entry_req_t *mp, vlib_main_t *vm)
cnat_nfv9_logging_info_t * cnat_nfv9_logging_info_pool
Definition: cnat_logging.c:93
#define VRF_MAP_ENTRY_EMPTY
Definition: cnat_db.h:506
cnat_syslog_logging_info_t * cnat_syslog_logging_info_pool
Definition: cnat_syslog.c:38
u16 nsessions
Definition: cnat_db.h:266
#define NAT44_COMMON_STATS
Definition: cnat_db.h:690
#define V4_DEF_ICMP_S_TO
Definition: cnat_config.h:29
unsigned short u16
Definition: types.h:57
u8 syslog_logging_policy
Definition: cnat_db.h:441
cnat_vrfmap_t * cnat_map_by_vrf
Definition: cnat_db_v2.c:218
cnat_user_db_entry_t * cnat_user_db_lookup_entry(cnat_db_key_bucket_t *uki)
Definition: cnat_db_v2.c:603
#define CNAT_MAIN_HASH_MASK
Definition: cnat_db.h:56
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
void cnat_table_entry_fill_map(u32 start_addr, u32 end_addr, cnat_portmap_v2_t **port_map_holder)
Definition: cnat_db_v2.c:87
u16 udp_act_session_timeout
Definition: cnat_config.c:29
u32 out2in_pkts
Definition: cnat_db.h:207
u32 num_entries
u64 in2out_drops_resource_depletion
Definition: cnat_db_v2.c:230
#define PLATFORM_MAX_TRANSLATION_ENTRIES
u16 flags
#define EMPTY
Definition: index_list.h:24
#define CNAT_TRANSLATION_ENTRY_ALL
#define CNAT_DB_FLAG_UDP_ACTIVE
Definition: cnat_db.h:163
#define CNAT_V4_GET_HASH(key64, hash, mask)
Definition: cnat_db.h:536
void cnat_set_vrf_params_with_default(cnat_vrfmap_t *my_vrfmap, u32 i_vrf, u32 i_vrf_id)
u16 src_port
#define CNAT_TRANSLATION_ENTRY_DYNAMIC
cnat_key_t in2out_key
Definition: cnat_db.h:201
u8 protocol
CLIB vectors are ubiquitous dynamically resized arrays with by user defined "headers".
#define S_WAO
Definition: cnat_db.h:413
u32 in2out_pkts
Definition: cnat_db.h:210
#define CNAT_MAX_ADDR_POOL_SIZE
Definition: cnat_cli.h:122