Initial commit of vpp code.
[vpp.git] / vnet / vnet / vcgn / cnat_util.c
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
48 (spp_api_cnat_v4_show_outside_entry_req_t *mp);
49
50 void spp_api_cnat_v4_show_inside_entry_req_t_handler
51 (spp_api_cnat_v4_show_inside_entry_req_t *mp);
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;
62     cnat_main_db_entry_t *db;
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           
84             db->entry_expires = cnat_current_time;
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
106     spp_api_cnat_v4_show_inside_entry_req_t mp1[2000];
107     spp_api_cnat_v4_show_outside_entry_req_t mp2[30000];
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 {
202     cnat_main_db_entry_t * db;
203     u32 index;
204
205     pool_header_t * p = vec_header(cnat_main_db, sizeof(pool_header_t) );
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;
212             cnat_delete_main_db_entry_v2(db);
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;
301     cnat_main_db_entry_t * db;
302     u32 hash_depth[MAX_DEPTH];
303
304     memset(hash_depth, 0, sizeof(u32)*MAX_DEPTH);
305
306     n = vec_len(cnat_in2out_hash);
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
348     n = vec_len(cnat_out2in_hash);
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",
561             vec_len(cnat_portmap_indices_by_vrf));
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,
587                           PORT_ALLOC_ANY, PORT_S_ODD,
588                           &pm_index, &ipv4_address, &aport);
589 #else
590     rv = cnat_port_alloc (pm, pm_inuse,
591                           PORT_ALLOC_ANY, PORT_S_ODD,
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,
607                               PORT_ALLOC_DIRECTED, PORT_SINGLE,
608                               &pm_index, &ipv4_address, &aport);
609 #else
610         rv = cnat_port_alloc (pm, pm_inuse,
611                               PORT_ALLOC_DIRECTED, PORT_SINGLE,
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(
778                            CNAT_DEBUG_FLAG_UDP_INSIDE_PACKET_DUMP);
779     } else {
780         mp->param[0] = spp_host_to_net_byte_order_32(
781                            CNAT_DEBUG_FLAG_UDP_OUTSIDE_PACKET_DUMP);
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(
805                            CNAT_DEBUG_FLAG_UDP_INSIDE_CHECKSUM_MODIFY);
806     } else {
807         mp->param[0] = spp_host_to_net_byte_order_32(
808                            CNAT_DEBUG_FLAG_UDP_OUTSIDE_CHECKSUM_MODIFY);
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",
875             vec_len(cnat_portmap_indices_by_vrf));
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
930 (spp_api_cnat_v4_add_vrf_map_t *mp);
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 {
944     spp_api_cnat_v4_add_vrf_map_t *mp;
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
1078     rv = cnat_dynamic_port_alloc_v2 (pm,  PORT_ALLOC_ANY, PORT_S_ODD,
1079                           &my_index, &ipv4_address, &aport, 
1080                           cnat_static_port_range
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++) {
1099         rv = cnat_dynamic_port_alloc_v2 (pm, PORT_ALLOC_DIRECTED, PORT_SINGLE, 
1100                           &my_index, &ipv4_address, &aport,
1101                           cnat_static_port_range
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++) {
1137         rv = cnat_dynamic_port_alloc_v2 (pm, PORT_ALLOC_DIRECTED, pt1, 
1138                           &my_index, &ipv4_address, &aport,
1139                           cnat_static_port_range
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) {
1157             rv = cnat_dynamic_port_alloc_v2 (pm, PORT_ALLOC_DIRECTED, pt2,
1158                           &my_index, &ipv4_address, &aport,
1159                           cnat_static_port_range
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",
1239             vec_len(cnat_portmap_indices_by_vrf));
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 {
1347     spp_api_cnat_v4_config_nfv9_logging_t *mp;
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;
1484             spp_api_cnat_v4_single_vrf_map_req *mp_sp;
1485
1486             u32 mp_size = sizeof(spp_api_cnat_v4_bulk_vrf_map_t) +
1487                           (sizeof(spp_api_cnat_v4_single_vrf_map_req))*2;
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
1496             mp_sp = (spp_api_cnat_v4_single_vrf_map_req *)
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) +
1555                 (sizeof(spp_api_cnat_v4_single_vrf_map_req))*2;
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 {
1593     spp_api_cnat_v4_config_nfv9_logging_t *mp;
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
1638 cnat_icmp_msg_t icmp_msg_gen_allowed ()
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
1670 cnat_icmp_msg_t v6_icmp_msg_gen_allowed ()
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;
1700 int v4_crc_zero_udp_allowed ()
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 <= 
1716                 crc_zero_udp_rate_limit_core)) {
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(
1729 void ipv4_decr_ttl_n_calc_csum(ipv4_header *ipv4))
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
2064 int icmpv4_generate_with_throttling (spp_ctx_t *ctx, ipv4_header *ipv4, 
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     
2106 int icmpv6_generate_with_throttling (spp_ctx_t *ctx, ipv6_header_t *ipv6,
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 inline 
2136 void calculate_window_scale(tcp_hdr_type *tcp_header, u8 *scale) {
2137     
2138     u8 check_options = 0;
2139
2140     *scale = 0;
2141     check_options = ((tcp_header->flags & TCP_FLAG_SYN) &&
2142                     (((tcp_header->hdr_len>>4) << 2) > sizeof(tcp_hdr_type)));
2143     
2144     if (PREDICT_FALSE(check_options)) {
2145          u8 *options_ptr = tcp_findoption(tcp_header, TCP_OPTION_WINDOW_SCALE);
2146
2147          /*
2148           * TCP option field: | kind 1B | len 1B | value 2B|
2149           *     where kind != [0, 1]
2150           */
2151          if (PREDICT_TRUE(options_ptr && 
2152                          (options_ptr[1] == TCP_OPTION_WINDOW_SCALE))) {
2153              u8 *ptr  = (u8*)(options_ptr + 2);
2154              *scale    = *ptr;
2155
2156              if(PREDICT_FALSE(*scale >= 14)) {
2157                  *scale = 14;
2158              }
2159
2160              return;
2161          }
2162     }    
2163 }            
2164
2165 #if 0
2166 ALWAYS_INLINE(
2167 void cnat_log_nat44_tcp_seq_mismatch(
2168                    cnat_main_db_entry_t *db,
2169                    cnat_vrfmap_t *vrfmap))
2170 {
2171      /* As of now, Netflow does not require this to be logged
2172       * So only syslog
2173       */
2174       if(PREDICT_TRUE(db->flags & CNAT_TAC_SEQ_MISMATCH)) {
2175               /* Already logged ..*/
2176           return;
2177       }
2178      /* else, set the flag and call the log API */
2179
2180      db->flags = db->flags | CNAT_TAC_SEQ_MISMATCH;
2181                                   
2182      cnat_syslog_nat44_tcp_seq_mismatch(db, vrfmap);
2183 }
2184          
2185                                     
2186 static int cnat_util_init (void *notused)
2187 {
2188     /* run SPP_API_CNAT_PORTMAP_CREATE first*/
2189     spp_msg_api_set_handler(SPP_API_CNAT_PORT_ALLOCATE,
2190                             spp_api_cnat_port_allocate_t_handler);
2191
2192
2193     spp_msg_api_set_handler(SPP_API_CNAT_PORT_CLEAR,
2194                             spp_api_cnat_port_clear_t_handler);
2195
2196     /* run vrfmap config first */
2197     spp_msg_api_set_handler(SPP_API_CNAT_PORT_CREATE,
2198                             spp_api_cnat_port_create_t_handler);
2199
2200     spp_msg_api_set_handler(SPP_API_CNAT_PORT_DELETE,
2201                             spp_api_cnat_port_delete_t_handler);
2202     return 0;
2203 }
2204
2205 void
2206 print_ipv6_pkt (ipv6_header_t *ip)
2207 {
2208     u32 i, total_len, l4_len=0;
2209
2210     u8 *pkt = (u8 *) ip;
2211
2212     total_len = spp_net_to_host_byte_order_16(&ip->payload_length);
2213
2214     /* we rarely need to debug > 200 bytes of packet */
2215     if(total_len > 200) {
2216         total_len = 200;
2217     }
2218
2219     printf("\n======== PRINTING PKT START======\n");
2220     printf("======== IPv6 PAYLOAD LEN %d ===========\n", total_len);
2221     for (i=0; i < 40; i++) {
2222        printf(" %02X ", *(pkt + i));
2223        if(i%16==15)
2224            printf("\n");
2225     }
2226     
2227     if (ip->next_header == IPV6_PROTO_TCP) {
2228         printf("\n======== TCP HEADER =================\n");
2229         l4_len = 20;
2230     }
2231     else if (ip->next_header == IPV6_PROTO_UDP) {
2232         printf("\n======== UDP HEADER =================\n");
2233         l4_len = 8;
2234     }
2235     else if (ip->next_header == IPV6_PROTO_ICMPV6) {
2236         printf("\n======== ICMP HEADER =================\n");
2237         l4_len = 8;
2238     }
2239
2240     for (i=40; i < (l4_len + 40); i++) {
2241        printf(" %02X ", *(pkt + i));
2242     }
2243
2244     printf("\n======== LAYER4 PAYLOAD ===================\n");
2245     for (i=(l4_len + 40); i < total_len; i++) {
2246        printf(" %02X ", *(pkt + i));
2247        if(i%16==15)
2248            printf("\n");
2249     }
2250
2251     printf("\n======== PRINTING PKT END =======\n");
2252 }
2253
2254
2255
2256 PLATFORM_SPP_INIT_FUNCTION(cnat_util_init);
2257 #endif