FD.io VPP  v17.01.1-3-gc6833f8
Vector Packet Processing
cnat_util.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * cnat_util.c - cnat helpers
4  *
5  * Copyright (c) 2009-2014 Cisco and/or its affiliates.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *------------------------------------------------------------------
18  */
19 
20 #include <vlib/vlib.h>
21 #include <vnet/vnet.h>
22 #include <vppinfra/vec.h>
23 #include <vppinfra/bitmap.h>
24 #include <vppinfra/hash.h>
25 #include <vppinfra/pool.h>
26 #include <vppinfra/clib.h>
27 #include <vppinfra/error.h>
28 
29 #include "tcp_header_definitions.h"
30 
31 #if 0
32 void spp_api_cnat_v4_config_dummy_t_handler
33 (spp_api_cnat_v4_config_dummy_t *mp);
34 
35 void spp_api_cnat_v4_config_dummy_max_t_handler
36 (spp_api_cnat_v4_config_dummy_max_t *mp);
37 
38 void spp_api_cnat_v4_config_icmp_timeout_t_handler
39 (spp_api_cnat_v4_config_icmp_timeout_t *mp);
40 
41 void spp_api_cnat_clear_db_request_t_handler
42 (spp_api_cnat_clear_db_request_t *mp);
43 
44 void spp_api_cnat_v4_debug_global_t_handler
45 (spp_api_cnat_v4_debug_global_t *mp);
46 
47 void spp_api_cnat_v4_show_outside_entry_req_t_handler
49 
50 void spp_api_cnat_v4_show_inside_entry_req_t_handler
52 
53 void spp_api_cnat_show_statistics_summary_req_t_handler
54 (spp_api_cnat_show_statistics_summary_req_t *mp);
55 
56 void cnat_db_create_db_entries_cmd (int argc, unsigned long *argv)
57 {
58  int i, j ;
59  int nusers = 3000;
60 
61  cnat_db_key_bucket_t key_info;
63  cnat_gen_icmp_info info;
64  cnat_key_t dest_info_dummy;
65 
66  memset(&dest_info_dummy, 0, sizeof(cnat_key_t));
67  printf ("Create %d users, 100 translations each...\n", nusers);
68 
69  for (i = 0; i < nusers; i++) {
70  for (j = 0; j < 100; j++) {
71 
72  key_info.k.k.vrf = CNAT_TCP | (1 & CNAT_VRF_MASK);
73  key_info.k.k.ipv4 = 0x0c000001+i;
74  key_info.k.k.port = 1024+j;
75 
76  db = cnat_get_main_db_entry_v2(&key_info, PORT_SINGLE,
77  PORT_TYPE_DYNAMIC, &info, &dest_info_dummy);
78 
79  if (db == 0) {
80  printf ("OOPS: cnat_main_db_create failed users %d trans %d\n", i, j);
81  return; /*jli*/
82  }
83 
85 
86  }
87  }
88 }
89 
90 void db_test_clear (int argc, unsigned long *argv)
91 {
92  spp_api_cnat_clear_db_request_t mp;
93 
94  mp.wildcard = argv[0];
95  mp.protocol = argv[1];
96  mp.port_num = argv[2];
97  mp.inside_vrf = argv[3];
98  mp.ip_addr = argv[4];
99  spp_api_cnat_clear_db_request_t_handler(&mp);
100 }
101 
102 /* test code*/
103 void cnat_db_test_show (int argc, unsigned long *argv)
104 {
105 
108 
109  if (argc > 1) {
110  if (argc != 7) {
111  printf("Usage: db test show dec((which)) dec((vrf)) dec((proto)) dec((ip)) dec((start_port)) dec((end_port)) dec((flags))\n");
112  return;
113  }
114 
115  mp1[0].vrf_id = argv[1];
116  mp1[0].protocol = argv[2];;
117  mp1[0].ipv4_addr = argv[3];
118  mp1[0].start_port = argv[4];
119  mp1[0].end_port = argv[5];
120  mp1[0].flags = argv[6];
121  mp1[0].all_entries = 0;
122 
123  if (argv[0] == 1) {
124  spp_api_cnat_v4_show_inside_entry_req_t_handler (&(mp1[0]));
125  } else {
126  spp_api_cnat_v4_show_outside_entry_req_t_handler (&(mp2[0]));
127  }
128 
129  return;
130  } else {
131  printf("inside entries \n");
132  mp1[0].ipv4_addr = 0x016994CA;
133  mp1[0].vrf_id = 1;
134  mp1[0].all_entries = 0;
135  mp1[0].start_port = 32765;
136  mp1[0].end_port = 65535;
137  mp1[0].protocol = 2;
138  mp1[0].flags = 3;
139 
140  spp_api_cnat_v4_show_inside_entry_req_t_handler (&(mp1[0]));
141 
142  mp2[0].ipv4_addr = 0x640200c1;
143  mp2[0].vrf_id = 0;
144  mp2[0].start_port = 1025;
145  mp2[0].end_port = 62235;
146  mp2[0].protocol = 2;
147  mp2[0].flags = 3;
148 
149  spp_api_cnat_v4_show_outside_entry_req_t_handler (&(mp2[0]));
150  }
151 
152 #if 1
153  {
154  spp_api_cnat_stats_node_mapping_t mp3[20000];
155  spp_api_cnat_stats_counter_mapping_t mp4[20000];
156  spp_api_cnat_stats_counter_values_t mp5[23000];
157 
158  mp3[0].rc = 0;
159  spp_api_cnat_stats_node_mapping_t_handler (&mp3);
160  mp4[0].rc = 0;
161  spp_api_cnat_stats_counter_mapping_t_handler (&mp4);
162 
163  mp5[0].flag = 1;
164  spp_api_cnat_stats_counter_values_t_handler(&mp5);
165  }
166 #endif
167 
168 #if 0
169  mp1.ipv4_addr = 0x0A010102;
170  mp1.vrf_id = 1;
171  mp1.all_entries = 1;
172  mp1.protocol = 1;
173 
174  spp_api_cnat_v4_show_inside_entry_req_t_handler (&mp1);
175 
176 
177  mp1.ipv4_addr = 0x0A010103;
178  mp1.vrf_id = 1;
179  mp1.all_entries = 1;
180  mp1.protocol = 2;
181 
182  spp_api_cnat_v4_show_inside_entry_req_t_handler (&mp1);
183 
184  mp6[0].inside_vrf_id = 1;
185  mp6[0].start_ipv4_address = 0x64020001;
186  mp6[0].end_ipv4_address = 0x64020101;
187  mp6[0].free_addr = 0;
188  mp6[0].flags = CNAT_TRANSLATION_ENTRY_STATIC;
189 
190  spp_api_cnat_v4_show_freeUsed_entry_req_t_handler(&mp6);
191 
192 #endif
193  printf("returned here");
194 
195  return;
196 }
197 
198 
199 
200 void cnat_db_clear_all_entries (int argc, unsigned long *argv)
201 {
203  u32 index;
204 
206 
207  for(index = 0; index < vec_len(cnat_main_db); index++) {
208 
209  if ( !clib_bitmap_get(p->free_bitmap, index)) {
210 
211  db = cnat_main_db + index;
213 
214  }
215  }
216 
217 }
218 
219 
220 void spp_log_cmd (int argc, unsigned long *argv)
221 {
222  u16 num_traces;
223  u16 error_code;
224  u16 num_args;
225  u32 arg[7];
226  u8 i;
227 
228  num_traces = argv[0];
229 
230  for (i = 0; i < num_traces; i++) {
231  error_code = argv[1 + 4*i];
232  num_args = argv[2 + 4*i];
233  arg[0] = argv[3 + 4*i];
234  arg[1] = argv[4 + 4*i];
235 
236  spp_printf(error_code, num_args, arg);
237  }
238 }
239 
240 
241 void cnat_db_create_random_entries (int argc, unsigned long *argv)
242 {
243 
244  platform_cnat_db_create_random_entries();
245 }
246 
247 #define MAX_DEPTH 10
248 
249 void show_user_db_hash_chain_len() {
250 
251  u32 max_len, len, n, i, max_idx, index, used;
252  cnat_user_db_entry_t * udb;
253  u32 hash_depth[MAX_DEPTH];
254 
255  memset(hash_depth, 0, sizeof(u32)*MAX_DEPTH);
256 
257  n = vec_len(cnat_user_hash);
258 
259  used = 0;
260  max_len = 0;
261  for(i=0;i<n;i++) {
262 
263  index = cnat_user_hash[i].next;
264 
265  len = 0;
266  if (index != EMPTY) used++;
267 
268  while (index != EMPTY) {
269  len++ ;
270  udb = cnat_user_db + index;
271  index = udb->user_hash.next;
272  }
273 
274  if(len < (MAX_DEPTH-1) ) {
275  hash_depth[len]++;
276  } else {
277  hash_depth[MAX_DEPTH-1]++;
278  }
279 
280  if (max_len < len) {
281  max_len = len;
282  max_idx = cnat_user_hash[i].next;
283  }
284  }
285 
286  printf("Max user db hash length %u, total buckets %u used %u\n",
287  max_len, n, used);
288 
289  for( i=1; i<(MAX_DEPTH - 1); i++) {
290  printf("Hash chain len %02d, entries count %d\n", i, hash_depth[i]);
291  }
292 
293  printf("Hash chain len >%02d, entries count %d\n",
294  MAX_DEPTH-1, hash_depth[MAX_DEPTH-1]);
295 
296 }
297 
298 void show_main_db_hash_chain_len() {
299 
300  u32 max_len, len, n, i, max_idx, index, used;
302  u32 hash_depth[MAX_DEPTH];
303 
304  memset(hash_depth, 0, sizeof(u32)*MAX_DEPTH);
305 
307 
308  used = 0;
309  max_len = 0;
310  for(i=0;i<n;i++) {
311 
312  index = cnat_in2out_hash[i].next;
313 
314  len = 0;
315  if (index != EMPTY) used++;
316 
317  while (index != EMPTY) {
318  len++ ;
319  db = cnat_main_db + index;
320  index = db->in2out_hash.next;
321  }
322 
323  if(len < (MAX_DEPTH-1) ) {
324  hash_depth[len]++;
325  } else {
326  hash_depth[MAX_DEPTH-1]++;
327  }
328 
329  if (max_len < len) {
330  max_len = len;
331  max_idx = cnat_in2out_hash[i].next;
332  }
333  }
334 
335  printf("Max main db I2O hash length %u, total buckets %u used %u\n",
336  max_len, n, used);
337 
338  for( i=1; i<(MAX_DEPTH - 1); i++) {
339  printf("Hash chain len %02d, entries count %d\n", i, hash_depth[i]);
340  }
341 
342  printf("Hash chain len >%02d, entries count %d\n",
343  MAX_DEPTH-1, hash_depth[MAX_DEPTH-1]);
344 
345 
346  memset(hash_depth, 0, sizeof(u32)*MAX_DEPTH);
347 
349  used = 0;
350  max_len = 0;
351 
352  for(i=0;i<n;i++) {
353 
354  index = cnat_out2in_hash[i].next;
355  len = 0;
356 
357  if (index != EMPTY) used++;
358 
359  while (index != EMPTY) {
360  len++ ;
361  db = cnat_main_db + index;
362  index = db->out2in_hash.next;
363  }
364 
365  if(len < (MAX_DEPTH-1) ) {
366  hash_depth[len]++;
367  } else {
368  hash_depth[MAX_DEPTH-1]++;
369  }
370 
371  if (max_len < len) {
372  max_len = len;
373  max_idx = cnat_in2out_hash[i].next;
374  }
375  }
376 
377  printf("Max main db O2I hash length %u, total buckets %u used %u\n",
378  max_len, n, used);
379 
380  for( i=1; i<(MAX_DEPTH - 1); i++) {
381  printf("Hash chain len %02d, entries count %d\n", i, hash_depth[i]);
382  }
383 
384  printf("Hash chain len >%02d, entries count %d\n",
385  MAX_DEPTH-1, hash_depth[MAX_DEPTH-1]);
386 
387 
388 }
389 
390 u32 db_free_entry (void * p) {
391 
392  pool_header_t * h;
393  u32 free;
394 
395  h = pool_header(p);
396 
397  free = p == 0 ? 0: vec_len(h->free_indices);
398 
399  return free;
400 }
401 
402 void cnat_db_summary (int argc, unsigned long *argv) {
403 
404  PLATFORM_DEBUG_PRINT("\n-----------------------------------------");
405  PLATFORM_DEBUG_PRINT("\nSummary DB");
406  PLATFORM_DEBUG_PRINT("\n-----------------------------------------\n");
407  u32 count1, count2, i;
408 #ifndef NO_NAT64_DEF
409  extern void nat64_session_db_summary();
410 #endif
411  /* main db active entry count*/
412  count1 = vec_len(cnat_main_db);
413  count2 = db_free_entry(cnat_main_db);
414 
415  PLATFORM_DEBUG_PRINT("main db entries: total %u, active %u, free %u\n", count1, count1 - count2, count2);
416 
417  /* user db active entry count */
418  count1 = vec_len(cnat_user_db);
419  count2 = db_free_entry(cnat_user_db);
420 
421  PLATFORM_DEBUG_PRINT("user db entries: total %u, active %u, free %u\n", count1, count1 - count2, count2);
422 
423 
424  /* user db active entry count */
425 #ifndef NO_NAT64_DEF
426  nat64_session_db_summary();
427 #endif
428 
429  /* main db hash i2o o2i usage count */
430  count1 = 0;
431  count2 = 0;
432 
433  for (i=0; i< CNAT_MAIN_HASH_SIZE; i++) {
434 
435  if(cnat_in2out_hash[i].next != ~0) count1++;
436  if(cnat_out2in_hash[i].next != ~0) count2++;
437 
438  }
439 
440  PLATFORM_DEBUG_PRINT("main hash in2out: total %6u, used %u (%.2f%%)\n",
441  CNAT_MAIN_HASH_SIZE, count1,
442  (100.0*count1)/CNAT_MAIN_HASH_SIZE);
443 
444  PLATFORM_DEBUG_PRINT("main hash out2in: total %6u, used %u (%.2f%%)\n",
445  CNAT_MAIN_HASH_SIZE, count2,
446  (100.0 * count1)/CNAT_MAIN_HASH_SIZE);
447 
448  /* use db hashing usage count */
449 
450  count1 = 0;
451 
452  for (i=0; i< CNAT_USER_HASH_SIZE; i++) {
453  if(cnat_user_hash[i].next != ~0) count1++;
454  }
455 
456  PLATFORM_DEBUG_PRINT("user db hash: total %6u, used %u (%.2f%%)\n",
457  CNAT_USER_HASH_SIZE, count1,
458  (100.0*count1)/CNAT_USER_HASH_SIZE);
459 
460  PLATFORM_DEBUG_PRINT("\nNull pointer exceptions:\n");
461  PLATFORM_DEBUG_PRINT("packet_pool: null enq : %10u, null deq : %10u\n",null_enq_pkt, null_deq_pkt);
462  PLATFORM_DEBUG_PRINT("ctx_pool : null enq : %10u, null deq : %10u\n",null_enq_ctx, null_deq_ctx);
463  PLATFORM_DEBUG_PRINT("wqe_pool : null enq : %10u, null deq : %10u\n",null_enq_wqe, null_deq_wqe);
464 
465  PLATFORM_DEBUG_PRINT("\nReceived Packet Errors on SPI:\n");
466  PLATFORM_DEBUG_PRINT("rcv_pkt_errs: %10u\n",rcv_pkt_errs);
467 
468  PLATFORM_DEBUG_PRINT("\nctx/sf allocation failure errors: \n");
469 #ifndef CGN_PERF_SCALE_DEBUG
470  PLATFORM_DEBUG_PRINT("Warning: collection of error counts <with timestamp> is disabled.\n");
471  PLATFORM_DEBUG_PRINT("sf alloc errors: %10u, ctx alloc errors: %10u\n",sf_alloc_errs,ctx_alloc_errs);
472 #else
473  for(i=0;i<COUNTER_BUFFER_SIZE;i++)
474  PLATFORM_DEBUG_PRINT("<%2d>Timestamp <sec>: %10u, sf errors: %10u, ctx errors: %10u\n",\
475  i,err_cnt_arr[i].timestamp,\
476  err_cnt_arr[i].sf_error_counter, \
477  err_cnt_arr[i].ctx_error_counter);
478 #endif
479 }
480 
481 void cnat_db_hash_summary (int argc, unsigned long *argv) {
482 
483  show_main_db_hash_chain_len();
484 
485  show_user_db_hash_chain_len();
486 }
487 
488 /*
489  * cnat_port_alloc
490  * This function is now deprecated...
491  *
492  */
493 #ifdef LB_PORT
494 int cnat_port_alloc (cnat_portmap_t *cnat_portmap, u16 *portmap_inuse,
495  int cnat_instance,
496  port_alloc_t atype, port_pair_t ptype,
497  int *index, u32 *ipv4_address, u16 *base_port)
498 #else
499 int cnat_port_alloc (cnat_portmap_t *cnat_portmap, u16 *portmap_inuse,
500  port_alloc_t atype, port_pair_t ptype,
501  int *index, u32 *ipv4_address, u16 *base_port)
502 #endif
503 {
504 
505  return (0);
506 }
507 
508 /*
509  * cnat_port_free
510  * This function is now deprecated...
511  *
512  */
513 #ifdef LB_PORT
514 void cnat_port_free (cnat_portmap_t *cnat_portmap, u16 *portmap_inuse,
515  int instance, int index, port_pair_t ptype, u16 base_port)
516 #else
517 void cnat_port_free (cnat_portmap_t *cnat_portmap, u16 *portmap_inuse,
518  int index, port_pair_t ptype, u16 base_port)
519 #endif
520 {
521 }
522 
523 void spp_api_cnat_port_allocate_t_handler(spp_api_cnat_port_allocate_t *mp)
524 {
525  int i, j, k1, k2;
526  int pm_index;
527  u32 ipv4_address;
528  u16 aport;
529  int rv;
530  char *out1, *out2, *out_f;
531  port_alloc_t pt1, pt2;
532  cnat_portmap_t *pm = 0;
533  u16 *pm_inuse = 0;
534  u32 *firstp =0;
535  u32 nr_ports =0;
536  u32 nodd_ports = 0;
537  u32 neven_ports = 0;
538 #ifdef LB_PORT
539  u32 my_instance = 1;
540 #endif
541  char out_r[12] = "allocated-r";
542  char out_o[12] = "allocated-o";
543  char out_e[12] = "allocated-e";
544 
545 
546  /*
547  * this command is run after db create portmap
548  * vrf is hardcode to 1
549  */
550 
551  /* Already have a portmap vector for this VRF? */
552  for (i = 0; i < vec_len(cnat_portmap_indices_by_vrf); i++) {
553  if (cnat_portmap_indices_by_vrf[i] == mp->vrf) {
554  pm = cnat_portmaps[i];
555  pm_inuse = cnat_portmaps_inuse[i];
556  goto found_portmaps;
557  }
558  }
559 
560  printf("need to run db create portmaps first 0x%d\n",
562  return;
563 
564 found_portmaps:
565  nr_ports = mp->nr_ports;
566  nodd_ports = mp->nodd_ports;
567  neven_ports = mp->neven_ports;
568 
569  if ((nr_ports + nodd_ports + neven_ports ) > (PORTS_PER_ADDR)) {
570  printf("invalid port# nr_ports %d + odd %d + even %d "
571  "should be less than 200 \n", nr_ports, nodd_ports, neven_ports);
572  return;
573  }
574 
575  /*
576  * first port
577  */
578  firstp = nr_ports ? (&nr_ports) : (nodd_ports ? (&nodd_ports) : (&neven_ports));
579  if (!(*firstp)) {
580  printf("invalid port# nr_ports %d odd %d even %d ",
581  nr_ports, nodd_ports, neven_ports);
582  }
583  out_f = nr_ports ? out_r : (nodd_ports ? out_o : out_e);
584 
585 #ifdef LB_PORT
586  rv = cnat_port_alloc (pm, pm_inuse, my_instance,
588  &pm_index, &ipv4_address, &aport);
589 #else
590  rv = cnat_port_alloc (pm, pm_inuse,
592  &pm_index, &ipv4_address, &aport);
593 #endif
594 
595  if (!rv) {
596  printf("failed-o\n");
597  return;
598  }
599  printf("%s %8d %10x %8d\n", out_f,
600  pm_index, ipv4_address, aport);
601 
602  (*firstp)--;
603 
604  for (i=0; i < nr_ports; i++) {
605 #ifdef LB_PORT
606  rv = cnat_port_alloc (pm, pm_inuse, my_instance,
608  &pm_index, &ipv4_address, &aport);
609 #else
610  rv = cnat_port_alloc (pm, pm_inuse,
612  &pm_index, &ipv4_address, &aport);
613 #endif
614  if (rv) {
615  printf("%s %8d %10x %8d\n", out_r,
616  pm_index, ipv4_address, aport);
617  } else {
618  printf("%s failed\n", out_r);
619  return;
620  }
621  }
622 
623  if (nodd_ports > neven_ports) {
624  k1 = nodd_ports;
625  k2 = neven_ports;
626  pt1 = PORT_S_ODD;
627  pt2 = PORT_S_EVEN;
628  out1 = out_o;
629  out2 = out_e;
630  } else {
631  k1= neven_ports;
632  pt1 = PORT_S_EVEN;
633  k2 = nodd_ports;
634  pt2 = PORT_S_ODD;
635  out1 = out_e;
636  out2 = out_o;
637  }
638 
639  j = 0;
640  for (i=0; i < k1; i++) {
641 #ifdef LB_PORT
642  rv = cnat_port_alloc (pm, pm_inuse, my_instance,
643  PORT_ALLOC_DIRECTED, pt1,
644  &pm_index, &ipv4_address, &aport);
645 #else
646  rv = cnat_port_alloc (pm, pm_inuse,
647  PORT_ALLOC_DIRECTED, pt1,
648  &pm_index, &ipv4_address, &aport);
649 #endif
650  if (rv) {
651  printf("%s %8d %10x %8d\n", out1,
652  pm_index, ipv4_address, aport);
653  } else {
654  printf("%s failed\n", out1);
655  return;
656  }
657 
658  if (j < k2) {
659 #ifdef LB_PORT
660  rv = cnat_port_alloc (pm, pm_inuse, my_instance,
661  PORT_ALLOC_DIRECTED, pt2,
662  &pm_index, &ipv4_address, &aport);
663 #else
664  rv = cnat_port_alloc (pm, pm_inuse,
665  PORT_ALLOC_DIRECTED, pt2,
666  &pm_index, &ipv4_address, &aport);
667 #endif
668 
669  if (rv) {
670  printf("%s %8d %10x %8d\n", out2,
671  pm_index, ipv4_address, aport);
672  j++;
673  } else {
674  printf("%s failed\n", __FUNCTION__);
675  return;
676  }
677  }
678  }
679 }
680 
681 void cnat_db_summary_stats (int argc, unsigned long *argv)
682 {
683  spp_api_cnat_show_statistics_summary_req_t mp[50000];
684 
685  spp_api_cnat_show_statistics_summary_req_t_handler(&(mp[0]));
686 }
687 
688 void cnat_debug_global_test (int argc, unsigned long *argv)
689 {
690  spp_api_cnat_v4_debug_global_t *mp;
691  spp_api_cnat_v4_config_dummy_t mp1;
692  spp_api_cnat_v4_config_icmp_timeout_t mp2[10];
693 
694  mp = spp_msg_api_alloc (sizeof (*mp));
695  memset(mp, 0, sizeof (*mp));
696 
697 
698  mp->_spp_msg_id = SPP_API_CNAT_V4_DEBUG_GLOBAL;
699  mp->debug_flag = argv[0];
700 
701  platform_send_msg(mp);
702 
703  mp2[0].default_value = 3;
704 
705  spp_api_cnat_v4_config_dummy_t_handler(&mp1);
706  spp_api_cnat_v4_config_icmp_timeout_t_handler(&(mp2[0]));
707 }
708 
709 void cnat_debug_inside_test (int argc, unsigned long *argv)
710 {
711 
712  spp_api_cnat_v4_debug_in2out_private_addr_t *mp;
713 
714  mp = spp_msg_api_alloc (sizeof (*mp));
715  memset(mp, 0, sizeof (*mp));
716 
717 
718  mp->_spp_msg_id = SPP_API_CNAT_V4_DEBUG_IN2OUT_PRIVATE_ADDR;
719 
720  mp->start_addr = spp_host_to_net_byte_order_32(argv[0]);
721  mp->end_addr = spp_host_to_net_byte_order_32(argv[1]);
722  mp->i_vrf = spp_host_to_net_byte_order_16(argv[2]);
723  mp->debug_flag = spp_host_to_net_byte_order_32(argv[3]);
724 
725  platform_send_msg(mp);
726 }
727 
728 void cnat_config_ports_user (int argc, unsigned long *argv)
729 {
730  spp_api_cnat_v4_config_port_limit_t *mp;
731 
732  mp = spp_msg_api_alloc (sizeof (*mp));
733  memset(mp, 0, sizeof (*mp));
734 
735 
736  mp->_spp_msg_id = SPP_API_CNAT_V4_CONFIG_PORT_LIMIT;
737 
738  mp->port_limit = spp_host_to_net_byte_order_16(argv[0]);
739 
740  platform_send_msg(mp);
741 
742 }
743 
744 void cnat_debug_outside_test (int argc, unsigned long *argv)
745 {
746 
747  spp_api_cnat_v4_debug_out2in_public_addr_t *mp;
748 
749  mp = spp_msg_api_alloc (sizeof (*mp));
750  memset(mp, 0, sizeof (*mp));
751 
752 
753  mp->_spp_msg_id = SPP_API_CNAT_V4_DEBUG_OUT2IN_PUBLIC_ADDR;
754 
755  mp->start_addr = spp_host_to_net_byte_order_32(argv[0]);
756  mp->end_addr = spp_host_to_net_byte_order_32(argv[1]);
757  mp->o_vrf = spp_host_to_net_byte_order_16(argv[2]);
758  mp->debug_flag = spp_host_to_net_byte_order_32(argv[3]);
759 
760  platform_send_msg(mp);
761 }
762 
763 void cnat_debug_udp_dump (int argc, unsigned long *argv)
764 {
765 
766  spp_api_cnat_p2mp_debug_request_t *mp;
767 
768  mp = spp_msg_api_alloc (sizeof (*mp));
769  memset(mp, 0, sizeof (*mp));
770 
771 
772  mp->_spp_msg_id = SPP_API_CNAT_P2MP_DEBUG_REQUEST;
773  mp->dump_type =
774  spp_host_to_net_byte_order_16(CNAT_DEBUG_GENERIC_COMMAND_DEBUG_FLAGS);
775 
776  if (spp_host_to_net_byte_order_32(argv[0]) == 1) {
777  mp->param[0] = spp_host_to_net_byte_order_32(
779  } else {
780  mp->param[0] = spp_host_to_net_byte_order_32(
782  }
783  mp->param[1] = spp_host_to_net_byte_order_32(argv[1]);
784 
785  platform_send_msg(mp);
786 
787 
788 
789 }
790 
791 void cnat_debug_udp_crc (int argc, unsigned long *argv)
792 {
793  spp_api_cnat_p2mp_debug_request_t *mp;
794 
795  mp = spp_msg_api_alloc (sizeof (*mp));
796  memset(mp, 0, sizeof (*mp));
797 
798 
799  mp->_spp_msg_id = SPP_API_CNAT_P2MP_DEBUG_REQUEST;
800  mp->dump_type =
801  spp_host_to_net_byte_order_16(CNAT_DEBUG_GENERIC_COMMAND_DEBUG_FLAGS);
802 
803  if (spp_host_to_net_byte_order_32(argv[0]) == 1) {
804  mp->param[0] = spp_host_to_net_byte_order_32(
806  } else {
807  mp->param[0] = spp_host_to_net_byte_order_32(
809  }
810  mp->param[1] = spp_host_to_net_byte_order_32(argv[1]);
811 
812  platform_send_msg(mp);
813 
814 }
815 
816 void cnat_db_allocate_port_cmd (int argc, unsigned long *argv)
817 {
818  spp_api_cnat_port_allocate_t *mp;
819 
820 
821  if (!argc) {
822  printf("no port# defined\n");
823  return;
824  }
825 
826  if ( argc < 3) {
827  printf("no port# defined\n");
828  return;
829  }
830 
831  if ((argc == 3) && (argv[0] == 0) && (argv[1] == 0) && (argv[2] == 0)) {
832  printf("no port# defined\n");
833  return;
834  }
835 
836  mp = spp_msg_api_alloc (sizeof (*mp));
837  memset(mp, 0, sizeof (*mp));
838 
839 
840  mp->_spp_msg_id = SPP_API_CNAT_PORT_ALLOCATE;
841  mp->nr_ports = argv[0];
842  mp->nodd_ports = argv[1];
843  mp->neven_ports = argv[2];
844  mp->vrf = 1;
845 
846  platform_send_msg(mp);
847 }
848 
849 
850 void spp_api_cnat_port_clear_t_handler(spp_api_cnat_port_clear_t *mp)
851 {
852  u32 i;
853  cnat_portmap_t *pm = 0;
854  u16 *pm_inuse = 0;
855 #ifdef LB_PORT
856  u32 my_instance = 1;
857 #endif
858 
859 
860  /*
861  * this command is run after db create port
862  * vrf is hardcode to 1
863  */
864 
865  /* Already have a portmap vector for this VRF? */
866  for (i = 0; i < vec_len(cnat_portmap_indices_by_vrf); i++) {
867  if (cnat_portmap_indices_by_vrf[i] == mp->vrf) {
868  pm = cnat_portmaps[i];
869  pm_inuse = cnat_portmaps_inuse[i];
870  goto found_portmaps;
871  }
872  }
873 
874  printf("portmap is not created 0x%d\n",
876  return;
877 
878 found_portmaps:
879  if (mp->pm_index >= vec_len(pm)) {
880  printf("invalid port_index 0x%d >= 0x%d\n",
881  mp->pm_index, vec_len(pm));
882  return;
883  }
884 
885 #ifdef LB_PORT
886  cnat_port_free(pm, pm_inuse, my_instance,
887  mp->pm_index, PORT_SINGLE, mp->port);
888 #else
889  cnat_port_free(pm, pm_inuse,
890  mp->pm_index, PORT_SINGLE, mp->port);
891 #endif
892  printf("\n pm_index %d port %d is deleted\n", mp->pm_index, mp->port);
893 }
894 
895 
896 
897 void cnat_db_clear_port_cmd (int argc, unsigned long *argv)
898 {
899  spp_api_cnat_port_clear_t *mp;
900 
901  if (!argc) {
902  printf("no port# defined\n");
903  return;
904  }
905 
906  if ( argc < 2 ) {
907  printf("no port# defined\n");
908  return;
909  }
910 
911  if (argc > 2) {
912  printf("too many port# defined\n");
913  return;
914  }
915 
916  mp = spp_msg_api_alloc (sizeof (*mp));
917  memset(mp, 0, sizeof (*mp));
918 
919 
920  mp->_spp_msg_id = SPP_API_CNAT_PORT_CLEAR;
921  mp->pm_index = argv[0];
922  mp->port = argv[1];
923  mp->vrf = 1;
924 
925  platform_send_msg(mp);
926 }
927 
928 
929 void spp_api_cnat_v4_add_vrf_map_t_handler
931 
932 void spp_api_cnat_v4_del_vrf_map_t_handler
933 (spp_api_cnat_v4_del_vrf_map_t *mp);
934 
935 void spp_api_cnat_v4_add_static_port_t_handler
936 (spp_api_cnat_v4_add_static_port_t *mp);
937 
938 void spp_api_cnat_v4_del_static_port_t_handler
939 (spp_api_cnat_v4_del_static_port_t *mp);
940 
941 
942 void cnat_db_create_vrfmap_cmd (int argc, unsigned long *argv)
943 {
945 
946  if ((argc != 4)) {
947  printf("need right input\n");
948  return;
949  }
950 
951  mp = spp_msg_api_alloc (sizeof (*mp));
952  memset(mp, 0, sizeof (*mp));
953  mp->_spp_msg_id = SPP_API_CNAT_V4_ADD_VRF_MAP;
954  mp->i_vrf = spp_host_to_net_byte_order_16(argv[0]);
955  mp->o_vrf = spp_host_to_net_byte_order_16(argv[1]);
956  mp->start_addr[0] = spp_host_to_net_byte_order_32(argv[2]);
957  mp->end_addr[0] = spp_host_to_net_byte_order_32(argv[3]);
958 
959  /*
960  * Some hardcoded values for the vrf ids
961  */
962  mp->i_vrf_id = spp_host_to_net_byte_order_32(0x00000100 | mp->i_vrf);
963  mp->o_vrf_id = spp_host_to_net_byte_order_32(0x00000200 | mp->o_vrf);
964 
965  platform_send_msg(mp);
966 }
967 
968 
969 void cnat_db_delete_vrfmap_cmd (int argc, unsigned long *argv)
970 {
971  spp_api_cnat_v4_del_vrf_map_t *mp;
972 
973  if (argc != 4) {
974  printf("need right input\n");
975  return;
976  }
977 
978  mp = spp_msg_api_alloc (sizeof (*mp));
979  memset(mp, 0, sizeof (*mp));
980  mp->_spp_msg_id = SPP_API_CNAT_V4_DEL_VRF_MAP;
981  mp->i_vrf = spp_host_to_net_byte_order_16(argv[0]);
982  mp->start_addr[0] = spp_host_to_net_byte_order_32(argv[2]);
983  mp->end_addr[0] = spp_host_to_net_byte_order_32(argv[3]);
984 
985  platform_send_msg(mp);
986 }
987 
988 void cnat_db_add_svi_cmd (int argc, unsigned long *argv)
989 {
990  spp_api_cnat_config_svi_params_t *mp;
991 
992  if (argc != 3) {
993  printf("need right input\n");
994  return;
995  }
996 
997 
998  mp = spp_msg_api_alloc (sizeof (*mp));
999  memset(mp, 0, sizeof (*mp));
1000  mp->_spp_msg_id = SPP_API_CNAT_CONFIG_SVI_PARAMS;
1001  mp->uidb_index = spp_host_to_net_byte_order_16(argv[1]);
1002  mp->svi_ipv4_addr = spp_host_to_net_byte_order_32(argv[2]);
1003  platform_send_msg(mp);
1004  return;
1005 }
1006 
1007 
1008 
1009 void spp_api_cnat_port_create_t_handler(spp_api_cnat_port_create_t *mp)
1010 {
1011  int i, j, k1, k2;
1012  int my_index;
1013  u32 ipv4_address;
1014  u16 aport;
1015  u32 pm_len =0;
1016  cnat_errno_t rv;
1017  u16 i_vrf;
1018  char *out1, *out2, *out_f;
1019  port_alloc_t pt1, pt2;
1020  cnat_vrfmap_t *my_vrfmap;
1021  cnat_portmap_v2_t *pm = 0;
1022  u32 *firstp =0;
1023  u32 nr_ports =0;
1024  u32 nodd_ports = 0;
1025  u32 neven_ports = 0;
1026 #ifdef LB_PORT
1027  u32 my_instance = 1;
1028 #endif
1029  char out_r[12] = "allocated-r";
1030  char out_o[12] = "allocated-o";
1031  char out_e[12] = "allocated-e";
1032 #ifndef NO_BULK_LOGGING
1033  int nfv9_log_req;
1034 #endif
1035 
1036  nr_ports = mp->nr_ports;
1037  nodd_ports = mp->nodd_ports;
1038  neven_ports = mp->neven_ports;
1039  i_vrf = mp->vrf;
1040 
1041  /*
1042  * this command is run after db create vrfmap
1043  * or using vrf id in init function
1044  */
1045  /* Already have a portmap vector for this VRF? */
1046  pool_foreach (my_vrfmap, cnat_map_by_vrf, ({
1047  if ((my_vrfmap->status == S_RUN) &&
1048  (my_vrfmap->i_vrf == i_vrf)) {
1049  pm = my_vrfmap->portmap_list;
1050  pm_len = vec_len(pm);
1051  if (pm_len) {
1052  goto found_portmaps;
1053  }
1054  }
1055  }));
1056 
1057  printf("need to run db create vrfmaps first for this vrf0x%d\n", pm_len);
1058  return;
1059 
1060 found_portmaps:
1061 
1062  if ((nr_ports + nodd_ports + neven_ports ) > (PORTS_PER_ADDR)) {
1063  printf("invalid port# nr_ports %d + odd %d + even %d "
1064  "should be less than 200 \n", nr_ports, nodd_ports, neven_ports);
1065  return;
1066  }
1067 
1068  /*
1069  * first port
1070  */
1071  firstp = nr_ports ? (&nr_ports) : (nodd_ports ? (&nodd_ports) : (&neven_ports));
1072  if (!(*firstp)) {
1073  printf("invalid port# nr_ports %d odd %d even %d ",
1074  nr_ports, nodd_ports, neven_ports);
1075  }
1076  out_f = nr_ports ? out_r : (nodd_ports ? out_o : out_e);
1077 
1079  &my_index, &ipv4_address, &aport,
1081 #ifndef NO_BULK_LOGGING
1082  , BULKSIZE_FROM_VRFMAP(my_vrfmap),
1083  &nfv9_log_req
1084 #endif
1085  , 0,
1086  &(my_vrfmap->rseed_ip)
1087  );
1088 
1089  if (rv != CNAT_SUCCESS) {
1090  printf("failed-o\n");
1091  return;
1092  }
1093  printf("%s %8d %10x %8d\n", out_f,
1094  my_index, ipv4_address, aport);
1095 
1096  (*firstp)--;
1097 
1098  for (i=0; i < nr_ports; i++) {
1100  &my_index, &ipv4_address, &aport,
1102 #ifndef NO_BULK_LOGGING
1103  , BULKSIZE_FROM_VRFMAP(my_vrfmap),
1104  &nfv9_log_req
1105 #endif
1106  , 0,
1107  &(my_vrfmap->rseed_ip)
1108  );
1109 
1110  if (rv == CNAT_SUCCESS) {
1111  printf("%s %8d %10x %8d\n", out_r,
1112  my_index, ipv4_address, aport);
1113  } else {
1114  printf("%s failed\n", __FUNCTION__);
1115  return;
1116  }
1117  }
1118 
1119  if (nodd_ports > neven_ports) {
1120  k1 = nodd_ports;
1121  k2 = neven_ports;
1122  pt1 = PORT_S_ODD;
1123  pt2 = PORT_S_EVEN;
1124  out1 = out_o;
1125  out2 = out_e;
1126  } else {
1127  k1= neven_ports;
1128  pt1 = PORT_S_EVEN;
1129  k2 = nodd_ports;
1130  pt2 = PORT_S_ODD;
1131  out1 = out_e;
1132  out2 = out_o;
1133  }
1134 
1135  j = 0;
1136  for (i=0; i < k1; i++) {
1138  &my_index, &ipv4_address, &aport,
1140 #ifndef NO_BULK_LOGGING
1141  , BULKSIZE_FROM_VRFMAP(my_vrfmap),
1142  &nfv9_log_req
1143 #endif
1144  , 0,
1145  &(my_vrfmap->rseed_ip)
1146  );
1147 
1148  if (rv == CNAT_SUCCESS) {
1149  printf("%s %8d %10x %8d\n", out1,
1150  my_index, ipv4_address, aport);
1151  } else {
1152  printf("%s failed\n", __FUNCTION__);
1153  return;
1154  }
1155 
1156  if (j < k2) {
1158  &my_index, &ipv4_address, &aport,
1160 #ifndef NO_BULK_LOGGING
1161  , BULKSIZE_FROM_VRFMAP(my_vrfmap),
1162  &nfv9_log_req
1163 #endif
1164  , 0,
1165  &(my_vrfmap->rseed_ip)
1166  );
1167 
1168  if (rv == CNAT_SUCCESS) {
1169  printf("%s %8d %10x %8d\n", out2,
1170  my_index, ipv4_address, aport);
1171  j++;
1172  } else {
1173  printf("%s failed\n", __FUNCTION__);
1174  return;
1175  return;
1176  }
1177  }
1178  }
1179 }
1180 
1181 
1182 void cnat_db_create_port_cmd (int argc, unsigned long *argv)
1183 {
1184  spp_api_cnat_port_create_t *mp;
1185 
1186  if (argc != 4) {
1187  printf("no proper input defined\n");
1188  return;
1189  }
1190 
1191  if ((argv[0] == 0) && (argv[1] == 0) && (argv[2] == 0)) {
1192  printf("no port# defined\n");
1193  return;
1194  }
1195 
1196  mp = spp_msg_api_alloc (sizeof (*mp));
1197  memset(mp, 0, sizeof (*mp));
1198 
1199 
1200  mp->_spp_msg_id = SPP_API_CNAT_PORT_CREATE;
1201  mp->nr_ports = argv[0];
1202  mp->nodd_ports = argv[1];
1203  mp->neven_ports = argv[2];
1204  mp->vrf = argv[3];
1205 
1206  platform_send_msg(mp);
1207 }
1208 
1209 void spp_api_cnat_port_delete_t_handler(spp_api_cnat_port_delete_t *mp)
1210 {
1211  u32 pm_len;
1212  cnat_vrfmap_t *my_vrfmap;
1213  cnat_portmap_v2_t *pm = 0;
1214 
1215  u32 my_index, my_port;
1216  u16 i_vrf;
1217 #ifdef LB_PORT
1218  u32 my_instance = 1;
1219 #endif
1220 
1221  my_index = mp->pm_index;
1222  my_port = mp->port;
1223  i_vrf = mp->vrf;
1224 
1225  /*
1226  * this command is run after db create port
1227  */
1228  pool_foreach (my_vrfmap, cnat_map_by_vrf, ({
1229  if (my_vrfmap->i_vrf == i_vrf) {
1230  pm = my_vrfmap->portmap_list;
1231  pm_len = vec_len(pm);
1232  if (pm_len) {
1233  goto found_portmaps;
1234  }
1235  }
1236  }));
1237 
1238  printf("portmap is not created 0x%d\n",
1240  return;
1241 
1242 found_portmaps:
1243  if (my_index >= pm_len) {
1244  printf("invalid port_index 0x%d >= 0x%d\n",
1245  my_index, pm_len);
1246  return;
1247  }
1248 
1249 #ifdef LB_PORT
1250  cnat_port_free_v2(pm, my_instance,
1251  my_index, PORT_SINGLE, mp->port,cnat_static_port_range);
1252 #else
1253  cnat_port_free_v2(pm, my_index, PORT_SINGLE, mp->port,cnat_static_port_range);
1254 #endif
1255  printf("\n pm_index %d port %d is deleted\n", mp->pm_index, mp->port);
1256 }
1257 
1258 void cnat_db_delete_port_cmd (int argc, unsigned long *argv)
1259 {
1260  spp_api_cnat_port_clear_t *mp;
1261 
1262  if (argc != 3) {
1263  printf("no proper input defined\n");
1264  return;
1265  }
1266 
1267  mp = spp_msg_api_alloc (sizeof (*mp));
1268  memset(mp, 0, sizeof (*mp));
1269 
1270 
1271  mp->_spp_msg_id = SPP_API_CNAT_PORT_DELETE;
1272  mp->pm_index = argv[0];
1273  mp->port = argv[1];
1274  mp->vrf = argv[2];
1275  platform_send_msg(mp);
1276 }
1277 
1278 void cnat_db_create_static_fwd_cmd (int argc, unsigned long *argv)
1279 {
1280  spp_api_cnat_v4_add_static_port_t *mp;
1281 
1282  if (argc != 4) {
1283  printf("need right input\n");
1284  return;
1285  }
1286 
1287  mp = spp_msg_api_alloc (sizeof (*mp));
1288  memset(mp, 0, sizeof (*mp));
1289  mp->_spp_msg_id = SPP_API_CNAT_V4_ADD_STATIC_PORT;
1290  mp->i_vrf = spp_host_to_net_byte_order_16(argv[0]);
1291  mp->i_ip = spp_host_to_net_byte_order_32(argv[1]);
1292  mp->i_port = spp_host_to_net_byte_order_16(argv[2]);
1293  mp->proto = argv[3];
1294 
1295  platform_send_msg(mp);
1296  return;
1297 }
1298 
1299 void cnat_db_create_static_fwd_stby_cmd (int argc, unsigned long *argv)
1300 {
1301  spp_api_cnat_v4_add_static_port_t *mp;
1302 
1303  if (argc != 7) {
1304  printf("need right input\n");
1305  return;
1306  }
1307 
1308  mp = spp_msg_api_alloc (sizeof (*mp));
1309  memset(mp, 0, sizeof (*mp));
1310  mp->_spp_msg_id = SPP_API_CNAT_V4_ADD_STATIC_PORT;
1311  mp->i_vrf = spp_host_to_net_byte_order_16(argv[0]);
1312  mp->i_ip = spp_host_to_net_byte_order_32(argv[1]);
1313  mp->i_port = spp_host_to_net_byte_order_16(argv[2]);
1314  mp->proto = argv[3];
1315  mp->o_vrf_id = spp_host_to_net_byte_order_32(argv[4]);
1316  mp->o_ip = spp_host_to_net_byte_order_32(argv[5]);
1317  mp->o_port = spp_host_to_net_byte_order_16(argv[6]);
1318 
1319 printf("\ni_vrf %d, ip 0x%x, port %d, o_ip, port %d", mp->i_vrf, mp->i_ip, mp->i_port, mp->o_ip, mp->o_port);
1320 
1321  platform_send_msg(mp);
1322  return;
1323 }
1324 
1325 void cnat_db_delete_static_fwd_cmd (int argc, unsigned long *argv)
1326 {
1327  spp_api_cnat_v4_del_static_port_t *mp;
1328 
1329  if (argc != 3) {
1330  printf("need right input\n");
1331  return;
1332  }
1333 
1334  mp = spp_msg_api_alloc (sizeof (*mp));
1335  memset(mp, 0, sizeof (*mp));
1336  mp->_spp_msg_id = SPP_API_CNAT_V4_DEL_STATIC_PORT;
1337  mp->i_vrf = spp_host_to_net_byte_order_16(argv[0]);
1338  mp->i_ip = spp_host_to_net_byte_order_32(argv[1]);
1339  mp->i_port = spp_host_to_net_byte_order_16(argv[2]);
1340 
1341  platform_send_msg(mp);
1342  return;
1343 }
1344 
1345 void cnat_nfv9_create_cmd (int argc, unsigned long *argv)
1346 {
1348 
1349  if (argc < 3) {
1350  printf("nfv9 create i_vrf ip_addr port [refresh_rate] [timeout] [mtu]");
1351  return;
1352  }
1353 
1354  mp = spp_msg_api_alloc (sizeof (*mp));
1355  memset(mp, 0, sizeof (*mp));
1356  mp->_spp_msg_id = SPP_API_CNAT_V4_CONFIG_NFV9_LOGGING;
1357  mp->enable = 1;
1358  mp->i_vrf = spp_host_to_net_byte_order_16(argv[0]);
1359 
1360  mp->ipv4_address = spp_host_to_net_byte_order_32(argv[1]);
1361  mp->port = spp_host_to_net_byte_order_16(argv[2]);
1362 
1363  if (argc > 3) {
1364  mp->refresh_rate = spp_host_to_net_byte_order_16(argv[3]);
1365  mp->timeout_rate = spp_host_to_net_byte_order_16(argv[4]);
1366  mp->path_mtu = spp_host_to_net_byte_order_16(argv[5]);
1367  } else {
1368  mp->refresh_rate = spp_host_to_net_byte_order_16(1000);
1369  mp->timeout_rate = spp_host_to_net_byte_order_16(30);
1370  mp->path_mtu = spp_host_to_net_byte_order_16(1500);
1371  }
1372  platform_send_msg(mp);
1373 }
1374 
1375 void cnat_delete_cgn (int argc, unsigned long *argv)
1376 {
1377  void *mp_send;
1378  spp_api_cnat_del_cgn_t *mp;
1379  u32 mp_size;
1380 
1381  mp_size = sizeof(spp_api_cnat_del_cgn_t);
1382 
1383  mp = spp_msg_api_alloc(mp_size);
1384  memset(mp, 0, mp_size);
1385 
1386  mp->_spp_msg_id = SPP_API_CNAT_DEL_CGN;
1387 
1388  mp_send = mp;
1389 
1390  platform_send_msg(mp);
1391 }
1392 
1393 void cnat_debug_global_all (int argc, unsigned long *argv)
1394 {
1395  spp_api_cnat_v4_debug_global_t *mp;
1396 
1397  mp = spp_msg_api_alloc (sizeof (*mp));
1398  memset(mp, 0, sizeof (*mp));
1399 
1400  mp->_spp_msg_id = SPP_API_CNAT_V4_DEBUG_GLOBAL;
1401  mp->debug_flag = CNAT_DEBUG_GLOBAL_ALL;
1402 
1403  platform_send_msg(mp);
1404 }
1405 
1406 void cnat_debug_global_none (int argc, unsigned long *argv)
1407 {
1408  spp_api_cnat_v4_debug_global_t *mp;
1409 
1410  mp = spp_msg_api_alloc (sizeof (*mp));
1411  memset(mp, 0, sizeof (*mp));
1412 
1413  mp->_spp_msg_id = SPP_API_CNAT_V4_DEBUG_GLOBAL;
1414  mp->debug_flag = CNAT_DEBUG_NONE;
1415 
1416  platform_send_msg(mp);
1417 }
1418 
1419 
1420 void cnat_bulk_cmd (int argc, unsigned long *argv)
1421 {
1422  void *mp_send;
1423 
1424  if (argc < 1) {
1425  printf("\nargc = %d", argc);
1426  printf("\n1. bulk cmd [0=static-port, 1=bulk_vrf, 2=policy_knob]");
1427  return;
1428  }
1429 
1430 
1431  switch (argv[0]) {
1432  case 0:
1433  {
1434  spp_api_cnat_v4_bulk_add_delete_static_port_t *mp;
1435  spp_api_cnat_v4_add_static_port_t *mp_sp;
1436  u32 mp_size =
1437  sizeof(spp_api_cnat_v4_bulk_add_delete_static_port_t) +
1438  (sizeof(spp_api_cnat_v4_add_static_port_t))*2;
1439 
1440  mp = spp_msg_api_alloc(mp_size);
1441  memset(mp, 0, mp_size);
1442 
1443  mp->_spp_msg_id = SPP_API_CNAT_V4_BULK_ADD_DELETE_STATIC_PORT;
1444 
1445  mp->num_static_port_entries = spp_host_to_net_byte_order_32(3);
1446 
1447  mp_sp = (spp_api_cnat_v4_add_static_port_t *) &(mp->pad2);
1448 
1449  mp_sp->_spp_msg_id = spp_host_to_net_byte_order_16(
1450  SPP_API_CNAT_V4_ADD_STATIC_PORT);
1451  mp_sp->proto = 2;
1452  mp_sp->i_vrf = spp_host_to_net_byte_order_16(0x1);
1453  mp_sp->i_ip = spp_host_to_net_byte_order_32(0x11111111);
1454  mp_sp->i_port = spp_host_to_net_byte_order_16(0x7777);
1455 
1456  mp_sp++;
1457 
1458 
1459  mp_sp->_spp_msg_id = spp_host_to_net_byte_order_16(
1460  SPP_API_CNAT_V4_ADD_STATIC_PORT);
1461  mp_sp->proto = 1;
1462  mp_sp->i_vrf = spp_host_to_net_byte_order_16(0x1);
1463  mp_sp->i_ip = spp_host_to_net_byte_order_32(0x22222222);
1464  mp_sp->i_port = spp_host_to_net_byte_order_16(0x6666);
1465 
1466  mp_sp++;
1467 
1468 
1469  mp_sp->_spp_msg_id = spp_host_to_net_byte_order_16(
1470  SPP_API_CNAT_V4_ADD_STATIC_PORT);
1471  mp_sp->proto = 1;
1472  mp_sp->i_vrf = spp_host_to_net_byte_order_16(0x1);
1473  mp_sp->i_ip = spp_host_to_net_byte_order_32(0x33333333);
1474  mp_sp->i_port = spp_host_to_net_byte_order_16(0x5555);
1475 
1476  mp_send = mp;
1477 
1478  }
1479  break;
1480 
1481  case 1:
1482  {
1483  spp_api_cnat_v4_bulk_vrf_map_t *mp;
1485 
1486  u32 mp_size = sizeof(spp_api_cnat_v4_bulk_vrf_map_t) +
1488 
1489  mp = spp_msg_api_alloc(mp_size);
1490  memset(mp, 0, mp_size);
1491 
1492  mp->_spp_msg_id = SPP_API_CNAT_V4_BULK_VRF_MAP;
1493 
1494  mp->num_vrfmap_entries = spp_host_to_net_byte_order_32(3);
1495 
1497  &(mp->vrf_policy_enable);
1498 
1499  mp_sp->i_vrf_id = spp_host_to_net_byte_order_32(0xe0000001);
1500  mp_sp->o_vrf_id = spp_host_to_net_byte_order_32(0xe0000000);
1501  mp_sp->i_vrf = spp_host_to_net_byte_order_16(0x1);
1502  mp_sp->o_vrf = spp_host_to_net_byte_order_16(0x0);
1503  mp_sp->start_addr = spp_host_to_net_byte_order_32(0x11111100);
1504  mp_sp->end_addr = spp_host_to_net_byte_order_32(0x111111ff);
1505  mp_sp->vrf_policy_enable = spp_host_to_net_byte_order_16(0x3);
1506  mp_sp->tcp_mss_value = spp_host_to_net_byte_order_16(0x111);
1507  mp_sp->vrf_nfv9_logging_ipv4_address = spp_host_to_net_byte_order_32(0x11000001);
1508  mp_sp->vrf_nfv9_logging_udp_port = spp_host_to_net_byte_order_16(0x1001);
1509  mp_sp->vrf_nfv9_refresh_rate = spp_host_to_net_byte_order_16(0x100);
1510  mp_sp->vrf_nfv9_timeout_rate = spp_host_to_net_byte_order_16(0x10);
1511  mp_sp->vrf_nfv9_path_mtu = spp_host_to_net_byte_order_16(0x100);
1512 
1513  mp_sp++;
1514 
1515  mp_sp->i_vrf_id = spp_host_to_net_byte_order_32(0xe0000002);
1516  mp_sp->o_vrf_id = spp_host_to_net_byte_order_32(0xe0000000);
1517  mp_sp->i_vrf = spp_host_to_net_byte_order_16(0x2);
1518  mp_sp->o_vrf = spp_host_to_net_byte_order_16(0x0);
1519  mp_sp->start_addr = spp_host_to_net_byte_order_32(0x22220000);
1520  mp_sp->end_addr = spp_host_to_net_byte_order_32(0x2222ffff);
1521  mp_sp->vrf_policy_enable = spp_host_to_net_byte_order_16(0x1);
1522  mp_sp->tcp_mss_value = spp_host_to_net_byte_order_16(0x222);
1523  mp_sp->vrf_nfv9_logging_ipv4_address = spp_host_to_net_byte_order_32(0x22000002);
1524  mp_sp->vrf_nfv9_logging_udp_port = spp_host_to_net_byte_order_16(0x2002);
1525  mp_sp->vrf_nfv9_refresh_rate = spp_host_to_net_byte_order_16(0x200);
1526  mp_sp->vrf_nfv9_timeout_rate = spp_host_to_net_byte_order_16(0x20);
1527  mp_sp->vrf_nfv9_path_mtu = spp_host_to_net_byte_order_16(0x200);
1528 
1529  mp_sp++;
1530 
1531  mp_sp->i_vrf_id = spp_host_to_net_byte_order_32(0xe0000003);
1532  mp_sp->o_vrf_id = spp_host_to_net_byte_order_32(0xe0000007);
1533  mp_sp->i_vrf = spp_host_to_net_byte_order_16(0x3);
1534  mp_sp->o_vrf = spp_host_to_net_byte_order_16(0x7);
1535  mp_sp->start_addr = spp_host_to_net_byte_order_32(0x33333000);
1536  mp_sp->end_addr = spp_host_to_net_byte_order_32(0x33333fff);
1537  mp_sp->vrf_policy_enable = spp_host_to_net_byte_order_16(0x1);
1538  mp_sp->tcp_mss_value = spp_host_to_net_byte_order_16(0x333);
1539  mp_sp->vrf_nfv9_logging_ipv4_address = spp_host_to_net_byte_order_32(0x33000003);
1540  mp_sp->vrf_nfv9_logging_udp_port = spp_host_to_net_byte_order_16(0x3003);
1541  mp_sp->vrf_nfv9_refresh_rate = spp_host_to_net_byte_order_16(0x300);
1542  mp_sp->vrf_nfv9_timeout_rate = spp_host_to_net_byte_order_16(0x30);
1543  mp_sp->vrf_nfv9_path_mtu = spp_host_to_net_byte_order_16(0x300);
1544 
1545  mp_send = mp;
1546  }
1547  break;
1548 
1549  case 2:
1550  {
1551  spp_api_cnat_v4_bulk_policy_knob_t *mp;
1552 
1553  u32 mp_size =
1554  sizeof(spp_api_cnat_v4_bulk_policy_knob_t) +
1556 
1557  mp = spp_msg_api_alloc(mp_size);
1558  memset(mp, 0, mp_size);
1559 
1560  mp->_spp_msg_id = SPP_API_CNAT_V4_BULK_POLICY_KNOB;
1561 
1562  mp->port_limit = spp_host_to_net_byte_order_16(345);
1563  mp->icmp_timeout = spp_host_to_net_byte_order_16(300);
1564  mp->udp_init_timeout = spp_host_to_net_byte_order_16(175);
1565  mp->udp_act_timeout = spp_host_to_net_byte_order_16(133);
1566  mp->tcp_init_timeout = spp_host_to_net_byte_order_16(222);
1567  mp->tcp_act_timeout = spp_host_to_net_byte_order_16(2345);
1568 
1569  mp->nat_policy_enable = spp_host_to_net_byte_order_32(0x7);
1570 
1571  mp->global_nfv9_logging_ipv4_address = spp_host_to_net_byte_order_32(0x77777777);
1572  mp->global_nfv9_logging_udp_port = spp_host_to_net_byte_order_16(0x7007);
1573  mp->global_nfv9_refresh_rate = spp_host_to_net_byte_order_16(0x700);
1574  mp->global_nfv9_timeout_rate = spp_host_to_net_byte_order_16(0x70);
1575  mp->global_nfv9_path_mtu = spp_host_to_net_byte_order_16(0x700);
1576 
1577  mp_send = mp;
1578  }
1579  break;
1580 
1581 
1582  default:
1583  printf("\nargv[2] = %d", argv[2]);
1584  printf("\n2. bulk cmd [0=static-port, 1=bulk_vrf, 2=policy_knob+bulk_vrf]");
1585  return;
1586 
1587  }
1588  platform_send_msg(mp_send);
1589 }
1590 
1591 void cnat_nfv9_delete_cmd (int argc, unsigned long *argv)
1592 {
1594 
1595  if (argc != 1) {
1596  printf("nfv9 delete i_vrf ");
1597  return;
1598  }
1599 
1600  mp = spp_msg_api_alloc (sizeof (*mp));
1601  memset(mp, 0, sizeof (*mp));
1602  mp->_spp_msg_id = SPP_API_CNAT_V4_CONFIG_NFV9_LOGGING;
1603  mp->enable = 0;
1604  mp->i_vrf = spp_host_to_net_byte_order_16(argv[0]);
1605  platform_send_msg(mp);
1606 }
1607 
1608 void cnat_generic_cmd (int argc, unsigned long *argv)
1609 {
1610  spp_api_cnat_generic_command_request_t *mp;
1611 
1612  if (argc != 9) {
1613  printf("generic command core type p1 p2 p3 p4 p5 p6 p7 ");
1614  return;
1615  }
1616 
1617  /*
1618  * Allocate a large buffer for message req and resp structure
1619  */
1620  mp = spp_msg_api_alloc (MAX_DEBUG_BUFFER_SIZE);
1621  memset(mp, 0, MAX_DEBUG_BUFFER_SIZE);
1622  mp->_spp_msg_id = SPP_API_CNAT_GENERIC_COMMAND_REQUEST;
1623  mp->core_num = argv[0];
1624  mp->params[0] = spp_host_to_net_byte_order_32(argv[1]);
1625  mp->params[1] = spp_host_to_net_byte_order_32(argv[2]);
1626  mp->params[2] = spp_host_to_net_byte_order_32(argv[3]);
1627  mp->params[3] = spp_host_to_net_byte_order_32(argv[4]);
1628  mp->params[4] = spp_host_to_net_byte_order_32(argv[5]);
1629  mp->params[5] = spp_host_to_net_byte_order_32(argv[6]);
1630  mp->params[6] = spp_host_to_net_byte_order_32(argv[7]);
1631  mp->params[7] = spp_host_to_net_byte_order_32(argv[8]);
1632  platform_send_msg(mp);
1633 }
1634 
1635 u32 icmp_sent_timestamps; /* 32 KB array per core */
1636 u8 v4_pkt_count = 0;
1637 
1639 {
1640 #ifdef DISABLE_ICMP_THROTTLE_FOR_DEBUG_PURPOSE
1641  return CNAT_ICMP_MSG;
1642 #else
1643  u32 current_timestamp;
1644  spp_node_main_vector_t *nmv;
1645  u32 updated_timestamp;
1646 
1647  v4_pkt_count ++;
1648 
1649  nmv = spp_get_node_main_vectorized_inline();
1650 
1651  current_timestamp = nmv->ticks / nmv->ticks_per_second;
1652 
1653  PLATFORM_UPDATE_TIMESTAMP
1654  if (PREDICT_FALSE(icmp_sent_timestamps != updated_timestamp)) {
1655  v4_pkt_count = 1;
1656  /* update timestamp */
1657  icmp_sent_timestamps = updated_timestamp;
1658  }
1659  if (PREDICT_TRUE(v4_pkt_count <= cnat_main_db_icmp_rate_limit_core)) {
1660  return CNAT_ICMP_MSG;
1661  } else {
1662  return CNAT_NO_ICMP_MSG;
1663  }
1664 #endif
1665 }
1666 
1667 u32 v6_icmp_sent_timestamps; /* 32 KB array per core */
1668 u8 v6_pkt_count = 0;
1669 
1671 {
1672 #ifdef DISABLE_ICMP_THROTTLE_FOR_DEBUG_PURPOSE
1673  return CNAT_ICMP_MSG;
1674 #else
1675  u32 current_timestamp;
1676  spp_node_main_vector_t *nmv;
1677  u32 updated_timestamp;
1678 
1679  nmv = spp_get_node_main_vectorized_inline();
1680 
1681  current_timestamp = nmv->ticks / nmv->ticks_per_second;
1682  PLATFORM_UPDATE_TIMESTAMP
1683  v6_pkt_count ++;
1684 
1685  if (PREDICT_FALSE(v6_icmp_sent_timestamps != updated_timestamp)) {
1686  v6_pkt_count = 1;
1687  /* update timestamp */
1688  v6_icmp_sent_timestamps = updated_timestamp;
1689  }
1690  if (PREDICT_TRUE(v6_pkt_count <= cnat_main_db_icmp_rate_limit_core)) {
1691  return CNAT_ICMP_MSG;
1692  } else {
1693  return CNAT_NO_ICMP_MSG;
1694  }
1695 #endif
1696 }
1697 
1698 u32 v4_udp_crc_zero_timestamps;
1699 u32 v4_udp_crc_zero_pkt_count = 0;
1701 {
1702  PLATFORM_V4_CRC_ZERO_UDP_ALLOWED
1703  /* Currently not supported for Brahmos. we need to take care of this */
1704  spp_node_main_vector_t *nmv;
1705  u32 hash_value, current_timestamp;
1706 
1707  nmv = spp_get_node_main_vectorized_inline();
1708 
1709  current_timestamp = nmv->ticks / nmv->ticks_per_second;
1710  v4_udp_crc_zero_pkt_count++;
1711  if (PREDICT_FALSE(v4_udp_crc_zero_timestamps != current_timestamp)) {
1712  v4_udp_crc_zero_pkt_count = 1;
1713  v4_udp_crc_zero_timestamps = current_timestamp;
1714  }
1715  if (PREDICT_TRUE(v4_udp_crc_zero_pkt_count <=
1717  return 1;
1718  } else {
1719  return 0;
1720  }
1721 }
1722 
1723 /*
1724  * ipv4_decr_ttl_n_calc_csum()
1725  * - It decrements the TTL and calculates the incremental IPv4 checksum
1726  */
1727 
1728 ALWAYS_INLINE(
1730 {
1731  u32 checksum;
1732  u16 old;
1733 
1734  old = ntohs(*(u16 *)&ipv4->ttl);
1735 
1736  /* Decrement TTL */
1737  ipv4->ttl--;
1738 
1739  /* Calculate incremental checksum */
1740  checksum = old + (~ntohs(*(u16 *)&ipv4->ttl) & 0xFFFF);
1741  checksum += ntohs(ipv4->checksum);
1742  checksum = (checksum & 0xFFFF) + (checksum >> 16);
1743  ipv4->checksum = htons(checksum + (checksum >> 16));
1744 }
1745 
1746 ALWAYS_INLINE(
1747 void calc_ipv4_checksum (ipv4_header *ipv4))
1748 {
1749  u16 *data = (u16 *) ipv4;
1750  u32 checksum = 0;
1751 
1752  checksum = crc_calc(ipv4);
1753 
1754  /* Now produce the 1's complement */
1755  ipv4->checksum = spp_host_to_net_byte_order_16(((u16) (~(u16)checksum)));
1756 }
1757 
1758 ALWAYS_INLINE(
1759 void calc_v4_icmp_checksum (icmp_v4_t *icmp, int ipv4_payload_size))
1760 {
1761  u16 *data = (u16 *) icmp;
1762  int num_hwords = (ipv4_payload_size)/2;
1763  u32 checksum = 0;
1764 
1765  icmp->checksum = 0;
1766  if (PREDICT_FALSE((ipv4_payload_size%2) != 0)) {
1767  num_hwords += 1;
1768  /* Append 0's in the last octet */
1769  *((u8 *)data + ipv4_payload_size) = 0;
1770  }
1771  while (num_hwords) {
1772  checksum += (u32)spp_net_to_host_byte_order_16(data++);
1773  num_hwords--;
1774  }
1775 
1776  /* Add in the carry of the original sum */
1777  checksum = (checksum & 0xFFFF) + (checksum >> 16);
1778  /* Add in the carry of the final sum */
1779  checksum = (checksum & 0xFFFF) + (checksum >> 16);
1780  /* Now produce the 1's complement */
1781  icmp->checksum = spp_host_to_net_byte_order_16(((u16) (~(u16)checksum)));
1782 }
1783 
1784 ALWAYS_INLINE(
1785 void calc_v6_icmp_checksum (ipv6_header_t *ipv6, u16 ip_payload_size))
1786 {
1787  u16 *data;
1788  u16 *data1;
1789  int i;
1790  icmp_v6_t *icmp;
1791  int num_hwords = (ip_payload_size)/2;
1792  u32 checksum = 0;
1793  pseudo_v6_header_t pseudo_header;
1794 
1795  icmp = (icmp_v6_t *) ((u8 *)ipv6 + IPV6_HDR_LEN);
1796  data = (u16 *) icmp;
1797  icmp->checksum = 0;
1798 
1799 #if 1
1800  if (PREDICT_FALSE((ip_payload_size%2) != 0)) {
1801  num_hwords += 1;
1802  /* Append 0's in the last octet */
1803  *((u8 *)data + ip_payload_size) = 0;
1804  }
1805 #endif
1806 
1807  /* construct the pseudo header */
1808 
1809  pseudo_header.src_addr[0] = ipv6->src_addr[0];
1810  pseudo_header.src_addr[1] = ipv6->src_addr[1];
1811  pseudo_header.src_addr[2] = ipv6->src_addr[2];
1812  pseudo_header.src_addr[3] = ipv6->src_addr[3];
1813  pseudo_header.dst_addr[0] = ipv6->dst_addr[0];
1814  pseudo_header.dst_addr[1] = ipv6->dst_addr[1];
1815  pseudo_header.dst_addr[2] = ipv6->dst_addr[2];
1816  pseudo_header.dst_addr[3] = ipv6->dst_addr[3];
1817  pseudo_header.payload_length = spp_host_to_net_byte_order_16(ip_payload_size);
1818  pseudo_header.next_header = spp_host_to_net_byte_order_16(ipv6->next_header);
1819 
1820  data1 = (u16 *) &pseudo_header;
1821 
1822  /* sizeof(pseudo_v6_header_t) = 36 */
1823  for (i = 0; i < 18; i++) {
1824  checksum += (u32)spp_net_to_host_byte_order_16(data1++);
1825  }
1826 
1827 checksum_calc:
1828 
1829  if (PREDICT_TRUE(num_hwords)) {
1830  checksum += (u32)spp_net_to_host_byte_order_16(data);
1831  num_hwords--;
1832  data++;
1833  goto checksum_calc;
1834  }
1835 
1836  /* Add in the carry of the original sum */
1837  checksum = (checksum & 0xFFFF) + (checksum >> 16);
1838  /* Add in the carry of the final sum */
1839  checksum = (checksum & 0xFFFF) + (checksum >> 16);
1840  /* Now produce the 1's complement */
1841  icmp->checksum = spp_host_to_net_byte_order_16(((u16) (~(u16)checksum)));
1842 }
1843 
1844 void icmp_error_generate_v6 (spp_ctx_t *ctx, u8 icmp_type,
1845  u8 icmp_code, u16 uidb_index) {
1846 
1847  u16 ip_hdr_len, ip_payload_size;
1848  u32 *src_p, * dst_p;
1849  icmp_v6_t *icmp;
1850  int i;
1851  ipv6_header_t *ip_old, *ip_new;
1852  u16 icmp_payload_len;
1853 
1854  /*
1855  * As per RFC 2463, we limit the maximum size of generated ICMPv6 message to * 1280. And hence if the packet is bigger than 1280, then it needs to be
1856  * truncated. Also, if the packet had multiple chained buffers, we need to
1857  * free all chained buffers, except the first one.
1858  */
1859  free_all_but_first_chained_buffers(ctx);
1860 
1861  ip_hdr_len = IPV6_HDR_LEN;
1862  /* offset to ip payload */
1863 
1864  ip_old = (ipv6_header_t *)PLATFORM_CTX_CURRENT_HDR;
1865  ip_new = (ipv6_header_t *) ((u8 *) PLATFORM_CTX_CURRENT_HDR - ICMPV6_ERR_SIZE);
1866  icmp = (icmp_v6_t*) ( (u8*)ip_new + ip_hdr_len);
1867 
1868  icmp_payload_len = ip_hdr_len +
1869  spp_net_to_host_byte_order_16(&(ip_old->payload_length)) ;
1870 
1871  ip_payload_size = ICMPV6_HDR_SIZE + icmp_payload_len;
1872  /*
1873  * There is no easy way to predict this case as the probablity that the IPv6
1874  * pkt is big depends on the type of traffic. Let us optimize the big
1875  * pkt case as it involves more processing
1876  *
1877  * If the pkt size exceeds IPV6_MIN_PATH_MTU truncate it to IPV6_MIN_PATH_MTU
1878  */
1879  if (PREDICT_TRUE((ip_payload_size + ip_hdr_len) > IPV6_MIN_PATH_MTU)) {
1880  ip_payload_size = IPV6_MIN_PATH_MTU - ip_hdr_len;
1881  }
1882 
1883  /* Following ICMP op has to be after ip header being copied */
1884  icmp->type = icmp_type;
1885  icmp->code = icmp_code;
1886 
1887  ip_new->version_trafficclass_flowlabel = spp_host_to_net_byte_order_32(
1888  VERSION_TRAFFICCLASS_FLOWLABEL);
1889  ip_new->payload_length = spp_host_to_net_byte_order_16(ip_payload_size);
1890  ip_new->next_header = IPV6_PROTO_ICMPV6;
1891  ip_new->hop_limit = 64;
1892  ip_new->dst_addr[0] = ip_old->src_addr[0];
1893  ip_new->dst_addr[1] = ip_old->src_addr[1];
1894  ip_new->dst_addr[2] = ip_old->src_addr[2];
1895  ip_new->dst_addr[3] = ip_old->src_addr[3];
1896 
1897  ip_new->src_addr[0] =
1898  spp_host_to_net_byte_order_32(svi_params_array[uidb_index].ipv6_addr[0]);
1899  ip_new->src_addr[1] =
1900  spp_host_to_net_byte_order_32(svi_params_array[uidb_index].ipv6_addr[1]);
1901  ip_new->src_addr[2] =
1902  spp_host_to_net_byte_order_32(svi_params_array[uidb_index].ipv6_addr[2]);
1903  ip_new->src_addr[3] =
1904  spp_host_to_net_byte_order_32(svi_params_array[uidb_index].ipv6_addr[3]);
1905  /* calc checksum for icmp */
1906 
1907  calc_v6_icmp_checksum(ip_new, ip_payload_size);
1908 #if 0
1909  printf("Flow = 0x%x\n", ip_new->version_trafficclass_flowlabel);
1910  printf("Hoplimit = 0x%x\n", ip_new->hop_limit);
1911  printf("Length= 0x%x\n", ip_new->payload_length);
1912  printf("Next header = 0x%x\n", ip_new->next_header);
1913  printf("Src add0 = 0x%x\n", ip_new->src_addr[0]);
1914  printf("Src add1 = 0x%x\n", ip_new->src_addr[1]);
1915  printf("Src add2 = 0x%x\n", ip_new->src_addr[2]);
1916  printf("Src add3 = 0x%x\n", ip_new->src_addr[3]);
1917  printf("Dst add0 = 0x%x\n", ip_new->dst_addr[0]);
1918  printf("Dst add1 = 0x%x\n", ip_new->dst_addr[1]);
1919  printf("Dst add2 = 0x%x\n", ip_new->dst_addr[2]);
1920  printf("Dst add3 = 0x%x\n", ip_new->dst_addr[3]);
1921  printf("Icmp type = 0x%x\n", icmp->type);
1922  printf("Icmp code = 0x%x\n", icmp->code);
1923 
1924  printf("\n\nICMP packet:\n");
1925  for (i = 0; i < 10; i ++) {
1926  printf("0x%x " , *((u8 *)icmp + i));
1927  if ((i%16) == 15) {
1928  printf("\n");
1929  }
1930  }
1931 #endif
1932 
1933  ctx->current_header -= ICMPV6_ERR_SIZE;
1934  ctx->current_length = ip_payload_size + ip_hdr_len;
1935  PLATFORM_CNAT_SET_TX_VRF(ctx,uidb_index);
1936 }
1937 
1938 void icmp_error_generate_v2 (ipv4_header *ip, u8 icmp_type,
1939  u8 icmp_code, u16 mtu, u32 src_ip)
1940 {
1941 
1942  u16 ip_hdr_len, ip_payload_size;
1943  u32 *src_p, * dst_p;
1944  icmp_v4_t *icmp;
1945 
1946  ip_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; /* offset to ip payload */
1947  icmp = (icmp_v4_t*) ( (u8*)ip + ip_hdr_len);
1948  ip_payload_size = sizeof(icmp_v4_t) + ip_hdr_len +
1949  ICMP_UNREACHABLE_IP_PAYLOAD_SIZE;
1950 
1951  src_p = (u32*)
1952  ((u8*)ip + ip_hdr_len + ICMP_UNREACHABLE_IP_PAYLOAD_SIZE - 4);
1953  dst_p = (u32*) ((u8*)src_p + sizeof(ipv4_header) +
1954  sizeof(icmp_v4_t));
1955 
1956  while(src_p >= (u32*)ip) *dst_p-- = *src_p--;
1957 
1958  /* Following ICMP op has to be after ip header being copied */
1959  icmp->type = icmp_type;
1960  icmp->code = icmp_code;
1961  icmp->identifier = 0;
1962  icmp->sequence = 0;
1963  if(PREDICT_FALSE(mtu != 0)) {
1964  icmp->sequence = spp_host_to_net_byte_order_16(mtu);
1965  }
1966 
1967 
1968  /* build icmp header, keep original tos, identification values */
1969  ip->version_hdr_len_words = 0x45;
1970  ip->total_len_bytes = sizeof(ipv4_header) + ip_payload_size;
1971  ip->total_len_bytes = spp_host_to_net_byte_order_16(ip->total_len_bytes);
1972  ip->frag_flags_offset = 0;
1973  ip->ttl = 64;
1974  ip->protocol = ICMP_PROT;
1975  ip->checksum = 0;
1976  ip->dest_addr = ip->src_addr;
1977  ip->src_addr = spp_host_to_net_byte_order_32(src_ip);
1978 
1979  /* calc checksum for ip and icmp */
1980 
1981  calc_ipv4_checksum(ip);
1982  calc_v4_icmp_checksum( (icmp_v4_t *) ((u8*) ip + sizeof(ipv4_header)),
1983  ip_payload_size);
1984 }
1985 
1986 void icmp_error_generate (ipv4_header *ip, u8 icmp_type,
1987  u8 icmp_code, u16 uidb_index) {
1988 
1989  u16 ip_hdr_len, ip_payload_size;
1990  u32 *src_p, * dst_p;
1991  icmp_v4_t *icmp;
1992 
1993  ip_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; /* offset to ip payload */
1994  icmp = (icmp_v4_t*) ( (u8*)ip + ip_hdr_len);
1995  ip_payload_size = sizeof(icmp_v4_t) + ip_hdr_len +
1996  ICMP_UNREACHABLE_IP_PAYLOAD_SIZE;
1997 
1998  src_p = (u32*)
1999  ((u8*)ip + ip_hdr_len + ICMP_UNREACHABLE_IP_PAYLOAD_SIZE - 4);
2000  dst_p = (u32*) ((u8*)src_p + sizeof(ipv4_header) +
2001  sizeof(icmp_v4_t));
2002 
2003  while(src_p >= (u32*)ip) *dst_p-- = *src_p--;
2004 
2005  /* Following ICMP op has to be after ip header being copied */
2006  icmp->type = icmp_type;
2007  icmp->code = icmp_code;
2008  icmp->identifier = 0;
2009  icmp->sequence = 0;
2010 
2011 
2012  /* build icmp header, keep original tos, identification values */
2013  ip->version_hdr_len_words = 0x45;
2014  ip->total_len_bytes = sizeof(ipv4_header) + ip_payload_size;
2015  ip->total_len_bytes = spp_host_to_net_byte_order_16(ip->total_len_bytes);
2016  ip->frag_flags_offset = 0;
2017  ip->ttl = 64;
2018  ip->protocol = ICMP_PROT;
2019  ip->checksum = 0;
2020  ip->dest_addr = ip->src_addr;
2021 
2022  ip->src_addr = spp_host_to_net_byte_order_32(svi_params_array[uidb_index].ipv4_addr);
2023 
2024  /* calc checksum for ip and icmp */
2025 
2026  calc_ipv4_checksum(ip);
2027  calc_v4_icmp_checksum( (icmp_v4_t *) ((u8*) ip + sizeof(ipv4_header)),
2028  ip_payload_size);
2029 #if 0
2030  printf("version_hdr_len_words = 0x%x\n", ip->version_hdr_len_words);
2031  printf("total_len_bytes = 0x%x\n", ip->total_len_bytes);
2032  printf("Frag = 0x%x\n", ip->frag_flags_offset);
2033  printf("ttl = 0x%x\n", ip->ttl);
2034  printf("Protocol = 0x%x\n", ip->protocol);
2035  printf("checksum = 0x%x\n", ip->checksum);
2036  printf("Dest addr = 0x%x\n", ip->dest_addr);
2037  printf("Src addr = 0x%x\n", ip->src_addr);
2038  printf("Icmp type = 0x%x\n", icmp->type);
2039  printf("Icmp code = 0x%x\n", icmp->code);
2040 #endif
2041 
2042 }
2043 
2044 int icmpv4_generate_with_throttling_v2 (spp_ctx_t *ctx, ipv4_header *ipv4,
2045  int icmp_type, int icmp_code,
2046  u16 mtu, u32 src_ip)
2047 {
2048  u16 ip_hdr_len;
2049  icmp_v4_t *icmp;
2050  u16 rx_uidb_index = ctx->ru.rx.uidb_index;
2051  if (icmp_msg_gen_allowed()) {
2052  free_all_but_first_chained_buffers(ctx);
2053  icmp_error_generate_v2(ipv4, icmp_type, icmp_code, mtu, src_ip);
2054  ctx->current_length = (u16)
2055  ((u8*)ctx->current_header - ctx->packet_data) +
2056  spp_net_to_host_byte_order_16(&ipv4->total_len_bytes);
2057  PLATFORM_CNAT_SET_TX_VRF(ctx,rx_uidb_index);
2058  return 1;
2059  } else {
2060  return 0;
2061  }
2062 }
2063 
2065  u16 rx_uidb_index)
2066 {
2067  int icmp_type;
2068  int icmp_code;
2069 
2070  if (icmp_msg_gen_allowed()) {
2071  /* ICMP error would be small, so one buffer is enough. Clear the other */
2072  free_all_but_first_chained_buffers(ctx);
2073 
2074  icmp_type = ICMPV4_TIMEEXCEEDED;
2075  icmp_code = ICMPV4_TIMTTL;
2076  icmp_error_generate(ipv4, icmp_type, icmp_code, rx_uidb_index);
2077  ctx->current_length = (u16)
2078  ((u8*)ctx->current_header - ctx->packet_data) +
2079  spp_net_to_host_byte_order_16(&ipv4->total_len_bytes);
2080  PLATFORM_CNAT_SET_TX_VRF(ctx,rx_uidb_index);
2081  return 1;
2082  } else {
2083  return 0;
2084  }
2085 }
2086 
2087 int icmpv4_generate_with_throttling_v1 (spp_ctx_t *ctx, ipv4_header *ipv4,
2088  u16 rx_uidb_index, u32 type, u32 code)
2089 {
2090  if (icmp_msg_gen_allowed()) {
2091  /* ICMP error would be small, so one buffer is enough. Clear the other */
2092  free_all_but_first_chained_buffers(ctx);
2093 
2094  icmp_error_generate(ipv4, type, code, rx_uidb_index);
2095  ctx->current_length = (u16)
2096  ((u8*)ctx->current_header - ctx->packet_data) +
2097  spp_net_to_host_byte_order_16(&ipv4->total_len_bytes);
2098  PLATFORM_CNAT_SET_TX_VRF(ctx,rx_uidb_index);
2099  return 1;
2100  } else {
2101  return 0;
2102  }
2103 }
2104 
2105 
2107  u16 rx_uidb_index)
2108 {
2109  int icmp_type;
2110  int icmp_code;
2111 
2112  if (v6_icmp_msg_gen_allowed()) {
2113  icmp_type = ICMPV6_TIMEEXCEEDED;
2114  icmp_code = ICMPV6_TIMTTL;
2115  icmp_error_generate_v6(ctx, icmp_type, icmp_code, rx_uidb_index);
2116  return 1;
2117  } else {
2118  return 0;
2119  }
2120 }
2121 
2122 int icmpv6_generate_with_throttling_v1 (spp_ctx_t *ctx, ipv6_header_t *ipv6,
2123  u16 rx_uidb_index, u32 type, u32 code)
2124 {
2125 
2126  if (v6_icmp_msg_gen_allowed()) {
2127  icmp_error_generate_v6(ctx, type, code, rx_uidb_index);
2128  return 1;
2129  } else {
2130  return 0;
2131  }
2132 }
2133 #endif
2134 
2135 void calculate_window_scale(tcp_hdr_type *tcp_header, u8 *scale) {
2136 
2137  u8 check_options = 0;
2138 
2139  *scale = 0;
2140  check_options = ((tcp_header->flags & TCP_FLAG_SYN) &&
2141  (((tcp_header->hdr_len>>4) << 2) > sizeof(tcp_hdr_type)));
2142 
2143  if (PREDICT_FALSE(check_options)) {
2144  u8 *options_ptr = tcp_findoption(tcp_header, TCP_OPTION_WINDOW_SCALE);
2145 
2146  /*
2147  * TCP option field: | kind 1B | len 1B | value 2B|
2148  * where kind != [0, 1]
2149  */
2150  if (PREDICT_TRUE(options_ptr &&
2151  (options_ptr[1] == TCP_OPTION_WINDOW_SCALE))) {
2152  u8 *ptr = (u8*)(options_ptr + 2);
2153  *scale = *ptr;
2154 
2155  if(PREDICT_FALSE(*scale >= 14)) {
2156  *scale = 14;
2157  }
2158 
2159  return;
2160  }
2161  }
2162 }
2163 
2164 #if 0
2165 ALWAYS_INLINE(
2168  cnat_vrfmap_t *vrfmap))
2169 {
2170  /* As of now, Netflow does not require this to be logged
2171  * So only syslog
2172  */
2174  /* Already logged ..*/
2175  return;
2176  }
2177  /* else, set the flag and call the log API */
2178 
2179  db->flags = db->flags | CNAT_TAC_SEQ_MISMATCH;
2180 
2181  cnat_syslog_nat44_tcp_seq_mismatch(db, vrfmap);
2182 }
2183 
2184 
2185 static int cnat_util_init (void *notused)
2186 {
2187  /* run SPP_API_CNAT_PORTMAP_CREATE first*/
2188  spp_msg_api_set_handler(SPP_API_CNAT_PORT_ALLOCATE,
2189  spp_api_cnat_port_allocate_t_handler);
2190 
2191 
2192  spp_msg_api_set_handler(SPP_API_CNAT_PORT_CLEAR,
2193  spp_api_cnat_port_clear_t_handler);
2194 
2195  /* run vrfmap config first */
2196  spp_msg_api_set_handler(SPP_API_CNAT_PORT_CREATE,
2197  spp_api_cnat_port_create_t_handler);
2198 
2199  spp_msg_api_set_handler(SPP_API_CNAT_PORT_DELETE,
2200  spp_api_cnat_port_delete_t_handler);
2201  return 0;
2202 }
2203 
2204 void
2206 {
2207  u32 i, total_len, l4_len=0;
2208 
2209  u8 *pkt = (u8 *) ip;
2210 
2211  total_len = spp_net_to_host_byte_order_16(&ip->payload_length);
2212 
2213  /* we rarely need to debug > 200 bytes of packet */
2214  if(total_len > 200) {
2215  total_len = 200;
2216  }
2217 
2218  printf("\n======== PRINTING PKT START======\n");
2219  printf("======== IPv6 PAYLOAD LEN %d ===========\n", total_len);
2220  for (i=0; i < 40; i++) {
2221  printf(" %02X ", *(pkt + i));
2222  if(i%16==15)
2223  printf("\n");
2224  }
2225 
2226  if (ip->next_header == IPV6_PROTO_TCP) {
2227  printf("\n======== TCP HEADER =================\n");
2228  l4_len = 20;
2229  }
2230  else if (ip->next_header == IPV6_PROTO_UDP) {
2231  printf("\n======== UDP HEADER =================\n");
2232  l4_len = 8;
2233  }
2234  else if (ip->next_header == IPV6_PROTO_ICMPV6) {
2235  printf("\n======== ICMP HEADER =================\n");
2236  l4_len = 8;
2237  }
2238 
2239  for (i=40; i < (l4_len + 40); i++) {
2240  printf(" %02X ", *(pkt + i));
2241  }
2242 
2243  printf("\n======== LAYER4 PAYLOAD ===================\n");
2244  for (i=(l4_len + 40); i < total_len; i++) {
2245  printf(" %02X ", *(pkt + i));
2246  if(i%16==15)
2247  printf("\n");
2248  }
2249 
2250  printf("\n======== PRINTING PKT END =======\n");
2251 }
2252 
2253 
2254 
2255 PLATFORM_SPP_INIT_FUNCTION(cnat_util_init);
2256 #endif
u32 rcv_pkt_errs
Definition: cnat_global.c:44
static u8 * tcp_findoption(tcp_hdr_type *tcp, u8 option)
u16 flags
Definition: cnat_db.h:159
cnat_main_db_entry_t * cnat_main_db
Definition: cnat_db_v2.c:201
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
void icmp_error_generate_v6(spp_ctx_t *ctx, u8 icmp_type, u8 icmp_code, u16 uidb_index)
#define COUNTER_BUFFER_SIZE
Definition: cnat_global.h:82
#define ICMPV6_TIMEEXCEEDED
#define PREDICT_TRUE(x)
Definition: clib.h:98
u32 null_deq_ctx
Definition: cnat_global.c:36
u32 cnat_main_db_icmp_rate_limit_core
Definition: cnat_config.c:51
void ipv4_decr_ttl_n_calc_csum(ipv4_header *ipv4)
Fixed length block allocator.
u32 * free_indices
Vector of free indices.
Definition: pool.h:58
u32 cnat_current_time
Definition: cnat_global.c:29
u16 cnat_static_port_range
Definition: cnat_config.c:53
cnat_icmp_msg_t v6_icmp_msg_gen_allowed()
Definition: cnat_db.h:153
u32 null_enq_pkt
Definition: cnat_global.c:32
#define CNAT_MAIN_HASH_SIZE
Definition: cnat_db.h:55
index_slist_t in2out_hash
Definition: cnat_db.h:156
#define TCP_FLAG_SYN
Definition: l2sess.h:48
cnat_errno_t
Definition: cnat_cli.h:26
#define ICMPV4_TIMTTL
void cnat_log_nat44_tcp_seq_mismatch(cnat_main_db_entry_t *db, cnat_vrfmap_t *vrfmap)
#define ICMPV6_ERR_SIZE
#define CNAT_TRANSLATION_ENTRY_STATIC
#define CNAT_VRF_MASK
Definition: cnat_db.h:96
index_slist_t out2in_hash
Definition: cnat_db.h:155
u32 sf_alloc_errs
Definition: cnat_global.c:42
#define IPV6_PROTO_TCP
index_slist_t * cnat_in2out_hash
Definition: cnat_db_v2.c:196
#define PLATFORM_DEBUG_PRINT(...)
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:348
void cnat_port_free_v2(cnat_portmap_v2_t *pm, int index, port_pair_t pair_type, u16 base_port, u16 static_port_range)
Definition: cnat_ports.c:1037
cnat_main_db_entry_t * cnat_get_main_db_entry_v2(cnat_db_key_bucket_t *ki, port_pair_t port_pair_type, port_type_t port_type, cnat_gen_icmp_info *info, cnat_key_t *dest_info)
Definition: cnat_db_v2.c:1647
void spp_printf(u16 error_code, u16 num_args, u32 *arg)
cnat_key_t k
Definition: cnat_db.h:113
u32 null_enq_ctx
Definition: cnat_global.c:35
#define PORTS_PER_ADDR
Definition: cnat_ports.h:26
u16 * cnat_portmap_indices_by_vrf
index_slist_t * cnat_user_hash
Definition: cnat_db_v2.c:197
static pool_header_t * pool_header(void *v)
Get pool header from user pool pointer.
Definition: pool.h:67
u32 null_enq_wqe
Definition: cnat_global.c:38
index_slist_t user_hash
Definition: cnat_db.h:287
#define CNAT_TAC_SEQ_MISMATCH
Definition: cnat_db.h:181
u16 ** cnat_portmaps_inuse
cnat_svi_params_entry svi_params_array[CNAT_MAX_VRFMAP_ENTRIES]
Definition: cnat_db_v2.c:226
#define S_RUN
Definition: cnat_db.h:416
u32 null_deq_wqe
Definition: cnat_global.c:39
#define PREDICT_FALSE(x)
Definition: clib.h:97
struct _spp_api_cnat_v4_config_nfv9_logging spp_api_cnat_v4_config_nfv9_logging_t
int icmpv6_generate_with_throttling(spp_ctx_t *ctx, ipv6_header_t *ipv4, u16 rx_uidb_index)
struct icmp_v4_s icmp_v4_t
int icmpv4_generate_with_throttling(spp_ctx_t *ctx, ipv4_header *ipv4, u16 rx_uidb_index)
cnat_user_db_entry_t * cnat_user_db
Definition: cnat_db_v2.c:202
struct tcp_hdr_type tcp_hdr_type
void calculate_window_scale(tcp_hdr_type *tcp_header, u8 *scale)
Definition: cnat_util.c:2135
static u32 crc_calc(ipv4_header *ipv4)
#define IPV6_PROTO_UDP
#define IPV6_PROTO_ICMPV6
cnat_errno_t cnat_dynamic_port_alloc_v2(cnat_portmap_v2_t *pm, port_alloc_t atype, port_pair_t pair_type, u32 *index, u32 *o_ipv4_address, u16 *o_port, u16 static_port_range, bulk_alloc_size_t bulk_size, int *nfv9_log_req, u16 ip_n_to_1, u32 *rseed_ip)
Definition: cnat_ports.c:554
#define ICMPV6_HDR_SIZE
struct _spp_api_cnat_v4_show_outside_entry_req spp_api_cnat_v4_show_outside_entry_req_t
struct _spp_api_cnat_v4_add_vrf_map spp_api_cnat_v4_add_vrf_map_t
static uword clib_bitmap_get(uword *ai, uword i)
Gets the ith bit value from a bitmap.
Definition: bitmap.h:197
cnat_db_key_t k
Definition: cnat_db.h:108
#define BULKSIZE_FROM_VRFMAP(vrfmap)
#define CNAT_DEBUG_GLOBAL_ALL
Definition: cnat_cli.h:94
Definition: cnat_db.h:285
unsigned int u32
Definition: types.h:88
u32 entry_expires
Definition: cnat_db.h:213
cnat_icmp_msg_t
Definition: cnat_db.h:522
#define IPV6_HDR_LEN
struct ipv4_header ipv4_header
port_alloc_t
Definition: cnat_ports.h:96
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
#define CNAT_TCP
Definition: cnat_db.h:94
u32 rseed_ip
Definition: cnat_db.h:443
port_pair_t
Definition: cnat_ports.h:82
cnat_portmap_t ** cnat_portmaps
struct counter_array_t err_cnt_arr[COUNTER_BUFFER_SIZE]
Definition: cnat_global.h:83
void print_ipv6_pkt(ipv6_header_t *ip)
void cnat_delete_main_db_entry_v2(cnat_main_db_entry_t *ep)
Definition: cnat_db_v2.c:763
u32 ctx_alloc_errs
Definition: cnat_global.c:41
uword * free_bitmap
Bitmap of indices of free objects.
Definition: pool.h:55
cnat_icmp_msg_t icmp_msg_gen_allowed()
Definition: cnat_syslog.c:448
unsigned short u16
Definition: types.h:57
#define CNAT_DEBUG_NONE
Definition: cnat_cli.h:85
cnat_vrfmap_t * cnat_map_by_vrf
Definition: cnat_db_v2.c:218
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
#define CNAT_USER_HASH_SIZE
Definition: cnat_db.h:59
u32 null_deq_pkt
Definition: cnat_global.c:33
#define ICMP_PROT
struct _spp_ctx spp_ctx_t
#define ICMPV6_TIMTTL
struct _spp_api_cnat_v4_single_vrf_map_req spp_api_cnat_v4_single_vrf_map_req
int v4_crc_zero_udp_allowed()
static void * vec_header(void *v, uword header_bytes)
Find a user vector header.
Definition: vec_bootstrap.h:92
#define EMPTY
Definition: index_list.h:24
#define IPV6_MIN_PATH_MTU
#define PLATFORM_CNAT_SET_TX_VRF(ctx, tx_vrf)
u32 db_free_entry(void *p)
u32 crc_zero_udp_rate_limit_core
Definition: cnat_config.c:52
#define ICMPV4_TIMEEXCEEDED
CLIB vectors are ubiquitous dynamically resized arrays with by user defined "headers".