vCGNAPT VNF initial check-in
[samplevnf.git] / VNFs / vCGNAPT / pipeline / pipeline_cgnapt_be.c
1 /*
2 // Copyright (c) 2017 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16
17 /**
18  * @file
19  * Pipeline CG-NAPT BE Implementation.
20  *
21  * Implementation of Pipeline CG-NAPT Back End (BE).
22  * Provides NAPT service on dataplane packets.
23  * Runs on a core as defined in the config file.
24  *
25  */
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <stdint.h>
30 #include <string.h>
31 #include <unistd.h>
32
33 #include <rte_common.h>
34 #include <rte_malloc.h>
35 #include <rte_ip.h>
36 #include <rte_tcp.h>
37 #include <rte_udp.h>
38 #include <rte_icmp.h>
39 #include <rte_hash.h>
40 #include <rte_byteorder.h>
41 #include <rte_table_lpm.h>
42 #include <rte_table_hash.h>
43 #include <rte_table_stub.h>
44 #include <rte_ring.h>
45 #include <rte_mempool.h>
46
47 #include <rte_jhash.h>
48 #include <rte_cycles.h>
49 #include <rte_ethdev.h>
50 #include <rte_pipeline.h>
51 #include <rte_timer.h>
52 #include <rte_config.h>
53 #include <rte_prefetch.h>
54 #include <rte_hexdump.h>
55
56 #include "pipeline_cgnapt_be.h"
57 #include "pipeline_cgnapt_common.h"
58 #include "pipeline_actions_common.h"
59 #include "hash_func.h"
60 #include "pipeline_arpicmp_be.h"
61 #include "vnf_common.h"
62 #include "app.h"
63 #include "pipeline_common_be.h"
64 #include "vnf_common.h"
65 #include "lib_sip_alg.h"
66 #include "lib_icmpv6.h"
67
68 #include "pipeline_common_fe.h"
69 #ifdef CT_CGNAT
70 #include "rte_ct_tcp.h"
71 #include "rte_cnxn_tracking.h"
72 #endif
73 #ifdef FTP_ALG
74 #include "lib_ftp_alg.h"
75 #endif
76 #ifdef PCP_ENABLE
77 #include "cgnapt_pcp_be.h"
78 #endif
79
80 /* To maintain all cgnapt pipeline pointers used for all stats */
81 struct pipeline_cgnapt *all_pipeline_cgnapt[128];
82 uint8_t n_cgnapt_pipeline;
83
84 /* To know egress or ingress port */
85 static uint8_t cgnapt_in_port_egress_prv[PIPELINE_MAX_PORT_IN];
86 static uint8_t cgnapt_prv_que_port_index[PIPELINE_MAX_PORT_IN];
87
88 /* Max port per client declarations */
89
90 struct rte_hash_parameters max_port_per_client_hash_params = {
91         .name = "MAX_PORT_PER_CLIENT",
92         .entries = MAX_DYN_ENTRY,
93         .key_len = sizeof(struct max_port_per_client_key),
94         .hash_func = rte_jhash,
95         .hash_func_init_val = 0,
96 };
97 #ifdef CT_CGNAT
98 struct rte_ct_cnxn_tracker *cgnat_cnxn_tracker;
99 #endif
100
101 /***** Common Port Allocation declarations *****/
102
103 struct rte_ring *port_alloc_ring[MAX_CGNAPT_SETS] = { NULL, NULL, NULL, NULL,
104                                                 NULL, NULL, NULL, NULL };
105 const char *napt_port_alloc_ring_name[MAX_CGNAPT_SETS] = {
106         "NAPT_PORT_ALLOC_0 ",
107         "NAPT_PORT_ALLOC_1 ",
108         "NAPT_PORT_ALLOC_2 ",
109         "NAPT_PORT_ALLOC_3 ",
110         "NAPT_PORT_ALLOC_4 ",
111         "NAPT_PORT_ALLOC_5 ",
112         "NAPT_PORT_ALLOC_6 ",
113         "NAPT_PORT_ALLOC_7 "
114 };
115
116 int vnf_set_count = -1;
117
118 struct app_params *myApp;
119
120 /***** Common Port Allocation declarations *****/
121 int napt_port_alloc_elem_count;
122
123 /***** Common Table declarations *****/
124 struct rte_hash_parameters napt_common_table_hash_params = {
125         .name = "NAPT_COM_TBL",
126         .entries = MAX_NAPT_ENTRIES,
127         .key_len = sizeof(struct pipeline_cgnapt_entry_key),
128         .hash_func = rte_jhash,
129         .hash_func_init_val = 0,
130         .extra_flag = 1,
131 };
132
133 /***** ARP local cache *****/
134 uint8_t link_hw_laddr_valid[MAX_NUM_LOCAL_MAC_ADDRESS] = {
135         0, 0, 0, 0, 0, 0, 0, 0,
136         0, 0, 0, 0, 0, 0, 0, 0
137 };
138
139 struct ether_addr link_hw_laddr[MAX_NUM_LOCAL_MAC_ADDRESS] = {
140         {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
141         {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
142         {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
143         {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
144         {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
145         {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
146         {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
147         {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
148         {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
149         {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
150         {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
151         {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
152         {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
153         {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
154         {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
155         {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }
156 };
157
158 /****** NAT64 declarations *****/
159
160 uint8_t well_known_prefix[16] = {
161         0x00, 0x64, 0xff, 0x9b,
162         0x00, 0x00, 0x00, 0x00,
163         0x00, 0x00, 0x00, 0x00,
164         0x00, 0x00, 0x00, 0x00
165 };
166
167 static uint32_t local_get_nh_ipv4(
168         uint32_t ip,
169         uint32_t *port,
170         uint32_t *nhip,
171         struct pipeline_cgnapt *p_nat);
172
173 static void do_local_nh_ipv4_cache(
174         uint32_t dest_if,
175         struct pipeline_cgnapt *p_nat);
176
177 static uint32_t local_get_nh_ipv6(
178         uint8_t *ip,
179         uint32_t *port,
180         uint8_t nhip[],
181         struct pipeline_cgnapt *p_nat);
182
183 static void do_local_nh_ipv6_cache(
184         uint32_t dest_if,
185         struct pipeline_cgnapt *p_nat);
186
187 static uint8_t check_arp_icmp(
188         struct rte_mbuf *pkt,
189         uint64_t pkt_mask,
190         struct pipeline_cgnapt *p_nat);
191
192 /* Finds next power of two for n. If n itself
193  * is a power of two then returns n
194  *
195  * @param n
196  *      Value usually 32-bit value
197  *
198  * @return
199  *      Value after roundup to power of 2
200 */
201 uint64_t nextPowerOf2(uint64_t n)
202 {
203         n--;
204         n |= n >> 1;
205         n |= n >> 2;
206         n |= n >> 4;
207         n |= n >> 8;
208         n |= n >> 16;
209         n |= n >> 32;
210         n++;
211         return n;
212 }
213
214 /**
215  * Function to get MAC addr of local link
216  *
217  * @params out_port
218  *  Physical port number
219  *
220  * @return
221  *  Outport Link MAC addr
222  */
223
224 struct ether_addr *get_local_link_hw_addr(uint8_t out_port)
225 {
226         return &link_hw_laddr[out_port];
227 }
228
229 /**
230  * Function to get MAC addr from array instead of hash table
231  *
232  * @params out_port
233  *  Physical port number
234  *
235  * @return
236  *  Outport Link MAC addr
237  */
238
239 uint8_t local_dest_mac_present(uint8_t out_port)
240 {
241         return link_hw_laddr_valid[out_port];
242 }
243
244 /**
245  * Function to get IPv4-IP NH from thread local array
246  *
247  * @params ip
248  *  IPv4 - IP
249  * @params port
250  *  NH port number
251  * @params nhip
252  *  NHIP of IPv4 type
253  * @params p_nat
254  *  CGNAPT pipeline ptr
255  *
256  * @return
257  *  1 on success, 0 for failure
258  */
259
260 static uint32_t local_get_nh_ipv4(
261         uint32_t ip,
262         uint32_t *port,
263         uint32_t *nhip,
264         struct pipeline_cgnapt *p_nat)
265 {
266         int i;
267         for (i = 0; i < p_nat->local_lib_arp_route_ent_cnt; i++) {
268                 if (((p_nat->local_lib_arp_route_table[i].ip &
269                         p_nat->local_lib_arp_route_table[i].mask) ==
270                         (ip & p_nat->local_lib_arp_route_table[i].mask))) {
271                         *port = p_nat->local_lib_arp_route_table[i].port;
272
273                         *nhip = p_nat->local_lib_arp_route_table[i].nh;
274                         return 1;
275                 }
276         }
277         return 0;
278 }
279
280 /**
281  * Function to make local copy for NH of type IPv4
282  *
283  * @params dest_if
284  *  Physical port number
285  * @params p_nat
286  *  CGNAPT pipeline ptr
287  *
288  */
289
290 static void do_local_nh_ipv4_cache(
291         uint32_t dest_if,
292         struct pipeline_cgnapt *p_nat)
293 {
294
295         /* Search for the entry and do local copy */
296         int i;
297
298         for (i = 0; i < MAX_ARP_RT_ENTRY; i++) {
299                 if (lib_arp_route_table[i].port == dest_if) {
300
301                         struct lib_arp_route_table_entry *lentry =
302                                 &p_nat->local_lib_arp_route_table
303                                         [p_nat->local_lib_arp_route_ent_cnt];
304
305                         lentry->ip   = lib_arp_route_table[i].ip;
306                         lentry->mask = lib_arp_route_table[i].mask;
307                         lentry->port = lib_arp_route_table[i].port;
308                         lentry->nh   = lib_arp_route_table[i].nh;
309
310                         p_nat->local_lib_arp_route_ent_cnt++;
311                                                 break;
312                 }
313         }
314 }
315
316
317 /**
318  * Function to get IPv6-IP NH from thread local array
319  *
320  * @params ip
321  *  Pointer to starting addr of IPv6
322  * @params port
323  *  NH port number
324  * @params nhip
325  *  NHIP of IPv6 type
326  * @params p_nat
327  *  CGNAPT pipeline ptr
328  *
329  * @return
330  *  1 on success, 0 for failure
331  */
332
333 static uint32_t local_get_nh_ipv6(
334         uint8_t *ip,
335         uint32_t *port,
336         uint8_t nhip[],
337         struct pipeline_cgnapt *p_nat)
338 {
339         int i = 0;
340         uint8_t netmask_ipv6[16];
341         uint8_t k = 0, l = 0, depthflags = 0, depthflags1 = 0;
342
343         for (i = 0; i < p_nat->local_lib_nd_route_ent_cnt; i++) {
344
345                 convert_prefixlen_to_netmask_ipv6(
346                         p_nat->local_lib_nd_route_table[i].depth,
347                         netmask_ipv6);
348
349                 for (k = 0; k < 16; k++)
350                         if (p_nat->local_lib_nd_route_table[i].ipv6[k] &
351                                         netmask_ipv6[k])
352                                 depthflags++;
353
354                 for (l = 0; l < 16; l++)
355                         if (ip[l] & netmask_ipv6[l])
356                                 depthflags1++;
357
358                 int j = 0;
359                 if (depthflags == depthflags1) {
360                         *port = p_nat->local_lib_nd_route_table[i].port;
361
362                         for (j = 0; j < 16; j++)
363                                 nhip[j] = p_nat->local_lib_nd_route_table[i].
364                                                 nhipv6[j];
365                         return 1;
366                 }
367
368                 depthflags = 0;
369                 depthflags1 = 0;
370                         }
371                         return 0;
372 }
373
374
375 /**
376  * Function to make local copy for NH of type IPv6
377  *
378  * @params dest_if
379  *  Physical port number
380  * @params p_nat
381  *  CGNAPT pipeline ptr
382  *
383  */
384
385 static void do_local_nh_ipv6_cache(
386         uint32_t dest_if,
387         struct pipeline_cgnapt *p_nat)
388 {
389                 /* Search for the entry and do local copy */
390         int i, l;
391         for (i = 0; i < MAX_ND_RT_ENTRY; i++) {
392
393                 if (lib_nd_route_table[i].port == dest_if) {
394
395                         struct lib_nd_route_table_entry *lentry =
396                                 &p_nat->local_lib_nd_route_table
397                                         [p_nat->local_lib_nd_route_ent_cnt];
398
399                         for (l = 0; l < 16; l++) {
400                                 lentry->ipv6[l]   =
401                                         lib_nd_route_table[i].ipv6[l];
402                                 lentry->nhipv6[l] =
403                                         lib_nd_route_table[i].nhipv6[l];
404                         }
405                         lentry->depth = lib_nd_route_table[i].depth;
406                         lentry->port  = lib_nd_route_table[i].port;
407
408                         p_nat->local_lib_nd_route_ent_cnt++;
409                         break;
410                         } //if
411                 } //for
412 }
413
414 #ifdef SIP_ALG
415 /* Commented code may be required for future usage, Please keep it*/
416 #if 0
417 static int retrieve_cgnapt_entry_alg(
418         struct pipeline_cgnapt_entry_key *key,
419         struct cgnapt_table_entry **entry_ptr1,
420         struct cgnapt_table_entry **entry_ptr2)
421 {
422         #ifdef CGNAPT_DBG_PRNT
423         printf("retrieve_cgnapt_entry key detail Entry:"
424                 "0x%x, %d, %d\n", key->ip, key->port,
425                 key->pid);
426         #endif
427
428         int position = rte_hash_lookup(napt_common_table, key);
429         if (position < 0) {
430                 printf("Invalid cgnapt entry position(first_key): %d\n",
431                         position);
432                 return 0;
433         }
434
435         *entry_ptr1 = &napt_hash_tbl_entries[position];
436
437         uint32_t prv_ip = (*entry_ptr1)->data.prv_ip;
438         uint32_t prv_port = (*entry_ptr1)->data.prv_port;
439         uint32_t prv_phy_port = (*entry_ptr1)->data.prv_phy_port;
440
441         struct pipeline_cgnapt_entry_key second_key;
442         second_key.ip = prv_ip;
443         second_key.port = prv_port;
444         second_key.pid = prv_phy_port;
445
446         position = rte_hash_lookup(napt_common_table, &second_key);
447         if (position < 0) {
448                 printf("Invalid cgnapt entry position(second_key): %d\n",
449                         position);
450                 return 0;
451         }
452
453         *entry_ptr2 = &napt_hash_tbl_entries[position];
454
455         return 1;
456 }
457 #endif
458
459 int add_dynamic_cgnapt_entry_alg(
460         struct pipeline *p,
461         struct pipeline_cgnapt_entry_key *key,
462         struct cgnapt_table_entry **entry_ptr1,
463         struct cgnapt_table_entry **entry_ptr2)
464 {
465         int port_num = 0, ret;
466
467         struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
468
469         #ifdef CGNAPT_DBG_PRNT
470         if (CGNAPT_DEBUG >= 1) {
471                 printf("Th%d add_dynamic_cgnapt_entry key detail Entry:"
472                 "0x%x, %d, %d\n", p_nat->pipeline_num, key->ip, key->port,
473                 key->pid);
474         }
475         #endif
476
477         int32_t position = rte_hash_lookup(napt_common_table, key);
478         if (position >= 0) {
479                 #ifdef CGNAPT_DBG_PRNT
480                 if (CGNAPT_DEBUG >= 1) {
481                         printf("%s: cgnapt entry exists in "
482                         "position(first_key): %d\n", __func__, position);
483                 }
484                 #endif
485                 *entry_ptr1 = &napt_hash_tbl_entries[position];
486                 /* not required, as it is not used in the caller */
487                 *entry_ptr2 = NULL;
488                 return 1;
489         }
490
491
492         ret = increment_max_port_counter(key->ip, key->pid, p_nat);
493         if (ret == MAX_PORT_INC_ERROR) {
494
495                 #ifdef CGNAPT_DBG_PRNT
496                 if (CGNAPT_DEBUG > 1)
497                         printf("add_dynamic_cgnapt_entry:"
498                         "increment_max_port_counter-1 failed\n");
499                 #endif
500
501                 return 0;
502         }
503
504         if (ret == MAX_PORT_INC_REACHED) {
505
506                 #ifdef CGNAPT_DBG_PRNT
507                 if (CGNAPT_DEBUG > 1)
508                         printf("add_dynamic_cgnapt_entry:"
509                         "increment_max_port_counter-2 failed\n");
510                 #endif
511
512                 return 0;
513         }
514
515         uint32_t public_ip;
516         port_num = get_free_iport(p_nat, &public_ip);
517
518         if (port_num == -1) {
519
520                 #ifdef CGNAPT_DBG_PRNT
521                 if (CGNAPT_DEBUG > 2) {
522                         printf("add_dynamic_cgnapt_entry: %d\n", port_num);
523                         printf("add_dynamic_cgnapt_entry key detail:0x%x, "
524                         "%d, %d\n", key->ip, key->port, key->pid);
525                 }
526                 #endif
527
528                 return 0;
529         }
530
531         /* check for max_clients_per_ip */
532         if (rte_atomic16_read
533                 (&all_public_ip
534                  [rte_jhash(&public_ip, 4, 0) % 16].count) ==
535                 p_nat->max_clients_per_ip) {
536                 /* For now just bail out
537                 * In future we can think about
538                 * retrying getting a new iport
539                 */
540                 release_iport(port_num, public_ip, p_nat);
541
542                 return 0;
543         }
544
545         rte_atomic16_inc(&all_public_ip
546                          [rte_jhash(&public_ip, 4, 0) %
547                                 16].count);
548
549         #ifdef CGNAPT_DBG_PRNT
550                 if ((rte_jhash(&public_ip, 4, 0) % 16) == 8)
551                         printf("pub ip:%x coutn:%d\n", public_ip,
552                         rte_atomic16_read(&all_public_ip
553                         [rte_jhash(&public_ip, 4, 0) % 16].count));
554         #endif
555
556         #ifdef CGNAPT_DBG_PRNT
557                 if (CGNAPT_DEBUG > 0) {
558                         printf("add_dynamic_cgnapt_entry: %d\n",
559                                 port_num);
560                         printf("add_dynamic_cgnapt_entry key detail: "
561                         "0x%x, %d, %d\n", key->ip, key->port, key->pid);
562         }
563         #endif
564
565         struct cgnapt_table_entry entry = {
566                 .head = {
567                  .action = RTE_PIPELINE_ACTION_PORT,
568                 /* made it configurable below */
569                  {.port_id = p->port_out_id[0]},
570                  },
571
572                 .data = {
573                         .prv_port = key->port,
574                         .pub_ip = public_ip,
575                         .pub_port = port_num,
576                         .prv_phy_port = key->pid,
577                         .pub_phy_port = get_pub_to_prv_port(
578                                         &public_ip,
579                                         IP_VERSION_4),
580                         .ttl = 0,
581                         /* if(timeout == -1) : static entry
582                         *  if(timeout == 0 ) : dynamic entry
583                         *  if(timeout >  0 ) : PCP requested entry
584                         */
585                         .timeout = 0,
586                         #ifdef PCP_ENABLE
587                         .timer = NULL,
588                         #endif
589                 }
590         };
591
592         entry.data.u.prv_ip = key->ip;
593         entry.data.type = CGNAPT_ENTRY_IPV4;
594
595         entry.head.port_id = entry.data.pub_phy_port; /* outgoing port info */
596
597         struct pipeline_cgnapt_entry_key second_key;
598         /* Need to add a second ingress entry */
599         second_key.ip = public_ip;
600         second_key.port = port_num;
601         second_key.pid = 0xffff;
602
603         #ifdef CGNAPT_DBG_PRNT
604         if (CGNAPT_DEBUG > 2)
605                 printf("add_dynamic_cgnapt_entry second key detail:"
606                 "0x%x, %d, %d\n", second_key.ip, second_key.port,
607                 second_key.pid);
608         #endif
609
610         int32_t position1 = rte_hash_add_key(napt_common_table, (void *)key);
611
612         if (position1 < 0) {
613                 printf("CG-NAPT entry add failed ...returning "
614                 "without adding ... %d\n", position1);
615                 return 0;
616         }
617
618
619         #ifdef CGNAPT_DBG_PRNT
620         if (CGNAPT_DEBUG) {
621                 printf("add_dynamic_cgnapt_entry:");
622                 print_key(key);
623                 print_cgnapt_entry(&entry);
624         }
625         #endif
626
627         memcpy(&napt_hash_tbl_entries[position1], &entry,
628                          sizeof(struct cgnapt_table_entry));
629
630         /* this pointer is returned to pkt miss function */
631         *entry_ptr1 = &napt_hash_tbl_entries[position1];
632
633         p_nat->n_cgnapt_entry_added++;
634         p_nat->dynCgnaptCount++;
635
636         /* Now modify the forward port for reverse entry */
637
638         /* outgoing port info */
639         entry.head.port_id = entry.data.prv_phy_port;
640
641         int32_t position2 = rte_hash_add_key(napt_common_table, &second_key);
642
643         if (position2 < 0) {
644                 printf("CG-NAPT entry reverse bulk add failed ..."
645                 "returning with fwd add ...%d\n",
646                          position2);
647                 return 0;
648         }
649
650         memcpy(&napt_hash_tbl_entries[position2], &entry,
651                          sizeof(struct cgnapt_table_entry));
652
653         *entry_ptr2 = &napt_hash_tbl_entries[position2];
654
655         #ifdef CGNAPT_DBG_PRNT
656         if (CGNAPT_DEBUG >= 1) {
657                 printf("add_dynamic_cgnapt_entry position: %d, %d\n",
658                         position1, position2);
659                 printf("add_dynamic_cgnapt_entry: entry_ptr1: %p, "
660                 "entry_ptr2: %p\n", *entry_ptr1, *entry_ptr2);
661         }
662         #endif
663
664         timer_thread_enqueue(key, &second_key, *entry_ptr1,
665                 *entry_ptr2, (struct pipeline *)p_nat);
666
667         p_nat->n_cgnapt_entry_added++;
668         p_nat->dynCgnaptCount++;
669
670         return 1;
671 }
672
673 #endif
674
675 void hw_checksum(struct rte_mbuf *pkt, enum PKT_TYPE ver)
676 {
677         struct tcp_hdr *tcp = NULL;
678         struct udp_hdr *udp = NULL;
679         struct icmp_hdr *icmp = NULL;
680         uint8_t *protocol;
681         void *ip_header = NULL;
682         uint16_t prot_offset = 0;
683         uint32_t pkt_type_is_ipv4 = 1;
684         int temp = 0;
685         pkt->ol_flags |= PKT_TX_IP_CKSUM;
686         pkt->l2_len = ETH_HDR_SIZE;
687
688
689
690         switch (ver) {
691         case PKT_TYPE_IPV4to6:
692                 temp = -20;
693         case PKT_TYPE_IPV6:
694
695                 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
696                                 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
697
698                 pkt_type_is_ipv4 = 0;
699                 pkt->ol_flags |= PKT_TX_IPV6;
700                 pkt->l3_len =
701                         sizeof(struct ipv6_hdr);
702                 tcp = (struct tcp_hdr *)
703                         ((unsigned char *)ip_header +
704                          sizeof(struct ipv6_hdr));
705                 udp = (struct udp_hdr *)
706                         ((unsigned char *)ip_header +
707                          sizeof(struct ipv6_hdr));
708                 icmp = (struct icmp_hdr *)
709                         ((unsigned char *)ip_header +
710                          sizeof(struct ipv6_hdr));
711
712                 prot_offset = PROT_OFST_IP6 + temp;
713                 break;
714         case PKT_TYPE_IPV6to4:
715                 temp = 20;
716         case PKT_TYPE_IPV4:
717
718                 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
719                                 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
720
721                 pkt->ol_flags |= PKT_TX_IPV4;
722                 pkt->l3_len =
723                         sizeof(struct ipv4_hdr);
724                 tcp = (struct tcp_hdr *)
725                         ((unsigned char *)ip_header +
726                          sizeof(struct ipv4_hdr));
727                 udp = (struct udp_hdr *)
728                         ((unsigned char *)ip_header +
729                          sizeof(struct ipv4_hdr));
730                 icmp = (struct icmp_hdr *)
731                         ((unsigned char *)ip_header +
732                          sizeof(struct ipv4_hdr));
733                 struct ipv4_hdr *ip_hdr =
734                         (struct ipv4_hdr *)ip_header;
735                 ip_hdr->hdr_checksum = 0;
736
737                 prot_offset = PROT_OFST_IP4 + temp;
738                 break;
739         default:
740                 printf("hw_checksum: pkt version is invalid\n");
741         }
742         protocol = (uint8_t *) RTE_MBUF_METADATA_UINT8_PTR(pkt,
743                          prot_offset);
744
745         switch (*protocol) {
746         case IP_PROTOCOL_TCP:   /* 6 */
747                 tcp->cksum = 0;
748                 pkt->ol_flags |= PKT_TX_TCP_CKSUM;
749                 if (pkt_type_is_ipv4) {
750                         tcp->cksum = rte_ipv4_phdr_cksum(
751                                 (struct ipv4_hdr *)ip_header,
752                                 pkt->ol_flags);
753                 } else {
754                         tcp->cksum = rte_ipv6_phdr_cksum(
755                                 (struct ipv6_hdr *)ip_header,
756                                 pkt->ol_flags);
757                 }
758                 break;
759         case IP_PROTOCOL_UDP:   /* 17 */
760                 udp->dgram_cksum = 0;
761                 pkt->ol_flags |= PKT_TX_UDP_CKSUM;
762                 if (pkt_type_is_ipv4) {
763                         udp->dgram_cksum =
764                                 rte_ipv4_phdr_cksum(
765                                 (struct ipv4_hdr *)ip_header,
766                                 pkt->ol_flags);
767                 } else {
768                         udp->dgram_cksum =
769                                 rte_ipv6_phdr_cksum(
770                                 (struct ipv6_hdr *)ip_header,
771                                 pkt->ol_flags);
772                 }
773                 break;
774         case IP_PROTOCOL_ICMP:  /* 1 */
775                 if (pkt_type_is_ipv4) {
776                         /* ICMP checksum code */
777                         struct ipv4_hdr *ip_hdr =
778                                 (struct ipv4_hdr *)ip_header;
779                         int size = rte_bswap16(ip_hdr->total_length) - 20;
780                         icmp->icmp_cksum = 0;
781                         icmp->icmp_cksum =
782                                 ~rte_raw_cksum(icmp,
783                                                         size);
784                 }
785                 break;
786
787         default:
788                 printf("hw_checksum() : Neither TCP or UDP pkt\n");
789                 break;
790         }
791 }
792
793
794 void sw_checksum(struct rte_mbuf *pkt, enum PKT_TYPE ver)
795 {
796         struct tcp_hdr *tcp = NULL;
797         struct udp_hdr *udp = NULL;
798         struct icmp_hdr *icmp = NULL;
799         uint8_t *protocol;
800         void *ip_header = NULL;
801         uint16_t prot_offset = 0;
802         uint32_t pkt_type_is_ipv4 = 1;
803         int temp = 0;
804
805         switch (ver) {
806         case PKT_TYPE_IPV4to6:
807                 temp = -20;
808         case PKT_TYPE_IPV6:
809
810                 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
811                                 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
812
813                 pkt_type_is_ipv4 = 0;
814                 tcp = (struct tcp_hdr *)
815                         ((unsigned char *)ip_header +
816                          sizeof(struct ipv6_hdr));
817                 udp = (struct udp_hdr *)
818                         ((unsigned char *)ip_header +
819                          sizeof(struct ipv6_hdr));
820                 icmp = (struct icmp_hdr *)
821                         ((unsigned char *)ip_header +
822                          sizeof(struct ipv6_hdr));
823
824                 prot_offset = PROT_OFST_IP6 + temp;
825                 break;
826         case PKT_TYPE_IPV6to4:
827                 temp = 20;
828         case PKT_TYPE_IPV4:
829
830                 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
831                                 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
832
833                 tcp = (struct tcp_hdr *)
834                         ((unsigned char *)ip_header +
835                          sizeof(struct ipv4_hdr));
836                 udp = (struct udp_hdr *)
837                         ((unsigned char *)ip_header +
838                          sizeof(struct ipv4_hdr));
839                 icmp = (struct icmp_hdr *)
840                         ((unsigned char *)ip_header +
841                          sizeof(struct ipv4_hdr));
842
843                 prot_offset = PROT_OFST_IP4 + temp;
844                 break;
845         default:
846                 printf("sw_checksum: pkt version is invalid\n");
847         }
848         protocol = (uint8_t *) RTE_MBUF_METADATA_UINT8_PTR(pkt,
849                          prot_offset);
850
851         switch (*protocol) {
852         case IP_PROTOCOL_TCP:   /* 6 */
853                 tcp->cksum = 0;
854                 if (pkt_type_is_ipv4) {
855                         struct ipv4_hdr *ip_hdr =
856                                 (struct ipv4_hdr *)ip_header;
857                         tcp->cksum = rte_ipv4_udptcp_cksum(ip_hdr,
858                                         (void *)tcp);
859                         ip_hdr->hdr_checksum = 0;
860                         ip_hdr->hdr_checksum = rte_ipv4_cksum(
861                                                 (struct ipv4_hdr *)ip_hdr);
862                 } else {
863                         tcp->cksum = rte_ipv6_udptcp_cksum(
864                                         (struct ipv6_hdr *)
865                                         ip_header, (void *)tcp);
866                 }
867                 break;
868         case IP_PROTOCOL_UDP:   /* 17 */
869                 udp->dgram_cksum = 0;
870                 if (pkt_type_is_ipv4) {
871                         struct ipv4_hdr *ip_hdr =
872                                 (struct ipv4_hdr *)ip_header;
873                         udp->dgram_cksum = rte_ipv4_udptcp_cksum(
874                                                 ip_hdr, (void *)udp);
875                         ip_hdr->hdr_checksum = 0;
876                         ip_hdr->hdr_checksum = rte_ipv4_cksum(ip_hdr);
877                 } else {
878                         udp->dgram_cksum = rte_ipv6_udptcp_cksum(
879                                         (struct ipv6_hdr *)
880                                         ip_header, (void *)udp);
881                 }
882                 break;
883         case IP_PROTOCOL_ICMP:  /* 1 */
884                 if (pkt_type_is_ipv4) {
885                         /* ICMP checksum code */
886                         struct ipv4_hdr *ip_hdr =
887                                 (struct ipv4_hdr *)ip_header;
888                         int size = rte_bswap16(ip_hdr->total_length) - 20;
889                         icmp->icmp_cksum = 0;
890                         icmp->icmp_cksum =
891                                 ~rte_raw_cksum(icmp,
892                                                         size);
893                         ip_hdr->hdr_checksum = 0;
894                         ip_hdr->hdr_checksum = rte_ipv4_cksum(ip_hdr);
895                 }
896                 break;
897
898         default:
899                 printf("sw_checksum() : Neither TCP or UDP pkt\n");
900                 break;
901         }
902 }
903
904 static uint8_t check_arp_icmp(
905         struct rte_mbuf *pkt,
906         uint64_t pkt_mask,
907         struct pipeline_cgnapt *p_nat)
908 {
909         uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
910         uint16_t *eth_proto = RTE_MBUF_METADATA_UINT16_PTR(
911                                 pkt, eth_proto_offset);
912         struct app_link_params *link;
913         uint8_t solicited_node_multicast_addr[16] = {
914                 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
915                 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00};
916
917         /* ARP outport number */
918         uint16_t out_port = p_nat->p.n_ports_out - 1;
919
920         uint8_t *protocol;
921         uint32_t prot_offset;
922
923         link = &myApp->link_params[pkt->port];
924
925
926         switch (rte_be_to_cpu_16(*eth_proto)) {
927
928         case ETH_TYPE_ARP:
929
930                 rte_pipeline_port_out_packet_insert(
931                         p_nat->p.p,
932                         out_port,
933                         pkt);
934
935                 /*
936                 * Pkt mask should be changed, and not changing the
937                 * drop mask
938                 */
939                 p_nat->invalid_packets |= pkt_mask;
940                 p_nat->arpicmpPktCount++;
941
942                 return 0;
943         break;
944         case ETH_TYPE_IPV4: {
945                 /* header room + eth hdr size +
946                 * src_aadr offset in ip header
947                 */
948                 uint32_t dst_addr_offset = MBUF_HDR_ROOM +
949                         ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
950                 uint32_t *dst_addr =
951                         RTE_MBUF_METADATA_UINT32_PTR(pkt,
952                         dst_addr_offset);
953                 prot_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
954                         IP_HDR_PROTOCOL_OFST;
955                 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt,
956                         prot_offset);
957                 if ((*protocol == IP_PROTOCOL_ICMP) &&
958                         link->ip == rte_be_to_cpu_32(*dst_addr)) {
959
960                         if (is_phy_port_privte(pkt->port)) {
961
962                                 rte_pipeline_port_out_packet_insert(
963                                         p_nat->p.p, out_port, pkt);
964
965                                 /*
966                                 * Pkt mask should be changed,
967                                 * and not changing the drop mask
968                                 */
969
970                                 p_nat->invalid_packets |= pkt_mask;
971                                 p_nat->arpicmpPktCount++;
972
973                                 return 0;
974                         }
975                 }
976                 return 1;
977         }
978         break;
979
980         #ifdef IPV6
981         case ETH_TYPE_IPV6:
982         if (dual_stack_enable) {
983
984                 /* Commented code may be required for future usage,
985                 * Please keep it
986                 */
987                 //uint32_t dst_addr_offset = MBUF_HDR_ROOM +
988                 //      ETH_HDR_SIZE + IPV6_HDR_DST_ADR_OFST;
989                 //uint32_t *dst_addr =
990                 //      RTE_MBUF_METADATA_UINT32_PTR(pkt,
991                 //      dst_addr_offset);
992                 uint32_t prot_offset_ipv6 = MBUF_HDR_ROOM +
993                         ETH_HDR_SIZE + IPV6_HDR_PROTOCOL_OFST;
994                 struct ipv6_hdr *ipv6_h;
995
996                 ipv6_h = (struct ipv6_hdr *) MBUF_HDR_ROOM +
997                         ETH_HDR_SIZE;
998                 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt,
999                         prot_offset_ipv6);
1000
1001                 if (ipv6_h->proto == ICMPV6_PROTOCOL_ID) {
1002                         if (!memcmp(ipv6_h->dst_addr, link->ipv6, 16)
1003                                 || !memcmp(ipv6_h->dst_addr,
1004                                 solicited_node_multicast_addr, 13)) {
1005                                 rte_pipeline_port_out_packet_insert(
1006                                         p_nat->p.p, out_port, pkt);
1007                                 /*
1008                                 * Pkt mask should be changed,
1009                                 * and not changing the drop mask
1010                                 */
1011                                 p_nat->invalid_packets |= pkt_mask;
1012                                 p_nat->arpicmpPktCount++;
1013                         } else {
1014                                 p_nat->invalid_packets |= pkt_mask;
1015                                 p_nat->naptDroppedPktCount++;
1016
1017                         #ifdef CGNAPT_DEBUGGING
1018                                 p_nat->naptDroppedPktCount1++;
1019                         #endif
1020                         }
1021                         return 0;
1022                 }
1023         }
1024         break;
1025         #endif
1026         default:
1027                 return 1;
1028         }
1029         return 1;
1030 }
1031
1032 /**
1033  * Function to create common NAPT table
1034  * Called during pipeline initialization
1035  * Creates the common NAPT table
1036  * If it is not already created and stores its pointer
1037  * in global napt_common_table pointer.
1038  *
1039  * @params nFlows
1040  *  Max number of NAPT flows. This parameter is configurable via config file.
1041  *
1042  * @return
1043  *  0 on success, negative on error.
1044  */
1045 int create_napt_common_table(uint32_t nFlows)
1046 {
1047         if (napt_common_table != NULL) {
1048                 printf("napt_common_table already exists.\n");
1049                 return -1;
1050         }
1051
1052         napt_common_table = rte_hash_create(&napt_common_table_hash_params);
1053
1054         if (napt_common_table == NULL) {
1055                 printf("napt_common_table creation failed.\n");
1056                 return -2;
1057         }
1058
1059         uint32_t number_of_entries = nFlows;
1060
1061         uint32_t size =
1062                 RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_table_entry) *
1063                                          number_of_entries);
1064         napt_hash_tbl_entries = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1065
1066         if (napt_hash_tbl_entries == NULL) {
1067                 printf("napt_hash_tbl_entries creation failed. %d, %d\n",
1068                                  nFlows, (int)sizeof(struct cgnapt_table_entry));
1069                 return -3;
1070         }
1071
1072         return 0;
1073 }
1074
1075 /**
1076  * Function to initialize bulk port allocation data structures
1077  * Called during pipeline initialization.
1078  *
1079  * Creates the port alloc ring for the VNF_set this pipeline belongs
1080  *
1081  * Creates global port allocation buffer pool
1082  *
1083  * Initializes the port alloc ring according to config data
1084  *
1085  * @param p_nat
1086  *  A pointer to struct pipeline_cgnapt
1087  *
1088  * @return
1089  *  0 on success, negative on error.
1090  */
1091 int napt_port_alloc_init(struct pipeline_cgnapt *p_nat)
1092 {
1093         p_nat->allocated_ports = NULL;
1094         p_nat->free_ports = NULL;
1095
1096         uint32_t vnf_set_num = p_nat->vnf_set;
1097         /*uint32_t vnf_set_num = get_vnf_set_num(p_nat->pipeline_num); */
1098
1099         printf("VNF set number for CGNAPT %d is %d.\n", p_nat->pipeline_num,
1100                          vnf_set_num);
1101         if (vnf_set_num == 0xFF) {
1102                 printf("VNF set number for CGNAPT %d is invalid %d.\n",
1103                                  p_nat->pipeline_num, vnf_set_num);
1104                 return -1;
1105         }
1106
1107         p_nat->port_alloc_ring = port_alloc_ring[vnf_set_num];
1108         if (p_nat->port_alloc_ring != NULL) {
1109                 printf("CGNAPT%d port_alloc_ring already exists.\n",
1110                                  p_nat->pipeline_num);
1111                 return 1;
1112         }
1113
1114         printf("napt_port_alloc_elem_count :%d\n",
1115                 napt_port_alloc_elem_count);
1116         napt_port_alloc_elem_count += 1;
1117         napt_port_alloc_elem_count =
1118                 nextPowerOf2(napt_port_alloc_elem_count);
1119         printf("Next power of napt_port_alloc_elem_count: %d\n",
1120                 napt_port_alloc_elem_count);
1121
1122         port_alloc_ring[vnf_set_num] =
1123                  rte_ring_create(napt_port_alloc_ring_name[vnf_set_num],
1124                         napt_port_alloc_elem_count, rte_socket_id(), 0);
1125         p_nat->port_alloc_ring = port_alloc_ring[vnf_set_num];
1126         if (p_nat->port_alloc_ring == NULL) {
1127                 printf("CGNAPT%d -  Failed to create port_alloc_ring\n",
1128                                         p_nat->pipeline_num);
1129                 return -1;
1130         }
1131
1132         /* Create port alloc buffer */
1133         /* Only one pool is enough for all vnf sets */
1134         if (napt_port_pool == NULL) {
1135
1136                 napt_port_pool = rte_mempool_create(
1137                                 "napt_port_pool",
1138                                 napt_port_alloc_elem_count,
1139                                 sizeof(struct napt_port_alloc_elem),
1140                                 0, 0, NULL, NULL, NULL,
1141                                 NULL, rte_socket_id(), 0);
1142         }
1143
1144         if (napt_port_pool == NULL) {
1145                 printf("CGNAPT - Create port pool failed\n");
1146                 return -1;
1147         }
1148
1149         /* Add all available public IP addresses and ports to the ring */
1150         uint32_t i, j = 0;
1151
1152 #ifdef NAT_ONLY_CONFIG_REQ
1153         if (nat_only_config_flag) {
1154                 printf("******* pub_ip_range_count:%d ***********\n",
1155                                  p_nat->pub_ip_range_count);
1156                 /* Initialize all public IP's addresses  */
1157                 int if_addrs;
1158                 uint32_t max_ips_remain;
1159
1160                 for (if_addrs = 0; if_addrs < p_nat->pub_ip_range_count;
1161                          if_addrs++) {
1162                         /* Add all available addresses to the ring */
1163
1164                         for (i = p_nat->pub_ip_range[if_addrs].start_ip;
1165                                  i <= p_nat->pub_ip_range[if_addrs].end_ip;) {
1166                         /* 1. Get a port alloc buffer from napt_port_pool */
1167                                 void *portsBuf;
1168
1169                                 if (j == 0) {
1170                         /* get new  napt_port_alloc_elem from pool */
1171                                 if (rte_mempool_get(napt_port_pool,
1172                                                 &portsBuf) < 0) {
1173                                 printf("CGNAPT - Error in getting port "
1174                                 "alloc buffer\n");
1175                                                 return -1;
1176                                         }
1177                                 }
1178
1179                         /* 2. Populate it with available ports and ip addr */
1180                                 struct napt_port_alloc_elem *pb =
1181                                         (struct napt_port_alloc_elem *)portsBuf;
1182
1183                         int temp;
1184                         temp = p_nat->pub_ip_range[if_addrs].end_ip -
1185                                 i + 1;
1186
1187                         /* Check if remaining port count is greater
1188                         *  than or equals to bulk count, if not give
1189                         *  remaining count ports than giving bulk count
1190                         */
1191                         if (temp < NUM_NAPT_PORT_BULK_ALLOC)
1192                                 max_ips_remain = temp;
1193                         else
1194                                 max_ips_remain =
1195                                         NUM_NAPT_PORT_BULK_ALLOC;
1196
1197                                 for (j = 0; j < max_ips_remain; j++) {
1198                                         pb->count = j + 1;
1199                                         pb->ip_addr[j] = i + j;
1200                                         pb->ports[j] = 0;
1201                                         if ((i + j) ==
1202                                                 p_nat->pub_ip_range[if_addrs].
1203                                                 end_ip)
1204                                                 break;
1205                                 }
1206
1207                                 /* 3. add the port alloc buffer to ring */
1208                                 if (rte_ring_enqueue(p_nat->port_alloc_ring,
1209                                 portsBuf) != 0) {
1210                                 printf("CGNAPT%d - Enqueue error - i %d,",
1211                                                  p_nat->pipeline_num, i);
1212                                         printf("j %d, if_addrs %d, pb %p\n",
1213                                                 j, if_addrs, pb);
1214                                         rte_ring_dump(stdout,
1215                                                 p_nat->port_alloc_ring);
1216                                         rte_mempool_put(napt_port_pool,
1217                                                         portsBuf);
1218                                         return -1;
1219                                 }
1220
1221                                 /* reset j and advance i */
1222                                 j = 0;
1223                                 i += max_ips_remain;
1224                         }
1225                 }
1226
1227                 return 1;
1228         }
1229 #endif
1230
1231         printf("******* p_nat->pub_ip_count:%d ***********\n",
1232                          p_nat->pub_ip_count);
1233         /* Initialize all public IP's ports  */
1234         int if_ports;
1235         uint32_t max_ports_remain;
1236
1237         for (if_ports = 0; if_ports < p_nat->pub_ip_count; if_ports++) {
1238                 /* Add all available ports to the ring */
1239
1240                 for (i = p_nat->pub_ip_port_set[if_ports].start_port;
1241                          i <= p_nat->pub_ip_port_set[if_ports].end_port;) {
1242                         /* 1. Get a port alloc buffer from napt_port_pool */
1243                         void *portsBuf;
1244
1245                         if (j == 0) {
1246                                 /* get new  napt_port_alloc_elem from pool */
1247                                 if (rte_mempool_get(napt_port_pool, &portsBuf) <
1248                                         0) {
1249                                         printf("CGNAPT - Error in getting "
1250                                         "port alloc buffer\n");
1251                                         return -1;
1252                                 }
1253                         }
1254
1255                         /* 2. Populate it with available ports and ip addr */
1256                         struct napt_port_alloc_elem *pb =
1257                                 (struct napt_port_alloc_elem *)portsBuf;
1258
1259                         int temp;
1260                         temp = p_nat->pub_ip_port_set[if_ports].end_port -
1261                                 i + 1;
1262                         /* Check if remaining port count is greater
1263                         *  than or equals to bulk count, if not give
1264                         *  remaining count ports than giving bulk count
1265                         */
1266                         if (temp < NUM_NAPT_PORT_BULK_ALLOC)
1267                                 max_ports_remain = temp;
1268                         else
1269                                 max_ports_remain =
1270                                         NUM_NAPT_PORT_BULK_ALLOC;
1271
1272                         for (j = 0; j < max_ports_remain; j++) {
1273                                 pb->count = j + 1;
1274                                 pb->ip_addr[j] =
1275                                         p_nat->pub_ip_port_set[if_ports].ip;
1276                                 pb->ports[j] = i + j;
1277                                 if ((i + j) == p_nat->pub_ip_port_set
1278                                                 [if_ports].end_port)
1279                                         break;
1280                         }
1281
1282                         /* 3. add the port alloc buffer to ring */
1283                         if (rte_ring_enqueue(p_nat->port_alloc_ring,
1284                                 portsBuf) != 0) {
1285                                 printf("CGNAPT%d - Enqueue error - i %d, j %d, "
1286                                 " if_ports %d, pb %p\n", p_nat->pipeline_num,
1287                                 i, j, if_ports, pb);
1288
1289                                 rte_ring_dump(stdout, p_nat->port_alloc_ring);
1290                                 rte_mempool_put(napt_port_pool, portsBuf);
1291                                 return -1;
1292                         }
1293
1294                         /* reset j and advance i */
1295                         j = 0;
1296                         i += max_ports_remain;
1297                 }
1298         }
1299
1300         return 1;
1301 }
1302
1303 static pipeline_msg_req_handler handlers[] = {
1304         [PIPELINE_MSG_REQ_PING] =
1305                 pipeline_msg_req_ping_handler,
1306         [PIPELINE_MSG_REQ_STATS_PORT_IN] =
1307                 pipeline_msg_req_stats_port_in_handler,
1308         [PIPELINE_MSG_REQ_STATS_PORT_OUT] =
1309                 pipeline_msg_req_stats_port_out_handler,
1310         [PIPELINE_MSG_REQ_STATS_TABLE] = pipeline_msg_req_stats_table_handler,
1311         [PIPELINE_MSG_REQ_PORT_IN_ENABLE] =
1312                 pipeline_msg_req_port_in_enable_handler,
1313         [PIPELINE_MSG_REQ_PORT_IN_DISABLE] =
1314                 pipeline_msg_req_port_in_disable_handler,
1315         [PIPELINE_MSG_REQ_CUSTOM] =
1316                 pipeline_cgnapt_msg_req_custom_handler,
1317 };
1318
1319 static pipeline_msg_req_handler custom_handlers[] = {
1320         [PIPELINE_CGNAPT_MSG_REQ_ENTRY_ADD] =
1321                 pipeline_cgnapt_msg_req_entry_add_handler,
1322         [PIPELINE_CGNAPT_MSG_REQ_ENTRY_DEL] =
1323                 pipeline_cgnapt_msg_req_entry_del_handler,
1324         [PIPELINE_CGNAPT_MSG_REQ_ENTRY_SYNC] =
1325                 pipeline_cgnapt_msg_req_entry_sync_handler,
1326         [PIPELINE_CGNAPT_MSG_REQ_ENTRY_DBG] =
1327                 pipeline_cgnapt_msg_req_entry_dbg_handler,
1328         [PIPELINE_CGNAPT_MSG_REQ_ENTRY_ADDM] =
1329                 pipeline_cgnapt_msg_req_entry_addm_handler,
1330         [PIPELINE_CGNAPT_MSG_REQ_VER] =
1331                 pipeline_cgnapt_msg_req_ver_handler,
1332         [PIPELINE_CGNAPT_MSG_REQ_NSP_ADD] =
1333                 pipeline_cgnapt_msg_req_nsp_add_handler,
1334         [PIPELINE_CGNAPT_MSG_REQ_NSP_DEL] =
1335                 pipeline_cgnapt_msg_req_nsp_del_handler,
1336
1337         #ifdef PCP_ENABLE
1338         [PIPELINE_CGNAPT_MSG_REQ_PCP] =
1339                 pipeline_cgnapt_msg_req_pcp_handler,
1340         #endif
1341 };
1342
1343 /**
1344  * Function to convert an IPv6 packet to IPv4 packet
1345  *
1346  * @param pkt
1347  *  A pointer to packet mbuf
1348  * @param in_ipv6_hdr
1349  *  A pointer to IPv6 header in the given pkt
1350  *
1351  */
1352 static void
1353 convert_ipv6_to_ipv4(struct rte_mbuf *pkt, struct ipv6_hdr *in_ipv6_hdr)
1354 {
1355         uint32_t ip_hdr_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE;
1356
1357         uint8_t *eth_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1358         uint8_t *ipv6_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, ip_hdr_offset);
1359
1360         struct ether_hdr eth_hdr;
1361         struct ipv4_hdr *ipv4_hdr_p;
1362         uint16_t frag_off = 0x4000;
1363         struct cgnapt_nsp_node *ll = nsp_ll;
1364         uint8_t ipv4_dest[4];
1365         int nsp = 0;
1366
1367         memcpy(&eth_hdr, eth_hdr_p, sizeof(struct ether_hdr));
1368         memcpy(in_ipv6_hdr, ipv6_hdr_p, sizeof(struct ipv6_hdr));
1369
1370         eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
1371
1372         char *data_area_p = rte_pktmbuf_adj(pkt, 20);
1373         if (data_area_p == NULL) {
1374                 printf("convert_ipv6_to_ipv4:data_area_p is NULL\n");
1375                 return;
1376         }
1377         ipv4_hdr_p = (struct ipv4_hdr *)(data_area_p + ETH_HDR_SIZE);
1378         memset(ipv4_hdr_p, 0, sizeof(struct ipv4_hdr));
1379
1380         memcpy(data_area_p, &eth_hdr, sizeof(struct ether_hdr));
1381
1382         #ifdef CGNAPT_DBG_PRNT
1383         if (CGNAPT_DEBUG == 1)
1384                 printf("convert_ipv6_to_ipv4: eth_hdr_p(%p), data_area_p(%p), "
1385                 "ipv4_hdr_p(%p)\n", eth_hdr_p, data_area_p, ipv4_hdr_p);
1386         #endif
1387
1388         ipv4_hdr_p->version_ihl = 0x4 << 4 | 0x5;
1389         ipv4_hdr_p->type_of_service =
1390                 rte_be_to_cpu_32(in_ipv6_hdr->vtc_flow) & 0x0ff00000 >> 20;
1391         ipv4_hdr_p->total_length =
1392                 rte_cpu_to_be_16(rte_be_to_cpu_16(
1393                                 in_ipv6_hdr->payload_len) + 20);
1394         ipv4_hdr_p->packet_id = 0;
1395         ipv4_hdr_p->fragment_offset = rte_cpu_to_be_16(frag_off);
1396         ipv4_hdr_p->time_to_live = in_ipv6_hdr->hop_limits;
1397         ipv4_hdr_p->next_proto_id = in_ipv6_hdr->proto;
1398         ipv4_hdr_p->hdr_checksum = 0;
1399         ipv4_hdr_p->src_addr = 0;
1400
1401         while (ll != NULL) {
1402                 if (!memcmp
1403                         (&in_ipv6_hdr->dst_addr[0], &ll->nsp.prefix[0],
1404                          ll->nsp.depth / 8)) {
1405                         if (ll->nsp.depth == 32)
1406                                 memcpy(&ipv4_dest[0], &in_ipv6_hdr->dst_addr[4],
1407                                                  4);
1408                         else if (ll->nsp.depth == 40) {
1409                                 ipv4_dest[0] = in_ipv6_hdr->dst_addr[5];
1410                                 ipv4_dest[1] = in_ipv6_hdr->dst_addr[6];
1411                                 ipv4_dest[2] = in_ipv6_hdr->dst_addr[7];
1412                                 ipv4_dest[3] = in_ipv6_hdr->dst_addr[9];
1413                         } else if (ll->nsp.depth == 48) {
1414                                 ipv4_dest[0] = in_ipv6_hdr->dst_addr[6];
1415                                 ipv4_dest[1] = in_ipv6_hdr->dst_addr[7];
1416                                 ipv4_dest[2] = in_ipv6_hdr->dst_addr[9];
1417                                 ipv4_dest[3] = in_ipv6_hdr->dst_addr[10];
1418                         } else if (ll->nsp.depth == 56) {
1419                                 ipv4_dest[0] = in_ipv6_hdr->dst_addr[7];
1420                                 ipv4_dest[1] = in_ipv6_hdr->dst_addr[9];
1421                                 ipv4_dest[2] = in_ipv6_hdr->dst_addr[10];
1422                                 ipv4_dest[3] = in_ipv6_hdr->dst_addr[11];
1423                         } else if (ll->nsp.depth == 64) {
1424                                 ipv4_dest[0] = in_ipv6_hdr->dst_addr[9];
1425                                 ipv4_dest[1] = in_ipv6_hdr->dst_addr[10];
1426                                 ipv4_dest[2] = in_ipv6_hdr->dst_addr[11];
1427                                 ipv4_dest[3] = in_ipv6_hdr->dst_addr[12];
1428                         } else if (ll->nsp.depth == 96) {
1429                                 ipv4_dest[0] = in_ipv6_hdr->dst_addr[12];
1430                                 ipv4_dest[1] = in_ipv6_hdr->dst_addr[13];
1431                                 ipv4_dest[2] = in_ipv6_hdr->dst_addr[14];
1432                                 ipv4_dest[3] = in_ipv6_hdr->dst_addr[15];
1433                         }
1434
1435                         nsp = 1;
1436                         break;
1437                 }
1438
1439                 ll = ll->next;
1440         }
1441
1442         if (nsp)
1443                 memcpy(&ipv4_hdr_p->dst_addr, &ipv4_dest[0], 4);
1444         else
1445                 memcpy(&ipv4_hdr_p->dst_addr, &in_ipv6_hdr->dst_addr[12], 4);
1446
1447 }
1448
1449 /**
1450  * Function to convert an IPv4 packet to IPv6 packet
1451  *
1452  * @param pkt
1453  *  A pointer to packet mbuf
1454  * @param in_ipv4_hdr
1455  *  A pointer to IPv4 header in the given pkt
1456  *
1457  */
1458 static void
1459 convert_ipv4_to_ipv6(struct rte_mbuf *pkt, struct ipv4_hdr *in_ipv4_hdr)
1460 {
1461         uint32_t ip_hdr_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE;
1462
1463         uint8_t *eth_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1464         uint8_t *ipv4_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, ip_hdr_offset);
1465
1466         struct ether_hdr eth_hdr;
1467         struct ipv6_hdr *ipv6_hdr_p;
1468
1469         memcpy(&eth_hdr, eth_hdr_p, sizeof(struct ether_hdr));
1470         memcpy(in_ipv4_hdr, ipv4_hdr_p, sizeof(struct ipv4_hdr));
1471
1472         eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
1473
1474         char *data_area_p = rte_pktmbuf_prepend(pkt, 20);
1475         if (data_area_p == NULL) {
1476                 printf("convert_ipv4_to_ipv6:data_area_p is NULL\n");
1477                 return;
1478         }
1479         ipv6_hdr_p = (struct ipv6_hdr *)(data_area_p + ETH_HDR_SIZE);
1480         memset(ipv6_hdr_p, 0, sizeof(struct ipv6_hdr));
1481
1482         memcpy(data_area_p, &eth_hdr, sizeof(struct ether_hdr));
1483
1484         ipv6_hdr_p->vtc_flow =
1485                 rte_cpu_to_be_32((0x6 << 28) |
1486                                  (in_ipv4_hdr->type_of_service << 20));
1487         ipv6_hdr_p->payload_len =
1488                 rte_cpu_to_be_16(rte_be_to_cpu_16(
1489                         in_ipv4_hdr->total_length) - 20);
1490         ipv6_hdr_p->proto = in_ipv4_hdr->next_proto_id;
1491         ipv6_hdr_p->hop_limits = in_ipv4_hdr->time_to_live;
1492
1493         ipv6_hdr_p->src_addr[0] = 0x00;
1494         ipv6_hdr_p->src_addr[1] = 0x64;
1495         ipv6_hdr_p->src_addr[2] = 0xff;
1496         ipv6_hdr_p->src_addr[3] = 0x9b;
1497         ipv6_hdr_p->src_addr[4] = 0x00;
1498         ipv6_hdr_p->src_addr[5] = 0x00;
1499         ipv6_hdr_p->src_addr[6] = 0x00;
1500         ipv6_hdr_p->src_addr[7] = 0x00;
1501         ipv6_hdr_p->src_addr[8] = 0x00;
1502         ipv6_hdr_p->src_addr[9] = 0x00;
1503         ipv6_hdr_p->src_addr[10] = 0x00;
1504         ipv6_hdr_p->src_addr[11] = 0x00;
1505         memcpy(&ipv6_hdr_p->src_addr[12], &in_ipv4_hdr->src_addr, 4);
1506
1507         memset(&ipv6_hdr_p->dst_addr, 0, 16);
1508
1509         return;
1510
1511 }
1512
1513 /**
1514  * Output port handler
1515  *
1516  * @param pkt
1517  *  A pointer to packet mbuf
1518  * @param arg
1519  *  Unused void pointer
1520  *
1521  */
1522 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1523 static void
1524 pkt_work_cgnapt_out(__rte_unused struct rte_mbuf *pkt, __rte_unused void *arg)
1525 {
1526 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1527         if ((cgnapt_num_func_to_inst == 5)
1528                 && (cgnapt_inst_index < INST_ARRAY_SIZE)) {
1529                 if (cgnapt_inst5_flag == 0) {
1530                         uint8_t *inst5_sig =
1531                                 RTE_MBUF_METADATA_UINT8_PTR(pkt,
1532                                         CGNAPT_INST5_OFST);
1533                         if (*inst5_sig == CGNAPT_INST5_SIG) {
1534                                 cgnapt_inst5_flag = 1;
1535                                 inst_end_time[cgnapt_inst_index] =
1536                                         rte_get_tsc_cycles();
1537                                 cgnapt_inst_index++;
1538                         }
1539                 }
1540         }
1541 #endif
1542
1543         /* cgnapt_pkt_out_count++; */
1544         #ifdef CGNAPT_DBG_PRNT
1545         if (CGNAPT_DEBUG)
1546                 print_pkt(pkt);
1547         #endif
1548 }
1549 #endif
1550
1551 /**
1552  * Output port handler to handle 4 pkts
1553  *
1554  * @param pkt
1555  *  A pointer to packet mbuf
1556  * @param arg
1557  *  Inport handler argument pointer
1558  *
1559  */
1560 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1561 static void pkt4_work_cgnapt_out(struct rte_mbuf **pkt, void *arg)
1562 {
1563         (void)pkt;
1564         (void)arg;
1565 /* TO BE IMPLEMENTED IF REQUIRED */
1566 }
1567 #endif
1568
1569 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1570 PIPELINE_CGNAPT_PORT_OUT_AH(port_out_ah_cgnapt,
1571                                 pkt_work_cgnapt_out, pkt4_work_cgnapt_out);
1572
1573 PIPELINE_CGNAPT_PORT_OUT_BAH(port_out_ah_cgnapt_bulk,
1574                                  pkt_work_cgnapt_out, pkt4_work_cgnapt_out);
1575 #endif
1576
1577 /**
1578  * Function to validate the packet and return version
1579  *
1580  * @param pkt
1581  *  A pointer to packet mbuf
1582  *
1583  * @return
1584  *  IP version of the valid pkt, -1 if invalid pkt
1585  */
1586 int rte_get_pkt_ver(struct rte_mbuf *pkt)
1587 {
1588         uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
1589         uint16_t *eth_proto =
1590                 RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
1591
1592         if (*eth_proto == rte_be_to_cpu_16(ETHER_TYPE_IPv4))
1593                 return IP_VERSION_4;
1594
1595         if (dual_stack_enable
1596                 && (*eth_proto == rte_be_to_cpu_16(ETHER_TYPE_IPv6)))
1597                 return IP_VERSION_6;
1598
1599         /* Check the protocol first, if not UDP or TCP return */
1600
1601         return -1;
1602 }
1603
1604 /**
1605  * A method to print the NAPT entry
1606  *
1607  * @param ent
1608  *  A pointer to struct cgnapt_table_entry
1609  */
1610 void my_print_entry(struct cgnapt_table_entry *ent)
1611 {
1612         printf("CGNAPT key:\n");
1613         printf("entry_type :%d\n", ent->data.type);
1614         printf("prv_ip: %x %x %x %x\n", ent->data.u.u32_prv_ipv6[0],
1615                          ent->data.u.u32_prv_ipv6[1], ent->data.u.u32_prv_ipv6[2],
1616                          ent->data.u.u32_prv_ipv6[3]);
1617         printf("prv_port:%d\n", ent->data.prv_port);
1618
1619         printf("pub_ip:%x\n", ent->data.pub_ip);
1620         printf("prv_phy_port:%d\n", ent->data.prv_phy_port);
1621         printf("pub_phy_port:%d\n", ent->data.pub_phy_port);
1622 }
1623
1624 /**
1625  * Function to print common CGNAPT table entries
1626  *
1627  */
1628 void print_common_table(void)
1629 {
1630         uint32_t count = 0;
1631         const void *key;
1632         void *data;
1633         uint32_t next = 0;
1634         int32_t index = 0;
1635         do {
1636                 index = rte_hash_iterate(napt_common_table,
1637                                 &key, &data, &next);
1638
1639                 if ((index != -EINVAL) && (index != -ENOENT)) {
1640                         printf("\n%04d  ", count);
1641                         //print_key((struct pipeline_cgnapt_entry_key *)key);
1642                         rte_hexdump(stdout, "KEY", key,
1643                                 sizeof(struct pipeline_cgnapt_entry_key));
1644                         int32_t position = rte_hash_lookup(
1645                                         napt_common_table, key);
1646                         print_cgnapt_entry(&napt_hash_tbl_entries[position]);
1647                 }
1648
1649                 count++;
1650         } while (index != -ENOENT);
1651 }
1652
1653 /**
1654  * Input port handler for mixed traffic
1655  * This is the main method in this file when running in mixed traffic mode.
1656  * Starting from the packet burst it filters unwanted packets,
1657  * calculates keys, does lookup and then based on the lookup
1658  * updates NAPT table and does packet NAPT translation.
1659  *
1660  * @param rte_p
1661  *  A pointer to struct rte_pipeline
1662  * @param pkts
1663  *  A pointer to array of packets mbuf
1664  * @param n_pkts
1665  *  Number of packets in the burst
1666  * @param arg
1667  *  Void pointer
1668  *
1669  * @return
1670  *  int that is not checked by caller
1671  */
1672
1673 static int cgnapt_in_port_ah_mix(struct rte_pipeline *rte_p,
1674                                  struct rte_mbuf **pkts,
1675                                  uint32_t n_pkts, void *arg)
1676 {
1677 /*
1678 *       Code flow
1679 *
1680 * 1. Read packet version, if invalid drop the packet
1681 * 2. Check protocol, if not UDP or TCP drop the packet
1682 * 3. Bring all valid packets together - useful for bulk lookup
1683 *       and calculate key for all packets
1684 *       a. If IPv4 : calculate key with full IP
1685 *       b. If IPv6 : calculate key with last 32-bit of IP
1686 * 4. Do bulk lookup with rte_hash_lookup_bulk(), if something went wrong
1687 *       drop all packets
1688 * 5. For lookup hit packets, read entry from table
1689 * 6. For lookup miss packets, add dynamic entry to table
1690 * 7. If pkt is IPv6
1691 *       a. If egress pkt, convert to IPv4 and NAPT it
1692 *       b. If ingress, drop the pkt
1693 * 8. If pkt is IPv4
1694 *       a. If egress pkt, NAPT it. Get MAC
1695 *       b. If first ingress pkt (with no egress entry), drop the pkt
1696 *                If not first ingress pkt
1697 *               I.  If IPv6 converted packet, convert back to IPv6,
1698                         NAPT it & get MAC
1699 *               II. If IPv4 packet, NAPT it & get MAC
1700 * 9. Send all packets out to corresponding ports
1701 */
1702         struct pipeline_cgnapt_in_port_h_arg *ap = arg;
1703         struct pipeline_cgnapt *p_nat = ap->p;
1704         uint8_t compacting_map[RTE_HASH_LOOKUP_BULK_MAX];
1705         uint32_t packets_for_lookup = 0;
1706         uint32_t i;
1707
1708         p_nat->valid_packets = 0;
1709         p_nat->invalid_packets = 0;
1710
1711         #ifdef CGNAPT_DBG_PRNT
1712         if (CGNAPT_DEBUG > 1)
1713                 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
1714         #endif
1715
1716         p_nat->pkt_burst_cnt = 0;       /* for dynamic napt */
1717
1718         uint16_t phy_port = 0;
1719         uint16_t *src_port = NULL;
1720         uint16_t *dst_port = NULL;
1721         uint32_t *src_addr = NULL;
1722         uint32_t *dst_addr = NULL;
1723         uint8_t *protocol = NULL;
1724         uint8_t *eth_dest = NULL;
1725         uint8_t *eth_src = NULL;
1726         uint16_t src_port_offset = 0;
1727         uint16_t dst_port_offset = 0;
1728         uint16_t src_addr_offset = 0;
1729         uint16_t dst_addr_offset = 0;
1730         uint16_t prot_offset = 0;
1731         uint16_t eth_offset = 0;
1732         int ver = 0;
1733
1734         enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
1735
1736         src_port_offset = SRC_PRT_OFST_IP4_TCP;
1737         dst_port_offset = DST_PRT_OFST_IP4_TCP;
1738
1739         for (i = 0; i < n_pkts; i++) {
1740                 p_nat->receivedPktCount++;
1741
1742                 /* bitmask representing only this packet */
1743                 uint64_t pkt_mask = 1LLU << i;
1744
1745                 /* remember this pkt as valid pkt */
1746                 p_nat->valid_packets |= pkt_mask;
1747
1748                 struct rte_mbuf *pkt = pkts[i];
1749
1750                 if (enable_hwlb)
1751                         if (!check_arp_icmp(pkt, pkt_mask, p_nat))
1752                                 continue;
1753
1754                 int ver = rte_get_pkt_ver(pkt);
1755
1756                 #ifdef CGNAPT_DBG_PRNT
1757                 printf("ver no. of the pkt:%d\n", ver);
1758                 #endif
1759
1760                 if (unlikely(ver < 0)) {
1761                         /* Not a valid pkt , ignore. */
1762                         /* remember invalid packets to be dropped */
1763                         p_nat->invalid_packets |= pkt_mask;
1764                         p_nat->naptDroppedPktCount++;
1765
1766                 #ifdef CGNAPT_DEBUGGING
1767                         p_nat->naptDroppedPktCount1++;
1768                 #endif
1769                         continue;
1770                 }
1771                 if (ver == 4)
1772                         prot_offset = PROT_OFST_IP4;
1773                 else
1774                         prot_offset = PROT_OFST_IP6;
1775                 protocol =
1776                         (uint8_t *) RTE_MBUF_METADATA_UINT32_PTR(pkt,
1777                                         prot_offset);
1778                 if (!
1779                         (*protocol == IP_PROTOCOL_TCP
1780                          || *protocol == IP_PROTOCOL_UDP
1781                          || *protocol == IP_PROTOCOL_ICMP)) {
1782                 /* remember invalid packets to be dropped */
1783                         p_nat->invalid_packets |= pkt_mask;
1784                         p_nat->naptDroppedPktCount++;
1785
1786                 #ifdef CGNAPT_DEBUGGING
1787                         p_nat->naptDroppedPktCount2++;
1788                 #endif
1789                         continue;
1790                 }
1791
1792                 #ifdef CGNAPT_DBG_PRNT
1793                 if (CGNAPT_DEBUG > 4)
1794                         print_pkt(pkt);
1795                 #endif
1796
1797                 #ifdef PCP_ENABLE
1798                 /* Handling PCP
1799                 * 1. Handel PCP for egress traffic
1800                 * 2. If PCP, then give response (send pkt) from the same port
1801                 * 3. Drop the PCP packet, should not be added in the NAPT table
1802                 */
1803                 if (pcp_enable) {
1804                 if (*protocol == IP_PROTOCOL_UDP) {
1805                         struct udp_hdr *udp;
1806                         if (ver == 4)
1807                                 udp = (struct udp_hdr *)
1808                                         RTE_MBUF_METADATA_UINT8_PTR(pkt,
1809                                                 IPV4_UDP_OFST);
1810                         else
1811                                 udp = (struct udp_hdr *)
1812                                         RTE_MBUF_METADATA_UINT8_PTR(pkt,
1813                                                 IPV6_UDP_OFST);
1814
1815                         if (rte_bswap16(udp->dst_port) ==
1816                                 PCP_SERVER_PORT) {
1817                                 handle_pcp_req(pkt, ver, p_nat);
1818                                 p_nat->invalid_packets |= pkt_mask;
1819                                 continue;
1820                         }
1821                 }
1822                 }
1823                 #endif
1824
1825                 if (ver == 4) {
1826
1827                         src_addr =
1828                                 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1829                                         SRC_ADR_OFST_IP4);
1830                         dst_addr =
1831                                 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1832                                         DST_ADR_OFST_IP4);
1833
1834                         if ((*protocol == IP_PROTOCOL_TCP)
1835                                 || (*protocol == IP_PROTOCOL_UDP)) {
1836
1837                                 src_port_offset = SRC_PRT_OFST_IP4_TCP;
1838                                 dst_port_offset = DST_PRT_OFST_IP4_TCP;
1839
1840                         } else if (*protocol == IP_PROTOCOL_ICMP) {
1841                                 /* Identifier */
1842                                 src_port_offset = IDEN_OFST_IP4_ICMP;
1843                                 /* Sequence number */
1844                                 dst_port_offset = SEQN_OFST_IP4_ICMP;
1845                         }
1846
1847                         src_port =
1848                                 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1849                                         src_port_offset);
1850                         dst_port =
1851                                 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1852                                         dst_port_offset);
1853                 } else {
1854
1855                         src_addr =
1856                                 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1857                                         SRC_ADR_OFST_IP6);
1858                         dst_addr =
1859                                 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1860                                         DST_ADR_OFST_IP6);
1861                         src_port =
1862                                 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1863                                         SRC_PRT_OFST_IP6);
1864                         dst_port =
1865                                 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1866                                         DST_PRT_OFST_IP6);
1867                 }
1868                 /* need to create compacted table of pointers to
1869                 * pass to bulk lookup
1870                 */
1871
1872                 compacting_map[packets_for_lookup] = i;
1873
1874                 //phy_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, phyport_offset);
1875                 phy_port = pkt->port;
1876
1877                 struct pipeline_cgnapt_entry_key key;
1878
1879                 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
1880
1881                 key.pid = phy_port;
1882                 if (get_in_port_dir(phy_port)) {
1883                         /* Egress */
1884                         if (ver == 4)
1885                                 key.ip = rte_bswap32(*src_addr);
1886                         else
1887                                 key.ip = rte_bswap32(src_addr[3]);
1888                         key.port = rte_bswap16(*src_port);
1889
1890                 #ifdef NAT_ONLY_CONFIG_REQ
1891                         if (nat_only_config_flag)
1892                                 key.port = 0xffff;
1893                 #endif
1894                 } else {
1895                         /* Ingress */
1896                         key.ip = rte_bswap32(*dst_addr);
1897
1898                         if (*protocol == IP_PROTOCOL_ICMP) {
1899                         /* common table lookupkey preparation from
1900                         * incoming ICMP Packet- Indentifier field
1901                         */
1902                                 key.port = rte_bswap16(*src_port);
1903                         } else {
1904                                 key.port = rte_bswap16(*dst_port);
1905                         }
1906
1907                 #ifdef NAT_ONLY_CONFIG_REQ
1908                         if (nat_only_config_flag)
1909                                 key.port = 0xffff;
1910                 #endif
1911
1912                         key.pid = 0xffff;
1913                 }
1914
1915                 memcpy(&(p_nat->keys[packets_for_lookup]), &key,
1916                                  sizeof(struct pipeline_cgnapt_entry_key));
1917                 p_nat->key_ptrs[packets_for_lookup] =
1918                         &(p_nat->keys[packets_for_lookup]);
1919                 packets_for_lookup++;
1920         }
1921
1922         if (unlikely(packets_for_lookup == 0)) {
1923                 /* no suitable packet for lookup */
1924                 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
1925                 return p_nat->valid_packets;
1926         }
1927
1928         /* lookup entries in the common napt table */
1929
1930         int lookup_result = rte_hash_lookup_bulk(napt_common_table,
1931                                                  (const void **)
1932                                                  &p_nat->key_ptrs,
1933                                                  packets_for_lookup,
1934                                                  &p_nat->lkup_indx[0]);
1935
1936         if (unlikely(lookup_result < 0)) {
1937                 /* unknown error, just discard all packets */
1938                 printf("Unexpected hash lookup error %d, discarding all "
1939                         "packets", lookup_result);
1940                 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
1941                 return 0;
1942         }
1943         //struct rte_pipeline_table_entry *entries[64];
1944         /* Now one by one check the result of our bulk lookup */
1945
1946         for (i = 0; i < packets_for_lookup; i++) {
1947                 /* index into hash table entries */
1948                 int hash_table_entry = p_nat->lkup_indx[i];
1949                 /* index into packet table of this packet */
1950                 uint8_t pkt_index = compacting_map[i];
1951                 /*bitmask representing only this packet */
1952                 uint64_t pkt_mask = 1LLU << pkt_index;
1953
1954                 struct cgnapt_table_entry *entry = NULL;
1955                 if (hash_table_entry < 0) {
1956
1957                         /* try to add new entry */
1958                         struct rte_pipeline_table_entry *table_entry = NULL;
1959
1960                         uint64_t dropmask =
1961                                 pkt_miss_cgnapt(p_nat->key_ptrs[i],
1962                                                 pkts[pkt_index],
1963                                                 &table_entry,
1964                                                 &p_nat->valid_packets,
1965                                                 pkt_index,
1966                                                 (void *)p_nat);
1967
1968                         if (!table_entry) {
1969                 /* ICMP Error message generation for
1970                 * Destination Host unreachable
1971                 */
1972                                 if (*protocol == IP_PROTOCOL_ICMP) {
1973                                         cgnapt_icmp_pkt = pkts[pkt_index];
1974                                         send_icmp_dest_unreachable_msg();
1975                                 }
1976
1977                                 /* Drop packet by adding to invalid pkt mask */
1978
1979                                 p_nat->invalid_packets |= dropmask;
1980                                 #ifdef CGNAPT_DEBUGGING
1981                                 if (p_nat->kpc2++ < 5) {
1982                                         printf("in_ah Th: %d",
1983                                                          p_nat->pipeline_num);
1984                                         print_key(p_nat->key_ptrs[i]);
1985                                 }
1986                                 #endif
1987
1988                                 p_nat->naptDroppedPktCount++;
1989
1990                                 #ifdef CGNAPT_DEBUGGING
1991                                 p_nat->naptDroppedPktCount3++;
1992                                 #endif
1993                                 continue;
1994                         }
1995
1996                         entry = (struct cgnapt_table_entry *)table_entry;
1997                 } else {
1998                         /* entry found for this packet */
1999                         entry = &napt_hash_tbl_entries[hash_table_entry];
2000                 }
2001
2002                 /*  apply napt and mac changes */
2003
2004                 p_nat->entries[pkt_index] = &(entry->head);
2005
2006                 phy_port = pkts[pkt_index]->port;
2007
2008                 struct ipv6_hdr ipv6_hdr;
2009                 struct ipv4_hdr ipv4_hdr;
2010
2011                 ver = rte_get_pkt_ver(pkts[pkt_index]);
2012                 #ifdef CGNAPT_DEBUGGING
2013                 if (CGNAPT_DEBUG >= 1) {
2014                         printf("ver:%d\n", ver);
2015                         printf("entry->data.type:%d\n", entry->data.type);
2016                 }
2017                 #endif
2018                 if ((ver == 6) && (entry->data.type == CGNAPT_ENTRY_IPV6)
2019                         && is_phy_port_privte(phy_port)) {
2020                         convert_ipv6_to_ipv4(pkts[pkt_index], &ipv6_hdr);
2021
2022                         pkt_type = PKT_TYPE_IPV6to4;
2023
2024                         #ifdef CGNAPT_DBG_PRNT
2025                         if (CGNAPT_DEBUG >= 1)
2026                                 printf("pkt_work_cganpt: "
2027                                 "convert_ipv6_to_ipv4\n");
2028                         #endif
2029
2030                         struct cgnapt_nsp_node *ll = nsp_ll;
2031                         int nsp = 0;
2032                         while (ll != NULL) {
2033                                 if (!memcmp(&ipv6_hdr.dst_addr[0],
2034                                         &ll->nsp.prefix[0],
2035                                          ll->nsp.depth / 8)) {
2036                                         nsp = 1;
2037                                         break;
2038                                 }
2039                                 ll = ll->next;
2040                         }
2041
2042                         if (!nsp
2043                                 && !memcmp(&ipv6_hdr.dst_addr[0],
2044                                                  &well_known_prefix[0], 12)) {
2045                                 nsp = 1;
2046                         }
2047
2048                         if (!nsp) {
2049                                 p_nat->invalid_packets |= 1LLU << pkt_index;
2050                                 p_nat->naptDroppedPktCount++;
2051
2052                                 #ifdef CGNAPT_DEBUGGING
2053                                 p_nat->naptDroppedPktCount5++;
2054                                 #endif
2055                                 continue;
2056                         }
2057
2058                 }
2059
2060                 /* As packet is already converted into IPv4 we must not operate
2061                 * IPv6 offsets on packet
2062                 * Only perform IPv4 operations
2063                 */
2064
2065                 if (ver == 6) {
2066
2067                         src_port_offset = SRC_PRT_OFST_IP6t4;
2068                         dst_port_offset = DST_PRT_OFST_IP6t4;
2069                         src_addr_offset = SRC_ADR_OFST_IP6t4;
2070                         dst_addr_offset = DST_ADR_OFST_IP6t4;
2071                         prot_offset = PROT_OFST_IP6t4;
2072                         eth_offset = ETH_OFST_IP6t4;
2073
2074                 } else {
2075
2076                         if ((*protocol == IP_PROTOCOL_TCP)
2077                                 || (*protocol == IP_PROTOCOL_UDP)) {
2078                                 src_port_offset = SRC_PRT_OFST_IP4_TCP;
2079                                 dst_port_offset = DST_PRT_OFST_IP4_TCP;
2080                         } else if (*protocol == IP_PROTOCOL_ICMP) {
2081                                 /* Identifier */
2082                                 src_port_offset = IDEN_OFST_IP4_ICMP;
2083                                 /* Sequence number */
2084                                 dst_port_offset = SEQN_OFST_IP4_ICMP;
2085                         }
2086
2087                         src_addr_offset = SRC_ADR_OFST_IP4;
2088                         dst_addr_offset = DST_ADR_OFST_IP4;
2089                         prot_offset = PROT_OFST_IP4;
2090                         eth_offset = MBUF_HDR_ROOM;
2091
2092                 }
2093
2094                 src_addr =
2095                         RTE_MBUF_METADATA_UINT32_PTR(pkts[pkt_index],
2096                                                  src_addr_offset);
2097                 dst_addr =
2098                         RTE_MBUF_METADATA_UINT32_PTR(pkts[pkt_index],
2099                                                  dst_addr_offset);
2100                 src_port =
2101                         RTE_MBUF_METADATA_UINT16_PTR(pkts[pkt_index],
2102                                                  src_port_offset);
2103                 dst_port =
2104                         RTE_MBUF_METADATA_UINT16_PTR(pkts[pkt_index],
2105                                                  dst_port_offset);
2106                 protocol =
2107                         RTE_MBUF_METADATA_UINT8_PTR(pkts[pkt_index],
2108                                 prot_offset);
2109
2110                 eth_dest =
2111                         RTE_MBUF_METADATA_UINT8_PTR(pkts[pkt_index],
2112                                 eth_offset);
2113                 eth_src =
2114                         RTE_MBUF_METADATA_UINT8_PTR(pkts[pkt_index],
2115                                                 eth_offset + 6);
2116
2117                 if (entry->data.ttl == NAPT_ENTRY_STALE)
2118                         entry->data.ttl = NAPT_ENTRY_VALID;
2119
2120                 struct ether_addr hw_addr;
2121                 uint32_t dest_address = 0;
2122                 uint8_t nh_ipv6[16];
2123                 uint32_t nhip = 0;
2124
2125                 uint32_t dest_if = 0xff;
2126                 uint32_t ret;
2127
2128                 uint16_t *outport_id =
2129                         RTE_MBUF_METADATA_UINT16_PTR(pkts[pkt_index],
2130                                                  cgnapt_meta_offset);
2131
2132                 if (is_phy_port_privte(phy_port)) {
2133
2134                         if (*protocol == IP_PROTOCOL_UDP
2135                         && rte_be_to_cpu_16(*dst_port) == 53) {
2136                         p_nat->invalid_packets |= 1LLU << pkt_index;
2137                         p_nat->naptDroppedPktCount++;
2138                         #ifdef CGNAPT_DEBUGGING
2139                         p_nat->naptDroppedPktCount6++;
2140                         #endif
2141                         continue;
2142                         }
2143
2144                         dest_address = rte_bswap32(*dst_addr);
2145                         ret = local_get_nh_ipv4(dest_address, &dest_if,
2146                                         &nhip, p_nat);
2147                         if (!ret) {
2148                                 dest_if = get_prv_to_pub_port(&dest_address,
2149                                                 IP_VERSION_4);
2150                                 if (dest_if == INVALID_DESTIF) {
2151                                         p_nat->invalid_packets |=
2152                                                 1LLU << pkt_index;
2153                                         p_nat->naptDroppedPktCount++;
2154                                         #ifdef CGNAPT_DEBUGGING
2155                                         p_nat->naptDroppedPktCount6++;
2156                                         #endif
2157                                         continue;
2158                                 }
2159                                 do_local_nh_ipv4_cache(dest_if, p_nat);
2160                         }
2161
2162                         *outport_id = p_nat->outport_id[dest_if];
2163                         int ret;
2164                         ret = get_dest_mac_addr_port(dest_address,
2165                                 &dest_if, &hw_addr);
2166
2167                         if (ret == ARP_FOUND) {
2168                                 memcpy(eth_dest, &hw_addr,
2169                                         sizeof(struct ether_addr));
2170                                 memcpy(eth_src, get_link_hw_addr(dest_if),
2171                                         sizeof(struct ether_addr));
2172                                 #ifdef CGNAPT_DBG_PRNT
2173                                 if (CGNAPT_DEBUG > 2) {
2174                                 printf("MAC found for ip 0x%x, port %d - "
2175                                         "%02x:%02x:%02x:%02x:%02x:%02x\n",
2176                                         dest_address, *outport_id,
2177                                 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
2178                                 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
2179                                 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
2180
2181                                 printf("Dest MAC before - "
2182                                         "%02x:%02x:%02x:%02x:%02x:%02x\n",
2183                                          eth_dest[0], eth_dest[1], eth_dest[2],
2184                                          eth_dest[3], eth_dest[4], eth_dest[5]);
2185                                 }
2186                                 #endif
2187
2188                                 #ifdef CGNAPT_DBG_PRNT
2189                                 if (CGNAPT_DEBUG > 2) {
2190                                 printf("Dest MAC after - "
2191                                 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2192                                 eth_dest[0], eth_dest[1], eth_dest[2],
2193                                 eth_dest[3], eth_dest[4], eth_dest[5]);
2194                                 }
2195                                 #endif
2196
2197                                 #ifdef CGNAPT_DBG_PRNT
2198                                 if (CGNAPT_DEBUG > 4)
2199                                         print_pkt(pkts[pkt_index]);
2200                                 #endif
2201
2202                         } else{
2203                                 if (ret == ARP_NOT_FOUND) {
2204                                         /* Commented code may be required
2205                                          * for future use, Please keep it */
2206                                         //request_arp(*outport_id, nhip,
2207                                         //      p_nat->p.p);
2208                                         printf("%s: ARP Not Found, nhip: %x, "
2209                                         "outport_id: %d\n", __func__, nhip,
2210                                         *outport_id);
2211                                 }
2212
2213                                 p_nat->invalid_packets |= pkt_mask;
2214                                 p_nat->naptDroppedPktCount++;
2215                                 #ifdef CGNAPT_DEBUGGING
2216                                 p_nat->naptDroppedPktCount4++;
2217                                 #endif
2218                                 continue;
2219                         }
2220
2221                         #ifdef CGNAPT_DBG_PRNT
2222                         if (CGNAPT_DEBUG > 2)
2223                                 printf("Egress: \tphy_port:%d\t "
2224                                 "get_prv_to_pub():%d \tout_port:%d\n",
2225                                 phy_port, dest_if,
2226                                 *outport_id);
2227                         #endif
2228
2229                         /* Egress */
2230                         *src_addr = rte_bswap32(entry->data.pub_ip);
2231
2232                         #ifdef NAT_ONLY_CONFIG_REQ
2233                         if (!nat_only_config_flag) {
2234                         #endif
2235                                 *src_port = rte_bswap16(entry->data.pub_port);
2236                         #ifdef NAT_ONLY_CONFIG_REQ
2237                         }
2238                         #endif
2239
2240                         p_nat->enaptedPktCount++;
2241                 } else {
2242                         /* Ingress */
2243                         if (*protocol == IP_PROTOCOL_UDP
2244                                 && rte_be_to_cpu_16(*src_port) == 53) {
2245                                 p_nat->invalid_packets |= 1LLU << pkt_index;
2246                                 p_nat->naptDroppedPktCount++;
2247                                 #ifdef CGNAPT_DEBUGGING
2248                                 p_nat->naptDroppedPktCount6++;
2249                                 #endif
2250                                 continue;
2251                         }
2252
2253                         #ifdef CGNAPT_DBG_PRNT
2254                         if (CGNAPT_DEBUG > 2)
2255                                 printf("Ingress: \tphy_port:%d\t "
2256                                 "get_pub_to_prv():%d \tout_port%d\n",
2257                                  phy_port, dest_if,
2258                                  *outport_id);
2259                         #endif
2260
2261                         if (entry->data.type == CGNAPT_ENTRY_IPV6) {
2262                                 convert_ipv4_to_ipv6(pkts[pkt_index],
2263                                                          &ipv4_hdr);
2264                                 pkt_type = PKT_TYPE_IPV4to6;
2265                                 /* Ethernet MTU check */
2266                         if ((rte_pktmbuf_data_len(pkts[pkt_index]) -
2267                                          14) > 1500) {
2268                                 p_nat->invalid_packets |= pkt_mask;
2269                                 p_nat->naptDroppedPktCount++;
2270                                 continue;
2271                         }
2272
2273                         eth_dest = eth_dest - 20;
2274                         eth_src = eth_src - 20;
2275
2276                         dst_port_offset = DST_PRT_OFST_IP4t6;
2277                         dst_addr_offset = DST_ADR_OFST_IP4t6;
2278                         dst_addr =
2279                                 RTE_MBUF_METADATA_UINT32_PTR(
2280                                         pkts[pkt_index],
2281                                         dst_addr_offset);
2282                         dst_port =
2283                                 RTE_MBUF_METADATA_UINT16_PTR(
2284                                         pkts[pkt_index],
2285                                         dst_port_offset);
2286
2287                         memcpy((uint8_t *) &dst_addr[0],
2288                                          &entry->data.u.prv_ipv6[0], 16);
2289                         memset(nh_ipv6, 0, 16);
2290
2291                         ret = local_get_nh_ipv6((uint8_t *)&dst_addr[0],
2292                                 &dest_if, &nh_ipv6[0], p_nat);
2293
2294                         if (!ret) {
2295                                 dest_if = get_prv_to_pub_port(
2296                                                 &dst_addr[0],
2297                                                 IP_VERSION_6);
2298                                 if (dest_if == INVALID_DESTIF) {
2299                                         p_nat->invalid_packets |=
2300                                                 1LLU << pkt_index;
2301                                         p_nat->naptDroppedPktCount++;
2302                                         #ifdef CGNAPT_DEBUGGING
2303                                         p_nat->naptDroppedPktCount6++;
2304                                         #endif
2305                                         continue;
2306                                 }
2307                                 do_local_nh_ipv6_cache(dest_if, p_nat);
2308                         }
2309                         *outport_id = p_nat->outport_id[dest_if];
2310
2311                         if (get_dest_mac_address_ipv6_port((uint8_t *)
2312                                 &dst_addr[0], &dest_if,
2313                                 &hw_addr, &nh_ipv6[0])){
2314
2315                                 #ifdef CGNAPT_DBG_PRNT
2316                                 if (CGNAPT_DEBUG > 2) {
2317                                 printf("MAC found for ip 0x%x, port %d - "
2318                                 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2319                                 dest_address, *outport_id,
2320                                 hw_addr.addr_bytes[0],
2321                                 hw_addr.addr_bytes[1], hw_addr.addr_bytes[2],
2322                                 hw_addr.addr_bytes[3], hw_addr.addr_bytes[4],
2323                                 hw_addr.addr_bytes[5]);
2324
2325                                 printf("Dest MAC before - "
2326                                 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2327                                 eth_dest[0], eth_dest[1], eth_dest[2],
2328                                 eth_dest[3], eth_dest[4], eth_dest[5]);
2329                                 }
2330                                 #endif
2331                                         memcpy(eth_dest, &hw_addr,
2332                                                 sizeof(struct ether_addr));
2333                                         memcpy(eth_src, get_link_hw_addr(
2334                                                 dest_if),
2335                                                 sizeof(struct ether_addr));
2336
2337                         #ifdef CGNAPT_DBG_PRNT
2338                         if (CGNAPT_DEBUG > 2) {
2339                                 printf("Dest MAC after - "
2340                                 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2341                                 eth_dest[0], eth_dest[1], eth_dest[2],
2342                                 eth_dest[3], eth_dest[4], eth_dest[5]);
2343                         }
2344                         #endif
2345
2346                         #ifdef CGNAPT_DBG_PRNT
2347                         if (CGNAPT_DEBUG > 4)
2348                                 print_pkt(pkts[pkt_index]);
2349                         #endif
2350                         } else {
2351
2352                                 p_nat->invalid_packets |= pkt_mask;
2353                                 p_nat->naptDroppedPktCount++;
2354                                 #ifdef CGNAPT_DEBUGGING
2355                                 p_nat->naptDroppedPktCount4++;
2356                                 #endif
2357                                 continue;
2358                         }
2359
2360                         #ifdef NAT_ONLY_CONFIG_REQ
2361                                 if (!nat_only_config_flag) {
2362                         #endif
2363                                 *dst_port =
2364                                         rte_bswap16(entry->data.prv_port);
2365                         #ifdef NAT_ONLY_CONFIG_REQ
2366                                 }
2367                         #endif
2368
2369                         } else {
2370                                 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
2371                                 dest_address = entry->data.u.prv_ip;
2372                                 ret = local_get_nh_ipv4(dest_address, &dest_if,
2373                                         &nhip, p_nat);
2374                                 if (!ret) {
2375                                         dest_if = get_pub_to_prv_port(
2376                                                 &dest_address, IP_VERSION_4);
2377                                 if (dest_if == INVALID_DESTIF) {
2378                                         p_nat->invalid_packets |=
2379                                                 1LLU << pkt_index;
2380                                         p_nat->naptDroppedPktCount++;
2381                                         #ifdef CGNAPT_DEBUGGING
2382                                         p_nat->naptDroppedPktCount6++;
2383                                         #endif
2384                                         continue;
2385                                 }
2386                                         do_local_nh_ipv4_cache(dest_if, p_nat);
2387                                 };
2388
2389                                 *outport_id = p_nat->outport_id[dest_if];
2390                                 int ret;
2391                                 ret = get_dest_mac_addr_port(dest_address,
2392                                         &dest_if, &hw_addr);
2393
2394                                 if (ret == ARP_FOUND) {
2395                                         memcpy(eth_dest, &hw_addr,
2396                                                 sizeof(struct ether_addr));
2397                                         memcpy(eth_src, get_link_hw_addr(
2398                                                 dest_if),
2399                                                 sizeof(struct ether_addr));
2400                                 #ifdef CGNAPT_DBG_PRNT
2401                                 if (CGNAPT_DEBUG > 2) {
2402                                 printf("MAC found for ip 0x%x, port %d - "
2403                                 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2404                                 dest_address, *outport_id,
2405                                  hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
2406                                  hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
2407                                  hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
2408
2409                                 printf("Dest MAC before - "
2410                                 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2411                                          eth_dest[0], eth_dest[1], eth_dest[2],
2412                                          eth_dest[3], eth_dest[4], eth_dest[5]);
2413                                 }
2414                                 #endif
2415
2416                                 #ifdef CGNAPT_DBG_PRNT
2417                                 if (CGNAPT_DEBUG > 2) {
2418                                 printf("Dest MAC after - "
2419                                 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2420                                          eth_dest[0], eth_dest[1], eth_dest[2],
2421                                          eth_dest[3], eth_dest[4], eth_dest[5]);
2422                                 }
2423                                 #endif
2424
2425                                 #ifdef CGNAPT_DBG_PRNT
2426                                 if (CGNAPT_DEBUG > 4)
2427                                         print_pkt(pkts[pkt_index]);
2428                                 #endif
2429
2430                                 } else {
2431                                         if (ret == ARP_NOT_FOUND) {
2432                                         printf("%s: ARP Not Found, nhip: %x, "
2433                                         "outport_id: %d\n", __func__, nhip,
2434                                         *outport_id);
2435                                         }
2436                                                 //request_arp(*outport_id,
2437                                                 //      nhip, p_nat->p.p);
2438                                 p_nat->invalid_packets |= pkt_mask;
2439                                 p_nat->naptDroppedPktCount++;
2440                                 #ifdef CGNAPT_DEBUGGING
2441                                 p_nat->naptDroppedPktCount4++;
2442                                 #endif
2443                                 continue;
2444                         }
2445
2446                         if (*protocol == IP_PROTOCOL_ICMP) {
2447                                 // Query ID reverse translation done here
2448                                 *src_port =
2449                                         rte_bswap16(entry->data.prv_port);
2450                                 } else {
2451                                         #ifdef NAT_ONLY_CONFIG_REQ
2452                                         if (!nat_only_config_flag) {
2453                                         #endif
2454                                                 *dst_port =
2455                                                         rte_bswap16(entry->
2456                                                                 data.prv_port);
2457                                         #ifdef NAT_ONLY_CONFIG_REQ
2458                                         }
2459                                         #endif
2460                                 }
2461                         }
2462
2463                         p_nat->inaptedPktCount++;
2464                 }
2465
2466                 p_nat->naptedPktCount++;
2467
2468                 #ifdef HW_CHECKSUM_REQ
2469                         if (p_nat->hw_checksum_reqd)
2470                                 hw_checksum(pkts[pkt_index], pkt_type);
2471                         else
2472                 #endif
2473                                 sw_checksum(pkts[pkt_index], pkt_type);
2474         }
2475
2476         if (p_nat->invalid_packets) {
2477                 /* get rid of invalid packets */
2478                 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2479
2480                 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2481
2482                 #ifdef CGNAPT_DBG_PRNT
2483                 if (CGNAPT_DEBUG > 1) {
2484                         printf("valid_packets:0x%jx\n", p_nat->valid_packets);
2485                         printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
2486                         printf("invalid_packets:0x%jx\n",
2487                                          p_nat->invalid_packets);
2488                         printf("rte_invalid_packets :0x%jx\n",
2489                                          rte_p->pkts_drop_mask);
2490                         printf("Total pkts dropped :0x%jx\n",
2491                                          rte_p->n_pkts_ah_drop);
2492                 }
2493                 #endif
2494         }
2495
2496         return p_nat->valid_packets;
2497 }
2498
2499 /**
2500  * Input port handler for IPv4 private traffic
2501  * Starting from the packet burst it filters unwanted packets,
2502  * calculates keys, does lookup and then based on the lookup
2503  * updates NAPT table and does packet NAPT translation.
2504  *
2505  * @param rte_p
2506  *  A pointer to struct rte_pipeline
2507  * @param pkts
2508  *  A pointer to array of packets mbuf
2509  * @param n_pkts
2510  *  Number of packets in the burst
2511  * @param arg
2512  *  Void pointer
2513  *
2514  * @return
2515  *  int that is not checked by caller
2516  */
2517
2518 static int cgnapt_in_port_ah_ipv4_prv(struct rte_pipeline *rte_p,
2519                                                 struct rte_mbuf **pkts,
2520                                                 uint32_t n_pkts, void *arg)
2521 {
2522         uint32_t i, j;
2523         struct pipeline_cgnapt_in_port_h_arg *ap = arg;
2524         struct pipeline_cgnapt *p_nat = ap->p;
2525
2526         #ifdef CGNAPT_TIMING_INST
2527         uint64_t entry_timestamp = 0, exit_timestamp;
2528
2529         if (p_nat->time_measurements_on) {
2530                 entry_timestamp = rte_get_tsc_cycles();
2531         /* check since exit ts not valid first time through */
2532                 if (likely(p_nat->in_port_exit_timestamp))
2533                         p_nat->external_time_sum +=
2534                                 entry_timestamp - p_nat->in_port_exit_timestamp;
2535         }
2536         #endif
2537
2538         p_nat->pkt_burst_cnt = 0;       /* for dynamic napt */
2539         p_nat->valid_packets = rte_p->pkts_mask;        /*n_pkts; */
2540         p_nat->invalid_packets = 0;
2541
2542         #ifdef CGNAPT_DBG_PRNT
2543         if (CGNAPT_DEBUG > 1)
2544                 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
2545         #endif
2546
2547         /* prefetching for mbufs should be done here */
2548         for (j = 0; j < n_pkts; j++)
2549                 rte_prefetch0(pkts[j]);
2550
2551         for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2552                 pkt4_work_cgnapt_key_ipv4_prv(&pkts[i], i, arg, p_nat);
2553
2554         for (; i < n_pkts; i++)
2555                 pkt_work_cgnapt_key_ipv4_prv(pkts[i], i, arg, p_nat);
2556
2557         p_nat->valid_packets &= ~(p_nat->invalid_packets);
2558
2559         if (unlikely(p_nat->valid_packets == 0)) {
2560                 /* no suitable packet for lookup */
2561                 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2562                 return p_nat->valid_packets;
2563         }
2564
2565         /* lookup entries in the common napt table */
2566
2567         int lookup_result = rte_hash_lookup_bulk(
2568                                 napt_common_table,
2569                                 (const void **)&p_nat->key_ptrs,
2570                                 /* should be minus num invalid pkts */
2571                                 n_pkts,
2572                                 /*new pipeline data member */
2573                                 &p_nat->lkup_indx[0]);
2574
2575         if (unlikely(lookup_result < 0)) {
2576                 /* unknown error, just discard all packets */
2577                 printf("Unexpected hash lookup error %d, discarding "
2578                         "all packets", lookup_result);
2579                 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
2580                 return 0;
2581         }
2582
2583         /* Now call second stage of pipeline to one by one
2584         * check the result of our bulk lookup
2585         */
2586
2587         /* prefetching for table entries should be done here */
2588         for (j = 0; j < n_pkts; j++) {
2589                 if (p_nat->lkup_indx[j] >= 0)
2590                         rte_prefetch0(&napt_hash_tbl_entries
2591                                                 [p_nat->lkup_indx[j]]);
2592         }
2593
2594         for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2595                 pkt4_work_cgnapt_ipv4_prv(pkts, i, arg, p_nat);
2596
2597         for (; i < n_pkts; i++)
2598                 pkt_work_cgnapt_ipv4_prv(pkts, i, arg, p_nat);
2599
2600         if (p_nat->invalid_packets) {
2601                 /* get rid of invalid packets */
2602                 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2603
2604                 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2605
2606         #ifdef CGNAPT_DBG_PRNT
2607         if (CGNAPT_DEBUG > 1) {
2608                 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
2609                 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
2610                 printf("invalid_packets:0x%jx\n",
2611                                  p_nat->invalid_packets);
2612                 printf("rte_invalid_packets :0x%jx\n",
2613                                  rte_p->pkts_drop_mask);
2614                 printf("Total pkts dropped :0x%jx\n",
2615                                  rte_p->n_pkts_ah_drop);
2616         }
2617         #endif
2618         }
2619
2620         #ifdef CGNAPT_TIMING_INST
2621         if (p_nat->time_measurements_on) {
2622                 exit_timestamp = rte_get_tsc_cycles();
2623                 p_nat->in_port_exit_timestamp = exit_timestamp;
2624                 p_nat->internal_time_sum += exit_timestamp - entry_timestamp;
2625                 p_nat->time_measurements++;
2626                 if (p_nat->time_measurements == p_nat->max_time_mesurements)
2627                         p_nat->time_measurements_on = 0;
2628         }
2629         #endif
2630
2631         return p_nat->valid_packets;
2632 }
2633
2634 /**
2635  * Input port handler for IPv4 public traffic
2636  * Starting from the packet burst it filters unwanted packets,
2637  * calculates keys, does lookup and then based on the lookup
2638  * updates NAPT table and does packet NAPT translation.
2639  *
2640  * @param rte_p
2641  *  A pointer to struct rte_pipeline
2642  * @param pkts
2643  *  A pointer to array of packets mbuf
2644  * @param n_pkts
2645  *  Number of packets in the burst
2646  * @param arg
2647  *  Void pointer
2648  *
2649  * @return
2650  *  int that is not checked by caller
2651  */
2652 static int cgnapt_in_port_ah_ipv4_pub(struct rte_pipeline *rte_p,
2653                                                 struct rte_mbuf **pkts,
2654                                                 uint32_t n_pkts, void *arg)
2655 {
2656         uint32_t i, j;
2657         struct pipeline_cgnapt_in_port_h_arg *ap = arg;
2658         struct pipeline_cgnapt *p_nat = ap->p;
2659
2660         #ifdef CGNAPT_TIMING_INST
2661         uint64_t entry_timestamp = 0, exit_timestamp;
2662
2663         if (p_nat->time_measurements_on) {
2664                 entry_timestamp = rte_get_tsc_cycles();
2665
2666                 /* check since exit ts not valid first time through */
2667                 if (likely(p_nat->in_port_exit_timestamp))
2668                         p_nat->external_time_sum +=
2669                                 entry_timestamp - p_nat->in_port_exit_timestamp;
2670         }
2671         #endif
2672
2673         p_nat->pkt_burst_cnt = 0;       /* for dynamic napt */
2674         p_nat->valid_packets = rte_p->pkts_mask;        /*n_pkts; */
2675         p_nat->invalid_packets = 0;
2676
2677         #ifdef CGNAPT_DBG_PRNT
2678         if (CGNAPT_DEBUG > 1)
2679                 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
2680         #endif
2681
2682         /* prefetching for mbufs should be done here */
2683         for (j = 0; j < n_pkts; j++)
2684                 rte_prefetch0(pkts[j]);
2685
2686         for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2687                 pkt4_work_cgnapt_key_ipv4_pub(&pkts[i], i, arg, p_nat);
2688
2689         for (; i < n_pkts; i++)
2690                 pkt_work_cgnapt_key_ipv4_pub(pkts[i], i, arg, p_nat);
2691
2692         p_nat->valid_packets &= ~(p_nat->invalid_packets);
2693
2694         if (unlikely(p_nat->valid_packets == 0)) {
2695                 /* no suitable packet for lookup */
2696                 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2697                 return p_nat->valid_packets;
2698         }
2699
2700         /* lookup entries in the common napt table */
2701
2702         int lookup_result = rte_hash_lookup_bulk(
2703                                 napt_common_table,
2704                                 (const void **)&p_nat->key_ptrs,
2705                                 /* should be minus num invalid pkts */
2706                                 n_pkts,
2707                                 /*new pipeline data member */
2708                                 &p_nat->lkup_indx[0]);
2709
2710         if (unlikely(lookup_result < 0)) {
2711                 /* unknown error, just discard all packets */
2712                 printf("Unexpected hash lookup error %d, discarding "
2713                         "all packets", lookup_result);
2714                 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
2715                 return 0;
2716         }
2717
2718         /* Now call second stage of pipeline to one by one
2719         * check the result of our bulk lookup
2720         */
2721
2722         /* prefetching for table entries should be done here */
2723         for (j = 0; j < n_pkts; j++) {
2724                 if (p_nat->lkup_indx[j] >= 0)
2725                         rte_prefetch0(&napt_hash_tbl_entries
2726                                                 [p_nat->lkup_indx[j]]);
2727         }
2728
2729         for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2730                 pkt4_work_cgnapt_ipv4_pub(pkts, i, arg, p_nat);
2731
2732         for (; i < n_pkts; i++)
2733                 pkt_work_cgnapt_ipv4_pub(pkts, i, arg, p_nat);
2734
2735         if (p_nat->invalid_packets) {
2736                 /* get rid of invalid packets */
2737                 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2738
2739                 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2740
2741         #ifdef CGNAPT_DBG_PRNT
2742         if (CGNAPT_DEBUG > 1) {
2743                 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
2744                 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
2745                 printf("invalid_packets:0x%jx\n",
2746                                  p_nat->invalid_packets);
2747                 printf("rte_invalid_packets :0x%jx\n",
2748                                  rte_p->pkts_drop_mask);
2749                 printf("Total pkts dropped :0x%jx\n",
2750                                  rte_p->n_pkts_ah_drop);
2751                 }
2752         #endif
2753         }
2754
2755         #ifdef CGNAPT_TIMING_INST
2756         if (p_nat->time_measurements_on) {
2757                 exit_timestamp = rte_get_tsc_cycles();
2758                 p_nat->in_port_exit_timestamp = exit_timestamp;
2759
2760                 p_nat->internal_time_sum += exit_timestamp - entry_timestamp;
2761                 p_nat->time_measurements++;
2762                 if (p_nat->time_measurements == p_nat->max_time_mesurements)
2763                         p_nat->time_measurements_on = 0;
2764         }
2765         #endif
2766
2767         return p_nat->valid_packets;
2768 }
2769
2770 /**
2771  * NAPT key calculation function for IPv4 private traffic
2772  * which handles 4 pkts
2773  *
2774  * @param pkt
2775  *  A pointer to array of packets mbuf
2776  * @param in_pkt_num
2777  *  Starting pkt number of pkts
2778  * @param arg
2779  *  Void pointer
2780  * @param p_nat
2781  *  A pointer to main CGNAPT structure
2782  *
2783  */
2784 void
2785 pkt4_work_cgnapt_key_ipv4_prv(
2786         struct rte_mbuf **pkt,
2787         uint32_t pkt_num,
2788         __rte_unused void *arg,
2789         struct pipeline_cgnapt *p_nat)
2790 {
2791         p_nat->receivedPktCount += 4;
2792         /* bitmask representing only this packet */
2793         uint64_t pkt_mask0 = 1LLU << pkt_num;
2794         uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
2795         uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
2796         uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
2797
2798         uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
2799                                 PROT_OFST_IP4);
2800         uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
2801                                 PROT_OFST_IP4);
2802         uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
2803                                 PROT_OFST_IP4);
2804         uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
2805                                 PROT_OFST_IP4);
2806
2807         uint32_t src_addr0 = RTE_MBUF_METADATA_UINT32(pkt[0],
2808                                 SRC_ADR_OFST_IP4);
2809         uint32_t src_addr1 = RTE_MBUF_METADATA_UINT32(pkt[1],
2810                                 SRC_ADR_OFST_IP4);
2811         uint32_t src_addr2 = RTE_MBUF_METADATA_UINT32(pkt[2],
2812                                 SRC_ADR_OFST_IP4);
2813         uint32_t src_addr3 = RTE_MBUF_METADATA_UINT32(pkt[3],
2814                                 SRC_ADR_OFST_IP4);
2815
2816         uint16_t src_port_offset0;
2817         uint16_t src_port_offset1;
2818         uint16_t src_port_offset2;
2819         uint16_t src_port_offset3;
2820
2821         uint16_t src_port0;
2822         uint16_t src_port1;
2823         uint16_t src_port2;
2824         uint16_t src_port3;
2825
2826         uint16_t phy_port0 = pkt[0]->port;
2827         uint16_t phy_port1 = pkt[1]->port;
2828         uint16_t phy_port2 = pkt[2]->port;
2829         uint16_t phy_port3 = pkt[3]->port;
2830
2831         struct pipeline_cgnapt_entry_key key0;
2832         struct pipeline_cgnapt_entry_key key1;
2833         struct pipeline_cgnapt_entry_key key2;
2834         struct pipeline_cgnapt_entry_key key3;
2835
2836         memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
2837         memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
2838         memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
2839         memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
2840
2841 /* --0-- */
2842         #ifdef CGNAPT_DBG_PRNT
2843         if (CGNAPT_DEBUG > 4)
2844                 print_pkt(pkt[0]);
2845         #endif
2846
2847         if (enable_hwlb) {
2848                 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
2849                         goto PKT1;
2850         }
2851
2852         switch (protocol0) {
2853         case IP_PROTOCOL_UDP:
2854         {
2855                 #ifdef PCP_ENABLE
2856                 if (pcp_enable) {
2857                 struct udp_hdr *udp;
2858
2859                 udp = (struct udp_hdr *)
2860                         RTE_MBUF_METADATA_UINT8_PTR(pkt[0],
2861                                                 IPV4_UDP_OFST);
2862
2863                 if (rte_bswap16(udp->dst_port) ==
2864                         PCP_SERVER_PORT) {
2865                         handle_pcp_req(pkt[0], IPV4_SZ, p_nat);
2866                         p_nat->invalid_packets |= pkt_mask0;
2867                         goto PKT1;
2868                 }
2869                 }
2870                 #endif
2871         }
2872         case IP_PROTOCOL_TCP:
2873
2874                 src_port_offset0 = SRC_PRT_OFST_IP4_TCP;
2875                 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
2876                                 src_port_offset0);
2877
2878         break;
2879
2880         case IP_PROTOCOL_ICMP:
2881                  /* Identifier */
2882                  src_port_offset0 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
2883                                          IP_HDR_SIZE + 4;
2884                  src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
2885                                 src_port_offset0);
2886
2887         break;
2888
2889         default:
2890                  /* remember invalid packets to be dropped */
2891                  p_nat->invalid_packets |= pkt_mask0;
2892                  p_nat->naptDroppedPktCount++;
2893
2894                  #ifdef CGNAPT_DEBUGGING
2895                  p_nat->naptDroppedPktCount2++;
2896                  #endif
2897                 goto PKT1;
2898         }
2899
2900         key0.pid = phy_port0;
2901         key0.ip = rte_bswap32(src_addr0);
2902         key0.port = rte_bswap16(src_port0);
2903
2904         #ifdef NAT_ONLY_CONFIG_REQ
2905         if (nat_only_config_flag)
2906                 key0.port = 0xffff;
2907         #endif
2908
2909          memcpy(&p_nat->keys[pkt_num], &key0,
2910                                 sizeof(struct pipeline_cgnapt_entry_key));
2911         p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
2912
2913 /* --1-- */
2914 PKT1:
2915
2916         #ifdef CGNAPT_DBG_PRNT
2917         if (CGNAPT_DEBUG > 4)
2918                 print_pkt(pkt[1]);
2919         #endif
2920
2921         if (enable_hwlb) {
2922                 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
2923                         goto PKT2;
2924         }
2925         switch (protocol1) {
2926         case IP_PROTOCOL_UDP:
2927         {
2928                 #ifdef PCP_ENABLE
2929                 if (pcp_enable) {
2930                 struct udp_hdr *udp;
2931
2932                 udp = (struct udp_hdr *)
2933                         RTE_MBUF_METADATA_UINT8_PTR(pkt[1],
2934                                                 IPV4_UDP_OFST);
2935
2936                 if (rte_bswap16(udp->dst_port) ==
2937                         PCP_SERVER_PORT) {
2938                         handle_pcp_req(pkt[1], IPV4_SZ, p_nat);
2939                         p_nat->invalid_packets |= pkt_mask1;
2940                         goto PKT2;
2941                 }
2942                 }
2943                 #endif
2944         }
2945         case IP_PROTOCOL_TCP:
2946
2947                 src_port_offset1 = SRC_PRT_OFST_IP4_TCP;
2948                 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
2949                                 src_port_offset1);
2950
2951         break;
2952
2953         case IP_PROTOCOL_ICMP:
2954                  /* Identifier */
2955                  src_port_offset1 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
2956                                          IP_HDR_SIZE + 4;
2957                  src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
2958                                 src_port_offset1);
2959
2960         break;
2961
2962         default:
2963                  /* remember invalid packets to be dropped */
2964                  p_nat->invalid_packets |= pkt_mask1;
2965                  p_nat->naptDroppedPktCount++;
2966
2967                  #ifdef CGNAPT_DEBUGGING
2968                  p_nat->naptDroppedPktCount2++;
2969                  #endif
2970                 goto PKT2;
2971         }
2972
2973         key1.pid = phy_port1;
2974         key1.ip = rte_bswap32(src_addr1);
2975         key1.port = rte_bswap16(src_port1);
2976
2977         #ifdef NAT_ONLY_CONFIG_REQ
2978         if (nat_only_config_flag)
2979                 key1.port = 0xffff;
2980         #endif
2981
2982          memcpy(&p_nat->keys[pkt_num + 1], &key1,
2983                                 sizeof(struct pipeline_cgnapt_entry_key));
2984         p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
2985
2986 /* --2-- */
2987 PKT2:
2988         #ifdef CGNAPT_DBG_PRNT
2989         if (CGNAPT_DEBUG > 4)
2990                 print_pkt(pkt[2]);
2991         #endif
2992
2993         if (enable_hwlb) {
2994                 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
2995                         goto PKT3;
2996         }
2997
2998         switch (protocol2) {
2999         case IP_PROTOCOL_UDP:
3000         {
3001                 #ifdef PCP_ENABLE
3002                 if (pcp_enable) {
3003                 struct udp_hdr *udp;
3004
3005                 udp = (struct udp_hdr *)
3006                         RTE_MBUF_METADATA_UINT8_PTR(pkt[2],
3007                                                 IPV4_UDP_OFST);
3008
3009                 if (rte_bswap16(udp->dst_port) ==
3010                         PCP_SERVER_PORT) {
3011                         handle_pcp_req(pkt[2], IPV4_SZ, p_nat);
3012                         p_nat->invalid_packets |= pkt_mask2;
3013                         goto PKT3;
3014                 }
3015                 }
3016                 #endif
3017         }
3018         case IP_PROTOCOL_TCP:
3019
3020                 src_port_offset2 = SRC_PRT_OFST_IP4_TCP;
3021                 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3022                                 src_port_offset2);
3023
3024         break;
3025
3026         case IP_PROTOCOL_ICMP:
3027                  /* Identifier */
3028                  src_port_offset2 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3029                                          IP_HDR_SIZE + 4;
3030                  src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3031                                 src_port_offset2);
3032
3033         break;
3034
3035         default:
3036                  /* remember invalid packets to be dropped */
3037                  p_nat->invalid_packets |= pkt_mask2;
3038                  p_nat->naptDroppedPktCount++;
3039
3040                  #ifdef CGNAPT_DEBUGGING
3041                  p_nat->naptDroppedPktCount2++;
3042                  #endif
3043                 goto PKT3;
3044         }
3045
3046         key2.pid = phy_port2;
3047         key2.ip = rte_bswap32(src_addr2);
3048         key2.port = rte_bswap16(src_port2);
3049
3050         #ifdef NAT_ONLY_CONFIG_REQ
3051         if (nat_only_config_flag)
3052                 key2.port = 0xffff;
3053         #endif
3054
3055          memcpy(&p_nat->keys[pkt_num + 2], &key2,
3056                                 sizeof(struct pipeline_cgnapt_entry_key));
3057         p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
3058
3059 /* --3-- */
3060 PKT3:
3061         #ifdef CGNAPT_DBG_PRNT
3062         if (CGNAPT_DEBUG > 4)
3063                 print_pkt(pkt[3]);
3064         #endif
3065         if (enable_hwlb) {
3066                 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
3067                         return;
3068         }
3069
3070         switch (protocol3) {
3071         case IP_PROTOCOL_UDP:
3072         {
3073                 #ifdef PCP_ENABLE
3074                 if (pcp_enable) {
3075                 struct udp_hdr *udp;
3076
3077                 udp = (struct udp_hdr *)
3078                         RTE_MBUF_METADATA_UINT8_PTR(pkt[3],
3079                                                 IPV4_UDP_OFST);
3080
3081                 if (rte_bswap16(udp->dst_port) ==
3082                         PCP_SERVER_PORT) {
3083                         handle_pcp_req(pkt[3], IPV4_SZ, p_nat);
3084                         p_nat->invalid_packets |= pkt_mask3;
3085                         return;
3086                 }
3087                 }
3088                 #endif
3089         }
3090         case IP_PROTOCOL_TCP:
3091
3092                 src_port_offset3 = SRC_PRT_OFST_IP4_TCP;
3093                 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3094                                 src_port_offset3);
3095
3096         break;
3097
3098         case IP_PROTOCOL_ICMP:
3099                  /* Identifier */
3100                  src_port_offset3 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3101                                          IP_HDR_SIZE + 4;
3102                  src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3103                                 src_port_offset3);
3104
3105         break;
3106
3107         default:
3108                  /* remember invalid packets to be dropped */
3109                  p_nat->invalid_packets |= pkt_mask3;
3110                  p_nat->naptDroppedPktCount++;
3111
3112                  #ifdef CGNAPT_DEBUGGING
3113                  p_nat->naptDroppedPktCount2++;
3114                  #endif
3115                 return;
3116         }
3117
3118         key3.pid = phy_port3;
3119         key3.ip = rte_bswap32(src_addr3);
3120         key3.port = rte_bswap16(src_port3);
3121
3122         #ifdef NAT_ONLY_CONFIG_REQ
3123         if (nat_only_config_flag)
3124                 key3.port = 0xffff;
3125         #endif
3126
3127          memcpy(&p_nat->keys[pkt_num + 3], &key3,
3128                                 sizeof(struct pipeline_cgnapt_entry_key));
3129         p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
3130 }
3131
3132 /**
3133  * NAPT key calculation function for IPv4 public traffic
3134  * which handles 4 pkts
3135  *
3136  * @param pkt
3137  *  A pointer to array of packets mbuf
3138  * @param in_pkt_num
3139  *  Starting pkt number of pkts
3140  * @param arg
3141  *  Void pointer
3142  * @param p_nat
3143  *  A pointer to main CGNAPT structure
3144  *
3145  */
3146 void
3147 pkt4_work_cgnapt_key_ipv4_pub(
3148         struct rte_mbuf **pkt,
3149         uint32_t pkt_num,
3150         __rte_unused void *arg,
3151         struct pipeline_cgnapt *p_nat)
3152 {
3153         p_nat->receivedPktCount += 4;
3154         /* bitmask representing only this packet */
3155         uint64_t pkt_mask0 = 1LLU << pkt_num;
3156         uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
3157         uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
3158         uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
3159
3160         uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
3161                                 PROT_OFST_IP4);
3162         uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
3163                                 PROT_OFST_IP4);
3164         uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
3165                                 PROT_OFST_IP4);
3166         uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
3167                                 PROT_OFST_IP4);
3168
3169         uint32_t dst_addr0 = RTE_MBUF_METADATA_UINT32(pkt[0],
3170                                 DST_ADR_OFST_IP4);
3171         uint32_t dst_addr1 = RTE_MBUF_METADATA_UINT32(pkt[1],
3172                                 DST_ADR_OFST_IP4);
3173         uint32_t dst_addr2 = RTE_MBUF_METADATA_UINT32(pkt[2],
3174                                 DST_ADR_OFST_IP4);
3175         uint32_t dst_addr3 = RTE_MBUF_METADATA_UINT32(pkt[3],
3176                                 DST_ADR_OFST_IP4);
3177
3178         uint16_t src_port_offset0;
3179         uint16_t src_port_offset1;
3180         uint16_t src_port_offset2;
3181         uint16_t src_port_offset3;
3182
3183         uint16_t dst_port_offset0;
3184         uint16_t dst_port_offset1;
3185         uint16_t dst_port_offset2;
3186         uint16_t dst_port_offset3;
3187
3188         uint16_t src_port0;
3189         uint16_t src_port1;
3190         uint16_t src_port2;
3191         uint16_t src_port3;
3192
3193         uint16_t dst_port0;
3194         uint16_t dst_port1;
3195         uint16_t dst_port2;
3196         uint16_t dst_port3;
3197
3198         struct pipeline_cgnapt_entry_key key0;
3199         struct pipeline_cgnapt_entry_key key1;
3200         struct pipeline_cgnapt_entry_key key2;
3201         struct pipeline_cgnapt_entry_key key3;
3202
3203         memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
3204         memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
3205         memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
3206         memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
3207
3208 /* --0-- */
3209         #ifdef CGNAPT_DBG_PRNT
3210         if (CGNAPT_DEBUG > 4)
3211                 print_pkt(pkt[0]);
3212         #endif
3213
3214         if (enable_hwlb) {
3215                 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
3216                         goto PKT1;
3217         }
3218
3219         switch (protocol0) {
3220         case IP_PROTOCOL_UDP:
3221         case IP_PROTOCOL_TCP:
3222
3223                 src_port_offset0 = SRC_PRT_OFST_IP4_TCP;
3224                 dst_port_offset0 = DST_PRT_OFST_IP4_TCP;
3225
3226                 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3227                                 src_port_offset0);
3228                 dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3229                                 dst_port_offset0);
3230
3231                 key0.port = rte_bswap16(dst_port0);
3232
3233         break;
3234
3235         case IP_PROTOCOL_ICMP:
3236                  /* Identifier */
3237                 src_port_offset0 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3238                                          IP_HDR_SIZE + 4;
3239                 /*Sequence number */
3240                 dst_port_offset0 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3241                                          IP_HDR_SIZE + 6;
3242
3243                 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3244                                 src_port_offset0);
3245                 dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3246                                 dst_port_offset0);
3247
3248                 key0.port = rte_bswap16(src_port0);
3249
3250         break;
3251
3252         default:
3253                  /* remember invalid packets to be dropped */
3254                  p_nat->invalid_packets |= pkt_mask0;
3255                  p_nat->naptDroppedPktCount++;
3256
3257                  #ifdef CGNAPT_DEBUGGING
3258                  p_nat->naptDroppedPktCount2++;
3259                  #endif
3260                 goto PKT1;
3261         }
3262
3263         key0.pid = 0xffff;
3264         key0.ip = rte_bswap32(dst_addr0);
3265
3266         #ifdef NAT_ONLY_CONFIG_REQ
3267         if (nat_only_config_flag)
3268                 key0.port = 0xffff;
3269         #endif
3270
3271          memcpy(&p_nat->keys[pkt_num], &key0,
3272                                 sizeof(struct pipeline_cgnapt_entry_key));
3273         p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3274
3275 /* --1-- */
3276 PKT1:
3277
3278          #ifdef CGNAPT_DBG_PRNT
3279         if (CGNAPT_DEBUG > 4)
3280                 print_pkt(pkt[1]);
3281         #endif
3282
3283         if (enable_hwlb) {
3284                 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
3285                         goto PKT2;
3286         }
3287
3288         switch (protocol1) {
3289         case IP_PROTOCOL_UDP:
3290         case IP_PROTOCOL_TCP:
3291
3292                 src_port_offset1 = SRC_PRT_OFST_IP4_TCP;
3293                 dst_port_offset1 = DST_PRT_OFST_IP4_TCP;
3294
3295                 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3296                                 src_port_offset1);
3297                 dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3298                                 dst_port_offset1);
3299
3300                 key1.port = rte_bswap16(dst_port1);
3301
3302         break;
3303
3304         case IP_PROTOCOL_ICMP:
3305                  /* Identifier */
3306                  src_port_offset1 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3307                                          IP_HDR_SIZE + 4;
3308                  /*Sequence number */
3309                  dst_port_offset1 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3310                                          IP_HDR_SIZE + 6;
3311
3312                  src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3313                                 src_port_offset1);
3314                  dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3315                                 dst_port_offset1);
3316
3317                 key1.port = rte_bswap16(src_port1);
3318         break;
3319
3320         default:
3321                  /* remember invalid packets to be dropped */
3322                  p_nat->invalid_packets |= pkt_mask1;
3323                  p_nat->naptDroppedPktCount++;
3324
3325                  #ifdef CGNAPT_DEBUGGING
3326                  p_nat->naptDroppedPktCount2++;
3327                  #endif
3328                 goto PKT2;
3329         }
3330
3331         key1.pid = 0xffff;
3332         key1.ip = rte_bswap32(dst_addr1);
3333
3334         #ifdef NAT_ONLY_CONFIG_REQ
3335         if (nat_only_config_flag)
3336                 key1.port = 0xffff;
3337         #endif
3338
3339          memcpy(&p_nat->keys[pkt_num + 1], &key1,
3340                                 sizeof(struct pipeline_cgnapt_entry_key));
3341         p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
3342
3343 /* --2-- */
3344 PKT2:
3345         #ifdef CGNAPT_DBG_PRNT
3346         if (CGNAPT_DEBUG > 4)
3347                 print_pkt(pkt[2]);
3348         #endif
3349
3350         if (enable_hwlb) {
3351                 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
3352                         goto PKT3;
3353         }
3354
3355         switch (protocol2) {
3356         case IP_PROTOCOL_UDP:
3357         case IP_PROTOCOL_TCP:
3358
3359                 src_port_offset2 = SRC_PRT_OFST_IP4_TCP;
3360                 dst_port_offset2 = DST_PRT_OFST_IP4_TCP;
3361
3362                 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3363                                 src_port_offset2);
3364                 dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3365                                 dst_port_offset2);
3366
3367                 key2.port = rte_bswap16(dst_port2);
3368
3369         break;
3370
3371         case IP_PROTOCOL_ICMP:
3372                  /* Identifier */
3373                  src_port_offset2 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3374                                          IP_HDR_SIZE + 4;
3375                  /*Sequence number */
3376                  dst_port_offset2 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3377                                          IP_HDR_SIZE + 6;
3378
3379                  src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3380                                 src_port_offset2);
3381                  dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3382                                 dst_port_offset2);
3383
3384                 key2.port = rte_bswap16(src_port2);
3385
3386         break;
3387
3388         default:
3389                  /* remember invalid packets to be dropped */
3390                  p_nat->invalid_packets |= pkt_mask2;
3391                  p_nat->naptDroppedPktCount++;
3392
3393                  #ifdef CGNAPT_DEBUGGING
3394                  p_nat->naptDroppedPktCount2++;
3395                  #endif
3396                 goto PKT3;
3397         }
3398
3399         key2.pid = 0xffff;
3400         key2.ip = rte_bswap32(dst_addr2);
3401
3402         #ifdef NAT_ONLY_CONFIG_REQ
3403         if (nat_only_config_flag)
3404                 key2.port = 0xffff;
3405         #endif
3406
3407          memcpy(&p_nat->keys[pkt_num + 2], &key2,
3408                                 sizeof(struct pipeline_cgnapt_entry_key));
3409         p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
3410
3411 /* --3-- */
3412 PKT3:
3413         #ifdef CGNAPT_DBG_PRNT
3414         if (CGNAPT_DEBUG > 4)
3415                 print_pkt(pkt[3]);
3416         #endif
3417
3418         if (enable_hwlb) {
3419                 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
3420                         return;
3421         }
3422
3423         switch (protocol3) {
3424         case IP_PROTOCOL_UDP:
3425         case IP_PROTOCOL_TCP:
3426
3427                 src_port_offset3 = SRC_PRT_OFST_IP4_TCP;
3428                 dst_port_offset3 = DST_PRT_OFST_IP4_TCP;
3429
3430                 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3431                                 src_port_offset3);
3432                 dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3433                                 dst_port_offset3);
3434
3435                 key3.port = rte_bswap16(dst_port3);
3436
3437         break;
3438
3439         case IP_PROTOCOL_ICMP:
3440                  /* Identifier */
3441                  src_port_offset3 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3442                                          IP_HDR_SIZE + 4;
3443                  /*Sequence number */
3444                  dst_port_offset3 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3445                                          IP_HDR_SIZE + 6;
3446
3447                  src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3448                                 src_port_offset3);
3449                  dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3450                                 dst_port_offset3);
3451
3452                 key3.port = rte_bswap16(src_port3);
3453
3454         break;
3455
3456         default:
3457                  /* remember invalid packets to be dropped */
3458                  p_nat->invalid_packets |= pkt_mask3;
3459                  p_nat->naptDroppedPktCount++;
3460
3461                  #ifdef CGNAPT_DEBUGGING
3462                  p_nat->naptDroppedPktCount2++;
3463                  #endif
3464                 return;
3465         }
3466
3467         key3.pid = 0xffff;
3468         key3.ip = rte_bswap32(dst_addr3);
3469
3470         #ifdef NAT_ONLY_CONFIG_REQ
3471         if (nat_only_config_flag)
3472                 key3.port = 0xffff;
3473         #endif
3474
3475          memcpy(&p_nat->keys[pkt_num + 3], &key3,
3476                                 sizeof(struct pipeline_cgnapt_entry_key));
3477         p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
3478 }
3479
3480 /**
3481  * NAPT key calculation function for IPv4 private traffic
3482  * which handles 1 pkt
3483  *
3484  * @param pkt
3485  *  A pointer to array of packets mbuf
3486  * @param in_pkt_num
3487  *  Pkt number of pkts
3488  * @param arg
3489  *  Void pointer
3490  * @param p_nat
3491  *  A pointer to main CGNAPT structure
3492  *
3493  */
3494 void
3495 pkt_work_cgnapt_key_ipv4_prv(
3496         struct rte_mbuf *pkt,
3497         uint32_t pkt_num,
3498         __rte_unused void *arg,
3499         struct pipeline_cgnapt *p_nat)
3500 {
3501         /* Egress */
3502         p_nat->receivedPktCount++;
3503
3504         /* bitmask representing only this packet */
3505         uint64_t pkt_mask = 1LLU << pkt_num;
3506         uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3507
3508         uint32_t src_addr = RTE_MBUF_METADATA_UINT32(pkt, SRC_ADR_OFST_IP4);
3509
3510         uint16_t src_port_offset;
3511
3512         uint16_t src_port;
3513
3514         uint16_t phy_port = pkt->port;
3515         struct pipeline_cgnapt_entry_key key;
3516
3517         memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
3518
3519
3520         #ifdef CGNAPT_DBG_PRNT
3521         if (CGNAPT_DEBUG > 4)
3522                 print_pkt(pkt);
3523         #endif
3524
3525         if (enable_hwlb) {
3526                 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
3527                         return;
3528         }
3529
3530         switch (protocol) {
3531         case IP_PROTOCOL_UDP:
3532         {
3533                 #ifdef PCP_ENABLE
3534                 if (pcp_enable) {
3535                 struct udp_hdr *udp;
3536
3537                 udp = (struct udp_hdr *)
3538                         RTE_MBUF_METADATA_UINT8_PTR(pkt,
3539                                                 IPV4_UDP_OFST);
3540
3541                 if (rte_bswap16(udp->dst_port) ==
3542                         PCP_SERVER_PORT) {
3543                         handle_pcp_req(pkt, IPV4_SZ, p_nat);
3544                         p_nat->invalid_packets |= pkt_mask;
3545                         return;
3546                 }
3547                 }
3548                 #endif
3549         }
3550         case IP_PROTOCOL_TCP:
3551
3552                 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3553                 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3554
3555                 key.port = rte_bswap16(src_port);
3556
3557         break;
3558         case IP_PROTOCOL_ICMP:
3559                 /* Identifier */
3560                 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3561                                         IP_HDR_SIZE + 4;
3562                 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3563
3564                 key.port = rte_bswap16(src_port);
3565
3566         break;
3567         default:
3568                 /* remember invalid packets to be dropped */
3569                 p_nat->invalid_packets |= pkt_mask;
3570                 p_nat->naptDroppedPktCount++;
3571
3572                 #ifdef CGNAPT_DEBUGGING
3573                 p_nat->naptDroppedPktCount2++;
3574                 #endif
3575                 return;
3576         }
3577
3578         key.pid = phy_port;
3579         key.ip = rte_bswap32(src_addr);
3580
3581         #ifdef NAT_ONLY_CONFIG_REQ
3582         if (nat_only_config_flag)
3583                 key.port = 0xffff;
3584         #endif
3585
3586         memcpy(&p_nat->keys[pkt_num], &key,
3587                          sizeof(struct pipeline_cgnapt_entry_key));
3588         p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3589 }
3590
3591 /**
3592  * NAPT key calculation function for IPv4 public traffic
3593  * which handles 1 pkt
3594  *
3595  * @param pkt
3596  *  A pointer to array of packets mbuf
3597  * @param in_pkt_num
3598  *  Pkt number of pkts
3599  * @param arg
3600  *  Void pointer
3601  * @param p_nat
3602  *  A pointer to main CGNAPT structure
3603  *
3604  */
3605 void
3606 pkt_work_cgnapt_key_ipv4_pub(
3607         struct rte_mbuf *pkt,
3608         uint32_t pkt_num,
3609         __rte_unused void *arg,
3610         struct pipeline_cgnapt *p_nat)
3611 {
3612         p_nat->receivedPktCount++;
3613
3614         /* bitmask representing only this packet */
3615         uint64_t pkt_mask = 1LLU << pkt_num;
3616         uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3617         uint32_t dst_addr = RTE_MBUF_METADATA_UINT32(pkt, DST_ADR_OFST_IP4);
3618         uint16_t src_port_offset;
3619         uint16_t dst_port_offset;
3620         uint16_t src_port;
3621         uint16_t dst_port;
3622         struct pipeline_cgnapt_entry_key key;
3623         memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
3624
3625         #ifdef CGNAPT_DBG_PRNT
3626         if (CGNAPT_DEBUG > 4)
3627                 print_pkt(pkt);
3628         #endif
3629
3630         if (enable_hwlb) {
3631                 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
3632                         return;
3633         }
3634
3635         switch (protocol) {
3636         case IP_PROTOCOL_UDP:
3637         case IP_PROTOCOL_TCP:
3638                 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3639                 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3640
3641                 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3642                 dst_port = RTE_MBUF_METADATA_UINT16(pkt, dst_port_offset);
3643
3644                 key.port = rte_bswap16(dst_port);
3645         break;
3646         case IP_PROTOCOL_ICMP:
3647                 /* Identifier */
3648                 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3649                                         IP_HDR_SIZE + 4;
3650                 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3651                                         IP_HDR_SIZE + 6;
3652
3653                 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3654                 dst_port = RTE_MBUF_METADATA_UINT16(pkt, dst_port_offset);
3655
3656                 /* common table lookupkey preparation from incoming
3657                 * ICMP Packet- Indentifier field
3658                 */
3659                 key.port = rte_bswap16(src_port);
3660         break;
3661         default:
3662                 /* remember invalid packets to be dropped */
3663                 p_nat->invalid_packets |= pkt_mask;
3664                 p_nat->naptDroppedPktCount++;
3665
3666                 #ifdef CGNAPT_DEBUGGING
3667                 p_nat->naptDroppedPktCount2++;
3668                 #endif
3669                 return;
3670         }
3671
3672         key.ip = rte_bswap32(dst_addr);
3673
3674         #ifdef NAT_ONLY_CONFIG_REQ
3675         if (nat_only_config_flag)
3676                 key.port = 0xffff;
3677         #endif
3678
3679         key.pid = 0xffff;
3680
3681         memcpy(&p_nat->keys[pkt_num], &key,
3682                          sizeof(struct pipeline_cgnapt_entry_key));
3683         p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3684 }
3685
3686
3687 /**
3688  * NAPT function for IPv4 private traffic which handles 1 pkt
3689  *
3690  * @param pkts
3691  *  A pointer to array of packet mbuf
3692  * @param in_pkt_num
3693  *  Pkt number of pkt
3694  * @param arg
3695  *  Void pointer
3696  * @param p_nat
3697  *  A pointer to main CGNAPT structure
3698  *
3699  */
3700 void
3701 pkt_work_cgnapt_ipv4_prv(
3702         struct rte_mbuf **pkts,
3703         uint32_t pkt_num,
3704         __rte_unused void *arg,
3705         struct pipeline_cgnapt *p_nat)
3706 {
3707         #ifdef CT_CGNAT
3708         struct rte_CT_helper ct_helper;
3709         memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
3710         #endif
3711
3712         /* index into hash table entries */
3713         int hash_table_entry = p_nat->lkup_indx[pkt_num];
3714         /*bitmask representing only this packet */
3715         uint64_t pkt_mask = 1LLU << pkt_num;
3716         struct rte_mbuf *pkt = pkts[pkt_num];
3717
3718         uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3719
3720         uint32_t dest_if = 0xff;        /* Added for Multiport */
3721         uint16_t *outport_id =
3722                 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
3723
3724         struct cgnapt_table_entry *entry = NULL;
3725
3726         enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
3727
3728         if (hash_table_entry < 0) {
3729
3730                 /* try to add new entry */
3731                 struct rte_pipeline_table_entry *table_entry = NULL;
3732
3733                 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
3734                                         pkt, &table_entry,
3735                                         &p_nat->valid_packets, pkt_num,
3736                                         (void *)p_nat);
3737
3738                 if (!table_entry) {
3739                         /* ICMP Error message generation for Destination
3740                          * Host unreachable
3741                          */
3742                         if (protocol == IP_PROTOCOL_ICMP) {
3743                                 cgnapt_icmp_pkt = pkt;
3744                                 send_icmp_dest_unreachable_msg();
3745                         }
3746
3747                         /* Drop packet by adding to invalid pkt mask */
3748
3749                         p_nat->invalid_packets |= dropmask;
3750                         #ifdef CGNAPT_DEBUGGING
3751                         if (p_nat->kpc2++ < 5) {
3752                                 printf("in_ah Th: %d", p_nat->pipeline_num);
3753                                 print_key(p_nat->key_ptrs[pkt_num]);
3754                         }
3755                         #endif
3756
3757                         p_nat->naptDroppedPktCount++;
3758
3759                         #ifdef CGNAPT_DEBUGGING
3760                         p_nat->naptDroppedPktCount3++;
3761                         #endif
3762                         return;
3763                 }
3764
3765                 entry = (struct cgnapt_table_entry *)table_entry;
3766         } else {
3767                 /* entry found for this packet */
3768                 entry = &napt_hash_tbl_entries[hash_table_entry];
3769         }
3770
3771         /*  apply napt and mac changes */
3772
3773         p_nat->entries[pkt_num] = &(entry->head);
3774
3775         uint32_t *src_addr =
3776                 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP4);
3777         uint32_t *dst_addr =
3778                 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
3779         uint16_t src_port_offset = 0;
3780         uint16_t dst_port_offset = 0;
3781         uint16_t *src_port;
3782         uint16_t *dst_port;
3783
3784         switch (protocol) {
3785         case IP_PROTOCOL_TCP:
3786                 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3787                 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3788                 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3789                 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3790
3791                 #ifdef CT_CGNAT
3792                 if ((rte_be_to_cpu_16(*src_port) == 21) ||
3793                         rte_be_to_cpu_16(*dst_port) == 21) {
3794
3795                         #ifdef ALGDBG
3796                         printf("cgnapt_ct_process: pkt_mask: % "PRIu64", "
3797                                 "pkt_num: %d\n", pkt_mask, pkt_num);
3798                         #endif
3799
3800                         pkt_mask =  cgnapt_ct_process(cgnat_cnxn_tracker, pkts,
3801                                 pkt_mask, &ct_helper);
3802                 }
3803                 #endif
3804         break;
3805         case IP_PROTOCOL_UDP:
3806                 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3807                 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3808                 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3809                 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3810         break;
3811         case IP_PROTOCOL_ICMP:
3812                 /* Identifier */
3813                 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3814                                         IP_HDR_SIZE + 4;
3815                 /*Sequence number */
3816                 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3817                                         IP_HDR_SIZE + 6;
3818                 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3819                 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3820         break;
3821         }
3822
3823         uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
3824         uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
3825
3826         if (entry->data.ttl == NAPT_ENTRY_STALE)
3827                 entry->data.ttl = NAPT_ENTRY_VALID;
3828
3829         struct ether_addr hw_addr;
3830         uint32_t dest_address = 0;
3831
3832         /* Egress */
3833         if (unlikely(protocol == IP_PROTOCOL_UDP
3834                                 && rte_be_to_cpu_16(*dst_port) == 53)) {
3835                 p_nat->invalid_packets |= pkt_mask;
3836                 p_nat->naptDroppedPktCount++;
3837
3838                 #ifdef CGNAPT_DEBUGGING
3839                 p_nat->naptDroppedPktCount6++;
3840                 #endif
3841                 return;
3842         }
3843
3844         dest_address = rte_bswap32(*dst_addr);
3845         /*Multiport Changes */
3846         uint32_t nhip = 0;
3847         uint32_t ret;
3848         ret = local_get_nh_ipv4(dest_address, &dest_if, &nhip, p_nat);
3849         if (!ret) {
3850                 dest_if = get_prv_to_pub_port(&dest_address, IP_VERSION_4);
3851
3852                 if (dest_if == INVALID_DESTIF) {
3853                         p_nat->invalid_packets |= pkt_mask;
3854                         p_nat->naptDroppedPktCount++;
3855                         #ifdef CGNAPT_DEBUGGING
3856                         p_nat->naptDroppedPktCount6++;
3857                         #endif
3858                         return;
3859                 }
3860
3861                 do_local_nh_ipv4_cache(dest_if, p_nat);
3862         }
3863
3864         *outport_id = p_nat->outport_id[dest_if];
3865
3866         #ifdef CGNAPT_DBG_PRNT
3867         if (CGNAPT_DEBUG > 2)
3868                 printf("Egress: \tphy_port:%d\t get_prv_to_pub():%d "
3869                                 "\tout_port:%d\n", pkt->port, dest_if,
3870                                 *outport_id);
3871         #endif
3872
3873         if (local_dest_mac_present(dest_if)) {
3874                 memcpy(eth_dest,
3875                                 get_local_link_hw_addr(dest_if),
3876                                 sizeof(struct ether_addr));
3877                 memcpy(eth_src, get_link_hw_addr(dest_if),
3878                                 sizeof(struct ether_addr));
3879         } else {
3880                 int ret;
3881                 ret = get_dest_mac_addr_port(dest_address, &dest_if, &hw_addr);
3882
3883                 if (unlikely(ret != ARP_FOUND)) {
3884
3885                         if (unlikely(ret == ARP_NOT_FOUND)) {
3886                                 //request_arp(*outport_id, nhip, p_nat->p.p);
3887                                 printf("%s: ARP Not Found, nhip: %x, "
3888                                 "outport_id: %d\n", __func__, nhip,
3889                                 *outport_id);
3890                         }
3891
3892                         /* Drop the pkt */
3893                         p_nat->invalid_packets |= pkt_mask;
3894                         p_nat->naptDroppedPktCount++;
3895
3896                         #ifdef CGNAPT_DEBUGGING
3897                         p_nat->naptDroppedPktCount4++;
3898                         #endif
3899                         return;
3900
3901                 }
3902
3903                 #ifdef CGNAPT_DBG_PRNT
3904                 if (CGNAPT_DEBUG > 2) {
3905                         printf("MAC found for ip 0x%x, port %d - %02x:%02x: "
3906                         "%02x:%02x:%02x:%02x\n", dest_address,
3907                         *outport_id,
3908                         hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
3909                         hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
3910                         hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
3911
3912                         printf("Dest MAC before - %02x:%02x:%02x: "
3913                         "%02x:%02x:%02x\n", eth_dest[0], eth_dest[1],
3914                         eth_dest[2], eth_dest[3], eth_dest[4], eth_dest[5]);
3915                 }
3916
3917                 #endif
3918
3919                 memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
3920
3921                 link_hw_laddr_valid[dest_if] = 1;
3922                 memcpy(&link_hw_laddr[dest_if], &hw_addr,
3923                                 sizeof(struct ether_addr));
3924
3925                 #ifdef CGNAPT_DBG_PRNT
3926                 if (CGNAPT_DEBUG > 2) {
3927                         printf("Dest MAC after - %02x:%02x:%02x:%02x:%02x"
3928                         ":%02x\n", eth_dest[0], eth_dest[1], eth_dest[2],
3929                         eth_dest[3], eth_dest[4], eth_dest[5]);
3930                 }
3931                 #endif
3932
3933                 memcpy(eth_src, get_link_hw_addr(dest_if),
3934                                 sizeof(struct ether_addr));
3935         }
3936
3937         {
3938                 /* Egress */
3939                 *src_addr = rte_bswap32(entry->data.pub_ip);
3940
3941
3942                 #ifdef NAT_ONLY_CONFIG_REQ
3943                 if (!nat_only_config_flag) {
3944                 #endif
3945                         *src_port = rte_bswap16(entry->data.pub_port);
3946                 #ifdef NAT_ONLY_CONFIG_REQ
3947                 }
3948                 #endif
3949
3950                 #ifdef SIP_ALG
3951                 uint16_t rtp_port = 0, rtcp_port = 0;
3952                 struct cgnapt_table_entry *entry_ptr1 = NULL,
3953                 *entry_ptr2 = NULL, *entry_ptr3 = NULL,
3954                 *entry_ptr4 = NULL;
3955
3956                 if (unlikely(protocol == IP_PROTOCOL_UDP
3957                                 && (rte_be_to_cpu_16(*dst_port) == 5060
3958                                 || rte_be_to_cpu_16(*src_port) == 5060))) {
3959
3960                         int ret = natSipAlgGetAudioPorts(pkt, &rtp_port,
3961                                         &rtcp_port);
3962                         /* Commented code may be required for debug
3963                         * and future use, Please keep it*/
3964                         #if 0
3965                         if (ret < 0) {
3966                                 printf("%s: Wrong SIP ALG packet1\n",
3967                                         __func__);
3968                                 p_nat->invalid_packets |= pkt_mask;
3969
3970                                 p_nat->naptDroppedPktCount++;
3971
3972                                 #ifdef CGNAPT_DEBUGGING
3973                                 p_nat->naptDroppedPktCount4++;
3974                                 #endif
3975                                 return;
3976                         }
3977                         #endif
3978
3979                         if (ret >= 0 && rtp_port != 0) {
3980                                 struct pipeline_cgnapt_entry_key rtp_key;
3981                                 rtp_key.ip = entry->data.u.prv_ip;
3982                                 rtp_key.port = rtp_port;
3983                                 rtp_key.pid = entry->data.prv_phy_port;
3984
3985                                 if (add_dynamic_cgnapt_entry_alg(
3986                                 (struct pipeline *)p_nat, &rtp_key,
3987                                 &entry_ptr1, &entry_ptr2) == 0) {
3988                                         printf("%s: Wrong SIP ALG packet2\n",
3989                                                 __func__);
3990                                         p_nat->invalid_packets |= pkt_mask;
3991
3992                                         p_nat->naptDroppedPktCount++;
3993
3994                                         #ifdef CGNAPT_DEBUGGING
3995                                         p_nat->naptDroppedPktCount4++;
3996                                         #endif
3997                                         return;
3998                                 }
3999                         }
4000
4001                         if (ret >= 0 && rtcp_port != 0) {
4002                                 struct pipeline_cgnapt_entry_key rtcp_key;
4003                                 rtcp_key.ip = entry->data.u.prv_ip;
4004                                 rtcp_key.port = rtcp_port;
4005                                 rtcp_key.pid = entry->data.prv_phy_port;
4006
4007                                 if (add_dynamic_cgnapt_entry_alg(
4008                                 (struct pipeline *)p_nat, &rtcp_key,
4009                                 &entry_ptr3, &entry_ptr4) == 0) {
4010                                         printf("%s: Wrong SIP ALG packet3\n",
4011                                                 __func__);
4012                                         p_nat->invalid_packets |= pkt_mask;
4013
4014                                         p_nat->naptDroppedPktCount++;
4015
4016                                         #ifdef CGNAPT_DEBUGGING
4017                                         p_nat->naptDroppedPktCount4++;
4018                                         #endif
4019                                         return;
4020                                 }
4021
4022                         }
4023                         //if(entry_ptr1 != NULL  && entry_ptr3 != NULL)
4024                         if (sip_alg_dpi(pkt, PRIVATE, entry->data.pub_ip,
4025                                 entry->data.pub_port, entry->data.u.prv_ip,
4026                                 entry->data.prv_port, (rtp_port == 0) ? 0 :
4027                                 entry_ptr1->data.pub_port,
4028                                 (rtcp_port == 0) ? 0 :
4029                                 entry_ptr3->data.pub_port) == 0) {
4030
4031                                 printf("%s: Wrong SIP ALG packet4\n",
4032                                                 __func__);
4033                                 p_nat->invalid_packets |= pkt_mask;
4034
4035                                 p_nat->naptDroppedPktCount++;
4036
4037                                 #ifdef CGNAPT_DEBUGGING
4038                                 p_nat->naptDroppedPktCount4++;
4039                                 #endif
4040                                 return;
4041                         }
4042                 }
4043                 #endif /* SIP_ALG */
4044
4045                 #ifdef FTP_ALG
4046
4047                 #ifdef ALGDBG
4048                 printf("@CGNAT-pktwork ct_position :%d, pkt_num %d pkt_mask= "
4049                         "%" PRIu64 "\n", ct_position, pkt_num, pkt_mask);
4050                 #endif
4051
4052                 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4053                         rte_be_to_cpu_16(*dst_port) == 21) {
4054
4055                 int32_t ct_position = cgnat_cnxn_tracker->positions[pkt_num];
4056                 if (ct_position < 0){
4057                         p_nat->invalid_packets |= pkt_mask;
4058                         p_nat->naptDroppedPktCount++;
4059                         return;
4060                 }
4061                         /* Commented code may be required for future usage,
4062                          * Please keep it
4063                          */
4064                         //if (cgnat_cnxn_tracker->hash_table_entries
4065                         //      [ct_position].alg_bypass_flag != BYPASS)
4066                         {
4067                         struct pipeline_cgnapt_entry_key data_channel_entry_key;
4068
4069                         data_channel_entry_key.ip = entry->data.pub_ip;
4070                         data_channel_entry_key.port = entry->data.pub_port;
4071                         data_channel_entry_key.pid = pkt->port;
4072                         ftp_alg_dpi(p_nat, &data_channel_entry_key, pkt,
4073                         cgnat_cnxn_tracker, ct_position, PRIVATE);
4074                         }
4075                 }
4076                 #endif /* FTP_ALG */
4077
4078                 p_nat->enaptedPktCount++;
4079         }
4080
4081         p_nat->naptedPktCount++;
4082
4083         #ifdef HW_CHECKSUM_REQ
4084                 if (p_nat->hw_checksum_reqd)
4085                         hw_checksum(pkt, pkt_type);
4086                 else
4087         #endif
4088                         sw_checksum(pkt, pkt_type);
4089
4090 }
4091
4092
4093 /**
4094  * NAPT function for IPv4 public traffic which handles 1 pkt
4095  *
4096  * @param pkts
4097  *  A pointer to array of packet mbuf
4098  * @param in_pkt_num
4099  *  Pkt number of pkt
4100  * @param arg
4101  *  Void pointer
4102  * @param p_nat
4103  *  A pointer to main CGNAPT structure
4104  *
4105  */
4106 void
4107 pkt_work_cgnapt_ipv4_pub(
4108         struct rte_mbuf **pkts,
4109         uint32_t pkt_num,
4110         __rte_unused void *arg,
4111         struct pipeline_cgnapt *p_nat)
4112 {
4113
4114         #ifdef CT_CGNAT
4115         struct rte_CT_helper ct_helper;
4116         memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4117         #endif
4118
4119         /* index into hash table entries */
4120         int hash_table_entry = p_nat->lkup_indx[pkt_num];
4121         /*bitmask representing only this packet */
4122         uint64_t pkt_mask = 1LLU << pkt_num;
4123         struct rte_mbuf *pkt = pkts[pkt_num];
4124
4125         uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
4126
4127         uint32_t dest_if = 0xff;        /* Added for Multiport */
4128         uint16_t *outport_id =
4129                 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
4130
4131         struct cgnapt_table_entry *entry = NULL;
4132
4133         enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4134
4135         if (hash_table_entry < 0) {
4136
4137                 /* try to add new entry */
4138                 struct rte_pipeline_table_entry *table_entry = NULL;
4139
4140                 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
4141                                         pkt, &table_entry,
4142                                         &p_nat->valid_packets, pkt_num,
4143                                         (void *)p_nat);
4144
4145                 if (!table_entry) {
4146                         /* ICMP Error message generation for
4147                         * Destination Host unreachable
4148                         */
4149                         if (protocol == IP_PROTOCOL_ICMP) {
4150                                 cgnapt_icmp_pkt = pkt;
4151                                 send_icmp_dest_unreachable_msg();
4152                         }
4153
4154                         /* Drop packet by adding to invalid pkt mask */
4155
4156                         p_nat->invalid_packets |= dropmask;
4157                         #ifdef CGNAPT_DEBUGGING
4158                         if (p_nat->kpc2++ < 5) {
4159                                 printf("in_ah Th: %d", p_nat->pipeline_num);
4160                                 print_key(p_nat->key_ptrs[pkt_num]);
4161                         }
4162                         #endif
4163
4164                         p_nat->naptDroppedPktCount++;
4165
4166                         #ifdef CGNAPT_DEBUGGING
4167                         p_nat->naptDroppedPktCount3++;
4168                         #endif
4169                         return;
4170                 }
4171
4172                 entry = (struct cgnapt_table_entry *)table_entry;
4173         } else {
4174                 /* entry found for this packet */
4175                 entry = &napt_hash_tbl_entries[hash_table_entry];
4176         }
4177
4178         /*  apply napt and mac changes */
4179
4180         p_nat->entries[pkt_num] = &(entry->head);
4181
4182         uint32_t *dst_addr =
4183                 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4184         uint16_t src_port_offset = 0;
4185         uint16_t dst_port_offset = 0;
4186
4187         if ((protocol == IP_PROTOCOL_TCP) || (protocol == IP_PROTOCOL_UDP)) {
4188                 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4189                 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4190         } else if (protocol == IP_PROTOCOL_ICMP) {
4191                 /* Identifier */
4192                 src_port_offset = MBUF_HDR_ROOM +
4193                                         ETH_HDR_SIZE +
4194                                         IP_HDR_SIZE + 4;
4195                 /*Sequence number */
4196                 dst_port_offset = MBUF_HDR_ROOM +
4197                                         ETH_HDR_SIZE +
4198                                         IP_HDR_SIZE + 6;
4199         }
4200
4201         uint16_t *src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
4202         uint16_t *dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
4203
4204         uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4205         uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4206
4207         if (entry->data.ttl == NAPT_ENTRY_STALE)
4208                 entry->data.ttl = NAPT_ENTRY_VALID;
4209
4210         struct ether_addr hw_addr;
4211         uint32_t dest_address = 0;
4212
4213         /* Multiport Changes */
4214         uint32_t nhip = 0;
4215         uint32_t ret;
4216
4217         {
4218                 /* Ingress */
4219                 if (unlikely(protocol == IP_PROTOCOL_UDP
4220                                  && rte_be_to_cpu_16(*src_port) == 53)) {
4221                         p_nat->invalid_packets |= pkt_mask;
4222                         p_nat->naptDroppedPktCount++;
4223                         #ifdef CGNAPT_DEBUGGING
4224                         p_nat->naptDroppedPktCount6++;
4225                         #endif
4226                         return;
4227                 }
4228
4229         dest_address = entry->data.u.prv_ip;
4230
4231         ret = local_get_nh_ipv4(dest_address, &dest_if, &nhip, p_nat);
4232         if (!ret) {
4233                 dest_if = get_prv_to_pub_port(&dest_address, IP_VERSION_4);
4234
4235                 if (dest_if == INVALID_DESTIF) {
4236                         p_nat->invalid_packets |= pkt_mask;
4237                         p_nat->naptDroppedPktCount++;
4238                         #ifdef CGNAPT_DEBUGGING
4239                         p_nat->naptDroppedPktCount6++;
4240                         #endif
4241                         return;
4242                 }
4243
4244                 do_local_nh_ipv4_cache(dest_if, p_nat);
4245         }
4246
4247                 *outport_id = p_nat->outport_id[dest_if];
4248
4249                 #ifdef CGNAPT_DBG_PRNT
4250                 if (CGNAPT_DEBUG > 2)
4251                         printf("Ingress: \tphy_port:%d\t get_pub_to_prv():%d "
4252                         "\tout_port%d\n", pkt->port, dest_if, *outport_id);
4253                 #endif
4254         }
4255
4256         if (local_dest_mac_present(dest_if)) {
4257                 memcpy(eth_dest,
4258                                  get_local_link_hw_addr(dest_if),
4259                                  sizeof(struct ether_addr));
4260                 memcpy(eth_src, get_link_hw_addr(dest_if),
4261                                  sizeof(struct ether_addr));
4262         } else {
4263                 int ret;
4264                 ret = get_dest_mac_addr_port(dest_address, &dest_if, &hw_addr);
4265
4266                 if (unlikely(ret != ARP_FOUND)) {
4267
4268                         if (unlikely(ret == ARP_NOT_FOUND)) {
4269                                 /* Commented code may be required for debug
4270                                  * and future use, Please keep it */
4271                                 //request_arp(*outport_id, nhip, p_nat->p.p);
4272                                 printf("%s: ARP Not Found, nhip: %x, "
4273                                 "outport_id: %d\n", __func__, nhip,
4274                                 *outport_id);
4275
4276                         }
4277
4278                         /* Drop the pkt */
4279                         p_nat->invalid_packets |= pkt_mask;
4280                         p_nat->naptDroppedPktCount++;
4281
4282                         #ifdef CGNAPT_DEBUGGING
4283                         p_nat->naptDroppedPktCount4++;
4284                         #endif
4285                         return;
4286
4287                 }
4288                 #ifdef CGNAPT_DBG_PRNT
4289                 if (CGNAPT_DEBUG > 2) {
4290                         printf
4291                                 ("MAC found for ip 0x%x, port %d - %02x:%02x: "
4292                                 "%02x:%02x:%02x:%02x\n", dest_address,
4293                                 *outport_id,
4294                                 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
4295                                 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
4296                                 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]
4297                                 );
4298
4299                         printf
4300                                 ("Dest MAC before - %02x:%02x:%02x:%02x "
4301                                 ":%02x:%02x\n", eth_dest[0], eth_dest[1],
4302                                 eth_dest[2], eth_dest[3], eth_dest[4],
4303                                 eth_dest[5]);
4304                 }
4305                 #endif
4306
4307                 memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
4308
4309                 link_hw_laddr_valid[dest_if] = 1;
4310                 memcpy(&link_hw_laddr[dest_if], &hw_addr,
4311                                  sizeof(struct ether_addr));
4312
4313                 #ifdef CGNAPT_DBG_PRNT
4314                 if (CGNAPT_DEBUG > 2) {
4315                         printf("Dest MAC after - "
4316                         "%02x:%02x:%02x:%02x:%02x:%02x\n",
4317                         eth_dest[0], eth_dest[1], eth_dest[2], eth_dest[3],
4318                         eth_dest[4], eth_dest[5]);
4319                 }
4320                 #endif
4321
4322                 memcpy(eth_src, get_link_hw_addr(dest_if),
4323                                  sizeof(struct ether_addr));
4324         }
4325
4326         {
4327                 /* Ingress */
4328
4329                 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
4330                 if (protocol == IP_PROTOCOL_ICMP) {
4331                         /* Query ID reverse translation done here */
4332                         /* dont care sequence num */
4333                         *src_port = rte_bswap16(entry->data.prv_port);
4334                 } else {
4335
4336                 #ifdef NAT_ONLY_CONFIG_REQ
4337                         if (!nat_only_config_flag) {
4338                 #endif
4339                                 *dst_port = rte_bswap16(entry->data.prv_port);
4340
4341                 #ifdef NAT_ONLY_CONFIG_REQ
4342                         }
4343                 #endif
4344                 #ifdef CT_CGNAT
4345                 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4346                         rte_be_to_cpu_16(*dst_port) == 21) {
4347                         pkt_mask = cgnapt_ct_process(cgnat_cnxn_tracker, pkts,
4348                                 pkt_mask, &ct_helper);
4349                 }
4350                 #endif
4351                 }
4352
4353                 #ifdef SIP_ALG
4354                 uint16_t rtp_port = 0, rtcp_port = 0;
4355                 struct cgnapt_table_entry *entry_ptr1 = NULL,
4356                         *entry_ptr3 = NULL;
4357
4358                 /* Commented code may be required for debug
4359                  * and future use, Please keep it */
4360                 #if 0
4361                 struct cgnapt_table_entry *entry_ptr2 = NULL,
4362                                 *entry_ptr4 = NULL;
4363                 #endif
4364
4365                 if (unlikely(protocol == IP_PROTOCOL_UDP
4366                                 && (rte_be_to_cpu_16(*dst_port) == 5060
4367                                 || rte_be_to_cpu_16(*src_port) == 5060))) {
4368                         /* Commented code may be required for future usage,
4369                          * Please keep it
4370                          */
4371                         #if 0
4372                         int ret = natSipAlgGetAudioPorts(pkt, &rtp_port,
4373                                         &rtcp_port);
4374                         if (ret < 0) {
4375                                 printf("%s: Wrong SIP ALG packet1\n",
4376                                         __func__);
4377                                 p_nat->invalid_packets |= pkt_mask;
4378
4379                                 p_nat->naptDroppedPktCount++;
4380
4381                                 #ifdef CGNAPT_DEBUGGING
4382                                 p_nat->naptDroppedPktCount4++;
4383                                 #endif
4384                                 return;
4385                         }
4386                         if (rtp_port != 0) {
4387                                 struct pipeline_cgnapt_entry_key rtp_key;
4388                                 rtp_key.ip = entry->data.pub_ip;
4389                                 rtp_key.port = rtp_port;
4390                                 rtp_key.pid = 0xffff;
4391
4392                                 if (retrieve_cgnapt_entry_alg(&rtp_key,
4393                                         &entry_ptr1, &entry_ptr2) == 0) {
4394                                         printf("%s: Wrong SIP ALG packet2\n",
4395                                                 __func__);
4396                                         p_nat->invalid_packets |= pkt_mask;
4397
4398                                         p_nat->naptDroppedPktCount++;
4399
4400                                         #ifdef CGNAPT_DEBUGGING
4401                                         p_nat->naptDroppedPktCount4++;
4402                                         #endif
4403                                         return;
4404                                 }
4405                         }
4406
4407                         if (rtcp_port != 0) {
4408                                 struct pipeline_cgnapt_entry_key rtcp_key;
4409                                 rtcp_key.ip = entry->data.pub_ip;
4410                                 rtcp_key.port = rtcp_port;
4411                                 rtcp_key.pid = 0xffff;
4412
4413                                 if (retrieve_cgnapt_entry_alg(&rtcp_key,
4414                                         &entry_ptr3, &entry_ptr4) == 0) {
4415                                         printf("%s: Wrong SIP ALG packet3\n",
4416                                                 __func__);
4417                                         p_nat->invalid_packets |= pkt_mask;
4418
4419                                         p_nat->naptDroppedPktCount++;
4420
4421                                         #ifdef CGNAPT_DEBUGGING
4422                                         p_nat->naptDroppedPktCount4++;
4423                                         #endif
4424                                         return;
4425                                 }
4426
4427                         }
4428                         #endif
4429
4430                         if (sip_alg_dpi(pkt, PUBLIC, entry->data.u.prv_ip,
4431                                 entry->data.prv_port, entry->data.pub_ip,
4432                                 entry->data.pub_port, (rtp_port == 0) ? 0 :
4433                                 entry_ptr1->data.prv_port,
4434                                 (rtcp_port == 0) ? 0 :
4435                                 entry_ptr3->data.prv_port) == 0) {
4436
4437                                 printf("%s: Wrong SIP ALG packet4\n",
4438                                                 __func__);
4439                                 p_nat->invalid_packets |= pkt_mask;
4440
4441                                 p_nat->naptDroppedPktCount++;
4442
4443                                 #ifdef CGNAPT_DEBUGGING
4444                                 p_nat->naptDroppedPktCount4++;
4445                                 #endif
4446                                 return;
4447
4448                         }
4449                 }
4450                 #endif /* SIP_ALG */
4451
4452                 #ifdef FTP_ALG
4453                 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4454                         rte_be_to_cpu_16(*dst_port) == 21) {
4455                         int32_t ct_position = cgnat_cnxn_tracker->
4456                                                 positions[pkt_num];
4457                 if (ct_position < 0){
4458                         p_nat->invalid_packets |= pkt_mask;
4459
4460                         p_nat->naptDroppedPktCount++;
4461                         return;
4462                 }
4463                         #ifdef ALGDBG
4464                         rte_hexdump(stdout, "CT Entry", &cgnat_cnxn_tracker->
4465                         hash_table_entries[ct_position].key, 40);
4466                         #endif
4467
4468                         /* Commented code may be required for debug
4469                         * and future use, Please keep it*/
4470                         //if (cgnat_cnxn_tracker->hash_table_entries
4471                         //      [ct_position].alg_bypass_flag != BYPASS)
4472                         {
4473                         /*enable ALG DPI */
4474                         struct pipeline_cgnapt_entry_key
4475                                 data_channel_entry_key;
4476
4477                         data_channel_entry_key.ip = entry->data.pub_ip;
4478                         data_channel_entry_key.port = entry->data.pub_port;
4479                         data_channel_entry_key.pid = 0xffff;
4480                         //printf("pkt_work_pub ftp_alg_dpi\n");
4481                         ftp_alg_dpi(p_nat, &data_channel_entry_key,  pkt,
4482                                 cgnat_cnxn_tracker, ct_position, PUBLIC);
4483
4484                         }
4485                 }
4486                 #endif
4487
4488                 p_nat->inaptedPktCount++;
4489         }
4490
4491         p_nat->naptedPktCount++;
4492
4493         #ifdef HW_CHECKSUM_REQ
4494                 if (p_nat->hw_checksum_reqd)
4495                         hw_checksum(pkt, pkt_type);
4496                 else
4497         #endif
4498                         sw_checksum(pkt, pkt_type);
4499 }
4500
4501
4502 /**
4503  * NAPT function for IPv4 private traffic which handles 4 pkts
4504  *
4505  * @param pkts
4506  *  A pointer to array of packets mbuf
4507  * @param in_pkt_num
4508  *  Starting pkt number of pkts
4509  * @param arg
4510  *  Void pointer
4511  * @param p_nat
4512  *  A pointer to main CGNAPT structure
4513  *
4514  */
4515 void
4516 pkt4_work_cgnapt_ipv4_prv(
4517         struct rte_mbuf **pkts,
4518         uint32_t in_pkt_num,
4519         __rte_unused void *arg,
4520         struct pipeline_cgnapt *p_nat)
4521 {
4522         uint32_t dest_if = 0xff;        /* Added for Multiport */
4523         struct rte_mbuf *pkt;
4524         uint8_t i;
4525         uint8_t pkt_num;
4526         enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4527
4528         #ifdef CT_CGNAT
4529         struct rte_CT_helper ct_helper;
4530         memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4531         #endif
4532
4533         for (i = 0; i < 4; i++) {
4534                 pkt_num = in_pkt_num + i;
4535                 pkt = pkts[pkt_num];
4536
4537                 /* index into hash table entries */
4538                 int hash_table_entry = p_nat->lkup_indx[pkt_num];
4539                 /*bitmask representing only this packet */
4540                 uint64_t pkt_mask = 1LLU << pkt_num;
4541
4542                 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
4543
4544                 uint16_t *outport_id =
4545                         RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
4546
4547                 struct cgnapt_table_entry *entry = NULL;
4548
4549                 if (hash_table_entry < 0) {
4550
4551                         /* try to add new entry */
4552                         struct rte_pipeline_table_entry *table_entry = NULL;
4553
4554                         uint64_t dropmask =
4555                                 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
4556                                                 &table_entry,
4557                                                 &p_nat->valid_packets, pkt_num,
4558                                                 (void *)p_nat);
4559
4560                         if (!table_entry) {
4561                                 /* ICMP Error message generation for
4562                                 * Destination Host unreachable
4563                                 */
4564                                 if (protocol == IP_PROTOCOL_ICMP) {
4565                                         cgnapt_icmp_pkt = pkt;
4566                                         send_icmp_dest_unreachable_msg();
4567                                 }
4568
4569                                 /* Drop packet by adding to invalid pkt mask */
4570
4571                                 p_nat->invalid_packets |= dropmask;
4572
4573                                 #ifdef CGNAPT_DEBUGGING
4574                                 if (p_nat->kpc2++ < 5) {
4575                                         printf("in_ah Th: %d",
4576                                                          p_nat->pipeline_num);
4577                                         print_key(p_nat->key_ptrs[pkt_num]);
4578                                 }
4579                                 #endif
4580
4581                                 p_nat->naptDroppedPktCount++;
4582
4583                                 #ifdef CGNAPT_DEBUGGING
4584                                 p_nat->naptDroppedPktCount3++;
4585                                 #endif
4586                                 continue;
4587                         }
4588
4589                         entry = (struct cgnapt_table_entry *)table_entry;
4590                 } else {
4591                         /* entry found for this packet */
4592                         entry = &napt_hash_tbl_entries[hash_table_entry];
4593                 }
4594
4595                 /*  apply napt and mac changes */
4596
4597                 p_nat->entries[pkt_num] = &(entry->head);
4598
4599                 uint32_t *src_addr =
4600                         RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP4);
4601                 uint32_t *dst_addr =
4602                         RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4603                 uint16_t src_port_offset = 0;
4604                 uint16_t dst_port_offset = 0;
4605                 uint16_t *src_port;
4606                 uint16_t *dst_port;
4607
4608                 #if 0
4609                 if ((protocol == IP_PROTOCOL_TCP)
4610                         || (protocol == IP_PROTOCOL_UDP)) {
4611                         src_port_offset = SRC_PRT_OFST_IP4_TCP;
4612                         dst_port_offset = DST_PRT_OFST_IP4_TCP;
4613                 } else if (protocol == IP_PROTOCOL_ICMP) {
4614                         /* Identifier */
4615                         src_port_offset = MBUF_HDR_ROOM +
4616                                                 ETH_HDR_SIZE +
4617                                                 IP_HDR_SIZE + 4;
4618                         /*Sequence number */
4619                         dst_port_offset = MBUF_HDR_ROOM +
4620                                                 ETH_HDR_SIZE +
4621                                                 IP_HDR_SIZE + 6;
4622                 }
4623                 #endif
4624
4625                 switch (protocol) {
4626                 case IP_PROTOCOL_TCP:
4627                         src_port_offset = SRC_PRT_OFST_IP4_TCP;
4628                         dst_port_offset = DST_PRT_OFST_IP4_TCP;
4629                         src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4630                                                 src_port_offset);
4631                         dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4632                                                 dst_port_offset);
4633
4634                         #ifdef CT_CGNAT
4635                         if ((rte_be_to_cpu_16(*src_port) == 21) ||
4636                                 rte_be_to_cpu_16(*dst_port) == 21) {
4637
4638                                 //To process CT , pkt_mask does it need
4639                                 //to be complemented ??
4640                                 #ifdef ALGDBG
4641                                 printf("cgnapt_ct_process: pkt_mask: "
4642                                         "% "PRIu64", pkt_num: %d\n",
4643                                         pkt_mask, pkt_num);
4644                                 #endif
4645
4646                                 pkt_mask =  cgnapt_ct_process(
4647                                                 cgnat_cnxn_tracker, pkts,
4648                                                 pkt_mask, &ct_helper);
4649                         }
4650                         #endif
4651                 break;
4652                 case IP_PROTOCOL_UDP:
4653                         src_port_offset = SRC_PRT_OFST_IP4_TCP;
4654                         dst_port_offset = DST_PRT_OFST_IP4_TCP;
4655                         src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4656                                         src_port_offset);
4657                         dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4658                                         dst_port_offset);
4659                 break;
4660                 case IP_PROTOCOL_ICMP:
4661                         /* Identifier */
4662                         src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
4663                                                 IP_HDR_SIZE + 4;
4664                         /*Sequence number */
4665                         dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
4666                                                 IP_HDR_SIZE + 6;
4667                         src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4668                                         src_port_offset);
4669                         dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4670                                         dst_port_offset);
4671                 break;
4672                 }
4673
4674
4675                 uint8_t *eth_dest =
4676                         RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4677                 uint8_t *eth_src =
4678                         RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4679
4680                 if (entry->data.ttl == NAPT_ENTRY_STALE)
4681                         entry->data.ttl = NAPT_ENTRY_VALID;
4682
4683                 struct ether_addr hw_addr;
4684                 uint32_t dest_address = 0;
4685                 /*Multiport Changes */
4686                 uint32_t nhip = 0;
4687                 uint32_t ret;
4688
4689                 {
4690
4691                         /* Egress */
4692                         if (unlikely(protocol == IP_PROTOCOL_UDP
4693                                 && rte_be_to_cpu_16(*dst_port) == 53)) {
4694                                 p_nat->invalid_packets |= pkt_mask;
4695                                 p_nat->naptDroppedPktCount++;
4696
4697                                 #ifdef CGNAPT_DEBUGGING
4698                                 p_nat->naptDroppedPktCount6++;
4699                                 #endif
4700                                 continue;
4701                         }
4702
4703                         dest_address = rte_bswap32(*dst_addr);
4704                 ret = local_get_nh_ipv4(dest_address, &dest_if, &nhip, p_nat);
4705                 if (!ret) {
4706                         dest_if = get_prv_to_pub_port(&dest_address,
4707                                         IP_VERSION_4);
4708                 if (dest_if == INVALID_DESTIF) {
4709                         p_nat->invalid_packets |= pkt_mask;
4710                         p_nat->naptDroppedPktCount++;
4711                         #ifdef CGNAPT_DEBUGGING
4712                         p_nat->naptDroppedPktCount6++;
4713                         #endif
4714                         continue;
4715                 }
4716                         do_local_nh_ipv4_cache(dest_if, p_nat);
4717                 }
4718                         *outport_id = p_nat->outport_id[dest_if];
4719
4720                 #ifdef CGNAPT_DBG_PRNT
4721                 if (CGNAPT_DEBUG > 2)
4722                         printf("Egress: \tphy_port:%d\t "
4723                         "get_prv_to_pub():%d \tout_port:%d\n",
4724                                  pkt->port, dest_if, *outport_id);
4725                 #endif
4726                 }
4727
4728                 if (local_dest_mac_present(dest_if)) {
4729                         memcpy(eth_dest,
4730                                          get_local_link_hw_addr(dest_if),
4731                                          sizeof(struct ether_addr));
4732                         memcpy(eth_src,
4733                                          get_link_hw_addr(dest_if),
4734                                          sizeof(struct ether_addr));
4735                 } else {
4736                 int ret;
4737                 ret = get_dest_mac_addr_port(dest_address, &dest_if, &hw_addr);
4738
4739                 if (unlikely(ret != ARP_FOUND)) {
4740
4741                         if (unlikely(ret == ARP_NOT_FOUND)) {
4742                                 printf("%s: ARP Not Found, nhip: %x, "
4743                                 "outport_id: %d\n", __func__, nhip,
4744                                 *outport_id);
4745                                 //request_arp(*outport_id, nhip, p_nat->p.p);
4746                         }
4747
4748                         /* Drop the pkt */
4749                         p_nat->invalid_packets |= pkt_mask;
4750                         p_nat->naptDroppedPktCount++;
4751
4752                         #ifdef CGNAPT_DEBUGGING
4753                         p_nat->naptDroppedPktCount4++;
4754                         #endif
4755                         continue;
4756
4757                 }
4758                         #ifdef CGNAPT_DBG_PRNT
4759                         if (CGNAPT_DEBUG > 2) {
4760                                 printf("MAC found for ip 0x%x, port %d - "
4761                                 "%02x:%02x:%02x:%02x:%02x:%02x\n",
4762                                         dest_address,
4763                                         *outport_id,
4764                                         hw_addr.addr_bytes[0],
4765                                         hw_addr.addr_bytes[1],
4766                                         hw_addr.addr_bytes[2],
4767                                         hw_addr.addr_bytes[3],
4768                                         hw_addr.addr_bytes[4],
4769                                         hw_addr.addr_bytes[5]
4770                                         );
4771
4772                                 printf("Dest MAC before - "
4773                                 "%02x:%02x:%02x:%02x:%02x:%02x\n",
4774                                 eth_dest[0], eth_dest[1], eth_dest[2],
4775                                 eth_dest[3], eth_dest[4], eth_dest[5]);
4776                         }
4777                         #endif
4778
4779                         memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
4780
4781                         link_hw_laddr_valid[dest_if] = 1;
4782                         memcpy(&link_hw_laddr[dest_if], &hw_addr,
4783                                          sizeof(struct ether_addr));
4784
4785                         #ifdef CGNAPT_DBG_PRNT
4786                         if (CGNAPT_DEBUG > 2) {
4787                                 printf("Dest MAC after - "
4788                                 "%02x:%02x:%02x:%02x:%02x:%02x\n",
4789                                 eth_dest[0], eth_dest[1], eth_dest[2],
4790                                 eth_dest[3], eth_dest[4], eth_dest[5]);
4791                         }
4792                         #endif
4793
4794                         memcpy(eth_src,
4795                                          get_link_hw_addr(dest_if),
4796                                          sizeof(struct ether_addr));
4797                 }
4798
4799                 {
4800                         /* Egress */
4801                         *src_addr = rte_bswap32(entry->data.pub_ip);
4802
4803                         #ifdef NAT_ONLY_CONFIG_REQ
4804                         if (!nat_only_config_flag) {
4805                         #endif
4806                                 *src_port = rte_bswap16(entry->data.pub_port);
4807                         #ifdef NAT_ONLY_CONFIG_REQ
4808                         }
4809                         #endif
4810
4811                         #ifdef SIP_ALG
4812                         uint16_t rtp_port = 0, rtcp_port = 0;
4813                         struct cgnapt_table_entry *entry_ptr1 = NULL,
4814                                 *entry_ptr2 = NULL, *entry_ptr3 = NULL,
4815                                 *entry_ptr4 = NULL;
4816
4817                         if (unlikely(protocol == IP_PROTOCOL_UDP
4818                                 && (rte_be_to_cpu_16(*dst_port) == 5060
4819                                 || rte_be_to_cpu_16(*src_port) == 5060))) {
4820
4821                                 int ret = natSipAlgGetAudioPorts(pkt,
4822                                                 &rtp_port, &rtcp_port);
4823                         /* Commented code may be required for future usage,
4824                          * Please keep it
4825                          */
4826                                 #if 0
4827                                 if (ret < 0) {
4828                                         printf("%s: Wrong SIP ALG packet1\n",
4829                                                 __func__);
4830                                         p_nat->invalid_packets |= pkt_mask;
4831
4832                                         p_nat->naptDroppedPktCount++;
4833
4834                                         #ifdef CGNAPT_DEBUGGING
4835                                         p_nat->naptDroppedPktCount4++;
4836                                         #endif
4837                                         continue;
4838                                 }
4839                                 #endif
4840
4841                                 if (ret >= 0 && rtp_port != 0) {
4842                                 struct pipeline_cgnapt_entry_key rtp_key;
4843                                 rtp_key.ip = entry->data.u.prv_ip;
4844                                 rtp_key.port = rtp_port;
4845                                 rtp_key.pid = entry->data.prv_phy_port;
4846
4847                                 if (add_dynamic_cgnapt_entry_alg(
4848                                 (struct pipeline *)p_nat, &rtp_key,
4849                                 &entry_ptr1, &entry_ptr2) == 0) {
4850                                         printf("%s: Wrong SIP ALG packet2\n",
4851                                                 __func__);
4852                                         p_nat->invalid_packets |= pkt_mask;
4853
4854                                         p_nat->naptDroppedPktCount++;
4855
4856                                         #ifdef CGNAPT_DEBUGGING
4857                                         p_nat->naptDroppedPktCount4++;
4858                                         #endif
4859                                         continue;
4860                                         }
4861                                 }
4862
4863                                 if (ret >= 0 && rtcp_port != 0) {
4864                                 struct pipeline_cgnapt_entry_key rtcp_key;
4865                                 rtcp_key.ip = entry->data.u.prv_ip;
4866                                 rtcp_key.port = rtcp_port;
4867                                 rtcp_key.pid = entry->data.prv_phy_port;
4868
4869                                 if (add_dynamic_cgnapt_entry_alg(
4870                                 (struct pipeline *)p_nat, &rtcp_key,
4871                                 &entry_ptr3, &entry_ptr4) == 0) {
4872
4873                                         printf("%s: Wrong SIP ALG packet3\n",
4874                                                 __func__);
4875                                         p_nat->invalid_packets |= pkt_mask;
4876
4877                                         p_nat->naptDroppedPktCount++;
4878
4879                                         #ifdef CGNAPT_DEBUGGING
4880                                         p_nat->naptDroppedPktCount4++;
4881                                         #endif
4882                                         continue;
4883                                 }
4884
4885                                 }
4886                                 //if(entry_ptr1 != NULL && entry_ptr3 != NULL)
4887                                 if (sip_alg_dpi(pkt, PRIVATE,
4888                                         entry->data.pub_ip,
4889                                         entry->data.pub_port,
4890                                         entry->data.u.prv_ip,
4891                                         entry->data.prv_port,
4892                                         (rtp_port == 0) ? 0 :
4893                                         entry_ptr1->data.pub_port,
4894                                         (rtcp_port == 0) ? 0 :
4895                                         entry_ptr3->data.pub_port) == 0) {
4896
4897                                         printf("%s: Wrong SIP ALG packet4\n",
4898                                                 __func__);
4899                                         p_nat->invalid_packets |= pkt_mask;
4900
4901                                         p_nat->naptDroppedPktCount++;
4902
4903                                         #ifdef CGNAPT_DEBUGGING
4904                                         p_nat->naptDroppedPktCount4++;
4905                                         #endif
4906                                         continue;
4907                                 }
4908                         }
4909                         #endif /* SIP_ALG */
4910
4911                 #ifdef FTP_ALG
4912                 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4913                         rte_be_to_cpu_16(*dst_port) == 21) {
4914
4915                         int32_t ct_position =
4916                                 cgnat_cnxn_tracker->positions[pkt_num];
4917                         #ifdef ALGDBG
4918                         printf("@CGNAT-pkt4work ct_position :%d, pkt_num %d "
4919                         "pkt_mask = %" PRIu64 "\n", ct_position,
4920                         pkt_num, pkt_mask);
4921                         #endif
4922
4923                 if (ct_position < 0){
4924                         p_nat->invalid_packets |= pkt_mask;
4925                         p_nat->naptDroppedPktCount++;
4926                         continue;
4927                 }
4928                         if (cgnat_cnxn_tracker->hash_table_entries[ct_position].
4929                                 alg_bypass_flag != BYPASS){
4930
4931                                 struct pipeline_cgnapt_entry_key
4932                                         data_channel_entry_key;
4933                                 /*enable ALG DPI */
4934                                 data_channel_entry_key.ip =
4935                                         entry->data.pub_ip;
4936                                 data_channel_entry_key.port =
4937                                         entry->data.pub_port;
4938                                 data_channel_entry_key.pid = 0xffff;
4939
4940                                 ftp_alg_dpi(p_nat, &data_channel_entry_key,
4941                                         pkt, cgnat_cnxn_tracker, ct_position,
4942                                         PRIVATE);
4943
4944                         }
4945                 }
4946                 #endif
4947                 p_nat->enaptedPktCount++;
4948                 }
4949
4950                 p_nat->naptedPktCount++;
4951
4952                 #ifdef HW_CHECKSUM_REQ
4953                         if (p_nat->hw_checksum_reqd)
4954                                 hw_checksum(pkt, pkt_type);
4955                         else
4956                 #endif
4957                                 sw_checksum(pkt, pkt_type);
4958         }
4959 }
4960
4961 /**
4962  * NAPT function for IPv4 public traffic which handles 4 pkts
4963  *
4964  * @param pkts
4965  *  A pointer to array of packets mbuf
4966  * @param in_pkt_num
4967  *  Starting pkt number of pkts
4968  * @param arg
4969  *  Void pointer
4970  * @param p_nat
4971  *  A pointer to main CGNAPT structure
4972  *
4973  */
4974 void
4975 pkt4_work_cgnapt_ipv4_pub(
4976         struct rte_mbuf **pkts,
4977         uint32_t in_pkt_num,
4978         __rte_unused void *arg,
4979         struct pipeline_cgnapt *p_nat)
4980 {
4981         #ifdef CT_CGNAT
4982         struct rte_CT_helper ct_helper;
4983         memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4984         #endif
4985         struct rte_mbuf *pkt;
4986         uint8_t i;
4987         uint8_t pkt_num;
4988         enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4989
4990         for (i = 0; i < 4; i++) {
4991                 pkt_num = in_pkt_num + i;
4992                 pkt = pkts[pkt_num];
4993
4994                 /* index into hash table entries */
4995                 int hash_table_entry = p_nat->lkup_indx[pkt_num];
4996                 /*bitmask representing only this packet */
4997                 uint64_t pkt_mask = 1LLU << pkt_num;
4998
4999                 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
5000
5001                 uint32_t dest_if = 0xff;        /* Added for Multiport */
5002                 uint16_t *outport_id =
5003                         RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
5004
5005                 struct cgnapt_table_entry *entry = NULL;
5006
5007                 if (hash_table_entry < 0) {
5008
5009                         /* try to add new entry */
5010                         struct rte_pipeline_table_entry *table_entry = NULL;
5011
5012                         uint64_t dropmask =
5013                                 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
5014                                                 &table_entry,
5015                                                 &p_nat->valid_packets, pkt_num,
5016                                                 (void *)p_nat);
5017
5018                         if (!table_entry) {
5019                                 /* ICMP Error message generation for
5020                                 * Destination Host unreachable
5021                                 */
5022                                 if (protocol == IP_PROTOCOL_ICMP) {
5023                                         cgnapt_icmp_pkt = pkt;
5024                                         send_icmp_dest_unreachable_msg();
5025                                 }
5026
5027                                 /* Drop packet by adding to invalid pkt mask */
5028
5029                                 p_nat->invalid_packets |= dropmask;
5030
5031                                 #ifdef CGNAPT_DEBUGGING
5032                                 if (p_nat->kpc2++ < 5) {
5033                                         printf("in_ah Th: %d",
5034                                                          p_nat->pipeline_num);
5035                                         print_key(p_nat->key_ptrs[pkt_num]);
5036                                 }
5037                                 #endif
5038
5039                                 p_nat->naptDroppedPktCount++;
5040
5041                                 #ifdef CGNAPT_DEBUGGING
5042                                 p_nat->naptDroppedPktCount3++;
5043                                 #endif
5044
5045                                 continue;
5046                         }
5047
5048                         entry = (struct cgnapt_table_entry *)table_entry;
5049                 } else {
5050                         /* entry found for this packet */
5051                         entry = &napt_hash_tbl_entries[hash_table_entry];
5052                 }
5053
5054                 /*  apply napt and mac changes */
5055
5056                 p_nat->entries[pkt_num] = &(entry->head);
5057
5058                 uint32_t *dst_addr =
5059                         RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
5060                 uint16_t src_port_offset = 0;
5061                 uint16_t dst_port_offset = 0;
5062
5063                 if ((protocol == IP_PROTOCOL_TCP)
5064                         || (protocol == IP_PROTOCOL_UDP)) {
5065                         src_port_offset = SRC_PRT_OFST_IP4_TCP;
5066                         dst_port_offset = DST_PRT_OFST_IP4_TCP;
5067                 } else if (protocol == IP_PROTOCOL_ICMP) {
5068                         /* Identifier */
5069                         src_port_offset = MBUF_HDR_ROOM +
5070                                                 ETH_HDR_SIZE +
5071                                                 IP_HDR_SIZE + 4;
5072                         /*Sequence number */
5073                         dst_port_offset = MBUF_HDR_ROOM +
5074                                                 ETH_HDR_SIZE +
5075                                                 IP_HDR_SIZE + 6;
5076                 }
5077
5078                 uint16_t *src_port =
5079                         RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
5080                 uint16_t *dst_port =
5081                         RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
5082
5083                 uint8_t *eth_dest =
5084                         RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
5085                 uint8_t *eth_src =
5086                         RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
5087
5088                 if (entry->data.ttl == NAPT_ENTRY_STALE)
5089                         entry->data.ttl = NAPT_ENTRY_VALID;
5090
5091                 struct ether_addr hw_addr;
5092                 uint32_t dest_address = 0;
5093                 /* Multiport Changes */
5094                 uint32_t nhip = 0;
5095                 uint32_t ret;
5096
5097                 /* Ingress */
5098                 {
5099                         if (unlikely(protocol == IP_PROTOCOL_UDP
5100                                 && rte_be_to_cpu_16(*src_port) == 53)) {
5101                                 p_nat->invalid_packets |= pkt_mask;
5102                                 p_nat->naptDroppedPktCount++;
5103                                 #ifdef CGNAPT_DEBUGGING
5104                                 p_nat->naptDroppedPktCount6++;
5105                                 #endif
5106                                 continue;
5107                         }
5108
5109                         dest_address = entry->data.u.prv_ip;
5110         ret = local_get_nh_ipv4(dest_address, &dest_if, &nhip, p_nat);
5111         if (!ret) {
5112                 dest_if = get_prv_to_pub_port(&dest_address, IP_VERSION_4);
5113
5114                 if (dest_if == INVALID_DESTIF) {
5115                         p_nat->invalid_packets |= pkt_mask;
5116                         p_nat->naptDroppedPktCount++;
5117                         #ifdef CGNAPT_DEBUGGING
5118                         p_nat->naptDroppedPktCount6++;
5119                         #endif
5120                         continue;
5121                 }
5122
5123                 do_local_nh_ipv4_cache(dest_if, p_nat);
5124         }
5125
5126                         *outport_id = p_nat->outport_id[dest_if];
5127
5128                         #ifdef CGNAPT_DBG_PRNT
5129                         if (CGNAPT_DEBUG > 2)
5130                                 printf("Ingress: \tphy_port:%d\t "
5131                                 "get_pub_to_prv():%d \tout_port%d\n",
5132                                          pkt->port, dest_if,
5133                                          *outport_id);
5134                         #endif
5135                 }
5136
5137                 if (local_dest_mac_present(dest_if)) {
5138                         memcpy(eth_dest,
5139                                          get_local_link_hw_addr(dest_if),
5140                                          sizeof(struct ether_addr));
5141                         memcpy(eth_src,
5142                                          get_link_hw_addr(dest_if),
5143                                          sizeof(struct ether_addr));
5144                 } else {
5145                 int ret;
5146                 ret = get_dest_mac_addr_port(dest_address, &dest_if, &hw_addr);
5147
5148                 if (unlikely(ret != ARP_FOUND)) {
5149
5150                         if (unlikely(ret == ARP_NOT_FOUND)) {
5151                                 printf("%s: ARP Not Found, nhip: %x, "
5152                                 "outport_id: %d\n", __func__, nhip,
5153                                 *outport_id);
5154                                 //request_arp(*outport_id, nhip, p_nat->p.p);
5155                         }
5156
5157                         /* Drop the pkt */
5158                         p_nat->invalid_packets |= pkt_mask;
5159                         p_nat->naptDroppedPktCount++;
5160
5161                         #ifdef CGNAPT_DEBUGGING
5162                         p_nat->naptDroppedPktCount4++;
5163                         #endif
5164                         continue;
5165
5166                 }
5167                         #ifdef CGNAPT_DBG_PRNT
5168                         if (CGNAPT_DEBUG > 2) {
5169                                 printf("MAC found for ip 0x%x, port %d - "
5170                                 "%02x:%02x:%02x:%02x:%02x:%02x\n",
5171                                 dest_address, *outport_id,
5172                                 hw_addr.addr_bytes[0],
5173                                 hw_addr.addr_bytes[1],
5174                                 hw_addr.addr_bytes[2],
5175                                 hw_addr.addr_bytes[3],
5176                                 hw_addr.addr_bytes[4],
5177                                 hw_addr.addr_bytes[5]
5178                                 );
5179
5180                                 printf("Dest MAC before - "
5181                                 "%02x:%02x:%02x:%02x:%02x:%02x\n",
5182                                 eth_dest[0], eth_dest[1], eth_dest[2],
5183                                 eth_dest[3], eth_dest[4], eth_dest[5]);
5184                         }
5185                         #endif
5186
5187                         memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
5188
5189                         link_hw_laddr_valid[dest_if] = 1;
5190                         memcpy(&link_hw_laddr[dest_if],
5191                                          &hw_addr, sizeof(struct ether_addr));
5192
5193                         #ifdef CGNAPT_DBG_PRNT
5194                         if (CGNAPT_DEBUG > 2) {
5195                                 printf("Dest MAC after - %02x:%02x:%02x: "
5196                                 "%02x:%02x:%02x\n",
5197                                 eth_dest[0], eth_dest[1], eth_dest[2],
5198                                 eth_dest[3], eth_dest[4], eth_dest[5]);
5199                         }
5200                         #endif
5201
5202                         memcpy(eth_src,
5203                                          get_link_hw_addr(dest_if),
5204                                          sizeof(struct ether_addr));
5205                 }
5206
5207                 {
5208                         /* Ingress */
5209
5210                         *dst_addr = rte_bswap32(entry->data.u.prv_ip);
5211                         if (protocol == IP_PROTOCOL_ICMP) {
5212                                 /* Query ID reverse translation done here */
5213                                 *src_port = rte_bswap16(entry->data.prv_port);
5214                                 /* dont care sequence num */
5215                         } else {
5216                         #ifdef NAT_ONLY_CONFIG_REQ
5217                                 if (!nat_only_config_flag) {
5218                         #endif
5219                                         *dst_port =
5220                                         rte_bswap16(entry->data.prv_port);
5221                         #ifdef NAT_ONLY_CONFIG_REQ
5222                                 }
5223                                 #endif
5224
5225                         #ifdef CT_CGNAT
5226                         if ((rte_be_to_cpu_16(*src_port) == 21) ||
5227                                 rte_be_to_cpu_16(*dst_port) == 21) {
5228                                 pkt_mask = cgnapt_ct_process(
5229                                         cgnat_cnxn_tracker, pkts,
5230                                 pkt_mask, &ct_helper);
5231                         }
5232                         #endif
5233                         }
5234
5235                         #ifdef SIP_ALG
5236                         uint16_t rtp_port = 0, rtcp_port = 0;
5237                         struct cgnapt_table_entry *entry_ptr1 = NULL,
5238                                 *entry_ptr3 = NULL;
5239                         /* Commented code may be required for future usage,
5240                          * Please keep it
5241                          */
5242                         #if 0
5243                         struct cgnapt_table_entry *entry_ptr2 = NULL,
5244                                         *entry_ptr4 = NULL;
5245                         #endif
5246
5247                         if (unlikely(protocol == IP_PROTOCOL_UDP
5248                                 && (rte_be_to_cpu_16(*dst_port) == 5060
5249                                 || rte_be_to_cpu_16(*src_port) == 5060))) {
5250                         /* Commented code may be required for future usage,
5251                          * Please keep it
5252                          */
5253                         #if 0
5254                                 int ret = natSipAlgGetAudioPorts(pkt,
5255                                         &rtp_port, &rtcp_port);
5256                                 if (ret < 0) {
5257                                         printf("%s: Wrong SIP ALG packet1\n",
5258                                                 __func__);
5259                                         p_nat->invalid_packets |= pkt_mask;
5260
5261                                         p_nat->naptDroppedPktCount++;
5262
5263                                         #ifdef CGNAPT_DEBUGGING
5264                                         p_nat->naptDroppedPktCount4++;
5265                                         #endif
5266                                         return;
5267                                 }
5268
5269                                 if (rtp_port != 0) {
5270                                 struct pipeline_cgnapt_entry_key rtp_key;
5271                                 rtp_key.ip = entry->data.pub_ip;
5272                                 rtp_key.port = rtp_port;
5273                                 rtp_key.pid = 0xffff;
5274
5275                                 if (retrieve_cgnapt_entry_alg(&rtp_key,
5276                                         &entry_ptr1, &entry_ptr2) == 0) {
5277                                         printf("%s: Wrong SIP ALG packet2\n",
5278                                         __func__);
5279                                         p_nat->invalid_packets |= pkt_mask;
5280
5281                                         p_nat->naptDroppedPktCount++;
5282
5283                                         #ifdef CGNAPT_DEBUGGING
5284                                         p_nat->naptDroppedPktCount4++;
5285                                         #endif
5286                                         return;
5287                                         }
5288                                 }
5289
5290                                 if (rtcp_port != 0) {
5291                                 struct pipeline_cgnapt_entry_key rtcp_key;
5292                                 rtcp_key.ip = entry->data.pub_ip;
5293                                 rtcp_key.port = rtcp_port;
5294                                 rtcp_key.pid = 0xffff;
5295
5296                                 if (retrieve_cgnapt_entry_alg(&rtcp_key,
5297                                         &entry_ptr3, &entry_ptr4) == 0) {
5298                                         printf("%s: Wrong SIP ALG packet3\n",
5299                                                 __func__);
5300                                         p_nat->invalid_packets |= pkt_mask;
5301                                         p_nat->naptDroppedPktCount++;
5302
5303                                         #ifdef CGNAPT_DEBUGGING
5304                                         p_nat->naptDroppedPktCount4++;
5305                                         #endif
5306                                         return;
5307                                 }
5308
5309                                 }
5310                         #endif
5311                                 if (sip_alg_dpi(pkt, PUBLIC,
5312                                         entry->data.u.prv_ip,
5313                                         entry->data.prv_port,
5314                                         entry->data.pub_ip,
5315                                         entry->data.pub_port,
5316                                         (rtp_port == 0) ? 0 :
5317                                         entry_ptr1->data.prv_port,
5318                                         (rtcp_port == 0) ? 0 :
5319                                         entry_ptr3->data.prv_port) == 0) {
5320
5321                                         printf("%s: Wrong SIP ALG packet4\n",
5322                                                 __func__);
5323                                         p_nat->invalid_packets |= pkt_mask;
5324
5325                                         p_nat->naptDroppedPktCount++;
5326
5327                                         #ifdef CGNAPT_DEBUGGING
5328                                         p_nat->naptDroppedPktCount4++;
5329                                         #endif
5330                                         continue;
5331                                 }
5332                         }
5333                         #endif /* SIP_ALG */
5334
5335                 #ifdef FTP_ALG
5336                 if ((rte_be_to_cpu_16(*src_port) == 21) ||
5337                         rte_be_to_cpu_16(*dst_port) == 21) {
5338
5339                         int32_t ct_position =
5340                                 cgnat_cnxn_tracker->positions[pkt_num];
5341                 if (ct_position < 0){
5342                         p_nat->invalid_packets |= pkt_mask;
5343
5344                         p_nat->naptDroppedPktCount++;
5345                         continue;
5346                 }
5347                         if (cgnat_cnxn_tracker->hash_table_entries
5348                                 [ct_position].alg_bypass_flag != BYPASS){
5349
5350                                 struct pipeline_cgnapt_entry_key
5351                                         data_channel_entry_key;
5352
5353                                 /*enable ALG DPI */
5354                                 data_channel_entry_key.ip =
5355                                         entry->data.pub_ip;
5356                                 data_channel_entry_key.port =
5357                                         entry->data.pub_port;
5358                                 data_channel_entry_key.pid = 0xffff;
5359
5360                                 ftp_alg_dpi(p_nat, &data_channel_entry_key,
5361                                                 pkt, cgnat_cnxn_tracker,
5362                                                 ct_position, PUBLIC);
5363
5364                         }
5365                 }
5366                 #endif
5367                         p_nat->inaptedPktCount++;
5368                 }
5369
5370                 p_nat->naptedPktCount++;
5371
5372                 #ifdef HW_CHECKSUM_REQ
5373                         if (p_nat->hw_checksum_reqd)
5374                                 hw_checksum(pkt, pkt_type);
5375                         else
5376                 #endif
5377                                 sw_checksum(pkt, pkt_type);
5378         }
5379 }
5380
5381 /**
5382  * NAPT key calculation function for IPv6 private traffic
5383  * which handles 1 pkt
5384  *
5385  * @param pkt
5386  *  A pointer to array of packets mbuf
5387  * @param in_pkt_num
5388  *  Pkt number of pkts
5389  * @param arg
5390  *  Void pointer
5391  * @param p_nat
5392  *  A pointer to main CGNAPT structure
5393  *
5394  */
5395 void
5396 pkt_work_cgnapt_key_ipv6_prv(
5397         struct rte_mbuf *pkt,
5398         uint32_t pkt_num,
5399         __rte_unused void *arg,
5400         struct pipeline_cgnapt *p_nat)
5401 {
5402         /* Egress */
5403         p_nat->receivedPktCount++;
5404
5405         /* bitmask representing only this packet */
5406         uint64_t pkt_mask = 1LLU << pkt_num;
5407
5408         uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
5409         uint32_t *src_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
5410                                 SRC_ADR_OFST_IP6);
5411         uint16_t src_port = RTE_MBUF_METADATA_UINT16(pkt, SRC_PRT_OFST_IP6);
5412
5413         uint16_t phy_port = pkt->port;
5414         struct pipeline_cgnapt_entry_key key;
5415
5416         memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
5417
5418         #ifdef CGNAPT_DBG_PRNT
5419         if (CGNAPT_DEBUG > 4)
5420                 print_pkt(pkt);
5421         #endif
5422
5423         if (enable_hwlb) {
5424                 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
5425                         return;
5426         }
5427
5428         switch (protocol) {
5429         case IP_PROTOCOL_UDP:
5430         {
5431                 #ifdef PCP_ENABLE
5432                 if (pcp_enable) {
5433                 struct udp_hdr *udp;
5434
5435                 udp = (struct udp_hdr *)
5436                         RTE_MBUF_METADATA_UINT8_PTR(pkt,
5437                                                 IPV6_UDP_OFST);
5438
5439                 if (rte_bswap16(udp->dst_port) ==
5440                         PCP_SERVER_PORT) {
5441                         handle_pcp_req(pkt, IPV6_SZ, p_nat);
5442                         p_nat->invalid_packets |= pkt_mask;
5443                         return;
5444                 }
5445                 }
5446                 #endif
5447         }
5448         case IP_PROTOCOL_TCP:
5449         case IP_PROTOCOL_ICMP:
5450                 /*we don't need icmp check in ipv6 */
5451         break;
5452
5453         default:
5454                 printf("wrong protocol: %d\n", protocol);
5455                 /* remember invalid packets to be dropped */
5456                 p_nat->invalid_packets |= pkt_mask;
5457                 p_nat->naptDroppedPktCount++;
5458
5459                 #ifdef CGNAPT_DEBUGGING
5460                 p_nat->naptDroppedPktCount2++;
5461                 #endif
5462                 return;
5463         }
5464
5465         key.pid = phy_port;
5466         key.ip = rte_bswap32(src_addr[3]);
5467         key.port = rte_bswap16(src_port);
5468
5469         #ifdef NAT_ONLY_CONFIG_REQ
5470         if (nat_only_config_flag)
5471                 key.port = 0xffff;
5472         #endif
5473
5474         memcpy(&p_nat->keys[pkt_num], &key,
5475                          sizeof(struct pipeline_cgnapt_entry_key));
5476         p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5477 }
5478
5479 /**
5480  * NAPT key calculation function for IPv6 public traffic
5481  * which handles 1 pkt
5482  *
5483  * @param pkt
5484  *  A pointer to array of packets mbuf
5485  * @param in_pkt_num
5486  *  Pkt number of pkts
5487  * @param arg
5488  *  Void pointer
5489  * @param p_nat
5490  *  A pointer to main CGNAPT structure
5491  *
5492  */
5493 void
5494 pkt_work_cgnapt_key_ipv6_pub(
5495         struct rte_mbuf *pkt,
5496         uint32_t pkt_num,
5497         __rte_unused void *arg,
5498         struct pipeline_cgnapt *p_nat)
5499 {
5500
5501         /* Ingress */
5502         p_nat->receivedPktCount++;
5503
5504         /* bitmask representing only this packet */
5505         uint64_t pkt_mask = 1LLU << pkt_num;
5506
5507         uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
5508
5509         uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
5510                                 DST_ADR_OFST_IP4);
5511         uint16_t dst_port = RTE_MBUF_METADATA_UINT16(pkt,
5512                                 DST_PRT_OFST_IP4_TCP);
5513
5514         struct pipeline_cgnapt_entry_key key;
5515
5516         memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
5517
5518         #ifdef CGNAPT_DBG_PRNT
5519         if (CGNAPT_DEBUG > 4)
5520                 print_pkt(pkt);
5521         #endif
5522
5523         if (enable_hwlb) {
5524                 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
5525                         return;
5526         }
5527
5528         switch (protocol) {
5529
5530         case IP_PROTOCOL_UDP:
5531         case IP_PROTOCOL_TCP:
5532         case IP_PROTOCOL_ICMP:
5533                 /*we don't need icmp check in ipv6 */
5534         break;
5535
5536         default:
5537                 /* remember invalid packets to be dropped */
5538                 p_nat->invalid_packets |= pkt_mask;
5539                 p_nat->naptDroppedPktCount++;
5540
5541                 #ifdef CGNAPT_DEBUGGING
5542                 p_nat->naptDroppedPktCount2++;
5543                 #endif
5544                 return;
5545         }
5546
5547         key.pid = 0xffff;
5548         key.ip = rte_bswap32(dst_addr[0]);
5549         key.port = rte_bswap16(dst_port);
5550
5551         #ifdef NAT_ONLY_CONFIG_REQ
5552         if (nat_only_config_flag)
5553                 key.port = 0xffff;
5554         #endif
5555
5556         memcpy(&p_nat->keys[pkt_num], &key,
5557                          sizeof(struct pipeline_cgnapt_entry_key));
5558         p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5559 }
5560
5561 /**
5562  * NAPT key calculation function for IPv6 private traffic
5563  * which handles 4 pkts
5564  *
5565  * @param pkt
5566  *  A pointer to array of packets mbuf
5567  * @param in_pkt_num
5568  *  Starting pkt number of pkts
5569  * @param arg
5570  *  Void pointer
5571  * @param p_nat
5572  *  A pointer to main CGNAPT structure
5573  *
5574  */
5575 void
5576 pkt4_work_cgnapt_key_ipv6_prv(
5577         struct rte_mbuf **pkt,
5578         uint32_t pkt_num,
5579         __rte_unused void *arg,
5580         struct pipeline_cgnapt *p_nat)
5581 {
5582         p_nat->receivedPktCount += 4;
5583
5584         /* bitmask representing only this packet */
5585         uint64_t pkt_mask0 = 1LLU << pkt_num;
5586         uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
5587         uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
5588         uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
5589
5590         uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
5591                                 PROT_OFST_IP6);
5592         uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
5593                                 PROT_OFST_IP6);
5594         uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
5595                                 PROT_OFST_IP6);
5596         uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
5597                                 PROT_OFST_IP6);
5598
5599         uint32_t *src_addr0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0],
5600                                 SRC_ADR_OFST_IP6);
5601         uint32_t *src_addr1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1],
5602                                 SRC_ADR_OFST_IP6);
5603         uint32_t *src_addr2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2],
5604                                 SRC_ADR_OFST_IP6);
5605         uint32_t *src_addr3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3],
5606                                 SRC_ADR_OFST_IP6);
5607
5608         uint16_t src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
5609                                 SRC_PRT_OFST_IP6);
5610         uint16_t src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
5611                                 SRC_PRT_OFST_IP6);
5612         uint16_t src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
5613                                 SRC_PRT_OFST_IP6);
5614         uint16_t src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
5615                                 SRC_PRT_OFST_IP6);
5616
5617         uint16_t phy_port0 = pkt[0]->port;
5618         uint16_t phy_port1 = pkt[1]->port;
5619         uint16_t phy_port2 = pkt[2]->port;
5620         uint16_t phy_port3 = pkt[3]->port;
5621
5622         struct pipeline_cgnapt_entry_key key0;
5623         struct pipeline_cgnapt_entry_key key1;
5624         struct pipeline_cgnapt_entry_key key2;
5625         struct pipeline_cgnapt_entry_key key3;
5626
5627         memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
5628         memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
5629         memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
5630         memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
5631
5632
5633
5634         #ifdef CGNAPT_DBG_PRNT
5635         if (CGNAPT_DEBUG > 4)
5636                 print_pkt(pkt[0]);
5637          #endif
5638
5639         if (enable_hwlb) {
5640                 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
5641                         goto PKT1;
5642         }
5643
5644         switch (protocol0) {
5645
5646         case IP_PROTOCOL_UDP:
5647         {
5648                 #ifdef PCP_ENABLE
5649                 if (pcp_enable) {
5650                 struct udp_hdr *udp;
5651
5652                 udp = (struct udp_hdr *)
5653                         RTE_MBUF_METADATA_UINT8_PTR(pkt[0],
5654                                                 IPV6_UDP_OFST);
5655
5656                 if (rte_bswap16(udp->dst_port) ==
5657                         PCP_SERVER_PORT) {
5658                         handle_pcp_req(pkt[0], IPV6_SZ, p_nat);
5659                         p_nat->invalid_packets |= pkt_mask0;
5660                         goto PKT1;
5661                 }
5662                 }
5663                 #endif
5664         }
5665         case IP_PROTOCOL_TCP:
5666         case IP_PROTOCOL_ICMP:
5667                  /*we don't need icmp check in ipv6 */
5668         break;
5669
5670         default:
5671                  /* remember invalid packets to be dropped */
5672                  p_nat->invalid_packets |= pkt_mask0;
5673                  p_nat->naptDroppedPktCount++;
5674
5675                  #ifdef CGNAPT_DEBUGGING
5676                  p_nat->naptDroppedPktCount2++;
5677                  #endif
5678
5679                 goto PKT1;
5680         }
5681
5682
5683          key0.pid = phy_port0;
5684          key0.ip = rte_bswap32(src_addr0[3]);
5685          key0.port = rte_bswap16(src_port0);
5686
5687         #ifdef NAT_ONLY_CONFIG_REQ
5688         if (nat_only_config_flag)
5689                 key0.port = 0xffff;
5690         #endif
5691
5692          memcpy(&p_nat->keys[pkt_num], &key0,
5693                                 sizeof(struct pipeline_cgnapt_entry_key));
5694          p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5695
5696  PKT1:
5697         #ifdef CGNAPT_DBG_PRNT
5698         if (CGNAPT_DEBUG > 4)
5699                 print_pkt(pkt[1]);
5700         #endif
5701
5702         if (enable_hwlb) {
5703                 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
5704                         goto PKT2;
5705         }
5706
5707         switch (protocol1) {
5708         case IP_PROTOCOL_UDP:
5709         {
5710                 #ifdef PCP_ENABLE
5711                 if (pcp_enable) {
5712                 struct udp_hdr *udp;
5713
5714                 udp = (struct udp_hdr *)
5715                         RTE_MBUF_METADATA_UINT8_PTR(pkt[1],
5716                                                 IPV6_UDP_OFST);
5717
5718                 if (rte_bswap16(udp->dst_port) ==
5719                         PCP_SERVER_PORT) {
5720                         handle_pcp_req(pkt[1], IPV6_SZ, p_nat);
5721                         p_nat->invalid_packets |= pkt_mask1;
5722                         goto PKT2;
5723                 }
5724                 }
5725                 #endif
5726         }
5727         case IP_PROTOCOL_TCP:
5728         case IP_PROTOCOL_ICMP:
5729                  /*we don't need icmp check in ipv6 */
5730         break;
5731
5732         default:
5733                  /* remember invalid packets to be dropped */
5734                  p_nat->invalid_packets |= pkt_mask1;
5735                  p_nat->naptDroppedPktCount++;
5736
5737                  #ifdef CGNAPT_DEBUGGING
5738                  p_nat->naptDroppedPktCount2++;
5739                  #endif
5740
5741                 goto PKT2;
5742         }
5743
5744          key1.pid = phy_port1;
5745          key1.ip = rte_bswap32(src_addr1[3]);
5746          key1.port = rte_bswap16(src_port1);
5747
5748         #ifdef NAT_ONLY_CONFIG_REQ
5749         if (nat_only_config_flag)
5750                 key1.port = 0xffff;
5751         #endif
5752
5753          memcpy(&p_nat->keys[pkt_num + 1], &key1,
5754                                 sizeof(struct pipeline_cgnapt_entry_key));
5755          p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
5756
5757  PKT2:
5758         #ifdef CGNAPT_DBG_PRNT
5759         if (CGNAPT_DEBUG > 4)
5760                 print_pkt(pkt[2]);
5761         #endif
5762
5763         if (enable_hwlb) {
5764                 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
5765                         goto PKT3;
5766         }
5767
5768         switch (protocol2) {
5769         case IP_PROTOCOL_UDP:
5770         {
5771                 #ifdef PCP_ENABLE
5772                 if (pcp_enable) {
5773                 struct udp_hdr *udp;
5774
5775                 udp = (struct udp_hdr *)
5776                         RTE_MBUF_METADATA_UINT8_PTR(pkt[2],
5777                                                 IPV6_UDP_OFST);
5778
5779                 if (rte_bswap16(udp->dst_port) ==
5780                         PCP_SERVER_PORT) {
5781                         handle_pcp_req(pkt[2], IPV6_SZ, p_nat);
5782                         p_nat->invalid_packets |= pkt_mask2;
5783                         goto PKT3;
5784                 }
5785                 }
5786                 #endif
5787         }
5788         case IP_PROTOCOL_TCP:
5789         case IP_PROTOCOL_ICMP:
5790                  /*we don't need icmp check in ipv6 */
5791         break;
5792
5793         default:
5794                  /* remember invalid packets to be dropped */
5795                  p_nat->invalid_packets |= pkt_mask2;
5796                  p_nat->naptDroppedPktCount++;
5797
5798                  #ifdef CGNAPT_DEBUGGING
5799                  p_nat->naptDroppedPktCount2++;
5800                  #endif
5801
5802                 goto PKT3;
5803         }
5804
5805          key2.pid = phy_port2;
5806          key2.ip = rte_bswap32(src_addr2[3]);
5807          key2.port = rte_bswap16(src_port2);
5808
5809         #ifdef NAT_ONLY_CONFIG_REQ
5810         if (nat_only_config_flag)
5811                 key2.port = 0xffff;
5812         #endif
5813
5814          memcpy(&p_nat->keys[pkt_num + 2], &key2,
5815                                 sizeof(struct pipeline_cgnapt_entry_key));
5816          p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
5817
5818  PKT3:
5819         #ifdef CGNAPT_DBG_PRNT
5820         if (CGNAPT_DEBUG > 4)
5821                 print_pkt(pkt[3]);
5822         #endif
5823
5824         if (enable_hwlb) {
5825                 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
5826                         return;
5827         }
5828
5829         switch (protocol3) {
5830         case IP_PROTOCOL_UDP:
5831         {
5832                 #ifdef PCP_ENABLE
5833                 if (pcp_enable) {
5834                 struct udp_hdr *udp;
5835
5836                 udp = (struct udp_hdr *)
5837                         RTE_MBUF_METADATA_UINT8_PTR(pkt[3],
5838                                                 IPV6_UDP_OFST);
5839
5840                 if (rte_bswap16(udp->dst_port) ==
5841                         PCP_SERVER_PORT) {
5842                         handle_pcp_req(pkt[3], IPV6_SZ, p_nat);
5843                         p_nat->invalid_packets |= pkt_mask3;
5844                         return;
5845                 }
5846                 }
5847                 #endif
5848         }
5849         case IP_PROTOCOL_TCP:
5850         case IP_PROTOCOL_ICMP:
5851                  /*we don't need icmp check in ipv6 */
5852         break;
5853
5854         default:
5855                  /* remember invalid packets to be dropped */
5856                  p_nat->invalid_packets |= pkt_mask2;
5857                  p_nat->naptDroppedPktCount++;
5858
5859                  #ifdef CGNAPT_DEBUGGING
5860                  p_nat->naptDroppedPktCount2++;
5861                  #endif
5862
5863                 return;
5864         }
5865
5866          key3.pid = phy_port3;
5867          key3.ip = rte_bswap32(src_addr3[3]);
5868          key3.port = rte_bswap16(src_port3);
5869
5870         #ifdef NAT_ONLY_CONFIG_REQ
5871         if (nat_only_config_flag)
5872                 key3.port = 0xffff;
5873         #endif
5874
5875          memcpy(&p_nat->keys[pkt_num + 3], &key3,
5876                                 sizeof(struct pipeline_cgnapt_entry_key));
5877          p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
5878
5879
5880 }
5881
5882 /**
5883  * NAPT key calculation function for IPv4 public traffic
5884  * which handles 4 pkts
5885  *
5886  * @param pkt
5887  *  A pointer to array of packets mbuf
5888  * @param in_pkt_num
5889  *  Starting pkt number of pkts
5890  * @param arg
5891  *  Void pointer
5892  * @param p_nat
5893  *  A pointer to main CGNAPT structure
5894  *
5895  */
5896 void
5897 pkt4_work_cgnapt_key_ipv6_pub(
5898         struct rte_mbuf **pkt,
5899         uint32_t pkt_num,
5900         __rte_unused void *arg,
5901         struct pipeline_cgnapt *p_nat)
5902 {
5903         p_nat->receivedPktCount += 4;
5904
5905         /* bitmask representing only this packet */
5906         uint64_t pkt_mask0 = 1LLU << pkt_num;
5907         uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
5908         uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
5909         uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
5910
5911         uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
5912                                 PROT_OFST_IP4);
5913         uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
5914                                 PROT_OFST_IP4);
5915         uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
5916                                 PROT_OFST_IP4);
5917         uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
5918                                 PROT_OFST_IP4);
5919
5920         uint32_t *dst_addr0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0],
5921                                 DST_ADR_OFST_IP4);
5922         uint32_t *dst_addr1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1],
5923                                 DST_ADR_OFST_IP4);
5924         uint32_t *dst_addr2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2],
5925                                 DST_ADR_OFST_IP4);
5926         uint32_t *dst_addr3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3],
5927                                 DST_ADR_OFST_IP4);
5928
5929         uint16_t dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
5930                                 DST_PRT_OFST_IP4_TCP);
5931         uint16_t dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
5932                                 DST_PRT_OFST_IP4_TCP);
5933         uint16_t dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
5934                                 DST_PRT_OFST_IP4_TCP);
5935         uint16_t dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
5936                                 DST_PRT_OFST_IP4_TCP);
5937
5938         struct pipeline_cgnapt_entry_key key0;
5939         struct pipeline_cgnapt_entry_key key1;
5940         struct pipeline_cgnapt_entry_key key2;
5941         struct pipeline_cgnapt_entry_key key3;
5942
5943         memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
5944         memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
5945         memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
5946         memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
5947
5948 /* --0-- */
5949
5950         #ifdef CGNAPT_DBG_PRNT
5951         if (CGNAPT_DEBUG > 4)
5952                 print_pkt(pkt[0]);
5953         #endif
5954
5955         if (enable_hwlb) {
5956                 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
5957                         goto PKT1;
5958         }
5959
5960         switch (protocol0) {
5961
5962         case IP_PROTOCOL_TCP:
5963         case IP_PROTOCOL_UDP:
5964         case IP_PROTOCOL_ICMP:
5965                 /*we don't need icmp check in ipv6 */
5966         break;
5967
5968         default:
5969                 /* remember invalid packets to be dropped */
5970                 p_nat->invalid_packets |= pkt_mask0;
5971                 p_nat->naptDroppedPktCount++;
5972
5973                 #ifdef CGNAPT_DEBUGGING
5974                 p_nat->naptDroppedPktCount2++;
5975                 #endif
5976                 goto PKT1;
5977         }
5978
5979         key0.pid = 0xffff;
5980         key0.ip = rte_bswap32(dst_addr0[0]);
5981         key0.port = rte_bswap16(dst_port0);
5982
5983         #ifdef NAT_ONLY_CONFIG_REQ
5984         if (nat_only_config_flag)
5985                 key0.port = 0xffff;
5986         #endif
5987
5988         memcpy(&p_nat->keys[pkt_num], &key0,
5989                          sizeof(struct pipeline_cgnapt_entry_key));
5990         p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5991
5992
5993 /* --1-- */
5994
5995 PKT1:
5996         #ifdef CGNAPT_DBG_PRNT
5997         if (CGNAPT_DEBUG > 4)
5998                 print_pkt(pkt[1]);
5999         #endif
6000
6001         if (enable_hwlb) {
6002                 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
6003                         goto PKT2;
6004         }
6005
6006         switch (protocol1) {
6007
6008         case IP_PROTOCOL_TCP:
6009         case IP_PROTOCOL_UDP:
6010         case IP_PROTOCOL_ICMP:
6011                 /*we don't need icmp check in ipv6 */
6012         break;
6013
6014         default:
6015                 /* remember invalid packets to be dropped */
6016                 p_nat->invalid_packets |= pkt_mask1;
6017                 p_nat->naptDroppedPktCount++;
6018
6019                 #ifdef CGNAPT_DEBUGGING
6020                 p_nat->naptDroppedPktCount2++;
6021                 #endif
6022                 goto PKT2;
6023         }
6024
6025         key1.pid = 0xffff;
6026         key1.ip = rte_bswap32(dst_addr1[0]);
6027         key1.port = rte_bswap16(dst_port1);
6028
6029         #ifdef NAT_ONLY_CONFIG_REQ
6030         if (nat_only_config_flag)
6031                 key1.port = 0xffff;
6032         #endif
6033
6034         memcpy(&p_nat->keys[pkt_num + 1], &key1,
6035                          sizeof(struct pipeline_cgnapt_entry_key));
6036         p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
6037
6038
6039 /* --2-- */
6040
6041 PKT2:
6042         #ifdef CGNAPT_DBG_PRNT
6043         if (CGNAPT_DEBUG > 4)
6044                 print_pkt(pkt[2]);
6045         #endif
6046
6047         if (enable_hwlb) {
6048                 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
6049                         goto PKT3;
6050         }
6051
6052         switch (protocol2) {
6053
6054         case IP_PROTOCOL_TCP:
6055         case IP_PROTOCOL_UDP:
6056         case IP_PROTOCOL_ICMP:
6057                 /*we don't need icmp check in ipv6 */
6058         break;
6059
6060         default:
6061                 /* remember invalid packets to be dropped */
6062                 p_nat->invalid_packets |= pkt_mask2;
6063                 p_nat->naptDroppedPktCount++;
6064
6065                 #ifdef CGNAPT_DEBUGGING
6066                 p_nat->naptDroppedPktCount2++;
6067                 #endif
6068                 goto PKT3;
6069         }
6070
6071         key2.pid = 0xffff;
6072         key2.ip = rte_bswap32(dst_addr2[0]);
6073         key2.port = rte_bswap16(dst_port2);
6074
6075         #ifdef NAT_ONLY_CONFIG_REQ
6076         if (nat_only_config_flag)
6077                 key2.port = 0xffff;
6078         #endif
6079
6080         memcpy(&p_nat->keys[pkt_num + 2], &key2,
6081                          sizeof(struct pipeline_cgnapt_entry_key));
6082
6083         p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
6084
6085
6086 /* --3-- */
6087
6088 PKT3:
6089         #ifdef CGNAPT_DBG_PRNT
6090         if (CGNAPT_DEBUG > 4)
6091                 print_pkt(pkt[3]);
6092         #endif
6093
6094         if (enable_hwlb) {
6095                 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
6096                         return;
6097         }
6098
6099         switch (protocol3) {
6100
6101         case IP_PROTOCOL_TCP:
6102         case IP_PROTOCOL_UDP:
6103         case IP_PROTOCOL_ICMP:
6104                 /*we don't need icmp check in ipv6 */
6105         break;
6106
6107         default:
6108                 /* remember invalid packets to be dropped */
6109                 p_nat->invalid_packets |= pkt_mask3;
6110                 p_nat->naptDroppedPktCount++;
6111
6112                 #ifdef CGNAPT_DEBUGGING
6113                 p_nat->naptDroppedPktCount2++;
6114                 #endif
6115                 return;
6116         }
6117
6118         key3.pid = 0xffff;
6119         key3.ip = rte_bswap32(dst_addr3[0]);
6120         key3.port = rte_bswap16(dst_port3);
6121
6122         #ifdef NAT_ONLY_CONFIG_REQ
6123         if (nat_only_config_flag)
6124                 key3.port = 0xffff;
6125         #endif
6126
6127         memcpy(&p_nat->keys[pkt_num + 3], &key3,
6128                          sizeof(struct pipeline_cgnapt_entry_key));
6129
6130         p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
6131 }
6132
6133 /**
6134  * NAPT function for IPv6 private traffic which handles 1 pkt
6135  *
6136  * @param pkts
6137  *  A pointer to array of packet mbuf
6138  * @param in_pkt_num
6139  *  Pkt number of pkt
6140  * @param arg
6141  *  Void pointer
6142  * @param p_nat
6143  *  A pointer to main CGNAPT structure
6144  *
6145  */
6146 void
6147 pkt_work_cgnapt_ipv6_prv(
6148         struct rte_mbuf *pkt,
6149         uint32_t pkt_num,
6150         __rte_unused void *arg,
6151         struct pipeline_cgnapt *p_nat)
6152 {
6153
6154         /* index into hash table entries */
6155         int hash_table_entry = p_nat->lkup_indx[pkt_num];
6156
6157         /*bitmask representing only this packet */
6158         uint64_t pkt_mask = 1LLU << pkt_num;
6159
6160         uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
6161
6162         /* Added for Multiport */
6163         uint32_t dest_if = INVALID_DESTIF;
6164         uint16_t *outport_id = RTE_MBUF_METADATA_UINT16_PTR(pkt,
6165                                 cgnapt_meta_offset);
6166
6167         struct cgnapt_table_entry *entry = NULL;
6168         enum PKT_TYPE pkt_type = PKT_TYPE_IPV6to4;
6169
6170         if (hash_table_entry < 0) {
6171
6172                 /* try to add new entry */
6173                 struct rte_pipeline_table_entry *table_entry = NULL;
6174
6175                 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
6176                                         pkt, &table_entry,
6177                                         &p_nat->valid_packets, pkt_num,
6178                                         (void *)p_nat);
6179
6180                 if (!table_entry) {
6181                         /* ICMP Error message generation for
6182                         * Destination Host unreachable
6183                         */
6184                         /* Do we need this check for ipv6? */
6185                         if (protocol == IP_PROTOCOL_ICMP) {
6186                                 cgnapt_icmp_pkt = pkt;
6187                                 send_icmp_dest_unreachable_msg();
6188                         }
6189
6190                         /* Drop packet by adding to invalid pkt mask */
6191
6192                         p_nat->invalid_packets |= dropmask;
6193
6194                         #ifdef CGNAPT_DEBUGGING
6195                         if (p_nat->kpc2++ < 5) {
6196                                 printf("in_ah Th: %d", p_nat->pipeline_num);
6197                                 print_key(p_nat->key_ptrs[pkt_num]);
6198                         }
6199                         #endif
6200
6201                         p_nat->naptDroppedPktCount++;
6202
6203                         #ifdef CGNAPT_DEBUGGING
6204                         p_nat->naptDroppedPktCount3++;
6205                         #endif
6206
6207                         return;
6208                 }
6209
6210                 entry = (struct cgnapt_table_entry *)table_entry;
6211         } else {
6212                 /* entry found for this packet */
6213                 entry = &napt_hash_tbl_entries[hash_table_entry];
6214         }
6215
6216         /*  apply napt and mac changes */
6217
6218         p_nat->entries[pkt_num] = &(entry->head);
6219
6220         struct ipv6_hdr ipv6_hdr;
6221
6222         struct ether_addr hw_addr;
6223         uint32_t dest_address = 0;
6224         uint32_t nhip = 0;
6225         /* Egress */
6226         {
6227
6228                 convert_ipv6_to_ipv4(pkt, &ipv6_hdr);
6229
6230                 #ifdef CGNAPT_DBG_PRNT
6231                 if (CGNAPT_DEBUG == 1)
6232                         printf("pkt_work_cganpt: convert_ipv6_to_ipv4\n");
6233                 #endif
6234
6235                 struct cgnapt_nsp_node *ll = nsp_ll;
6236                 int nsp = 0;
6237
6238                 while (ll != NULL) {
6239                         if (!memcmp
6240                                 (&ipv6_hdr.dst_addr[0], &ll->nsp.prefix[0],
6241                                  ll->nsp.depth / 8)) {
6242                                 nsp = 1;
6243                                 break;
6244                         }
6245                         ll = ll->next;
6246                 }
6247
6248                 if (!nsp
6249                         && !memcmp(&ipv6_hdr.dst_addr[0], &well_known_prefix[0],
6250                                          12)) {
6251                         nsp = 1;
6252                 }
6253
6254                 if (!nsp) {
6255                         p_nat->invalid_packets |= pkt_mask;
6256                         p_nat->naptDroppedPktCount++;
6257
6258                         #ifdef CGNAPT_DEBUGGING
6259                         p_nat->naptDroppedPktCount5++;
6260                         #endif
6261
6262                         return;
6263                 }
6264
6265         }
6266
6267         /* As packet is already converted into IPv4 we must not
6268         * operate IPv6 offsets on packet
6269         * Only perform IPv4 operations
6270         */
6271
6272         uint32_t *src_addr =
6273                 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP6t4);
6274         uint32_t *dst_addr =
6275                 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP6t4);
6276         uint16_t *src_port =
6277                 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP6t4);
6278         uint16_t *dst_port =
6279                 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP6t4);
6280
6281         uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt,
6282                                 ETH_OFST_IP6t4);
6283         uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt,
6284                                 ETH_OFST_IP6t4 + 6);
6285
6286         if (entry->data.ttl == NAPT_ENTRY_STALE)
6287                 entry->data.ttl = NAPT_ENTRY_VALID;
6288         {
6289                 /* Egress */
6290                 if (unlikely(protocol == IP_PROTOCOL_UDP
6291                                  && rte_be_to_cpu_16(*dst_port) == 53)) {
6292                         p_nat->invalid_packets |= pkt_mask;
6293                         p_nat->naptDroppedPktCount++;
6294
6295                         #ifdef CGNAPT_DEBUGGING
6296                         p_nat->naptDroppedPktCount6++;
6297                         #endif
6298
6299                         return;
6300                 }
6301
6302                 dest_address = rte_bswap32(*dst_addr);
6303                 /*Multiport Changes */
6304         uint32_t nhip = 0;
6305         uint32_t ret;
6306         ret = local_get_nh_ipv4(dest_address, &dest_if, &nhip, p_nat);
6307         if (!ret) {
6308                 dest_if = get_prv_to_pub_port(&dest_address, IP_VERSION_4);
6309
6310                 if (dest_if == INVALID_DESTIF) {
6311                         p_nat->invalid_packets |= pkt_mask;
6312                         p_nat->naptDroppedPktCount++;
6313                         #ifdef CGNAPT_DEBUGGING
6314                         p_nat->naptDroppedPktCount6++;
6315                         #endif
6316                         return;
6317                 }
6318
6319                 do_local_nh_ipv4_cache(dest_if, p_nat);
6320         }
6321                 *outport_id = p_nat->outport_id[dest_if];
6322
6323                 #ifdef CGNAPT_DBG_PRNT
6324                 if (CGNAPT_DEBUG > 2)
6325                         printf("Egress: \tphy_port:%d\t get_prv_to_pub():%d "
6326                         "\tout_port:%d\n", pkt->port,
6327                         dest_if, *outport_id);
6328                 #endif
6329         }
6330
6331         #ifdef CGNAPT_DBG_PRNT
6332         static int static_count;
6333
6334         if (static_count++ < 10) {
6335                 print_pkt(pkt);
6336                 my_print_entry(entry);
6337                 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6338                 printf("dest_add:%x\n", entry->data.u.prv_ip);
6339                 printf("dest_add:%x\n", *dst_addr);
6340                 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6341         }
6342         #endif
6343
6344         if (local_dest_mac_present(dest_if)) {
6345                 memcpy(eth_dest,
6346                                 get_local_link_hw_addr(dest_if),
6347                                 sizeof(struct ether_addr));
6348                 memcpy(eth_src, get_link_hw_addr(dest_if),
6349                                 sizeof(struct ether_addr));
6350         } else {
6351                 int ret;
6352                 ret = get_dest_mac_addr_port(dest_address, &dest_if, &hw_addr);
6353
6354                 if (unlikely(ret != ARP_FOUND)) {
6355
6356                         if (unlikely(ret == ARP_NOT_FOUND)) {
6357                                 printf("%s: ARP Not Found, nhip: %x, "
6358                                 "outport_id: %d\n", __func__, nhip,
6359                                 *outport_id);
6360                                 //request_arp(*outport_id, nhip, p_nat->p.p);
6361                         }
6362
6363                         /* Drop the pkt */
6364                         p_nat->invalid_packets |= pkt_mask;
6365                         p_nat->naptDroppedPktCount++;
6366
6367                         #ifdef CGNAPT_DEBUGGING
6368                         p_nat->naptDroppedPktCount4++;
6369                         #endif
6370                         return;
6371
6372                 }
6373                 #ifdef CGNAPT_DBG_PRNT
6374                 if (CGNAPT_DEBUG > 2) {
6375                         printf("MAC found for ip 0x%x, port %d - %02x:%02x: "
6376                         "%02x:%02x:%02x:%02x\n", dest_address,
6377                         *outport_id,
6378                         hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
6379                         hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
6380                         hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
6381
6382                         printf("Dest MAC before - %02x:%02x:%02x:%02x: "
6383                         "%02x:%02x\n", eth_dest[0], eth_dest[1],
6384                         eth_dest[2], eth_dest[3],
6385                         eth_dest[4], eth_dest[5]);
6386                 }
6387                 #endif
6388
6389                 memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
6390
6391                 #ifdef CGNAPT_DBG_PRNT
6392                 if (CGNAPT_DEBUG > 2) {
6393                         printf("Dest MAC after - "
6394                         "%02x:%02x:%02x:%02x:%02x:%02x\n",
6395                         eth_dest[0], eth_dest[1], eth_dest[2], eth_dest[3],
6396                         eth_dest[4], eth_dest[5]);
6397                 }
6398                 #endif
6399
6400                 memcpy(eth_src, get_link_hw_addr(dest_if),
6401                                  sizeof(struct ether_addr));
6402         }
6403
6404         {
6405                 /* Egress */
6406                 *src_addr = rte_bswap32(entry->data.pub_ip);
6407
6408                 #ifdef NAT_ONLY_CONFIG_REQ
6409                 if (!nat_only_config_flag) {
6410                 #endif
6411                         *src_port = rte_bswap16(entry->data.pub_port);
6412
6413                 #ifdef NAT_ONLY_CONFIG_REQ
6414                 }
6415                 #endif
6416
6417                 p_nat->enaptedPktCount++;
6418         }
6419
6420         p_nat->naptedPktCount++;
6421
6422                 #ifdef HW_CHECKSUM_REQ
6423                         if (p_nat->hw_checksum_reqd)
6424                                 hw_checksum(pkt, pkt_type);
6425                         else
6426                 #endif
6427                                 sw_checksum(pkt, pkt_type);
6428 }
6429
6430
6431 /**
6432  * NAPT function for IPv6 public traffic which handles 1 pkt
6433  *
6434  * @param pkts
6435  *  A pointer to array of packet mbuf
6436  * @param in_pkt_num
6437  *  Pkt number of pkt
6438  * @param arg
6439  *  Void pointer
6440  * @param p_nat
6441  *  A pointer to main CGNAPT structure
6442  *
6443  */
6444 void
6445 pkt_work_cgnapt_ipv6_pub(
6446         struct rte_mbuf *pkt,
6447         uint32_t pkt_num,
6448         __rte_unused void *arg,
6449         struct pipeline_cgnapt *p_nat)
6450 {
6451
6452         /* index into hash table entries */
6453         int hash_table_entry = p_nat->lkup_indx[pkt_num];
6454         /*bitmask representing only this packet */
6455         uint64_t pkt_mask = 1LLU << pkt_num;
6456
6457         uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
6458
6459         uint32_t dest_if = INVALID_DESTIF;      /* Added for Multiport */
6460         uint16_t *outport_id =
6461                 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6462         struct cgnapt_table_entry *entry = NULL;
6463
6464         enum PKT_TYPE pkt_type = PKT_TYPE_IPV4to6;
6465
6466         if (hash_table_entry < 0) {
6467
6468                 /* Drop ingress initial traffic */
6469
6470                 p_nat->invalid_packets |= pkt_mask;
6471                 p_nat->naptDroppedPktCount++;
6472
6473                 #ifdef CGNAPT_DEBUGGING
6474                 p_nat->naptDroppedPktCount3++;
6475                 if (p_nat->kpc2++ < 5) {
6476                         printf("in_ah Th: %d", p_nat->pipeline_num);
6477                         print_key(p_nat->key_ptrs[pkt_num]);
6478                 }
6479                 #endif
6480
6481                 return;
6482
6483         } else {
6484                 /* entry found for this packet */
6485                 entry = &napt_hash_tbl_entries[hash_table_entry];
6486         }
6487
6488         /*  apply napt and mac changes */
6489
6490         p_nat->entries[pkt_num] = &(entry->head);
6491         if (entry->data.type != CGNAPT_ENTRY_IPV6) {
6492                 p_nat->invalid_packets |= pkt_mask;
6493                 p_nat->naptDroppedPktCount++;
6494                 return;
6495         }
6496
6497         struct ipv4_hdr ipv4_hdr;
6498         uint16_t *src_port =
6499                 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP4_TCP);
6500
6501         uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
6502         uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
6503
6504         if (entry->data.ttl == NAPT_ENTRY_STALE)
6505                 entry->data.ttl = NAPT_ENTRY_VALID;
6506
6507         struct ether_addr hw_addr;
6508         uint8_t dest_addr_ipv6[16];
6509         uint8_t nh_ipv6[16];
6510
6511         /* Ingress */
6512         {
6513
6514                 if (unlikely(protocol == IP_PROTOCOL_UDP
6515                                  && rte_be_to_cpu_16(*src_port) == 53)) {
6516                         p_nat->invalid_packets |= pkt_mask;
6517                         p_nat->naptDroppedPktCount++;
6518                         #ifdef CGNAPT_DEBUGGING
6519                         p_nat->naptDroppedPktCount6++;
6520                         #endif
6521                         return;
6522                 }
6523
6524                 memcpy(&dest_addr_ipv6[0], &entry->data.u.prv_ipv6[0], 16);
6525                 uint8_t nhipv6[16];
6526                 int ret;
6527                 ret = local_get_nh_ipv6(&dest_addr_ipv6[0], &dest_if,
6528                                 &nhipv6[0], p_nat);
6529                 if (!ret) {
6530                         dest_if = get_prv_to_pub_port((uint32_t *)
6531                                         &dest_addr_ipv6[0],
6532                                         IP_VERSION_6);
6533
6534                 if (dest_if == INVALID_DESTIF) {
6535                         p_nat->invalid_packets |= pkt_mask;
6536                         p_nat->naptDroppedPktCount++;
6537                         #ifdef CGNAPT_DEBUGGING
6538                         p_nat->naptDroppedPktCount6++;
6539                         #endif
6540                         return;
6541                 }
6542
6543                         do_local_nh_ipv6_cache(dest_if, p_nat);
6544                 }
6545                 *outport_id = p_nat->outport_id[dest_if];
6546         }
6547
6548         #ifdef CGNAPT_DEBUGGING
6549         static int static_count;
6550
6551         if (static_count++ < 10) {
6552                 print_pkt(pkt);
6553                 my_print_entry(entry);
6554                 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6555                 printf("dest_add:%x\n", entry->data.u.prv_ip);
6556                 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6557         }
6558         #endif
6559
6560         memset(nh_ipv6, 0, 16);
6561         if (get_dest_mac_address_ipv6_port(
6562                 &dest_addr_ipv6[0],
6563                 &dest_if,
6564                 &hw_addr,
6565                 &nh_ipv6[0])) {
6566
6567                 #ifdef CGNAPT_DBG_PRNT
6568                 if (CGNAPT_DEBUG > 2) {
6569                         printf("MAC found for ip 0x%x, port %d - "
6570                         "%02x:%02x:%02x:%02x:%02x:%02x\n",
6571                         *((uint32_t *)dest_addr_ipv6 + 12),
6572                         *outport_id,
6573                         hw_addr.addr_bytes[0],
6574                         hw_addr.addr_bytes[1], hw_addr.addr_bytes[2],
6575                         hw_addr.addr_bytes[3], hw_addr.addr_bytes[4],
6576                         hw_addr.addr_bytes[5]);
6577
6578                         printf("Dest MAC before - "
6579                         "%02x:%02x:%02x:%02x:%02x:%02x\n",
6580                         eth_dest[0], eth_dest[1], eth_dest[2],
6581                         eth_dest[3], eth_dest[4], eth_dest[5]);
6582                 }
6583                 #endif
6584
6585                 memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
6586
6587                 #ifdef CGNAPT_DBG_PRNT
6588                 if (CGNAPT_DEBUG > 2) {
6589                         printf("Dest MAC after - "
6590                         "%02x:%02x:%02x:%02x:%02x:%02x\n",
6591                         eth_dest[0], eth_dest[1], eth_dest[2], eth_dest[3],
6592                         eth_dest[4], eth_dest[5]);
6593                 }
6594                 #endif
6595
6596                 memcpy(eth_src, get_link_hw_addr(dest_if),
6597                                  sizeof(struct ether_addr));
6598         } else {
6599                 p_nat->invalid_packets |= pkt_mask;
6600                 p_nat->naptDroppedPktCount++;
6601
6602                 #ifdef CGNAPT_DEBUGGING
6603                 p_nat->naptDroppedPktCount4++;
6604                 #endif
6605
6606                 return;
6607         }
6608         /* Ingress */
6609         {
6610
6611                 convert_ipv4_to_ipv6(pkt, &ipv4_hdr);
6612
6613                 /* Ethernet MTU check */
6614                 if ((rte_pktmbuf_data_len(pkt) - 14) > 1500) {
6615                         p_nat->invalid_packets |= pkt_mask;
6616                         p_nat->naptDroppedPktCount++;
6617                         return;
6618                 }
6619                 uint32_t *dst_addr =
6620                         RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4t6);
6621                 uint16_t *dst_port =
6622                         RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP4t6);
6623
6624                 memcpy((uint8_t *) &dst_addr[0], &entry->data.u.prv_ipv6[0],
6625                                  16);
6626
6627                 #ifdef NAT_ONLY_CONFIG_REQ
6628                 if (!nat_only_config_flag) {
6629                 #endif
6630                         *dst_port = rte_bswap16(entry->data.prv_port);
6631
6632                 #ifdef NAT_ONLY_CONFIG_REQ
6633                 }
6634                 #endif
6635
6636                 p_nat->inaptedPktCount++;
6637         }
6638
6639         p_nat->naptedPktCount++;
6640
6641                 #ifdef HW_CHECKSUM_REQ
6642                         if (p_nat->hw_checksum_reqd)
6643                                 hw_checksum(pkt, pkt_type);
6644                         else
6645                 #endif
6646                                 sw_checksum(pkt, pkt_type);
6647 }
6648
6649
6650 /**
6651  * NAPT function for IPv6 private traffic which handles 4 pkts
6652  *
6653  * @param pkts
6654  *  A pointer to array of packets mbuf
6655  * @param in_pkt_num
6656  *  Starting pkt number of pkts
6657  * @param arg
6658  *  Void pointer
6659  * @param p_nat
6660  *  A pointer to main CGNAPT structure
6661  *
6662  */
6663 void
6664 pkt4_work_cgnapt_ipv6_prv(
6665         struct rte_mbuf **pkts,
6666         uint32_t in_pkt_num,
6667         __rte_unused void *arg,
6668         struct pipeline_cgnapt *p_nat)
6669 {
6670         struct rte_mbuf *pkt;
6671         uint8_t i;
6672         uint8_t pkt_num;
6673
6674         enum PKT_TYPE pkt_type = PKT_TYPE_IPV6to4;
6675
6676         for (i = 0; i < 4; i++) {
6677                 pkt_num = in_pkt_num + i;
6678                 pkt = pkts[i];
6679
6680                 /* index into hash table entries */
6681                 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6682                 /*bitmask representing only this packet */
6683                 uint64_t pkt_mask = 1LLU << pkt_num;
6684
6685                 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
6686                 uint32_t dest_if = INVALID_DESTIF;
6687                 uint16_t *outport_id =
6688                         RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6689                 struct cgnapt_table_entry *entry = NULL;
6690
6691                 if (hash_table_entry < 0) {
6692
6693                         /* try to add new entry */
6694                         struct rte_pipeline_table_entry *table_entry = NULL;
6695
6696                         uint64_t dropmask =
6697                                 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
6698                                                 &table_entry,
6699                                                 &p_nat->valid_packets, pkt_num,
6700                                                 (void *)p_nat);
6701
6702                         if (!table_entry) {
6703                                 /* ICMP Error message generation for
6704                                 * Destination Host unreachable
6705                                 */
6706                                 /* Do we need this check for ipv6? */
6707                                 if (protocol == IP_PROTOCOL_ICMP) {
6708                                         cgnapt_icmp_pkt = pkt;
6709                                         send_icmp_dest_unreachable_msg();
6710                                 }
6711
6712                                 /* Drop packet by adding to invalid pkt mask */
6713
6714                                 p_nat->invalid_packets |= dropmask;
6715
6716                                 #ifdef CGNAPT_DEBUGGING
6717                                 if (p_nat->kpc2++ < 5) {
6718                                         printf("in_ah Th: %d",
6719                                                          p_nat->pipeline_num);
6720                                         print_key(p_nat->key_ptrs[pkt_num]);
6721                                 }
6722                                 #endif
6723
6724                                 p_nat->naptDroppedPktCount++;
6725
6726                                 #ifdef CGNAPT_DEBUGGING
6727                                 p_nat->naptDroppedPktCount3++;
6728                                 #endif
6729
6730                                 continue;
6731                         }
6732
6733                         entry = (struct cgnapt_table_entry *)table_entry;
6734                 } else {
6735                         /* entry found for this packet */
6736                         entry = &napt_hash_tbl_entries[hash_table_entry];
6737                 }
6738
6739                 /*  apply napt and mac changes */
6740
6741                 p_nat->entries[pkt_num] = &(entry->head);
6742
6743                 struct ipv6_hdr ipv6_hdr;
6744                 struct ether_addr hw_addr;
6745                 uint32_t dest_address = 0;
6746                 uint8_t nh_ipv6[16];
6747                 uint32_t nhip = 0;
6748
6749                 /* Egress */
6750                 {
6751                         convert_ipv6_to_ipv4(pkt, &ipv6_hdr);
6752
6753                         #ifdef CGNAPT_DBG_PRNT
6754                         if (CGNAPT_DEBUG >= 1)
6755                                 printf("pkt_work_cganpt: "
6756                                 "convert_ipv6_to_ipv4\n");
6757                         #endif
6758
6759                         struct cgnapt_nsp_node *ll = nsp_ll;
6760                         int nsp = 0;
6761
6762                         while (ll != NULL) {
6763                                 if (!memcmp(&ipv6_hdr.dst_addr[0],
6764                                         &ll->nsp.prefix[0],
6765                                          ll->nsp.depth / 8)) {
6766                                         nsp = 1;
6767                                         break;
6768                                 }
6769                                 ll = ll->next;
6770                         }
6771
6772                         if (!nsp
6773                                 && !memcmp(&ipv6_hdr.dst_addr[0],
6774                                                  &well_known_prefix[0], 12)) {
6775                                 nsp = 1;
6776                         }
6777
6778                         if (!nsp) {
6779                                 p_nat->invalid_packets |= pkt_mask;
6780                                 p_nat->naptDroppedPktCount++;
6781
6782                                 #ifdef CGNAPT_DEBUGGING
6783                                 p_nat->naptDroppedPktCount5++;
6784                                 #endif
6785                                 continue;
6786                         }
6787
6788                 }
6789
6790                 /* As packet is already converted into IPv4 we must not
6791                 * operate IPv6 offsets on packet only perform IPv4 operations
6792                 */
6793
6794                 uint32_t *src_addr =
6795                         RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP6t4);
6796                 uint32_t *dst_addr =
6797                         RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP6t4);
6798                 uint16_t *src_port =
6799                         RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP6t4);
6800                 uint16_t *dst_port =
6801                         RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP6t4);
6802
6803                 uint8_t *eth_dest =
6804                         RTE_MBUF_METADATA_UINT8_PTR(pkt, ETH_OFST_IP6t4);
6805                 uint8_t *eth_src =
6806                         RTE_MBUF_METADATA_UINT8_PTR(pkt, ETH_OFST_IP6t4 + 6);
6807
6808                 if (entry->data.ttl == NAPT_ENTRY_STALE)
6809                         entry->data.ttl = NAPT_ENTRY_VALID;
6810
6811                 /* Egress */
6812                 {
6813
6814                         if (unlikely(protocol == IP_PROTOCOL_UDP
6815                                 && rte_be_to_cpu_16(*dst_port) == 53)) {
6816                                 p_nat->invalid_packets |= pkt_mask;
6817                                 p_nat->naptDroppedPktCount++;
6818
6819                                 #ifdef CGNAPT_DEBUGGING
6820                                 p_nat->naptDroppedPktCount6++;
6821                                 #endif
6822                                 continue;
6823                         }
6824
6825                         dest_address = rte_bswap32(*dst_addr);
6826         uint32_t nhip;
6827         uint32_t ret;
6828         ret = local_get_nh_ipv4(dest_address, &dest_if, &nhip, p_nat);
6829         if (!ret) {
6830                 dest_if = get_prv_to_pub_port(&dest_address, IP_VERSION_4);
6831
6832                 if (dest_if == INVALID_DESTIF) {
6833                         p_nat->invalid_packets |= pkt_mask;
6834                         p_nat->naptDroppedPktCount++;
6835                         #ifdef CGNAPT_DEBUGGING
6836                         p_nat->naptDroppedPktCount6++;
6837                         #endif
6838                         continue;
6839                 }
6840
6841                 do_local_nh_ipv4_cache(dest_if, p_nat);
6842         }
6843                 *outport_id = p_nat->outport_id[dest_if];
6844
6845                 #ifdef CGNAPT_DBG_PRNT
6846                         if (CGNAPT_DEBUG > 2)
6847                                 printf("Egress: \tphy_port:%d\t"
6848                                 "get_prv_to_pub():%d \tout_port:%d\n",
6849                                 pkt->port, dest_if, *outport_id);
6850                 #endif
6851                 }
6852
6853                 #ifdef CGNAPT_DEBUGGING
6854                 static int static_count;
6855
6856                 if (static_count++ < 10) {
6857                         print_pkt(pkt);
6858                         my_print_entry(entry);
6859                         printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6860                         printf("dest_add:%x\n", entry->data.u.prv_ip);
6861                         printf("dest_add:%x\n", *dst_addr);
6862                         printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6863                 }
6864                 #endif
6865
6866                 memset(nh_ipv6, 0, 16);
6867
6868                 {
6869                 int ret;
6870                 ret = get_dest_mac_addr_port(dest_address, &dest_if, &hw_addr);
6871
6872                 if (unlikely(ret != ARP_FOUND)) {
6873
6874                         if (unlikely(ret == ARP_NOT_FOUND)) {
6875                                 /* Commented code may be required for debug
6876                                  * and future use, Please keep it */
6877                                 //request_arp(*outport_id, nhip, p_nat->p.p);
6878                                 printf("%s: ARP Not Found, nhip: %x, "
6879                                 "outport_id: %d\n", __func__, nhip,
6880                                 *outport_id);
6881                         }
6882
6883                         /* Drop the pkt */
6884                         p_nat->invalid_packets |= pkt_mask;
6885                         p_nat->naptDroppedPktCount++;
6886
6887                         #ifdef CGNAPT_DEBUGGING
6888                         p_nat->naptDroppedPktCount4++;
6889                         #endif
6890                         continue;
6891
6892                 }
6893
6894                         #ifdef CGNAPT_DBG_PRNT
6895                         if (CGNAPT_DEBUG > 2) {
6896                                 printf("MAC found for ip 0x%x, port %d - "
6897                                 "%02x:%02x:%02x:%02x:%02x:%02x\n",
6898                                 dest_address, *outport_id,
6899                                          hw_addr.addr_bytes[0],
6900                                          hw_addr.addr_bytes[1],
6901                                          hw_addr.addr_bytes[2],
6902                                          hw_addr.addr_bytes[3],
6903                                          hw_addr.addr_bytes[4],
6904                                          hw_addr.addr_bytes[5]
6905                                         );
6906
6907                                 printf("Dest MAC before - "
6908                                 "%02x:%02x:%02x:%02x:%02x:%02x\n",
6909                                 eth_dest[0], eth_dest[1], eth_dest[2],
6910                                 eth_dest[3], eth_dest[4], eth_dest[5]);
6911                         }
6912                         #endif
6913
6914                         memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
6915
6916                         #ifdef CGNAPT_DBG_PRNT
6917                         if (CGNAPT_DEBUG > 2) {
6918                                 printf("Dest MAC after - "
6919                                 "%02x:%02x:%02x:%02x:%02x:%02x\n",
6920                                 eth_dest[0], eth_dest[1], eth_dest[2],
6921                                 eth_dest[3], eth_dest[4], eth_dest[5]);
6922                         }
6923                         #endif
6924
6925                         memcpy(eth_src,
6926                                          get_link_hw_addr(dest_if),
6927                                          sizeof(struct ether_addr));
6928                 }
6929
6930                 {
6931                         /* Egress */
6932                         *src_addr = rte_bswap32(entry->data.pub_ip);
6933
6934                         #ifdef NAT_ONLY_CONFIG_REQ
6935                         if (!nat_only_config_flag) {
6936                         #endif
6937                                 *src_port = rte_bswap16(entry->data.pub_port);
6938
6939                         #ifdef NAT_ONLY_CONFIG_REQ
6940                         }
6941                         #endif
6942
6943                         p_nat->enaptedPktCount++;
6944                 }
6945
6946                 p_nat->naptedPktCount++;
6947
6948                 #ifdef HW_CHECKSUM_REQ
6949                         if (p_nat->hw_checksum_reqd)
6950                                 hw_checksum(pkt, pkt_type);
6951                         else
6952                 #endif
6953                                 sw_checksum(pkt, pkt_type);
6954         }
6955 }
6956
6957 /**
6958  * NAPT function for IPv6 public traffic which handles 4 pkts
6959  *
6960  * @param pkts
6961  *  A pointer to array of packets mbuf
6962  * @param in_pkt_num
6963  *  Starting pkt number of pkts
6964  * @param arg
6965  *  Void pointer
6966  * @param p_nat
6967  *  A pointer to main CGNAPT structure
6968  *
6969  */
6970 void
6971 pkt4_work_cgnapt_ipv6_pub(
6972         struct rte_mbuf **pkts,
6973         uint32_t in_pkt_num,
6974         __rte_unused void *arg,
6975         struct pipeline_cgnapt *p_nat)
6976 {
6977         struct rte_mbuf *pkt;
6978         uint8_t i;
6979         uint8_t pkt_num;
6980
6981         enum PKT_TYPE pkt_type = PKT_TYPE_IPV4to6;
6982
6983         for (i = 0; i < 4; i++) {
6984                 pkt_num = in_pkt_num + i;
6985                 pkt = pkts[i];
6986
6987                 /* index into hash table entries */
6988                 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6989                 /*bitmask representing only this packet */
6990                 uint64_t pkt_mask = 1LLU << pkt_num;
6991
6992                 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
6993                 uint16_t *outport_id =
6994                         RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6995                 struct cgnapt_table_entry *entry = NULL;
6996
6997                 if (hash_table_entry < 0) {
6998
6999                         /* Drop ingress initial traffic */
7000
7001                         p_nat->invalid_packets |= pkt_mask;
7002                         p_nat->naptDroppedPktCount++;
7003                         #ifdef CGNAPT_DEBUGGING
7004                         p_nat->naptDroppedPktCount3++;
7005                         if (p_nat->kpc2++ < 5) {
7006                                 printf("in_ah Th: %d", p_nat->pipeline_num);
7007                                 print_key(p_nat->key_ptrs[pkt_num]);
7008                         }
7009                         #endif
7010
7011                         continue;
7012
7013                 } else {
7014                         /* entry found for this packet */
7015                         entry = &napt_hash_tbl_entries[hash_table_entry];
7016                 }
7017
7018                 /*  apply napt and mac changes */
7019
7020                 p_nat->entries[pkt_num] = &(entry->head);
7021                 if (entry->data.type != CGNAPT_ENTRY_IPV6) {
7022                         p_nat->invalid_packets |= pkt_mask;
7023                         p_nat->naptDroppedPktCount++;
7024                         continue;
7025                 }
7026
7027                 struct ipv4_hdr ipv4_hdr;
7028
7029                 uint16_t *src_port =
7030                         RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP4_TCP);
7031
7032                 uint8_t *eth_dest =
7033                         RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
7034                 uint8_t *eth_src =
7035                         RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
7036
7037                 if (entry->data.ttl == NAPT_ENTRY_STALE)
7038                         entry->data.ttl = NAPT_ENTRY_VALID;
7039
7040                 struct ether_addr hw_addr;
7041                 uint8_t dest_addr_ipv6[16];
7042                 uint8_t nh_ipv6[16];
7043                 uint32_t dest_if = INVALID_DESTIF;
7044                 /* Ingress */
7045                 {
7046
7047                         if (unlikely(protocol == IP_PROTOCOL_UDP
7048                                 && rte_be_to_cpu_16(*src_port) == 53)) {
7049                                 p_nat->invalid_packets |= pkt_mask;
7050                                 p_nat->naptDroppedPktCount++;
7051                                 #ifdef CGNAPT_DEBUGGING
7052                                 p_nat->naptDroppedPktCount6++;
7053                                 #endif
7054                                 continue;
7055                         }
7056
7057                         memcpy(&dest_addr_ipv6[0], &entry->data.u.prv_ipv6[0],
7058                                          16);
7059                         uint8_t nhipv6[16];
7060                         int ret;
7061                         ret = local_get_nh_ipv6(&dest_addr_ipv6[0], &dest_if,
7062                                 &nhipv6[0], p_nat);
7063                         if (!ret) {
7064                                 dest_if = get_prv_to_pub_port((uint32_t *)
7065                                         &dest_addr_ipv6[0], IP_VERSION_6);
7066
7067                                 if (dest_if == INVALID_DESTIF) {
7068                                         p_nat->invalid_packets |= pkt_mask;
7069                                         p_nat->naptDroppedPktCount++;
7070                                         #ifdef CGNAPT_DEBUGGING
7071                                         p_nat->naptDroppedPktCount6++;
7072                                         #endif
7073                                         return;
7074                                 }
7075
7076                                 do_local_nh_ipv6_cache(dest_if, p_nat);
7077                         }
7078
7079                         *outport_id = p_nat->outport_id[dest_if];
7080                 }
7081
7082                 #ifdef CGNAPT_DEBUGGING
7083                 static int static_count;
7084
7085                 if (static_count++ < 10) {
7086                         print_pkt(pkt);
7087                         my_print_entry(entry);
7088                         printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
7089                         printf("dest_add:%x\n", entry->data.u.prv_ip);
7090                         printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
7091                 }
7092                 #endif
7093
7094                 memset(nh_ipv6, 0, 16);
7095                 if (get_dest_mac_address_ipv6
7096                         (&dest_addr_ipv6[0], &dest_if,
7097                          &hw_addr, &nh_ipv6[0])) {
7098                         #ifdef CGNAPT_DBG_PRNT
7099                         if (CGNAPT_DEBUG > 2) {
7100                                 printf("MAC found for ip 0x%x, port %d - "
7101                                 "%02x:%02x:%02x:%02x:%02x:%02x\n",
7102                                 *((uint32_t *)dest_addr_ipv6 + 12),
7103                                 *outport_id,
7104                                 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
7105                                 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
7106                                 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
7107
7108                                 printf("Dest MAC before - "
7109                                 "%02x:%02x:%02x:%02x:%02x:%02x\n",
7110                                 eth_dest[0], eth_dest[1], eth_dest[2],
7111                                 eth_dest[3], eth_dest[4], eth_dest[5]);
7112                         }
7113                         #endif
7114
7115                         memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
7116
7117                         #ifdef CGNAPT_DBG_PRNT
7118                         if (CGNAPT_DEBUG > 2) {
7119                                 printf("Dest MAC after - "
7120                                 "%02x:%02x:%02x:%02x:%02x:%02x\n",
7121                                 eth_dest[0], eth_dest[1], eth_dest[2],
7122                                 eth_dest[3], eth_dest[4], eth_dest[5]);
7123                         }
7124                         #endif
7125
7126                         memcpy(eth_src,
7127                                          get_link_hw_addr(dest_if),
7128                                          sizeof(struct ether_addr));
7129                 } else {
7130                         p_nat->invalid_packets |= pkt_mask;
7131                         p_nat->naptDroppedPktCount++;
7132
7133                         #ifdef CGNAPT_DEBUGGING
7134                         p_nat->naptDroppedPktCount4++;
7135                         #endif
7136
7137                         continue;
7138                 }
7139
7140                 {
7141                         /* Ingress */
7142
7143                         convert_ipv4_to_ipv6(pkt, &ipv4_hdr);
7144
7145                         /* Ethernet MTU check */
7146                         if ((rte_pktmbuf_data_len(pkt) - 14) > 1500) {
7147                                 p_nat->invalid_packets |= pkt_mask;
7148                                 p_nat->naptDroppedPktCount++;
7149                                 continue;
7150                         }
7151                         uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
7152                                                         DST_ADR_OFST_IP4t6);
7153                         uint16_t *dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
7154                                                         DST_PRT_OFST_IP4t6);
7155
7156                         memcpy((uint8_t *) &dst_addr[0],
7157                                          &entry->data.u.prv_ipv6[0], 16);
7158
7159                         #ifdef NAT_ONLY_CONFIG_REQ
7160                         if (!nat_only_config_flag) {
7161                         #endif
7162                                 *dst_port = rte_bswap16(entry->data.prv_port);
7163
7164                         #ifdef NAT_ONLY_CONFIG_REQ
7165                         }
7166                         #endif
7167
7168                         p_nat->inaptedPktCount++;
7169                 }
7170
7171                 p_nat->naptedPktCount++;
7172
7173                 #ifdef HW_CHECKSUM_REQ
7174                         if (p_nat->hw_checksum_reqd)
7175                                 hw_checksum(pkt, pkt_type);
7176                         else
7177                 #endif
7178                                 sw_checksum(pkt, pkt_type);
7179         }
7180 }
7181
7182 /**
7183  * Input port handler for IPv6 private traffic
7184  * Starting from the packet burst it filters unwanted packets,
7185  * calculates keys, does lookup and then based on the lookup
7186  * updates NAPT table and does packet NAPT translation.
7187  *
7188  * @param rte_p
7189  *  A pointer to struct rte_pipeline
7190  * @param pkts
7191  *  A pointer to array of packets mbuf
7192  * @param n_pkts
7193  *  Number of packets in the burst
7194  * @param arg
7195  *  Void pointer
7196  *
7197  * @return
7198  *  int that is not checked by caller
7199  */
7200 static int cgnapt_in_port_ah_ipv6_prv(struct rte_pipeline *rte_p,
7201                                                 struct rte_mbuf **pkts,
7202                                                 uint32_t n_pkts, void *arg)
7203 {
7204         uint32_t i, j;
7205         struct pipeline_cgnapt_in_port_h_arg *ap = arg;
7206         struct pipeline_cgnapt *p_nat = ap->p;
7207
7208         p_nat->pkt_burst_cnt = 0;       /* for dynamic napt */
7209         p_nat->valid_packets = rte_p->pkts_mask;        /*n_pkts; */
7210         p_nat->invalid_packets = 0;
7211
7212         #ifdef CGNAPT_DBG_PRNT
7213         if (CGNAPT_DEBUG > 1)
7214                 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
7215         #endif
7216
7217         /* prefetching for mbufs should be done here */
7218         for (j = 0; j < n_pkts; j++)
7219                 rte_prefetch0(pkts[j]);
7220
7221         for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7222                 pkt4_work_cgnapt_key_ipv6_prv(&pkts[i], i, arg, p_nat);
7223
7224         for (; i < n_pkts; i++)
7225                 pkt_work_cgnapt_key_ipv6_prv(pkts[i], i, arg, p_nat);
7226
7227         p_nat->valid_packets &= ~(p_nat->invalid_packets);
7228
7229         if (unlikely(p_nat->valid_packets == 0)) {
7230                 /* no suitable packet for lookup */
7231                 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7232                 return p_nat->valid_packets;
7233         }
7234
7235         /* lookup entries in the common napt table */
7236
7237         int lookup_result = rte_hash_lookup_bulk(
7238                                 napt_common_table,
7239                                 (const void **) &p_nat->key_ptrs,
7240                                 /* should be minus num invalid pkts */
7241                                 n_pkts,
7242                                 /*new pipeline data member */
7243                                 &p_nat->lkup_indx[0]);
7244
7245         if (unlikely(lookup_result < 0)) {
7246                 /* unknown error, just discard all packets */
7247                 printf("Unexpected hash lookup error %d, "
7248                         "discarding all packets",
7249                          lookup_result);
7250                 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
7251                 return 0;
7252         }
7253
7254         /* Now call second stage of pipeline to one by one
7255         * check the result of our bulk lookup
7256         */
7257
7258         /* prefetching for table entries should be done here */
7259         for (j = 0; j < n_pkts; j++) {
7260                 if (p_nat->lkup_indx[j] >= 0)
7261                         rte_prefetch0(&napt_hash_tbl_entries
7262                                                 [p_nat->lkup_indx[j]]);
7263         }
7264
7265         for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7266                 pkt4_work_cgnapt_ipv6_prv(&pkts[i], i, arg, p_nat);
7267
7268         for (; i < n_pkts; i++)
7269                 pkt_work_cgnapt_ipv6_prv(pkts[i], i, arg, p_nat);
7270
7271         if (p_nat->invalid_packets) {
7272                 /* get rid of invalid packets */
7273                 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7274
7275                 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7276
7277                 #ifdef CGNAPT_DBG_PRNT
7278                 if (CGNAPT_DEBUG > 1) {
7279                         printf("valid_packets:0x%jx\n", p_nat->valid_packets);
7280                         printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
7281                         printf("invalid_packets:0x%jx\n",
7282                                          p_nat->invalid_packets);
7283                         printf("rte_invalid_packets :0x%jx\n",
7284                                          rte_p->pkts_drop_mask);
7285                         printf("Total pkts dropped :0x%jx\n",
7286                                          rte_p->n_pkts_ah_drop);
7287                 }
7288                 #endif
7289         }
7290
7291         return p_nat->valid_packets;
7292 }
7293
7294
7295 /**
7296  * Input port handler for IPv6 public traffic
7297  * Starting from the packet burst it filters unwanted packets,
7298  * calculates keys, does lookup and then based on the lookup
7299  * updates NAPT table and does packet NAPT translation.
7300  *
7301  * @param rte_p
7302  *  A pointer to struct rte_pipeline
7303  * @param pkts
7304  *  A pointer to array of packets mbuf
7305  * @param n_pkts
7306  *  Number of packets in the burst
7307  * @param arg
7308  *  Void pointer
7309  *
7310  * @return
7311  *  int that is not checked by caller
7312  */
7313 static int cgnapt_in_port_ah_ipv6_pub(struct rte_pipeline *rte_p,
7314                                                 struct rte_mbuf **pkts,
7315                                                 uint32_t n_pkts, void *arg)
7316 {
7317         uint32_t i, j;
7318         struct pipeline_cgnapt_in_port_h_arg *ap = arg;
7319         struct pipeline_cgnapt *p_nat = ap->p;
7320
7321         p_nat->pkt_burst_cnt = 0;       /* for dynamic napt */
7322         p_nat->valid_packets = rte_p->pkts_mask;        /*n_pkts; */
7323         p_nat->invalid_packets = 0;
7324
7325         #ifdef CGNAPT_DBG_PRNT
7326         if (CGNAPT_DEBUG > 1)
7327                 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
7328         #endif
7329
7330         /* prefetching for mbufs should be done here */
7331         for (j = 0; j < n_pkts; j++)
7332                 rte_prefetch0(pkts[j]);
7333
7334         for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7335                 pkt4_work_cgnapt_key_ipv6_pub(&pkts[i], i, arg, p_nat);
7336
7337         for (; i < n_pkts; i++)
7338                 pkt_work_cgnapt_key_ipv6_pub(pkts[i], i, arg, p_nat);
7339
7340         p_nat->valid_packets &= ~(p_nat->invalid_packets);
7341
7342         if (unlikely(p_nat->valid_packets == 0)) {
7343                 /* no suitable packet for lookup */
7344                 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7345                 return p_nat->valid_packets;
7346         }
7347
7348         /* lookup entries in the common napt table */
7349
7350         int lookup_result = rte_hash_lookup_bulk(
7351                                 napt_common_table,
7352                                 (const void **) &p_nat->key_ptrs,
7353                                 /* should be minus num invalid pkts */
7354                                  n_pkts,
7355                                 /*new pipeline data member */
7356                                  &p_nat->lkup_indx[0]);
7357
7358         if (unlikely(lookup_result < 0)) {
7359                 /* unknown error, just discard all packets */
7360                 printf("Unexpected hash lookup error %d, "
7361                         "discarding all packets",
7362                          lookup_result);
7363                 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
7364                 return 0;
7365         }
7366
7367         /* Now call second stage of pipeline to one by one
7368         * check the result of our bulk lookup
7369         */
7370
7371         /* prefetching for table entries should be done here */
7372         for (j = 0; j < n_pkts; j++) {
7373                 if (p_nat->lkup_indx[j] >= 0)
7374                         rte_prefetch0(&napt_hash_tbl_entries
7375                                                 [p_nat->lkup_indx[j]]);
7376         }
7377
7378         for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7379                 pkt4_work_cgnapt_ipv6_pub(&pkts[i], i, arg, p_nat);
7380
7381         for (; i < n_pkts; i++)
7382                 pkt_work_cgnapt_ipv6_pub(pkts[i], i, arg, p_nat);
7383
7384         if (p_nat->invalid_packets) {
7385                 /* get rid of invalid packets */
7386                 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7387
7388                 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7389
7390                 #ifdef CGNAPT_DBG_PRNT
7391                 if (CGNAPT_DEBUG > 1) {
7392                         printf("valid_packets:0x%jx\n", p_nat->valid_packets);
7393                         printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
7394                         printf("invalid_packets:0x%jx\n",
7395                                          p_nat->invalid_packets);
7396                         printf("rte_invalid_packets :0x%jx\n",
7397                                          rte_p->pkts_drop_mask);
7398                         printf("Total pkts dropped :0x%jx\n",
7399                                          rte_p->n_pkts_ah_drop);
7400                 }
7401                 #endif
7402         }
7403
7404         return p_nat->valid_packets;
7405 }
7406
7407 /**
7408  * Function to send ICMP dest unreachable msg
7409  *
7410  */
7411 void send_icmp_dest_unreachable_msg(void)
7412 {
7413
7414         struct ether_hdr *eth_h;
7415         struct ipv4_hdr *ip_h;
7416         struct icmp_hdr *icmp_h;
7417         struct rte_mbuf *icmp_pkt = cgnapt_icmp_pkt;
7418
7419         if (icmp_pkt == NULL) {
7420                 if (ARPICMP_DEBUG)
7421                         printf("Error allocating icmp_pkt rte_mbuf\n");
7422                 return;
7423         }
7424         uint16_t port_id;
7425         port_id = icmp_pkt->port;
7426
7427         struct app_link_params *link;
7428         link = &mylink[port_id];
7429         eth_h = rte_pktmbuf_mtod(icmp_pkt, struct ether_hdr *);
7430         ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
7431         icmp_h = (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
7432
7433         struct ether_addr gw_addr;
7434         struct ether_addr dst_addr;
7435         ether_addr_copy(&eth_h->s_addr, &dst_addr);
7436         rte_eth_macaddr_get(port_id, &gw_addr);
7437         ether_addr_copy(&gw_addr, &eth_h->s_addr);
7438         ether_addr_copy(&dst_addr, &eth_h->d_addr);
7439
7440         eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
7441         ip_h->version_ihl = IP_VHL_DEF;
7442         ip_h->type_of_service = 0;
7443         ip_h->total_length = rte_cpu_to_be_16(sizeof(struct ipv4_hdr) +
7444                                 sizeof(struct icmp_hdr));
7445         ip_h->packet_id = 0xaabb;
7446         ip_h->fragment_offset = 0x0000;
7447         ip_h->time_to_live = 64;
7448         ip_h->next_proto_id = 1;
7449
7450         uint32_t *src_addr;
7451         uint32_t src_addr_offset =
7452                 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_SRC_ADR_OFST;
7453         src_addr =
7454                 RTE_MBUF_METADATA_UINT32_PTR(cgnapt_icmp_pkt, src_addr_offset);
7455
7456         ip_h->dst_addr = *src_addr;
7457         ip_h->src_addr = rte_bswap32(link->ip);
7458
7459         ip_h->dst_addr = *src_addr;
7460         ip_h->src_addr = rte_bswap32(link->ip);
7461
7462         ip_h->hdr_checksum = 0;
7463         ip_h->hdr_checksum = rte_ipv4_cksum(ip_h);
7464         icmp_h->icmp_type = 3;  /* Destination Unreachable */
7465         icmp_h->icmp_code = 13; /* Communication administratively prohibited */
7466
7467         icmp_h->icmp_cksum = ~rte_raw_cksum(icmp_h, sizeof(struct icmp_hdr));
7468
7469         icmp_pkt->pkt_len = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
7470                 sizeof(struct icmp_hdr);
7471         icmp_pkt->data_len = icmp_pkt->pkt_len;
7472         if (ARPICMP_DEBUG) {
7473                 printf("Sending ICMP error message - "
7474                         "Destination Unreachable\n");
7475         }
7476         rte_pipeline_port_out_packet_insert(myP, port_id, icmp_pkt);
7477 }
7478
7479 /**
7480  * Function to add a dynamic NAPT entry pair
7481  *
7482  * @param p
7483  *  A pointer to struct pipeline
7484  * @param key
7485  *  A pointer to struct pipeline_cgnapt_entry_key
7486  * @param time_out
7487  *  expairy time of an dynamic or PCP req entry
7488  * @param src_addr
7489  *  uint8_t pointer of source address
7490  *
7491  * @return
7492  *  A pointer to struct cgnapt_table_entry for added entry
7493  */
7494
7495 struct cgnapt_table_entry *add_dynamic_cgnapt_entry(
7496         struct pipeline *p,
7497         struct pipeline_cgnapt_entry_key *key,
7498         uint32_t timeout,
7499         uint8_t pkt_type,
7500         uint8_t *src_addr,
7501         uint8_t *err)
7502 {
7503         int port_num = 0;
7504         void *entry_ptr, *ret_ptr;
7505         int ret = 0, i;
7506
7507         struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
7508
7509         #ifdef CGNAPT_DBG_PRNT
7510         if (CGNAPT_DEBUG >= 1) {
7511                 printf("Th%d add_dynamic_cgnapt_entry key detail Entry:"
7512                 "0x%x, %d, %d\n", p_nat->pipeline_num, key->ip, key->port,
7513                 key->pid);
7514         }
7515         #endif
7516
7517         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX && i < p_nat->pkt_burst_cnt;
7518                  i++) {
7519                 if (p_nat->cgnapt_dyn_ent_table[i].ip == key->ip
7520                         && p_nat->cgnapt_dyn_ent_table[i].port == key->port
7521                         && p_nat->cgnapt_dyn_ent_table[i].pid == key->pid) {
7522
7523                         #ifdef CGNAPT_DBG_PRNT
7524                         if (CGNAPT_DEBUG > 1)
7525                                 printf("add_dynamic_cgnapt_entry:pkt_burst "
7526                                 "array key matched!!!\n");
7527                         #endif
7528
7529                         return &napt_hash_tbl_entries
7530                                 [p_nat->cgnapt_dyn_ent_index[i]];
7531                 }
7532         }
7533
7534         #ifdef NAT_ONLY_CONFIG_REQ
7535         if (!nat_only_config_flag) {
7536         #endif
7537
7538         ret = increment_max_port_counter(key->ip, key->pid, p_nat);
7539         if (ret == MAX_PORT_INC_ERROR) {
7540
7541                 #ifdef CGNAPT_DEBUGGING
7542                 p_nat->missedpktcount5++;
7543                 #endif
7544
7545                 #ifdef CGNAPT_DBG_PRNT
7546                 if (CGNAPT_DEBUG > 1)
7547                         printf("add_dynamic_cgnapt_entry:"
7548                         "increment_max_port_counter-1 failed\n");
7549                 #endif
7550
7551                 *err = 1;
7552                 return NULL;
7553         }
7554
7555         if (ret == MAX_PORT_INC_REACHED) {
7556
7557                 #ifdef CGNAPT_DEBUGGING
7558                 p_nat->missedpktcount6++;
7559                 #endif
7560
7561                 #ifdef CGNAPT_DBG_PRNT
7562                 if (CGNAPT_DEBUG > 1)
7563                         printf("add_dynamic_cgnapt_entry:"
7564                         "increment_max_port_counter-2 failed\n");
7565                 #endif
7566
7567                 *err = 1;
7568                 return NULL;
7569         }
7570
7571         #ifdef NAT_ONLY_CONFIG_REQ
7572         }
7573         #endif
7574
7575         uint32_t public_ip;
7576         port_num = get_free_iport(p_nat, &public_ip);
7577
7578         if (port_num == -1) {
7579
7580                 #ifdef CGNAPT_DBG_PRNT
7581                 if (CGNAPT_DEBUG > 2) {
7582                         printf("add_dynamic_cgnapt_entry: %d\n", port_num);
7583                         printf("add_dynamic_cgnapt_entry key detail:0x%x, "
7584                         "%d, %d\n", key->ip, key->port, key->pid);
7585                 }
7586                 #endif
7587
7588                 #ifdef CGNAPT_DEBUGGING
7589                 p_nat->missedpktcount7++;
7590                 #endif
7591
7592                 *err = 1;
7593                 return NULL;
7594         }
7595
7596         #ifdef NAT_ONLY_CONFIG_REQ
7597         if (!nat_only_config_flag) {
7598         #endif
7599
7600         if (ret == 2) { //MPPC_NEW_ENTRY
7601
7602                 /* check for max_clients_per_ip */
7603                 if (rte_atomic16_read
7604                         (&all_public_ip
7605                         [rte_jhash(&public_ip, 4, 0) %
7606                         CGNAPT_MAX_PUB_IP].count) ==
7607                         p_nat->max_clients_per_ip) {
7608
7609                 /* For now just bail out
7610                 * In future we can think about
7611                 * retrying getting a new iport
7612                 */
7613
7614                 release_iport(port_num, public_ip, p_nat);
7615
7616                 #ifdef CGNAPT_DEBUGGING
7617                                 p_nat->missedpktcount10++;
7618                 #endif
7619                                 *err = 1;
7620                                 return NULL;
7621                         }
7622
7623                         rte_atomic16_inc(&all_public_ip
7624                                          [rte_jhash(&public_ip, 4, 0) %
7625                                                 CGNAPT_MAX_PUB_IP].count);
7626
7627                 #ifdef CGNAPT_DBG_PRNT
7628                         if ((rte_jhash(&public_ip, 4, 0) %
7629                                 CGNAPT_MAX_PUB_IP) == 8)
7630                                 printf("pub ip:%x coutn:%d\n", public_ip,
7631                                 rte_atomic16_read(&all_public_ip
7632                                 [rte_jhash(&public_ip, 4, 0) %
7633                                 CGNAPT_MAX_PUB_IP].count));
7634                 #endif
7635
7636                 }
7637                 #ifdef NAT_ONLY_CONFIG_REQ
7638                 }
7639                 #endif
7640
7641                 #ifdef CGNAPT_DBG_PRNT
7642                         if (CGNAPT_DEBUG > 0) {
7643                                 printf("add_dynamic_cgnapt_entry: %d\n",
7644                                         port_num);
7645                                 printf("add_dynamic_cgnapt_entry key detail: "
7646                                 "0x%x, %d, %d\n", key->ip, key->port, key->pid);
7647                 }
7648                 #endif
7649
7650                 struct cgnapt_table_entry entry = {
7651                         .head = {
7652                          .action = RTE_PIPELINE_ACTION_PORT,
7653                         /* made it configurable below */
7654                          {.port_id = p->port_out_id[0]},
7655                          },
7656
7657                         .data = {
7658                                 .prv_port = key->port,
7659                                 .pub_ip = public_ip,
7660                                 .pub_port = port_num,
7661                                 .prv_phy_port = key->pid,
7662                                 .pub_phy_port = get_pub_to_prv_port(
7663                                                 &public_ip,
7664                                                 IP_VERSION_4),
7665                                 .ttl = 0,
7666                                 /* if(timeout == -1) : static entry
7667                                 *  if(timeout == 0 ) : dynamic entry
7668                                 *  if(timeout >  0 ) : PCP requested entry
7669                                 */
7670                                 .timeout = timeout > 0 ? timeout : 0,
7671                                 #ifdef PCP_ENABLE
7672                                 .timer = NULL,
7673                                 #endif
7674                         }
7675                 };
7676
7677         #ifdef NAT_ONLY_CONFIG_REQ
7678                 if (nat_only_config_flag) {
7679                         entry.data.prv_port = 0xffff;
7680                         entry.data.pub_port = 0xffff;
7681                 }
7682         #endif
7683
7684         if (pkt_type == CGNAPT_ENTRY_IPV6) {
7685                 entry.data.type = CGNAPT_ENTRY_IPV6;
7686                 memcpy(&entry.data.u.prv_ipv6[0], src_addr, 16);
7687         } else {
7688                 entry.data.u.prv_ip = key->ip;
7689                 entry.data.type = CGNAPT_ENTRY_IPV4;
7690         }
7691
7692         //entry.head.port_id = CGNAPT_PUB_PORT_ID; /* outgoing port info */
7693         entry.head.port_id = entry.data.pub_phy_port; /* outgoing port info */
7694
7695         struct pipeline_cgnapt_entry_key second_key;
7696         /* Need to add a second ingress entry */
7697         second_key.ip = public_ip;
7698         second_key.port = port_num;
7699         second_key.pid = 0xffff;
7700
7701         #ifdef NAT_ONLY_CONFIG_REQ
7702         if (nat_only_config_flag)
7703                 second_key.port = 0xffff;
7704         #endif
7705
7706         #ifdef CGNAPT_DBG_PRNT
7707         if (CGNAPT_DEBUG > 2)
7708                 printf("add_dynamic_cgnapt_entry second key detail:"
7709                 "0x%x, %d, %d\n", second_key.ip, second_key.port,
7710                 second_key.pid);
7711         #endif
7712
7713         int32_t position = rte_hash_add_key(napt_common_table, (void *)key);
7714
7715         if (position < 0) {
7716                 #ifdef CGNAPT_DEBUGGING
7717                 p_nat->missedpktcount8++;
7718                 #endif
7719
7720                 printf("CG-NAPT entry add failed ...returning "
7721                 "without adding ... %d\n", position);
7722                 *err = 1;
7723                 return NULL;
7724         }
7725
7726         #ifdef CGNAPT_DBG_PRNT
7727         if (CGNAPT_DEBUG) {
7728                 printf("add_dynamic_cgnapt_entry\n");
7729                 print_key(key);
7730                 print_cgnapt_entry(&entry);
7731         }
7732         #endif
7733
7734         memcpy(&napt_hash_tbl_entries[position], &entry,
7735                          sizeof(struct cgnapt_table_entry));
7736
7737         /* this pointer is returned to pkt miss function */
7738         ret_ptr = &napt_hash_tbl_entries[position];
7739
7740         p_nat->n_cgnapt_entry_added++;
7741         p_nat->dynCgnaptCount++;
7742
7743         /* Now modify the forward port for reverse entry */
7744
7745         /* outgoing port info */
7746         //entry.head.port_id = CGNAPT_PRV_PORT_ID;
7747         /* outgoing port info */
7748         entry.head.port_id = entry.data.prv_phy_port;
7749
7750         int32_t position2 = rte_hash_add_key(napt_common_table, &second_key);
7751
7752         if (position2 < 0) {
7753                 #ifdef CGNAPT_DEBUGGING
7754                 p_nat->missedpktcount9++;
7755                 #endif
7756                 printf("CG-NAPT entry reverse bulk add failed ..."
7757                 "returning with fwd add ...%d\n",
7758                          position2);
7759                 *err = 1;
7760                 return NULL;
7761         }
7762
7763         memcpy(&napt_hash_tbl_entries[position2], &entry,
7764                          sizeof(struct cgnapt_table_entry));
7765
7766         entry_ptr = &napt_hash_tbl_entries[position2];
7767
7768         timer_thread_enqueue(key, &second_key, ret_ptr,
7769                 entry_ptr, (struct pipeline *)p_nat);
7770
7771         p_nat->n_cgnapt_entry_added++;
7772         p_nat->dynCgnaptCount++;
7773
7774         if (p_nat->pkt_burst_cnt < RTE_PORT_IN_BURST_SIZE_MAX) {
7775                 memcpy(&p_nat->cgnapt_dyn_ent_table[p_nat->pkt_burst_cnt], key,
7776                                  sizeof(struct pipeline_cgnapt_entry_key));
7777                 p_nat->cgnapt_dyn_ent_index[p_nat->pkt_burst_cnt] = position;
7778                 p_nat->pkt_burst_cnt++;
7779         }
7780         return ret_ptr;
7781 }
7782
7783 int pkt_miss_cgnapt_count;
7784 /**
7785  * Function handle a missed NAPT entry lookup
7786  * Will attempt to add a dynamic entry pair.
7787  *
7788  * @param p
7789  *  A pointer to struct pipeline
7790  * @param key
7791  *  A pointer to struct pipeline_cgnapt_entry_key
7792  * @param pkt
7793  *  A pointer to pkt struct rte_mbuf
7794  * @param pkt_mask
7795  *  uint64_t pointer to pkt mask
7796  * @param table_entry
7797  *  A pointer to struct rte_pipeline_table_entry to be created and returned
7798  * @param pkt_num
7799  *  number of this pkt in current burst
7800  *
7801  * @return
7802  *  A uint64_t mask for drop packets
7803  */
7804 uint64_t
7805 pkt_miss_cgnapt(struct pipeline_cgnapt_entry_key *key,
7806                 struct rte_mbuf *pkt,
7807                 struct rte_pipeline_table_entry **table_entry,
7808                 __rte_unused uint64_t *pkts_mask,
7809                 uint32_t pkt_num, void *arg)
7810 {
7811
7812         #ifdef CGNAPT_DBG_PRNT
7813         if (CGNAPT_DEBUG > 0)
7814                 printf("\n pkt_miss_cgnapt\n");
7815         #endif
7816         /*  In egress case
7817         *   get src address
7818         *   see if get_port passes for this src address
7819         *   if passed add a new egress entry and a
7820         *  corresponding new ingress entry
7821         *   return the fwd entry to calling function using input pointer
7822         *   else if get_port fails drop packet
7823         */
7824
7825         struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)arg;
7826
7827         uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
7828         uint32_t src_addr_offset_ipv6 =
7829                 MBUF_HDR_ROOM + ETH_HDR_SIZE + IPV6_HDR_SRC_ADR_OFST;
7830         uint16_t phy_port = pkt->port;
7831
7832         uint16_t *eth_proto =
7833                 RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
7834
7835         uint8_t *src_addr = NULL;
7836         uint8_t src_addr_ipv6[16];
7837         uint8_t pkt_type = CGNAPT_ENTRY_IPV4;
7838         /* To drop the packet */
7839         uint64_t drop_mask = 0;
7840
7841         if (p_nat->is_static_cgnapt) {
7842                 drop_mask |= 1LLU << pkt_num;
7843                 p_nat->missedPktCount++;
7844
7845                 #ifdef CGNAPT_DEBUGGING
7846                 p_nat->missedpktcount1++;
7847                 #endif
7848                 return drop_mask;
7849         }
7850
7851         if (rte_be_to_cpu_16(*eth_proto) == ETHER_TYPE_IPv6) {
7852                 src_addr =
7853                         RTE_MBUF_METADATA_UINT8_PTR(pkt, src_addr_offset_ipv6);
7854                 pkt_type = CGNAPT_ENTRY_IPV6;
7855                 memcpy(src_addr_ipv6, src_addr, 16);
7856         }
7857
7858         uint8_t err = 0;
7859
7860         /* some validation first */
7861         if (is_phy_port_privte(phy_port)) {
7862                 /* dynamic NAPT entry creation */
7863                 *table_entry = (struct rte_pipeline_table_entry *)
7864                         add_dynamic_cgnapt_entry(
7865                                 (struct pipeline *)&p_nat->p,
7866                                 key,
7867                                 DYNAMIC_CGNAPT_TIMEOUT,
7868                                 pkt_type,
7869                                 src_addr_ipv6, &err);
7870
7871                 if (!(*table_entry)) {
7872                         if (err) {
7873                                 drop_mask |= 1LLU << pkt_num;
7874                                 p_nat->missedPktCount++;
7875
7876                                 #ifdef CGNAPT_DEBUGGING
7877                                 p_nat->missedpktcount2++;
7878                                 #endif
7879
7880                                 #ifdef CGNAPT_DBG_PRNT
7881                                 if (CGNAPT_DEBUG > 1)
7882                                         printf("Add Dynamic NAT entry failed "
7883                                         "in pkt!!!\n");
7884                                 #endif
7885                 } else {
7886                                 #ifdef CGNAPT_DEBUGGING
7887                                 p_nat->missedpktcount11++;
7888                                 #endif
7889                 }
7890
7891                 }
7892
7893         } else if (!is_phy_port_privte(phy_port)) {
7894
7895                 #ifdef CGNAPT_DBG_PRNT
7896                 if (CGNAPT_DEBUG >= 2) {
7897                         printf("Initial Ingress entry creation NOT ALLOWED "
7898                         "%d\n", phy_port);
7899                 }
7900                 #endif
7901
7902                 drop_mask |= 1LLU << pkt_num;
7903                 p_nat->missedPktCount++;
7904
7905                 #ifdef CGNAPT_DEBUGGING
7906                 p_nat->missedpktcount3++;
7907                 #endif
7908         } else {
7909
7910                 #ifdef CGNAPT_DBG_PRNT
7911                 if (CGNAPT_DEBUG > 1)
7912                         printf("NOT a PRIVATE or PUBLIC port!!!!!\n");
7913                 #endif
7914
7915                 drop_mask |= 1LLU << pkt_num;
7916                 p_nat->missedPktCount++;
7917
7918                 #ifdef CGNAPT_DEBUGGING
7919                 p_nat->missedpktcount4++;
7920                 #endif
7921         }
7922
7923         #ifdef CGNAPT_DBG_PRNT
7924         if (CGNAPT_DEBUG > 5)
7925                 print_pkt(pkt);
7926         #endif
7927
7928         return drop_mask;
7929 }
7930
7931 int numprints;
7932
7933 /**
7934  * Function to print the contents of a packet
7935  *
7936  * @param pkt
7937  *  A pointer to pkt struct rte_mbuf
7938  */
7939 void print_pkt(struct rte_mbuf *pkt)
7940 {
7941         int i = 0, j = 0;
7942
7943         printf("\nPacket Contents:\n");
7944
7945         uint8_t *rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
7946
7947         for (i = 0; i < 20; i++) {
7948                 for (j = 0; j < 20; j++)
7949                         printf("%02x ", rd[(20 * i) + j]);
7950
7951                 printf("\n");
7952         }
7953 }
7954
7955 rte_table_hash_op_hash cgnapt_hash_func[] = {
7956         hash_default_key8,
7957         hash_default_key16,
7958         hash_default_key24,
7959         hash_default_key32,
7960         hash_default_key40,
7961         hash_default_key48,
7962         hash_default_key56,
7963         hash_default_key64
7964 };
7965
7966 /**
7967  * Function to parse incoming pipeline arguments
7968  * Called during pipeline initialization
7969  *
7970  * @param p
7971  *  A pointer to struct pipeline_cgnapt
7972  * @param params
7973  *  A pointer to struct pipeline_params
7974  *
7975  * @return
7976  *  0 if success, negative if failure
7977  */
7978 static int
7979 pipeline_cgnapt_parse_args(struct pipeline_cgnapt *p,
7980                                  struct pipeline_params *params)
7981 {
7982         uint32_t n_flows_present = 0;
7983         uint32_t key_offset_present = 0;
7984         uint32_t key_size_present = 0;
7985         uint32_t hash_offset_present = 0;
7986         uint32_t n_entries_present = 0;
7987         uint32_t max_port_present = 0;
7988         uint32_t max_client_present = 0;
7989         uint32_t public_ip_range_present = 0;
7990         uint32_t public_ip_port_range_present = 0;
7991         uint32_t i;
7992         uint8_t public_ip_count = 0;
7993         uint8_t public_ip_range_count = 0;
7994         uint8_t dest_if_offset_present = 0;
7995         uint8_t cgnapt_meta_offset_present = 0;
7996         uint8_t prv_que_handler_present = 0;
7997         uint8_t n_prv_in_port = 0;
7998
7999         if (CGNAPT_DEBUG > 2) {
8000                 printf("CGNAPT pipeline_cgnapt_parse_args params->n_args: %d\n",
8001                                  params->n_args);
8002         }
8003         for (i = 0; i < params->n_args; i++) {
8004                 char *arg_name = params->args_name[i];
8005                 char *arg_value = params->args_value[i];
8006
8007                 if (CGNAPT_DEBUG > 2) {
8008                         printf("CGNAPT args[%d]: %s %d, %s\n", i, arg_name,
8009                                          atoi(arg_value), arg_value);
8010                 }
8011                 if (strcmp(arg_name, "prv_que_handler") == 0) {
8012
8013                         if (prv_que_handler_present) {
8014                                 printf("Duplicate pktq_in_prv ..\n\n");
8015                                 return -1;
8016                         }
8017                         prv_que_handler_present = 1;
8018                         n_prv_in_port = 0;
8019
8020                         char *token;
8021                         int rxport = 0;
8022                         /* get the first token */
8023                         token = strtok(arg_value, "(");
8024                         token = strtok(token, ")");
8025                         token = strtok(token, ",");
8026                         printf("***** prv_que_handler *****\n");
8027
8028                         if (token == NULL) {
8029                                 printf("string is null\n");
8030                                 printf("invalid prv_que_handler value/n");
8031                                 return -1;
8032                         }
8033                         printf("string is :%s\n", token);
8034
8035                         /* walk through other tokens */
8036                         while (token != NULL) {
8037                                 printf(" %s\n", token);
8038                                 rxport =  atoi(token);
8039                                 cgnapt_prv_que_port_index[n_prv_in_port++] =
8040                                                         rxport;
8041                                 if (rxport < PIPELINE_MAX_PORT_IN)
8042                                 cgnapt_in_port_egress_prv[rxport] = 1;
8043                                 token = strtok(NULL, ",");
8044                         }
8045
8046                         if (n_prv_in_port == 0) {
8047                                 printf("VNF common parse err - "
8048                                 "no prv RX phy port\n");
8049                                 return -1;
8050                         }
8051                 continue;
8052                 }
8053
8054                 if (strcmp(arg_name, "cgnapt_meta_offset") == 0) {
8055                         if (cgnapt_meta_offset_present) {
8056                                 printf("CG-NAPT parse error:");
8057                                 printf("cgnapt_meta_offset initizlized "
8058                                 "mulitple times\n");
8059                                 return -1;
8060                         }
8061                         cgnapt_meta_offset_present = 1;
8062                         int temp;
8063                         temp = atoi(arg_value);
8064
8065                         if (temp > 256) {
8066                                 printf("cgnapt_meta_offset is invalid :");
8067                                 printf("Not be more than metadata size\n");
8068                                 return -1;
8069                         }
8070                         cgnapt_meta_offset = (uint16_t) temp;
8071                 }
8072                 if (strcmp(arg_name, "vnf_set") == 0)
8073                         vnf_set_count++;
8074
8075                 if (strcmp(arg_name, "public_ip_range") == 0) {
8076                         public_ip_range_present = 1;
8077                         if (public_ip_port_range_present) {
8078                                 printf("CG-NAPT parse error:");
8079                                 printf("public_ip_range with "
8080                                 "public_ip_port_range_present\n");
8081                                 return -1;
8082                         }
8083
8084                         p->pub_ip_range = rte_realloc(p->pub_ip_range,
8085                                                                 sizeof(struct
8086                                                                  pub_ip_range),
8087                                                                 RTE_CACHE_LINE_SIZE);
8088
8089                         if (!p->pub_ip_range) {
8090                                 printf("Memory allocation failed for "
8091                                 "pub_ip_range\n");
8092                                 return -1;
8093                         }
8094
8095                         uint32_t sip = 0, eip = 0;
8096
8097                         if (sscanf(arg_value, "(%x,%x)", &sip, &eip) != 2) {
8098                                 printf("public_ip_range is invalid\n");
8099                                 return -1;
8100                         }
8101
8102                         if (sip <= 0 || eip <= 0 || sip >= eip) {
8103                                 printf("public_ip_range is invalid %x-%x\n",
8104                                                  sip, eip);
8105                                 return -1;
8106                         }
8107
8108                         printf("public_ip_range: %d-%d\n",
8109                                          p->pub_ip_range[public_ip_range_count].
8110                                         start_ip = sip,
8111                                          p->pub_ip_range[public_ip_range_count].
8112                                         end_ip = eip);
8113
8114                         p->pub_ip_range_count = ++public_ip_range_count;
8115                         continue;
8116                 }
8117
8118                 if (strcmp(arg_name, "public_ip_port_range") == 0) {
8119                         public_ip_port_range_present = 1;
8120                         if (nat_only_config_flag || public_ip_range_present) {
8121
8122                         printf("CG-NAPT parse error:");
8123                         printf("nat_only_config_flag OR ");
8124                         printf("public_ip_range_present with "
8125                         "public_ip_port_range_present\n");
8126                                 return -1;
8127                         }
8128
8129                         p->pub_ip_port_set = rte_realloc(
8130                                                 p->pub_ip_port_set,
8131                                                 sizeof(struct pub_ip_port_set),
8132                                                 RTE_CACHE_LINE_SIZE);
8133
8134                         if (!p->pub_ip_port_set) {
8135                                 printf("Memory allocation failed for "
8136                                 "public IP\n");
8137                                 return -1;
8138                         }
8139
8140                         uint32_t ip = 0;
8141                         int sp = 0, ep = 0;
8142
8143                         if (sscanf(arg_value, "%x:(%d,%d)",
8144                                         &ip, &sp, &ep) != 3) {
8145                                 printf("Public IP or Port-range is invalid\n");
8146                                 return -1;
8147                         }
8148
8149                         if (ip <= 0 || sp <= 0 || ep <= 0 || sp > ep) {
8150                                 printf("Public IP or Port-range is invalid "
8151                                 "%x:%d-%d\n", ip, sp, ep);
8152                                 return -1;
8153                         }
8154
8155                         printf("public_ip: 0x%x Range:%d-%d\n",
8156                         p->pub_ip_port_set[public_ip_count].ip = ip,
8157                         p->pub_ip_port_set[public_ip_count].start_port = sp,
8158                         p->pub_ip_port_set[public_ip_count].end_port = ep);
8159
8160                         napt_port_alloc_elem_count += (ep - sp + 1);
8161                         printf("parse - napt_port_alloc_elem_count :%d\n",
8162                                 napt_port_alloc_elem_count);
8163
8164                 /* Store all public IPs of all CGNAPT threads
8165                 * in the global variable
8166                 */
8167                  /* to revisit indexing */
8168                         all_public_ip[rte_jhash(&ip, 4, 0) %
8169                                 CGNAPT_MAX_PUB_IP].ip = ip;
8170                         p->pub_ip_count = ++public_ip_count;
8171                         printf("public_ip_count:%d hash:%d\n", public_ip_count,
8172                                          rte_jhash(&ip, 4, 0) % CGNAPT_MAX_PUB_IP);
8173                         continue;
8174                 }
8175
8176                 /* hw_checksum_reqd */
8177                 if (strcmp(arg_name, "hw_checksum_reqd") == 0) {
8178                         int temp;
8179                         temp = atoi(arg_value);
8180                         if ((temp != 0) && (temp != 1)) {
8181                                 printf("hw_checksum_reqd is invalid\n");
8182                                 return -1;
8183                         }
8184                         p->hw_checksum_reqd = temp;
8185                         continue;
8186                 }
8187
8188                 /* nat_only_config_flag */
8189                 if (strcmp(arg_name, "nat_only_config_flag") == 0) {
8190                         nat_only_config_flag = 1;
8191                         if (public_ip_port_range_present) {
8192
8193                         printf("CG-NAPT parse error:");
8194                         printf("nat_only_config_flag with "
8195                         "public_ip_port_range_present\n");
8196                                 return -1;
8197                         }
8198                         continue;
8199                 }
8200
8201                 /*  max_port_per_client */
8202                 if (strcmp(arg_name, "max_port_per_client") == 0) {
8203                         if (max_port_present) {
8204                                 printf("CG-NAPT Parse Error: "
8205                                 "duplicate max_port_per_client\n");
8206                                 return -1;
8207                         }
8208                         max_port_present = 1;
8209
8210                         int max = 0;
8211                         max = atoi(arg_value);
8212                         if (max <= 0) {
8213                                 printf("max_port_per_client is invalid !!!\n");
8214                                 return -1;
8215                         }
8216
8217                         p->max_port_per_client = (uint16_t) max;
8218
8219                         if (p->max_port_per_client <= 0) {
8220                                 printf("max port per client is invalid\n");
8221                                 return -1;
8222                         }
8223
8224                         printf("max_port_per_client comp: %d\n",
8225                                          p->max_port_per_client);
8226                         continue;
8227                 }
8228
8229                 /*  max_clients_per_ip */
8230                 if (strcmp(arg_name, "max_clients_per_ip") == 0) {
8231                         if (max_client_present) {
8232                                 printf("CG-NAPT parse Error: duplicate "
8233                                 "max_clients_per_ip\n");
8234                                 return -1;
8235                         }
8236                         max_client_present = 1;
8237
8238                         if (nat_only_config_flag) {
8239                                 printf("CG-NAPT parse error:");
8240                                 printf("nat_only_config_flag with "
8241                                 "max_clients_per_ip\n");
8242                                 return -1;
8243                         }
8244
8245                         int max = 0;
8246                         max = atoi(arg_value);
8247                         if (max <= 0) {
8248                                 printf("max_clients_per_ip is invalid !!!\n");
8249                                 return -1;
8250                         }
8251
8252                         p->max_clients_per_ip = (uint16_t) max;
8253
8254                         if (p->max_clients_per_ip <= 0) {
8255                                 printf("max_clients_per_ip is invalid\n");
8256                                 return -1;
8257                         }
8258
8259                         printf("max_clients_per_ip: %d\n",
8260                                          p->max_clients_per_ip);
8261                         continue;
8262                 }
8263
8264                 /* n_entries */
8265                 if (strcmp(arg_name, "n_entries") == 0) {
8266                         if (n_entries_present)
8267                                 return -1;
8268                         n_entries_present = 1;
8269
8270                         p->n_entries = atoi(arg_value);
8271                         if (p->n_entries == 0)
8272                                 return -1;
8273
8274                         continue;
8275                 }
8276
8277                 /* n_flows */
8278                 if (strcmp(arg_name, "n_flows") == 0) {
8279                         if (n_flows_present)
8280                                 return -1;
8281                         n_flows_present = 1;
8282
8283                         p->n_flows = atoi(arg_value);
8284                         if (p->n_flows == 0)
8285                                 return -1;
8286
8287                         napt_common_table_hash_params.entries = p->n_flows;
8288                         continue;
8289                 }
8290                 /* dest_if_offset Multiport Changes */
8291                 if (strcmp(arg_name, "dest_if_offset") == 0) {
8292                         if (dest_if_offset_present)
8293                                 return -1;
8294                         //dest_if_offset_present = 1;
8295
8296                         dest_if_offset = atoi(arg_value);
8297
8298                         continue;
8299                 }
8300
8301                 /* key_offset */
8302                 if (strcmp(arg_name, "key_offset") == 0) {
8303                         if (key_offset_present)
8304                                 return -1;
8305                         key_offset_present = 1;
8306
8307                         p->key_offset = atoi(arg_value);
8308
8309                         continue;
8310                 }
8311
8312                 /* key_size */
8313                 if (strcmp(arg_name, "key_size") == 0) {
8314                         if (key_size_present)
8315                                 return -1;
8316                         key_size_present = 1;
8317
8318                         p->key_size = atoi(arg_value);
8319                         if ((p->key_size == 0) ||
8320                                 (p->key_size > PIPELINE_CGNAPT_KEY_MAX_SIZE) ||
8321                                 (p->key_size % 8))
8322                                 return -1;
8323
8324                         continue;
8325                 }
8326
8327                 /* hash_offset */
8328                 if (strcmp(arg_name, "hash_offset") == 0) {
8329                         if (hash_offset_present)
8330                                 return -1;
8331                         hash_offset_present = 1;
8332
8333                         p->hash_offset = atoi(arg_value);
8334
8335                         continue;
8336                 }
8337
8338                 /* traffic_type */
8339                 if (strcmp(arg_name, "pkt_type") == 0) {
8340                         if (strcmp(arg_value, "ipv4") == 0) {
8341                                 p->traffic_type = TRAFFIC_TYPE_IPV4;
8342                                 printf("Traffic is set to IPv4\n");
8343                         } else if (strcmp(arg_value, "ipv6") == 0) {
8344                                 p->traffic_type = TRAFFIC_TYPE_IPV6;
8345                                 printf("Traffic is set to IPv6\n");
8346                         }
8347                         continue;
8348                 }
8349
8350                 /* cgnapt_debug */
8351                 if (strcmp(arg_name, "cgnapt_debug") == 0) {
8352                         CGNAPT_DEBUG = atoi(arg_value);
8353
8354                         continue;
8355                 }
8356
8357                 /* any other  Unknown argument return -1 */
8358         }
8359
8360         #ifdef NAT_ONLY_CONFIG_REQ
8361         if (nat_only_config_flag) {
8362                 if (!public_ip_range_count) {
8363                         printf("No public_ip_range %d for NAT only config.\n",
8364                                          public_ip_range_count);
8365                         printf("Running static NAT only configuration\n");
8366                         p->is_static_cgnapt = 1;
8367                 }
8368         }
8369         #else
8370
8371         if (!p->max_port_per_client)
8372                 p->is_static_cgnapt = 1;
8373         #endif
8374
8375         /* Check that mandatory arguments are present */
8376         if ((n_flows_present == 0) ||
8377                 (cgnapt_meta_offset_present == 0))
8378                 return -1;
8379
8380         return 0;
8381
8382 }
8383
8384 /**
8385  * Function to initialize the pipeline
8386  *
8387  * @param params
8388  *  A pointer to struct pipeline_params
8389  * @param arg
8390  *  Void pointer - points to app params
8391  *
8392  * @return
8393  *  void pointer to the pipeline, NULL 0 if failure
8394  */
8395 static void *pipeline_cgnapt_init(struct pipeline_params *params, void *arg)
8396         /* (struct app_params *app) save it for use in port in handler */
8397 {
8398         struct pipeline *p;
8399         struct pipeline_cgnapt *p_nat;
8400         uint32_t size, i, in_ports_arg_size;
8401
8402         /* Check input arguments */
8403         if ((params == NULL) ||
8404                 (params->n_ports_in == 0) || (params->n_ports_out == 0))
8405                 return NULL;
8406
8407         /* Memory allocation */
8408         size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_cgnapt));
8409         p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8410         p_nat = (struct pipeline_cgnapt *)p;
8411         if (p == NULL)
8412                 return NULL;
8413
8414         all_pipeline_cgnapt[n_cgnapt_pipeline++] = p_nat;
8415
8416         strcpy(p->name, params->name);
8417         p->log_level = params->log_level;
8418
8419         PLOG(p, HIGH, "CG-NAPT");
8420         /* Initialize all counters and arrays */
8421
8422         p_nat->n_cgnapt_entry_deleted = 0;
8423         p_nat->n_cgnapt_entry_added = 0;
8424         p_nat->naptedPktCount = 0;
8425         p_nat->naptDroppedPktCount = 0;
8426         p_nat->inaptedPktCount = 0;
8427         p_nat->enaptedPktCount = 0;
8428         p_nat->receivedPktCount = 0;
8429         p_nat->missedPktCount = 0;
8430         p_nat->dynCgnaptCount = 0;
8431         p_nat->arpicmpPktCount = 0;
8432
8433         p_nat->app_params_addr = (uint64_t) arg;
8434         for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
8435                 p_nat->links_map[i] = 0xff;
8436                 p_nat->outport_id[i] = 0xff;
8437                 cgnapt_in_port_egress_prv[i] = 0;
8438                 cgnapt_prv_que_port_index[i] = 0;
8439         }
8440         p_nat->pipeline_num = 0xff;
8441         p_nat->hw_checksum_reqd = 0;
8442         p_nat->pub_ip_port_set = NULL;
8443         p_nat->pub_ip_count = 0;
8444         p_nat->traffic_type = TRAFFIC_TYPE_MIX;
8445         p_nat->vnf_set = 0xff;
8446
8447         /* For every init it should be reset */
8448         napt_port_alloc_elem_count = 0;
8449
8450         #ifdef CGNAPT_TIMING_INST
8451         p_nat->in_port_exit_timestamp = 0;
8452         p_nat->external_time_sum = 0;
8453         p_nat->internal_time_sum = 0;
8454         p_nat->time_measurements = 0;
8455         p_nat->max_time_mesurements = 10000;
8456         p_nat->time_measurements_on = 0;
8457         #endif
8458
8459         #ifdef CGNAPT_DEBUGGING
8460
8461         p_nat->naptDebugCount = 0;
8462
8463         p_nat->naptDroppedPktCount1 = 0;
8464         p_nat->naptDroppedPktCount2 = 0;
8465         p_nat->naptDroppedPktCount3 = 0;
8466         p_nat->naptDroppedPktCount4 = 0;
8467         p_nat->naptDroppedPktCount5 = 0;
8468         p_nat->naptDroppedPktCount6 = 0;
8469
8470         p_nat->missedpktcount1 = 0;
8471         p_nat->missedpktcount2 = 0;
8472         p_nat->missedpktcount3 = 0;
8473         p_nat->missedpktcount4 = 0;
8474         p_nat->missedpktcount5 = 0;
8475         p_nat->missedpktcount6 = 0;
8476         p_nat->missedpktcount7 = 0;
8477         p_nat->missedpktcount8 = 0;
8478         p_nat->missedpktcount9 = 0;
8479         p_nat->missedpktcount10 = 0;
8480         p_nat->missedpktcount11 = 0;
8481         p_nat->missedpktcount12 = 0;
8482
8483         p_nat->max_port_dec_err1 = 0;
8484         p_nat->max_port_dec_err2 = 0;
8485         p_nat->max_port_dec_err3 = 0;
8486         p_nat->max_port_dec_success = 0;
8487
8488         p_nat->pfb_err = 0;
8489         p_nat->pfb_ret = 0;
8490         p_nat->pfb_get = 0;
8491         p_nat->pfb_suc = 0;
8492         p_nat->gfp_suc = 0;
8493         p_nat->gfp_get = 0;
8494         p_nat->gfp_ret = 0;
8495         p_nat->gfp_err = 0;
8496
8497         p_nat->kpc2 = 0;
8498         p_nat->kpc1 = 0;
8499         #endif
8500
8501         #ifdef SIP_ALG
8502         static int sip_enabled;
8503         if (!sip_enabled)
8504                 lib_sip_alg_init();
8505         sip_enabled = 1;
8506         #endif /* SIP_ALG */
8507
8508         /*struct rte_pipeline_table_entry *entries[RTE_HASH_LOOKUP_BULK_MAX];*/
8509         /* bitmap of valid packets */
8510         p_nat->valid_packets = 0;
8511         /* bitmap of invalid packets to be dropped */
8512         p_nat->invalid_packets = 0;
8513
8514         for (i = 0; i < RTE_HASH_LOOKUP_BULK_MAX; i++)
8515                 p_nat->key_ptrs[i] = &(p_nat->keys[i]);
8516
8517         p_nat->port_alloc_ring = NULL;
8518
8519         /* Parse arguments */
8520         if (pipeline_cgnapt_parse_args(p_nat, params))
8521                 return NULL;
8522
8523         p_nat->vnf_set = vnf_set_count;
8524
8525         /* Pipeline */
8526         {
8527                 struct rte_pipeline_params pipeline_params = {
8528                         .name = params->name,
8529                         .socket_id = params->socket_id,
8530                         .offset_port_id = cgnapt_meta_offset,
8531                 };
8532
8533                 p->p = rte_pipeline_create(&pipeline_params);
8534                 if (p->p == NULL) {
8535                         rte_free(p);
8536                         return NULL;
8537                 }
8538                 myP = p->p;
8539         }
8540
8541         #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8542
8543         uint32_t instr_size =
8544                 RTE_CACHE_LINE_ROUNDUP((sizeof(uint64_t)) *
8545                         (INST_ARRAY_SIZE));
8546         inst_start_time =
8547                 (uint64_t *) rte_zmalloc(NULL, instr_size,
8548                 RTE_CACHE_LINE_SIZE);
8549         inst_end_time =
8550                 (uint64_t *) rte_zmalloc(NULL, instr_size,
8551                         RTE_CACHE_LINE_SIZE);
8552         inst_diff_time =
8553                 (uint32_t *) rte_zmalloc(NULL, instr_size / 2,
8554                         RTE_CACHE_LINE_SIZE);
8555         if ((inst_start_time == NULL) || (inst_end_time == NULL)
8556                 || (inst_diff_time == NULL)) {
8557                 printf("Inst array alloc failed .... ");
8558                 return NULL;
8559         }
8560         #endif
8561
8562         /* Memory allocation for in_port_h_arg */
8563         in_ports_arg_size = RTE_CACHE_LINE_ROUNDUP(
8564                         (sizeof(struct pipeline_cgnapt_in_port_h_arg)) *
8565                                          (params->n_ports_in));
8566         struct pipeline_cgnapt_in_port_h_arg *ap =
8567                 (struct pipeline_cgnapt_in_port_h_arg *)
8568                         rte_zmalloc(NULL,
8569                                 in_ports_arg_size,
8570                                 RTE_CACHE_LINE_SIZE);
8571         if (ap == NULL)
8572                 return NULL;
8573
8574         myApp = (struct app_params *) arg;
8575
8576         /* Input ports */
8577         p->n_ports_in = params->n_ports_in;
8578         for (i = 0; i < p->n_ports_in; i++) {
8579                 /* passing our cgnapt pipeline in call back arg */
8580                 (ap[i]).p = p_nat;
8581                 (ap[i]).in_port_id = i;
8582
8583                 struct rte_pipeline_port_in_params port_params = {
8584                         .ops =
8585                                 pipeline_port_in_params_get_ops(&params->port_in
8586                                                                 [i]),
8587                         .arg_create =
8588                                 pipeline_port_in_params_convert(&params->port_in
8589                                                                 [i]),
8590                         .f_action = cgnapt_in_port_ah_mix,
8591                         .arg_ah = &(ap[i]),
8592                         .burst_size = params->port_in[i].burst_size,
8593                 };
8594
8595                 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8596                 if (i == 0)
8597                         instrumentation_port_in_arg = &(ap[i]);
8598                 #endif
8599
8600                 if (p_nat->traffic_type == TRAFFIC_TYPE_IPV4) {
8601                         /* Private in-port handler */
8602                         /* Multiport changes */
8603                         if (cgnapt_in_port_egress_prv[i]) {
8604                                 port_params.f_action =
8605                                         cgnapt_in_port_ah_ipv4_prv;
8606                                 printf("CGNAPT port %d is IPv4 Prv\n", i);
8607                         } else{
8608                                 port_params.f_action =
8609                                         cgnapt_in_port_ah_ipv4_pub;
8610                                 printf("CGNAPT port %d is IPv4 Pub\n", i);
8611                         }
8612                 }
8613
8614                 if (p_nat->traffic_type == TRAFFIC_TYPE_IPV6) {
8615                         if (cgnapt_in_port_egress_prv[i]) {
8616                                 port_params.f_action =
8617                                         cgnapt_in_port_ah_ipv6_prv;
8618                                 printf("CGNAPT port %d is IPv6 Prv\n", i);
8619                         } else{
8620                                 port_params.f_action =
8621                                         cgnapt_in_port_ah_ipv6_pub;
8622                                 printf("CGNAPT port %d is IPv6 Pub\n", i);
8623                         }
8624                 }
8625
8626                 int status = rte_pipeline_port_in_create(p->p,
8627                                                          &port_params,
8628                                                          &p->port_in_id[i]);
8629
8630                 if (status) {
8631                         rte_pipeline_free(p->p);
8632                         rte_free(p);
8633                         return NULL;
8634                 }
8635
8636         }
8637
8638         /* Output ports */
8639         p->n_ports_out = params->n_ports_out;
8640         for (i = 0; i < p->n_ports_out; i++) {
8641                 struct rte_pipeline_port_out_params port_params = {
8642                         .ops = pipeline_port_out_params_get_ops(
8643                                                 &params->port_out[i]),
8644                         .arg_create = pipeline_port_out_params_convert(
8645                                         &params->port_out[i]),
8646                         #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8647                         .f_action = port_out_ah_cgnapt,
8648                         #else
8649                         .f_action = NULL,
8650                         #endif
8651                         .arg_ah = NULL,
8652                 };
8653
8654                 int status = rte_pipeline_port_out_create(p->p,
8655                                                                 &port_params,
8656                                                                 &p->port_out_id[i]);
8657
8658                 if (status) {
8659                         rte_pipeline_free(p->p);
8660                         rte_free(p);
8661                         return NULL;
8662                 }
8663         }
8664
8665         int pipeline_num = 0;
8666         int ignore;
8667         ignore = sscanf(params->name, "PIPELINE%d", &pipeline_num);
8668         if (ignore != 1) {
8669                 printf("Not able to read pipeline number\n");
8670                 return NULL;
8671         }
8672                 p_nat->pipeline_num = (uint8_t) pipeline_num;
8673         register_pipeline_Qs(p_nat->pipeline_num, p);
8674         set_link_map(p_nat->pipeline_num, p, p_nat->links_map);
8675         set_outport_id(p_nat->pipeline_num, p, p_nat->outport_id);
8676
8677         /* Tables */
8678         p->n_tables = 1;
8679         {
8680
8681                 if (napt_common_table == NULL) {
8682                         if (create_napt_common_table(p_nat->n_flows)) {
8683                                 PLOG(p, HIGH,
8684                                 "CG-NAPT create_napt_common_table failed.");
8685                                 return NULL;
8686                         }
8687                 }
8688
8689                 struct rte_pipeline_table_params table_params = {
8690                         .ops = &rte_table_stub_ops,
8691                         .arg_create = NULL,
8692                         .f_action_hit = NULL,
8693                         .f_action_miss = NULL,
8694                         .arg_ah = NULL,
8695                         .action_data_size = 0,
8696                 };
8697
8698                 int status = rte_pipeline_table_create(p->p,
8699                                                                  &table_params,
8700                                                                  &p->table_id[0]);
8701
8702                 if (status) {
8703                         rte_pipeline_free(p->p);
8704                         rte_free(p);
8705                         return NULL;
8706                 }
8707                 struct rte_pipeline_table_entry default_entry = {
8708                         .action = RTE_PIPELINE_ACTION_PORT_META
8709                 };
8710                 struct rte_pipeline_table_entry *default_entry_ptr;
8711                 status = rte_pipeline_table_default_entry_add(
8712                                 p->p,
8713                                 p->table_id[0],
8714                                 &default_entry,
8715                                 &default_entry_ptr);
8716                 if (status) {
8717                         rte_pipeline_free(p->p);
8718                         rte_free(p);
8719                         return NULL;
8720                 }
8721         }
8722
8723         /* Connecting input ports to tables */
8724         for (i = 0; i < p->n_ports_in; i++) {
8725                 int status = rte_pipeline_port_in_connect_to_table(p->p,
8726                                                                          p->port_in_id
8727                                                                          [i],
8728                                                                          p->table_id
8729                                                                          [0]);
8730
8731                 if (status) {
8732                         rte_pipeline_free(p->p);
8733                         rte_free(p);
8734                         return NULL;
8735                 }
8736         }
8737
8738         /* Enable input ports */
8739         for (i = 0; i < p->n_ports_in; i++) {
8740                 int status = rte_pipeline_port_in_enable(p->p,
8741                                                          p->port_in_id[i]);
8742
8743                 if (status) {
8744                         rte_pipeline_free(p->p);
8745                         rte_free(p);
8746                         return NULL;
8747                 }
8748         }
8749
8750         /* Check pipeline consistency */
8751         if (rte_pipeline_check(p->p) < 0) {
8752                 rte_pipeline_free(p->p);
8753                 rte_free(p);
8754                 return NULL;
8755         }
8756
8757         /* Message queues */
8758         p->n_msgq = params->n_msgq;
8759         for (i = 0; i < p->n_msgq; i++)
8760                 p->msgq_in[i] = params->msgq_in[i];
8761         for (i = 0; i < p->n_msgq; i++)
8762                 p->msgq_out[i] = params->msgq_out[i];
8763
8764         /* Message handlers */
8765         memcpy(p->handlers, handlers, sizeof(p->handlers));
8766         memcpy(p_nat->custom_handlers,
8767                          custom_handlers, sizeof(p_nat->custom_handlers));
8768
8769         if (!p_nat->is_static_cgnapt) {
8770                 printf("Initializing dyn napt components ... %d\n",
8771                                  p_nat->pipeline_num);
8772                 if (napt_port_alloc_init(p_nat) == -1) {
8773                         printf("Error - napt_port_alloc_init failed - %d\n",
8774                                          p_nat->pipeline_num);
8775                         return NULL;
8776                 }
8777                 int rc = 0;
8778
8779                 if (max_port_per_client_hash == NULL) {
8780                         rc = init_max_port_per_client(p_nat);
8781                         if (rc < 0) {
8782                                 printf("CGNAPT Error - "
8783                                 "init_max_port_per_client failed %d", rc);
8784                                 return NULL;
8785                         }
8786                 }
8787
8788         }
8789
8790         if (!icmp_pool_init) {
8791                 icmp_pool_init = 1;
8792                 /* create the arp_icmp mbuf rx pool */
8793                 cgnapt_icmp_pktmbuf_tx_pool =
8794                         rte_pktmbuf_pool_create("icmp_mbuf_tx_pool", 63, 32, 0,
8795                                                 RTE_MBUF_DEFAULT_BUF_SIZE,
8796                                                 rte_socket_id());
8797                 if (cgnapt_icmp_pktmbuf_tx_pool == NULL) {
8798                         PLOG(p, HIGH, "ICMP mbuf pool create failed.");
8799                         return NULL;
8800                 }
8801
8802                 cgnapt_icmp_pkt =
8803                         rte_pktmbuf_alloc(cgnapt_icmp_pktmbuf_tx_pool);
8804
8805                 if (cgnapt_icmp_pkt == NULL) {
8806                         printf("Failed to allocate cgnapt_icmp_pkt\n");
8807                         return NULL;
8808                 }
8809         }
8810
8811         #ifdef CT_CGNAT
8812
8813         cgnat_cnxn_tracker =  rte_zmalloc(NULL, rte_ct_get_cnxn_tracker_size(),
8814                                 RTE_CACHE_LINE_SIZE);
8815
8816         if (cgnat_cnxn_tracker == NULL) {
8817                 printf("CGNAPT CT memory not allocated\n");
8818                 return NULL;
8819         }
8820         rte_ct_initialize_default_timeouts(cgnat_cnxn_tracker);
8821
8822         printf("CGNAPT CT Flows %d\n", p_nat->n_flows);
8823         int ret;
8824         ret = rte_ct_initialize_cnxn_tracker(cgnat_cnxn_tracker,
8825                                                         p_nat->n_flows,
8826                                                         "CGNAT_CT_COMMON_TABLE");
8827         if (ret == -1)
8828                 return NULL;
8829         #endif
8830
8831         #ifdef FTP_ALG
8832         lib_ftp_alg_init();
8833         #endif
8834
8835         #ifdef PCP_ENABLE
8836         if (pcp_init() == PCP_INIT_SUCCESS)
8837                 printf("PCP contents are initialized successfully\n");
8838         else
8839                 printf("Error in initializing PCP contents\n");
8840         #endif
8841
8842         return p;
8843 }
8844
8845 /**
8846  * Function for pipeline cleanup
8847  *
8848  * @param pipeline
8849  *  A void pointer to pipeline
8850  *
8851  * @return
8852  *  0
8853  */
8854 static int pipeline_cgnapt_free(void *pipeline)
8855 {
8856         struct pipeline *p = (struct pipeline *)pipeline;
8857
8858         /* Check input arguments */
8859         if (p == NULL)
8860                 return -1;
8861
8862         /* Free resources */
8863         rte_pipeline_free(p->p);
8864         rte_free(p);
8865         return 0;
8866 }
8867
8868 static int
8869 pipeline_cgnapt_track(void *pipeline, __rte_unused uint32_t port_in,
8870                                 uint32_t *port_out)
8871 {
8872         struct pipeline *p = (struct pipeline *)pipeline;
8873
8874         /* Check input arguments */
8875         if ((p == NULL) || (port_in >= p->n_ports_in) || (port_out == NULL))
8876                 return -1;
8877
8878         if (p->n_ports_in == 1) {
8879                 *port_out = 0;
8880                 return 0;
8881         }
8882
8883         return -1;
8884 }
8885
8886 /**
8887  * Function for pipeline timers
8888  *
8889  * @param pipeline
8890  *  A void pointer to pipeline
8891  *
8892  * @return
8893  *  0
8894  */
8895 static int pipeline_cgnapt_timer(void *pipeline)
8896 {
8897         struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)pipeline;
8898
8899         pipeline_msg_req_handle(&p_nat->p);
8900
8901         rte_pipeline_flush(((struct pipeline *)p_nat)->p);
8902
8903         return 0;
8904 }
8905
8906 /**
8907  * Function for pipeline custom handlers
8908  *
8909  * @param pipeline
8910  *  A void pointer to pipeline
8911  * @param msg
8912  *  void pointer for incoming data
8913  *
8914  * @return
8915  *  void pointer of response
8916  */
8917 void *pipeline_cgnapt_msg_req_custom_handler(struct pipeline *p, void *msg)
8918 {
8919         struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
8920         struct pipeline_custom_msg_req *req = msg;
8921         pipeline_msg_req_handler f_handle;
8922
8923         f_handle = (req->subtype < PIPELINE_CGNAPT_MSG_REQS) ?
8924                 p_nat->custom_handlers[req->subtype] :
8925                 pipeline_msg_req_invalid_handler;
8926
8927         if (f_handle == NULL)
8928                 f_handle = pipeline_msg_req_invalid_handler;
8929
8930         return f_handle(p, req);
8931 }
8932
8933 /**
8934  * Function for adding NSP data
8935  *
8936  * @param pipeline
8937  *  A void pointer to pipeline
8938  * @param msg
8939  *  void pointer for incoming data
8940  *
8941  * @return
8942  *  void pointer of response
8943  */
8944 void *pipeline_cgnapt_msg_req_nsp_add_handler(
8945         __rte_unused struct pipeline *p,
8946         void *msg)
8947 {
8948         struct pipeline_cgnapt_nsp_add_msg_req *req = msg;
8949         struct pipeline_cgnapt_nsp_add_msg_rsp *rsp = msg;
8950         int size = 0;
8951         struct cgnapt_nsp_node *node = NULL, *ll = nsp_ll;
8952
8953         if (!
8954                 (req->nsp.depth == 32 || req->nsp.depth == 40
8955                  || req->nsp.depth == 48 || req->nsp.depth == 56
8956                  || req->nsp.depth == 64 || req->nsp.depth == 96)) {
8957                 rsp->status = 0xE;
8958                 rsp->key_found = 0;
8959                 return rsp;
8960         }
8961
8962         printf("be initial cond\n");
8963         if (nsp_ll == NULL) {
8964                 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_nsp_node));
8965                 node = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8966                 if (node == NULL) {
8967                         printf("be 1st cond\n");
8968                         rsp->status = 0xE;
8969                         rsp->key_found = 0;
8970                         return rsp;
8971                 }
8972
8973                 memcpy(&node->nsp, &req->nsp,
8974                                  sizeof(struct pipeline_cgnapt_nsp_t));
8975                 node->next = NULL;
8976                 nsp_ll = node;
8977         } else {
8978                 while (ll != NULL) {
8979                         if (!memcmp(ll->nsp.prefix, req->nsp.prefix, 16)
8980                                 && ll->nsp.depth == req->nsp.depth) {
8981                                 printf("be 2st cond\n");
8982                                 rsp->status = 0xE;
8983                                 rsp->key_found = 1;
8984                                 return rsp;
8985                         }
8986                         ll = ll->next;
8987                 }
8988
8989                 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_nsp_node));
8990                 node = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8991                 if (node == NULL) {
8992                         printf("be 3st cond\n");
8993                         rsp->status = 0xE;
8994                         rsp->key_found = 0;
8995                         return rsp;
8996                 }
8997
8998                 memcpy(&node->nsp, &req->nsp,
8999                                  sizeof(struct pipeline_cgnapt_nsp_t));
9000                 node->next = nsp_ll;
9001                 nsp_ll = node;
9002         }
9003
9004         rsp->status = 0;
9005         rsp->key_found = 0;
9006
9007         printf("be 4st cond\n");
9008         return rsp;
9009 }
9010
9011 /**
9012  * Function for deleting NSP data
9013  *
9014  * @param pipeline
9015  *  A void pointer to pipeline
9016  * @param msg
9017  *  void pointer for incoming data
9018  *
9019  * @return
9020  *  void pointer of response
9021  */
9022 void *pipeline_cgnapt_msg_req_nsp_del_handler(
9023         __rte_unused struct pipeline *p,
9024         void *msg)
9025 {
9026         struct pipeline_cgnapt_nsp_del_msg_req *req = msg;
9027         struct pipeline_cgnapt_nsp_del_msg_rsp *rsp = msg;
9028         struct cgnapt_nsp_node *prev = NULL, *ll = nsp_ll;
9029
9030         while (ll != NULL) {
9031                 if (!memcmp(ll->nsp.prefix, req->nsp.prefix, 16)
9032                         && ll->nsp.depth == req->nsp.depth) {
9033                         if (prev != NULL)
9034                                 prev->next = ll->next;
9035                         else
9036                                 nsp_ll = NULL;
9037
9038                         rte_free(ll);
9039
9040                         rsp->status = 0;
9041                         rsp->key_found = 1;
9042
9043                         return rsp;
9044                 }
9045
9046                 prev = ll;
9047                 ll = ll->next;
9048         }
9049
9050         rsp->status = 0xE;
9051         rsp->key_found = 0;
9052
9053         return rsp;
9054 }
9055
9056 /**
9057  * Function for adding NAPT entry
9058  *
9059  * @param pipeline
9060  *  A void pointer to pipeline
9061  * @param msg
9062  *  void pointer for incoming data
9063  *
9064  * @return
9065  *  void pointer of response
9066  */
9067 void *pipeline_cgnapt_msg_req_entry_add_handler(struct pipeline *p, void *msg)
9068 {
9069         struct pipeline_cgnapt_entry_add_msg_req *req = msg;
9070         struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9071         uint8_t type = req->data.type;
9072         uint32_t src_ip = (type == CGNAPT_ENTRY_IPV4) ?
9073                         req->data.u.prv_ip :
9074                         rte_bswap32(req->data.u.u32_prv_ipv6[3]);
9075
9076         uint8_t src_ipv6[16];
9077
9078         uint32_t dest_ip = req->data.pub_ip;
9079         uint16_t src_port = req->data.prv_port;
9080         uint16_t dest_port = req->data.pub_port;
9081         uint16_t rx_port = req->data.prv_phy_port;
9082         uint32_t ttl = req->data.ttl;
9083
9084         if (type == CGNAPT_ENTRY_IPV6)
9085                 memcpy(src_ipv6, req->data.u.prv_ipv6, 16);
9086
9087         printf("CG-NAPT addm - PrvIP %x, PrvPort %d,", src_ip, src_port);
9088         printf("PubIP %x, PubPort %d,", dest_ip, dest_port);
9089
9090          printf("PhyPort %d, ttl %u,", rx_port, ttl);
9091          printf("entry_type %d\n", type);
9092
9093          #ifdef NAT_ONLY_CONFIG_REQ
9094         if (nat_only_config_flag) {
9095                 if (!p_nat->is_static_cgnapt) {
9096                         int i;
9097
9098                 for (i = 0; i < p_nat->pub_ip_range_count; i++) {
9099                         if (((dest_ip >= p_nat->pub_ip_range[i].start_ip)
9100                         && (dest_ip <= p_nat->pub_ip_range[i].end_ip))) {
9101                         printf("Error - static port cannot be in Dynamic "
9102                                 "port range");
9103                         printf("%x-%x\n", p_nat->pub_ip_range[i].start_ip,
9104                                 p_nat->pub_ip_range[i].end_ip);
9105                                 return msg;
9106                         }
9107                 }
9108         }
9109
9110                 if (pipeline_cgnapt_msg_req_entry_addm_pair(p, msg,
9111                         src_ip, src_port,
9112                         dest_ip, dest_port,
9113                         rx_port, ttl,
9114                         type, src_ipv6)) {
9115                         printf("Error - ");
9116                         printf("pipeline_cgnapt_msg_req_entry_addm_handler\n");
9117                                 return msg;
9118                 }
9119
9120                 printf("Success - pipeline_cgnapt_msg_req_entry_addm_handler");
9121                 printf("added %d rule pairs.\n", count);
9122
9123                 return msg;
9124         }
9125          #endif
9126
9127         if (!p_nat->is_static_cgnapt) {
9128                 int i;
9129
9130         for (i = 0; i < p_nat->pub_ip_count; i++) {
9131                          /* Check port range if same Public-IP */
9132                 if (dest_ip != p_nat->pub_ip_port_set[i].ip)
9133                         continue;
9134                 if (((dest_port >= p_nat->pub_ip_port_set[i].start_port) &&
9135                         (dest_port <= p_nat->pub_ip_port_set[i].end_port))) {
9136                         printf("Error - port cannot be in Dynamic "
9137                         "port range %d-%d\n",
9138                         p_nat->pub_ip_port_set[i].start_port,
9139                         p_nat->pub_ip_port_set[i].end_port);
9140                                 return msg;
9141                 }
9142         }
9143         }
9144
9145         if (pipeline_cgnapt_msg_req_entry_addm_pair
9146                 (p, msg, src_ip, src_port, dest_ip, dest_port, rx_port,
9147                 ttl, type, src_ipv6)) {
9148                 printf("Error - pipeline_cgnapt_msg_req_entry_add_handler\n");
9149                         return msg;
9150         }
9151
9152
9153          printf("\nSuccess - pipeline_cgnapt_msg_req_entry_add_handler "
9154                 "added\n");
9155
9156         return msg;
9157 }
9158
9159 /**
9160  * Function for adding a NAPT entry pair
9161  *
9162  * @param pipeline
9163  *  A void pointer to pipeline
9164  * @param msg
9165  *  void pointer for incoming data
9166  * @param src_ip
9167  *  source ip address
9168  * @param src_port
9169  *  source port
9170  * @param dest_ip
9171  *  destination ip address
9172  * @param dest_port
9173  *  destination port
9174  * @param rx_port
9175  *  Physical receive port
9176  * @param ttl
9177  * time to live value
9178  * @param type
9179  *  type of entry IPv4 vs IPv6
9180  * @param src_ipv6[]
9181  *  uint8_t array of IPv6 address
9182  *
9183  * @return
9184  *  0 if success, negative if fails
9185  */
9186 int
9187 pipeline_cgnapt_msg_req_entry_addm_pair(
9188         struct pipeline *p, __rte_unused void *msg,
9189         uint32_t src_ip, uint16_t src_port,
9190         uint32_t dest_ip, uint16_t dest_port,
9191         uint16_t rx_port, uint32_t ttl,
9192         uint8_t type, uint8_t src_ipv6[16])
9193 {
9194
9195         struct pipeline_cgnapt_entry_key key;
9196         struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9197
9198         key.ip = src_ip;
9199         key.port = src_port;
9200         key.pid = rx_port;
9201
9202         struct cgnapt_table_entry entry = {
9203                 .head = {
9204                          .action = RTE_PIPELINE_ACTION_PORT,
9205                          .port_id = CGNAPT_PUB_PORT_ID,
9206                          },
9207
9208                 .data = {
9209                          /*.prv_ip = src_ip, */
9210                          .prv_port = src_port,
9211                          .pub_ip = dest_ip,
9212                          .pub_port = dest_port,
9213                          .prv_phy_port = rx_port,
9214                          .pub_phy_port = get_prv_to_pub_port(&dest_ip,
9215                                                 IP_VERSION_4),
9216                          .ttl = ttl,
9217                          .timeout = STATIC_CGNAPT_TIMEOUT,
9218                          #ifdef PCP_ENABLE
9219                          .timer = NULL,
9220                          #endif
9221                         }
9222         };
9223
9224         if (type == CGNAPT_ENTRY_IPV4) {
9225                 entry.data.type = CGNAPT_ENTRY_IPV4;
9226                 entry.data.u.prv_ip = src_ip;
9227         } else {
9228                 entry.data.type = CGNAPT_ENTRY_IPV6;
9229                 memcpy(entry.data.u.prv_ipv6, src_ipv6, 16);
9230         }
9231
9232         /* Also need to add a paired entry on our own */
9233         /*
9234         * Need to change key
9235         * Need to change entry header
9236         * Will keep the same entry and take care
9237         * of translation in table hit handler
9238         */
9239         struct pipeline_cgnapt_entry_key second_key;
9240
9241         /* Need to add a second ingress entry */
9242         second_key.ip = dest_ip;
9243         second_key.port = dest_port;
9244         second_key.pid = 0xffff;
9245
9246         #ifdef NAT_ONLY_CONFIG_REQ
9247         if (nat_only_config_flag) {
9248                 key.port = 0xffff;
9249                 entry.data.pub_port = 0xffff;
9250                 second_key.port = 0xffff;
9251         }
9252         #endif
9253
9254         if (CGNAPT_DEBUG > 2)
9255                 printf("key.ip %x, key.port %d", key.ip, key.port);
9256                 printf("key.pid %d, in_type %d,", key.pid, type);
9257                 printf("entry_type %d\n", entry.data.type);
9258
9259         int32_t position = rte_hash_add_key(napt_common_table, &key);
9260
9261         if (position < 0) {
9262                 printf("CG-NAPT entry bulk add failed");
9263                 printf(" ... returning without adding ...\n");
9264                 return -1;
9265         }
9266
9267         memcpy(&napt_hash_tbl_entries[position], &entry,
9268                          sizeof(struct cgnapt_table_entry));
9269
9270         #ifdef CGNAPT_DEBUGGING
9271         if (p_nat->kpc1++ < 5)
9272                 print_key(&key);
9273         #endif
9274
9275         p_nat->n_cgnapt_entry_added++;
9276
9277         /* Now modify the forward port for reverse entry */
9278         entry.head.port_id = CGNAPT_PRV_PORT_ID;
9279
9280         position = rte_hash_add_key(napt_common_table, &second_key);
9281
9282         if (position < 0) {
9283                 printf("CG-NAPT entry reverse bulk add failed");
9284                 printf(" ... returning with fwd add ...%d\n", position);
9285                 return 2;
9286         }
9287
9288         memcpy(&napt_hash_tbl_entries[position], &entry,
9289                          sizeof(struct cgnapt_table_entry));
9290
9291         #ifdef CGNAPT_DEBUGGING
9292         if (p_nat->kpc1 < 5)
9293                 print_key(&second_key);
9294         #endif
9295
9296         p_nat->n_cgnapt_entry_added++;
9297         return 0;
9298 }
9299
9300 /**
9301  * Function for adding multiple NAPT entries
9302  *
9303  * @param pipeline
9304  *  A void pointer to pipeline
9305  * @param msg
9306  *  void pointer for incoming data
9307  *
9308  * @return
9309  *  void pointer of response
9310  */
9311 void *pipeline_cgnapt_msg_req_entry_addm_handler(struct pipeline *p, void *msg)
9312 {
9313         struct pipeline_cgnapt_entry_addm_msg_req *req = msg;
9314         struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9315         uint32_t uenum = 0;
9316         uint32_t max_ue = req->data.num_ue;
9317         uint8_t type = req->data.type;
9318         uint32_t src_ip = (type == CGNAPT_ENTRY_IPV4) ?
9319                         req->data.u.prv_ip :
9320                         rte_bswap32(req->data.u.u32_prv_ipv6[3]);
9321
9322         uint8_t src_ipv6[16];
9323
9324         uint32_t dest_ip = req->data.pub_ip;
9325         uint16_t src_port = req->data.prv_port;
9326         uint16_t dest_port = req->data.pub_port;
9327         uint16_t rx_port = req->data.prv_phy_port;
9328         uint32_t ttl = req->data.ttl;
9329         uint16_t max_src_port = req->data.prv_port_max;
9330         uint16_t max_dest_port = req->data.pub_port_max;
9331         uint32_t count = 0;
9332         uint16_t src_port_start = src_port;
9333         uint16_t dest_port_start = dest_port;
9334         uint32_t src_ip_temp;
9335
9336         if (type == CGNAPT_ENTRY_IPV6)
9337                 memcpy(src_ipv6, req->data.u.prv_ipv6, 16);
9338
9339         printf("CG-NAPT addm - PrvIP %x, PrvPort %d,", src_ip, src_port);
9340         printf("PubIP %x, PubPort %d,", dest_ip, dest_port);
9341         printf("PhyPort %d, ttl %u, NumUe %d,", rx_port, ttl, max_ue);
9342         printf("mPrvPort %d, mPubPort %d,", max_src_port, max_dest_port);
9343         printf("entry_type %d\n", type);
9344
9345         #ifdef NAT_ONLY_CONFIG_REQ
9346         if (nat_only_config_flag) {
9347                 if (!p_nat->is_static_cgnapt) {
9348                         int i;
9349
9350                 for (i = 0; i < p_nat->pub_ip_range_count; i++) {
9351                         if (((dest_ip >= p_nat->pub_ip_range[i].start_ip)
9352                         && (dest_ip <= p_nat->pub_ip_range[i].end_ip)) ||
9353                         (((dest_ip + max_ue) >=
9354                                                 p_nat->pub_ip_range[i].start_ip) &&
9355                         ((dest_ip + max_ue) <=
9356                                          p_nat->pub_ip_range[i].end_ip))) {
9357                         printf("Error - static port cannot be in Dynamic "
9358                                 "port range");
9359                         printf("%x-%x\n", p_nat->pub_ip_range[i].start_ip,
9360                                 p_nat->pub_ip_range[i].end_ip);
9361
9362                                 return msg;
9363                                 }
9364                         }
9365                 }
9366
9367                 for (uenum = 0; uenum < max_ue; uenum++) {
9368
9369                 if (pipeline_cgnapt_msg_req_entry_addm_pair(p, msg,
9370                         src_ip, src_port,
9371                         dest_ip, dest_port,
9372                         rx_port, ttl,
9373                         type, src_ipv6)) {
9374                         printf("Error - ");
9375                         printf("pipeline_cgnapt_msg_req_entry_addm_handler\n");
9376                                 return msg;
9377                         }
9378
9379                         count++;
9380
9381                         src_ip++;
9382                         dest_ip++;
9383                 }
9384
9385                 printf("Success - pipeline_cgnapt_msg_req_entry_addm_handler");
9386                 printf("added %d rule pairs.\n", count);
9387
9388                 return msg;
9389         }
9390         #endif
9391
9392         if (!p_nat->is_static_cgnapt) {
9393                 int i;
9394
9395         for (i = 0; i < p_nat->pub_ip_count; i++) {
9396                         /* Check port range if same Public-IP */
9397                 if (dest_ip != p_nat->pub_ip_port_set[i].ip)
9398                         continue;
9399                 if (((dest_port >= p_nat->pub_ip_port_set[i].start_port) &&
9400                         (dest_port <= p_nat->pub_ip_port_set[i].end_port)) ||
9401                 ((max_dest_port >= p_nat->pub_ip_port_set[i].start_port)
9402                 && max_dest_port <= p_nat->pub_ip_port_set[i].end_port)) {
9403                 printf("Error - port cannot be in Dynamic port range %d-%d\n",
9404                         p_nat->pub_ip_port_set[i].start_port,
9405                         p_nat->pub_ip_port_set[i].end_port);
9406                                 return msg;
9407                 }
9408         }
9409         }
9410
9411         for (uenum = 0; uenum < max_ue; uenum++) {
9412                 if (pipeline_cgnapt_msg_req_entry_addm_pair
9413                         (p, msg, src_ip, src_port, dest_ip, dest_port, rx_port,
9414                          ttl, type, src_ipv6)) {
9415                 printf("Error - pipeline_cgnapt_msg_req_entry_addm_handler\n");
9416                         return msg;
9417                 }
9418
9419                 count++;
9420
9421                 src_port++;
9422                 if (src_port > max_src_port) {
9423                         src_port = src_port_start;
9424                         src_ip++;
9425                         if (req->data.type == CGNAPT_ENTRY_IPV6) {
9426                                 src_ip_temp = rte_bswap32(src_ip);
9427                                 memcpy(&src_ipv6[12], &src_ip_temp, 4);
9428                         }
9429                 }
9430                 dest_port++;
9431                 if (dest_port > max_dest_port) {
9432                         dest_port = dest_port_start;
9433                         dest_ip++;
9434                 }
9435         }
9436
9437         printf("\nSuccess - pipeline_cgnapt_msg_req_entry_addm_handler added");
9438         printf("%d rule pairs.\n", count);
9439
9440         return msg;
9441 }
9442
9443 /**
9444  * Function for deleting NAPT entry
9445  *
9446  * @param pipeline
9447  *  A void pointer to pipeline
9448  * @param msg
9449  *  void pointer for incoming data
9450  *
9451  * @return
9452  *  void pointer of response
9453  */
9454 void *pipeline_cgnapt_msg_req_entry_del_handler(struct pipeline *p, void *msg)
9455 {
9456         struct pipeline_cgnapt_entry_delete_msg_req *req = msg;
9457         struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9458         struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9459
9460         if (CGNAPT_DEBUG) {
9461                 uint8_t *KeyP = (void *)(&req->key);
9462                 int i = 0;
9463
9464                 printf("pipeline_cgnapt_msg_req_entry_del_handler - Key: ");
9465                 for (i = 0; i < (int)sizeof(struct pipeline_cgnapt_entry_key);
9466                          i++)
9467                         printf(" %02x", KeyP[i]);
9468                 printf(" ,KeySize %u\n",
9469                                  (int)sizeof(struct pipeline_cgnapt_entry_key));
9470         }
9471
9472         struct cgnapt_table_entry entry;
9473
9474         /* If ingress key */
9475         if (!is_phy_port_privte(req->key.pid))
9476                 req->key.pid = 0xffff;
9477
9478         #ifdef NAT_ONLY_CONFIG_REQ
9479         if (nat_only_config_flag)
9480                 req->key.port = 0xffff;
9481         #endif
9482
9483         int32_t position;
9484         position = rte_hash_lookup(napt_common_table, &req->key);
9485         if (position == -ENOENT) {
9486                 printf("Entry not found\n");
9487                 return NULL;
9488         }
9489         memcpy(&entry, &napt_hash_tbl_entries[position],
9490                 sizeof(struct cgnapt_table_entry));
9491         position = rte_hash_del_key(napt_common_table, &req->key);
9492         p_nat->n_cgnapt_entry_deleted++;
9493
9494         struct pipeline_cgnapt_entry_key second_key;
9495
9496         if (is_phy_port_privte(req->key.pid)) {
9497                 /* key is for egress - make second key for ingress */
9498                 second_key.ip = entry.data.pub_ip;
9499                 second_key.port = entry.data.pub_port;
9500                 second_key.pid = 0xffff;
9501
9502         } else {
9503                 /* key is for ingress - make second key for egress */
9504                 second_key.ip = entry.data.u.prv_ip;
9505                 second_key.port = entry.data.prv_port;
9506                 second_key.pid = entry.data.prv_phy_port;
9507         }
9508
9509         #ifdef NAT_ONLY_CONFIG_REQ
9510         if (nat_only_config_flag)
9511                 second_key.port = 0xffff;
9512         #endif
9513
9514         position = rte_hash_del_key(napt_common_table, &second_key);
9515         p_nat->n_cgnapt_entry_deleted++;
9516
9517         return rsp;
9518 }
9519
9520 void *pipeline_cgnapt_msg_req_entry_sync_handler(struct pipeline *p, void *msg)
9521 {
9522         struct pipeline_cgnapt_entry_delete_msg_req *req = msg;
9523         struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9524
9525         rsp->status = rte_pipeline_table_entry_delete(
9526                                 p->p,
9527                                 p->table_id[0],
9528                                 &req->key,
9529                                 &rsp->key_found, NULL);
9530
9531         return rsp;
9532 }
9533
9534 /**
9535  * Function to print the NAPT key
9536  *
9537  * @param key
9538  *  A pointer to struct pipeline_cgnapt_entry_key
9539  */
9540 void print_key(struct pipeline_cgnapt_entry_key *key)
9541 {
9542         uint8_t *KeyP = (void *)(key);
9543         int i = 0;
9544
9545         printf("\nKey: ");
9546         for (i = 0; i < (int)sizeof(struct pipeline_cgnapt_entry_key); i++)
9547                 printf(" %02x", KeyP[i]);
9548 }
9549
9550 /**
9551  * Function to print the table entry
9552  *
9553  * @param entry
9554  *  A pointer to struct rte_pipeline_table_entry
9555  */
9556 void print_entry1(struct rte_pipeline_table_entry *entry)
9557 {
9558         uint8_t *entryP = (void *)(entry);
9559         int i = 0;
9560
9561         printf("Entry: ");
9562         for (i = 0; i < (int)sizeof(struct rte_pipeline_table_entry); i++)
9563                 printf(" %02x", entryP[i]);
9564 }
9565
9566 /**
9567  * Function to print the NAPT table entry
9568  *
9569  * @param entry
9570  *  A pointer to struct cgnapt_table_entry
9571  */
9572 void print_cgnapt_entry(struct cgnapt_table_entry *entry)
9573 {
9574         uint8_t *entryP = (void *)(entry);
9575         int i = 0;
9576
9577         printf("CGNAPT Entry: ");
9578         for (i = 0; i < (int)sizeof(struct cgnapt_table_entry); i++)
9579                 printf(" %02x", entryP[i]);
9580         printf(" size:%d\n", (int)sizeof(struct cgnapt_table_entry));
9581 }
9582
9583 /**
9584  * Function to get a free port
9585  *
9586  * @param p_nat
9587  *  A pointer to struct pipeline_cgnapt
9588  * @param public_ip
9589  *  A uint32_t pointer to return corresponding ip address
9590  *
9591  * @return
9592  *  free port number, 0 if error
9593  */
9594 int get_free_iport(struct pipeline_cgnapt *p_nat, uint32_t *public_ip)
9595 {
9596         int port = -1;
9597         /* If we don't have a valid napt_port_alloc_elem get one from
9598         * port_alloc_ring
9599         */
9600         if (p_nat->allocated_ports == NULL) {
9601                 void *ports;
9602                 int ret;
9603
9604                 ret = rte_ring_dequeue(p_nat->port_alloc_ring, &ports);
9605                 if (ret == 0) {
9606                         p_nat->allocated_ports =
9607                                 (struct napt_port_alloc_elem *)ports;
9608
9609                         #ifdef CGNAPT_DEBUGGING
9610                         p_nat->gfp_get++;
9611                         #endif
9612
9613                         #ifdef CGNAPT_DBG_PRNT
9614                         if (CGNAPT_DEBUG > 3)
9615                                 printf("p_nat->allocated_ports %p\n",
9616                                                  p_nat->allocated_ports);
9617                         #endif
9618                 } else {
9619                         printf("CGNAPT Err - get_free_iport rte_ring_dequeue "
9620                         "failed");
9621                         printf("%d, %d, %d\n", rte_ring_count(
9622                         p_nat->port_alloc_ring), rte_ring_free_count(
9623                         p_nat->port_alloc_ring), ret);
9624
9625                         #ifdef CGNAPT_DEBUGGING
9626                         #ifdef CGNAPT_DBG_PRNT
9627                         printf("Th%d GFP:: %" PRIu64 ", %" PRIu64 ", "
9628                         "%" PRIu64", %" PRIu64 ",\n", p_nat->pipeline_num,
9629                         p_nat->gfp_get, p_nat->gfp_ret, p_nat->gfp_suc,
9630                         p_nat->gfp_err);
9631
9632                         p_nat->gfp_err++;
9633                         #endif
9634                         #endif
9635                         return port;
9636                 }
9637         }
9638
9639         /* get the port from index count-1 and decrease count */
9640         port = p_nat->allocated_ports->ports
9641                         [p_nat->allocated_ports->count - 1];
9642         *public_ip = p_nat->allocated_ports->ip_addr
9643                         [p_nat->allocated_ports->count - 1];
9644
9645         p_nat->allocated_ports->count -= 1;
9646
9647         /* if count is zero, return buffer to mem pool */
9648         if (p_nat->allocated_ports->count == 0) {
9649                 rte_mempool_put(napt_port_pool, p_nat->allocated_ports);
9650
9651                 #ifdef CGNAPT_DEBUGGING
9652                 p_nat->gfp_ret++;
9653                 #ifdef CGNAPT_DBG_PRNT
9654                 printf("Th%d Returned to pool p_nat->allocated_ports %p,",
9655                                  p_nat->pipeline_num, p_nat->allocated_ports);
9656                 printf("%" PRIu64 ", %" PRIu64 ",",
9657                         p_nat->gfp_get, p_nat->gfp_ret);
9658                 printf("%" PRIu64 ", %" PRIu64 ",\n",
9659                         p_nat->gfp_suc, p_nat->gfp_err);
9660                 #endif
9661                 #endif
9662
9663                 p_nat->allocated_ports = NULL;
9664         }
9665
9666         #ifdef CGNAPT_DEBUGGING
9667         p_nat->gfp_suc++;
9668         #endif
9669
9670         return port;
9671 }
9672
9673 /**
9674  * Function to free a port
9675  *
9676  * @param port_num
9677  *  Port number to free
9678  * @param public_ip
9679  *  Corresponding ip address
9680  * @param p_nat
9681  *  A pointer to struct pipeline_cgnapt
9682  *
9683  */
9684 void release_iport(uint16_t port_num, uint32_t public_ip,
9685                          struct pipeline_cgnapt *p_nat)
9686 {
9687         /* If we don't have a valid napt_port_alloc_elem get one
9688         * from mem pool
9689         */
9690         if (p_nat->free_ports == NULL) {
9691                 void *ports;
9692
9693                 #ifdef CGNAPT_DEBUGGING
9694                 p_nat->pfb_get++;
9695                 #endif
9696
9697                 if (rte_mempool_get(napt_port_pool, &ports) < 0) {
9698                         #ifdef CGNAPT_DEBUGGING
9699                         p_nat->pfb_err++;
9700                         #endif
9701                         printf("CGNAPT release_iport error in getting "
9702                         "port alloc buffer\n");
9703                         return;
9704                 }
9705
9706                 p_nat->free_ports = (struct napt_port_alloc_elem *)ports;
9707                 p_nat->free_ports->count = 0;
9708         }
9709
9710         /* put the port at index count and increase count */
9711         p_nat->free_ports->ip_addr[p_nat->free_ports->count] = public_ip;
9712         p_nat->free_ports->ports[p_nat->free_ports->count] = port_num;
9713         p_nat->free_ports->count += 1;
9714
9715         /* if napt_port_alloc_elem is full add it to ring */
9716         {
9717
9718         #ifdef CGNAPT_DEBUGGING
9719         p_nat->pfb_ret++;
9720         #endif
9721
9722         #ifdef CGNAPT_DBG_PRNT
9723         if (CGNAPT_DEBUG >= 2) {
9724                 printf("CGNAPT port_alloc_ring before EnQ Cnt %d, Free %d\n",
9725                                  rte_ring_count(p_nat->port_alloc_ring),
9726                                  rte_ring_free_count(p_nat->port_alloc_ring));
9727                 }
9728         #endif
9729
9730         if (rte_ring_enqueue(p_nat->port_alloc_ring,
9731                 (void *)p_nat->free_ports) != 0) {
9732                 printf("CGNAPT release_iport  Enqueue error %p\n",
9733                         p_nat->free_ports);
9734
9735                 #ifdef CGNAPT_DEBUGGING
9736                 p_nat->pfb_err++;
9737                 #endif
9738                 }
9739
9740                 #ifdef CGNAPT_DBG_PRNT
9741                 if (CGNAPT_DEBUG >= 2) {
9742                         printf("CGNAPT port_alloc_ring after EnQ Cnt %d",
9743                                 rte_ring_count(p_nat->port_alloc_ring));
9744                         printf("Free %d\n",
9745                                 rte_ring_free_count(p_nat->port_alloc_ring));
9746                 }
9747                 #endif
9748
9749                 p_nat->free_ports = NULL;
9750         }
9751
9752         #ifdef CGNAPT_DEBUGGING
9753         p_nat->pfb_suc++;
9754         #endif
9755 }
9756
9757 /**
9758  * Function to initialize max ports per client data structures
9759  * Called during dynamic NAPT initialization.
9760  *
9761  * @param p_nat
9762  *  A pointer to struct pipeline_cgnapt
9763  *
9764  * @return
9765  *  0 if success, negative if error
9766  */
9767 int init_max_port_per_client(
9768         __rte_unused struct pipeline_cgnapt *p_nat)
9769 {
9770         if (max_port_per_client_hash)
9771                 return -1;
9772
9773         /*MPPC_ALREADY_EXISTS */
9774
9775         int i = 0;
9776
9777         max_port_per_client_hash =
9778                 rte_hash_create(&max_port_per_client_hash_params);
9779         if (!max_port_per_client_hash)
9780                 return -2;
9781
9782         /*MPPC_HASH_CREATE_ERROR */
9783
9784         max_port_per_client_array =
9785                 rte_zmalloc(NULL,
9786                         sizeof(struct max_port_per_client) * MAX_DYN_ENTRY,
9787                         RTE_CACHE_LINE_SIZE);
9788         if (!max_port_per_client_array)
9789                 return -3;
9790
9791         /*MPPC_ARRAY_CREATE_ERROR */
9792
9793         for (i = 0; i < MAX_DYN_ENTRY; i++) {
9794                 max_port_per_client_array[i].prv_ip = 0;
9795                 max_port_per_client_array[i].prv_phy_port = 0;
9796                 max_port_per_client_array[i].max_port_cnt = 0;
9797         }
9798
9799         return 0;
9800         /*MPPC_SUCCESS */
9801 }
9802
9803 /**
9804  * Function to check if max ports for a client is reached
9805  *
9806  * @param prv_ip_param
9807  *  A uint32_t ip address of client
9808  * @param prv_phy_port_param
9809  *  A uint32_t physical port id of the client
9810  * @param p_nat
9811  *  A pointer to struct pipeline_cgnapt
9812  *
9813  * @return
9814  *  0 if max port not reached, 1 if reached, -1 if error
9815  */
9816 int is_max_port_per_client_reached(uint32_t prv_ip_param,
9817                                          uint32_t prv_phy_port_param,
9818                                          struct pipeline_cgnapt *p_nat)
9819 {
9820         int index = MAX_PORT_INVALID_KEY;
9821
9822         struct max_port_per_client_key key = {
9823                 .prv_ip = prv_ip_param,
9824                 .prv_phy_port = prv_phy_port_param,
9825         };
9826
9827         index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9828
9829         if (index < 0)
9830                 return MAX_PORT_INVALID_KEY;
9831
9832         if (max_port_per_client_array[index].max_port_cnt >=
9833                 p_nat->max_port_per_client)
9834                 return MAX_PORT_REACHED;
9835
9836         return MAX_PORT_NOT_REACHED;
9837 }
9838
9839 /**
9840  * Function to increase max ports for a client
9841  *
9842  * @param prv_ip_param
9843  *  A uint32_t ip address of client
9844  * @param prv_phy_port_param
9845  *  A uint32_t physical port id of the client
9846  * @param p_nat
9847  *  A pointer to struct pipeline_cgnapt
9848  *
9849  * @return
9850  *  0 if max port reached, 1 if success, 2 if new entry, -1 if error
9851  */
9852 int increment_max_port_counter(uint32_t prv_ip_param,
9853                                          uint32_t prv_phy_port_param,
9854                                          struct pipeline_cgnapt *p_nat)
9855 {
9856         int index = MAX_PORT_INC_ERROR;
9857
9858         struct max_port_per_client_key key = {
9859                 .prv_ip = prv_ip_param,
9860                 .prv_phy_port = prv_phy_port_param,
9861         };
9862
9863         index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9864
9865         if (index == -EINVAL)
9866                 return MAX_PORT_INC_ERROR;
9867
9868         if (index == -ENOENT) {
9869                 if (max_port_per_client_add_entry(prv_ip_param,
9870                                                         prv_phy_port_param,
9871                                                         p_nat) <= 0)
9872                         return MAX_PORT_INC_ERROR;
9873
9874                 return 2;       /*return MAX_PORT_NEW_ENTRY; */
9875         }
9876
9877         if (CGNAPT_DEBUG > 2)
9878                 printf("%s: max_port_cnt(%d), p_nat_max(%d)\n", __func__,
9879                         max_port_per_client_array[index].max_port_cnt,
9880                         p_nat->max_port_per_client);
9881
9882         if (max_port_per_client_array[index].max_port_cnt <
9883                 p_nat->max_port_per_client) {
9884                 max_port_per_client_array[index].max_port_cnt++;
9885                 return MAX_PORT_INC_SUCCESS;
9886         }
9887
9888         return MAX_PORT_INC_REACHED;
9889 }
9890
9891 /**
9892  * Function to decrease max ports for a client
9893  *
9894  * @param prv_ip_param
9895  *  A uint32_t ip address of client
9896  * @param prv_phy_port_param
9897  *  A uint32_t physical port id of the client
9898  * @param p_nat
9899  *  A pointer to struct pipeline_cgnapt
9900  *
9901  * @return
9902  *  0 if count already 0, 1 if success, -1 if error
9903  */
9904 int decrement_max_port_counter(uint32_t prv_ip_param,
9905                                          uint32_t prv_phy_port_param,
9906                                          struct pipeline_cgnapt *p_nat)
9907 {
9908         int index = MAX_PORT_DEC_ERROR;
9909
9910         struct max_port_per_client_key key = {
9911                 .prv_ip = prv_ip_param,
9912                 .prv_phy_port = prv_phy_port_param,
9913         };
9914
9915         index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9916         if (index < 0) {
9917
9918                 #ifdef CGNAPT_DEBUGGING
9919                 p_nat->max_port_dec_err1++;
9920                 #endif
9921                 return MAX_PORT_DEC_ERROR;
9922
9923         }
9924
9925         if (max_port_per_client_array[index].max_port_cnt > 0) {
9926                 /* If it is the last port,ret this info which is used for
9927                 *  max_cli_per_pub_ip
9928                 */
9929
9930                 max_port_per_client_array[index].max_port_cnt--;
9931                 /* Count should be atomic but we are good as we have only
9932                 * one task handling this counter at a time (core affinity)
9933                 */
9934         }
9935
9936         if (max_port_per_client_array[index].max_port_cnt <= 0) {
9937                 if (max_port_per_client_del_entry
9938                         (prv_ip_param, prv_phy_port_param, p_nat) <= 0) {
9939
9940                         #ifdef CGNAPT_DEBUGGING
9941                         p_nat->max_port_dec_err2++;
9942                         #endif
9943                         return MAX_PORT_DEC_ERROR;
9944                 }
9945
9946                 #ifdef CGNAPT_DEBUGGING
9947                 p_nat->max_port_dec_err3++;
9948                 #endif
9949
9950                 return MAX_PORT_DEC_REACHED;
9951         }
9952
9953         #ifdef CGNAPT_DEBUGGING
9954         p_nat->max_port_dec_success++;
9955         #endif
9956
9957         return MAX_PORT_DEC_SUCCESS;
9958 }
9959
9960 /**
9961  * Function to add a max ports per client entry
9962  *
9963  * @param prv_ip_param
9964  *  A uint32_t ip address of client
9965  * @param prv_phy_port_param
9966  *  A uint32_t physical port id of the client
9967  * @param p_nat
9968  *  A pointer to struct pipeline_cgnapt
9969  *
9970  * @return
9971  *  0 no success, 1 if success, -1 if error
9972  */
9973 int max_port_per_client_add_entry(
9974         uint32_t prv_ip_param,
9975         uint32_t prv_phy_port_param,
9976         __rte_unused struct pipeline_cgnapt *p_nat)
9977 {
9978         int index = MAX_PORT_ADD_ERROR;
9979
9980         struct max_port_per_client_key key = {
9981                 .prv_ip = prv_ip_param,
9982                 .prv_phy_port = prv_phy_port_param,
9983         };
9984
9985         index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9986         if (index == -EINVAL)
9987                 return MAX_PORT_ADD_ERROR;
9988
9989         if (index >= 0)
9990                 return MAX_PORT_ADD_UNSUCCESS;
9991
9992         if (index == -ENOENT) {
9993
9994                 #ifdef CGNAPT_DBG_PRNT
9995                 if (CGNAPT_DEBUG > 2)
9996                         printf("max_port_per_client_add_entry fn: "
9997                         "Entry does not exist\n");
9998                 #endif
9999
10000                 index =
10001                         rte_hash_add_key(max_port_per_client_hash,
10002                                          (const void *)&key);
10003                 if (index == -ENOSPC)
10004                         return MAX_PORT_ADD_UNSUCCESS;
10005
10006                 #ifdef CGNAPT_DBG_PRNT
10007                 if (CGNAPT_DEBUG > 2)
10008                         printf("max_port_per_client_add_entry fn:"
10009                         "Add entry index(%d)\n", index);
10010                 #endif
10011
10012                 max_port_per_client_array[index].prv_ip = prv_ip_param;
10013                 max_port_per_client_array[index].prv_phy_port =
10014                         prv_phy_port_param;
10015         }
10016
10017         max_port_per_client_array[index].max_port_cnt++;
10018         return MAX_PORT_ADD_SUCCESS;
10019 }
10020
10021 /**
10022  * Function to delete a max ports per client entry
10023  *
10024  * @param prv_ip_param
10025  *  A uint32_t ip address of client
10026  * @param prv_phy_port_param
10027  *  A uint32_t physical port id of the client
10028  * @param p_nat
10029  *  A pointer to struct pipeline_cgnapt
10030  *
10031  * @return
10032  *  0 no success, 1 if success, -1 if error
10033  */
10034 int max_port_per_client_del_entry(
10035         uint32_t prv_ip_param,
10036         uint32_t prv_phy_port_param,
10037         __rte_unused struct pipeline_cgnapt *p_nat)
10038 {
10039         int index = MAX_PORT_DEL_ERROR;
10040
10041         struct max_port_per_client_key key = {
10042                 .prv_ip = prv_ip_param,
10043                 .prv_phy_port = prv_phy_port_param,
10044         };
10045
10046         index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
10047
10048         if (index == -EINVAL)
10049                 return MAX_PORT_DEL_ERROR;
10050
10051         if (index == -ENOENT)
10052                 return MAX_PORT_DEL_UNSUCCESS;
10053
10054         index = rte_hash_del_key(max_port_per_client_hash, (const void *)&key);
10055         max_port_per_client_array[index].prv_ip = 0;
10056         max_port_per_client_array[index].prv_phy_port = 0;
10057         max_port_per_client_array[index].max_port_cnt = 0;
10058
10059         return MAX_PORT_DEL_SUCCESS;
10060 }
10061
10062 /**
10063  * Function to execute debug commands
10064  *
10065  * @param p
10066  *  A pointer to struct pipeline
10067  * @param msg
10068  *  void pointer to incoming arguments
10069  */
10070 void *pipeline_cgnapt_msg_req_entry_dbg_handler(struct pipeline *p, void *msg)
10071 {
10072         struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
10073         uint8_t *Msg = msg;
10074         struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
10075
10076         rsp->status = 0;
10077
10078         if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_STATS_SHOW) {
10079                 printf("\nCG-NAPT Packet Stats:\n");
10080                 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10081                 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10082                 printf("Dropped %" PRIu64 ",",  p_nat->naptDroppedPktCount);
10083                 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10084                 printf("ingress %" PRIu64 ",",  p_nat->inaptedPktCount);
10085                 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10086                 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10087
10088                 #ifdef CGNAPT_DEBUGGING
10089                 printf("\n Drop detail 1:%" PRIu64 ",",
10090                                 p_nat->naptDroppedPktCount1);
10091                 printf("\n Drop detail 2:%" PRIu64 ",",
10092                                 p_nat->naptDroppedPktCount2);
10093                 printf("\n Drop detail 3:%" PRIu64 ",",
10094                                 p_nat->naptDroppedPktCount3);
10095                 printf("\n Drop detail 4:%" PRIu64 ",",
10096                                 p_nat->naptDroppedPktCount4);
10097                 printf("\n Drop detail 5:%" PRIu64 ",",
10098                                 p_nat->naptDroppedPktCount5);
10099                 printf("\n Drop detail 6:%" PRIu64 "",
10100                                 p_nat->naptDroppedPktCount6);
10101
10102                 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10103                                 p_nat->missedpktcount1,
10104                                 p_nat->missedpktcount2);
10105                 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10106                                 p_nat->missedpktcount3,
10107                                 p_nat->missedpktcount4);
10108                 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10109                                 p_nat->missedpktcount5,
10110                                 p_nat->missedpktcount6);
10111                 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10112                                 p_nat->missedpktcount7,
10113                                 p_nat->missedpktcount8);
10114                 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10115                                 p_nat->missedpktcount9,
10116                                 p_nat->missedpktcount10);
10117
10118                 #endif
10119
10120                 return rsp;
10121         }
10122
10123         if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_STATS_CLEAR) {
10124                 printf("\nCG-NAPT Packet Stats:\n");
10125                 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10126                 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10127                 printf("Dropped %" PRIu64 ",",  p_nat->naptDroppedPktCount);
10128                 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10129                 printf("ingress %" PRIu64 ",",  p_nat->inaptedPktCount);
10130                 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10131                 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10132
10133                 p_nat->naptedPktCount = 0;
10134                 p_nat->naptDroppedPktCount = 0;
10135                 p_nat->inaptedPktCount = 0;
10136                 p_nat->enaptedPktCount = 0;
10137                 p_nat->receivedPktCount = 0;
10138                 p_nat->missedPktCount = 0;
10139                 p_nat->arpicmpPktCount = 0;
10140                 printf("CG-NAPT Packet Stats cleared\n");
10141                 return rsp;
10142         }
10143
10144         if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DBG_LEVEL) {
10145                 CGNAPT_DEBUG = Msg[CGNAPT_DBG_CMD_OFST + 1];
10146                 printf("CG-NAPT debug level set to %d\n", CGNAPT_DEBUG);
10147                 return rsp;
10148         }
10149
10150         if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DBG_SHOW) {
10151
10152                 printf("\nNAPT entries - added %" PRIu64 ",",
10153                                 p_nat->n_cgnapt_entry_added);
10154                 printf("deleted %" PRIu64 ",", p_nat->n_cgnapt_entry_deleted);
10155                 printf("current %" PRIu64 "", p_nat->n_cgnapt_entry_added -
10156                                 p_nat->n_cgnapt_entry_deleted);
10157
10158                 printf("\nCG-NAPT Packet Stats:\n");
10159                 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10160                 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10161                 printf("Dropped %" PRIu64 ",",  p_nat->naptDroppedPktCount);
10162                 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10163                 printf("ingress %" PRIu64 ",",  p_nat->inaptedPktCount);
10164                 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10165                 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10166
10167                 return rsp;
10168         }
10169         #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
10170         if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_INSTRUMENTATION) {
10171                 if (Msg[CGNAPT_DBG_CMD_OFST1] ==
10172                         CGNAPT_CMD_INSTRUMENTATION_SUB0) {
10173
10174                 int index = 0;
10175                 uint32_t diff_sum = 0;
10176
10177                 printf("CG-NAPT Instrumentation ...\n");
10178                 printf("Instrumentation data collected for fn# %d\n",
10179                         cgnapt_num_func_to_inst);
10180                 printf("Current collection index %d\n",
10181                 cgnapt_inst_index);
10182
10183         if (Msg[CGNAPT_DBG_CMD_OFST + 2] == 2) {
10184                 printf("Timer Start:\n");
10185
10186                 for (index = 0; index < INST_ARRAY_SIZE; index++) {
10187                         if ((index % 5) == 0)
10188                                 printf("\n");
10189                         printf(" 0x%jx", inst_start_time[index]);
10190                 }
10191                 printf("\n\nTimer End:\n");
10192
10193                 for (index = 0; index < INST_ARRAY_SIZE; index++) {
10194                         if ((index % 5) == 0)
10195                                 printf("\n");
10196                         printf(" 0x%jx", inst_end_time[index]);
10197                 }
10198         }
10199
10200         for (index = 0; index < INST_ARRAY_SIZE; index++) {
10201                 inst_diff_time[index] = (uint32_t) (inst_end_time[index] -
10202                                                 inst_start_time[index]);
10203         }
10204
10205         if (Msg[CGNAPT_DBG_CMD_OFST + 2] ==
10206                 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
10207                 printf("\n\nTimer Diff:\n");
10208
10209         for (index = 0; index < INST_ARRAY_SIZE; index++) {
10210                 if (Msg[CGNAPT_DBG_CMD_OFST + 2] ==
10211                         CGNAPT_CMD_INSTRUMENTATION_SUB1) {
10212                         if ((index % 5) == 0)
10213                                 printf("\n");
10214                         printf(" 0x%08x", inst_diff_time[index]);
10215                 }
10216
10217                 diff_sum += inst_diff_time[index];
10218         }
10219
10220         printf("\ndiff_sum %u, INST_ARRAY_SIZE %d, Ave Time %u\n",
10221                 diff_sum, INST_ARRAY_SIZE, (diff_sum / INST_ARRAY_SIZE));
10222         } else if (Msg[CGNAPT_DBG_CMD_OFST + 1] ==
10223                 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
10224                 /* p plid entry dbg 7 1 0
10225                 *  p plid entry dbg 7 1 1 <--- pkt_work_cgnapt
10226                 *  p plid entry dbg 7 1 2 <--- pkt4_work_cgnapt
10227                 *  p plid entry dbg 7 1 3 <--- pkt_work_cgnapt_key
10228                 *  p plid entry dbg 7 1 4 <--- pkt4_work_cgnapt_key
10229                 *  p plid entry dbg 7 1 5 <--- in port ah to out port ah
10230                 *                               - pkt life in the system
10231                 *  p plid entry dbg 7 1 6 <--- how long this instrumentation
10232                 *                               itself is taking
10233                 */
10234                 cgnapt_inst_index = 0;
10235                 cgnapt_num_func_to_inst = Msg[CGNAPT_DBG_CMD_OFST + 2];
10236                 printf("Instrumentation data collection started for fn# %d\n",
10237                                  cgnapt_num_func_to_inst);
10238         } else if (Msg[CGNAPT_DBG_CMD_OFST + 1] ==
10239                         CGNAPT_CMD_INSTRUMENTATION_SUB2) {
10240                 /*  p plid entry dbg 7 2 0
10241                 *   Test all major functions by calling them multiple times
10242                 *   pkt_work_cgnapt, pkt4_work_cgnapt, pkt_work_cgnapt_key,
10243                 *   pkt4_work_cgnapt_key
10244                 */
10245                 if (cgnapt_test_pktmbuf_pool == NULL) {
10246                         cgnapt_test_pktmbuf_pool = rte_pktmbuf_pool_create(
10247                                 "cgnapt_test_pktmbuf_pool", 63, 32, 0,
10248                                 RTE_MBUF_DEFAULT_BUF_SIZE,
10249                                 rte_socket_id());
10250                 }
10251
10252                 if (cgnapt_test_pktmbuf_pool == NULL)
10253                         printf("CGNAPT test mbuf pool create failed.\n");
10254
10255                         struct rte_mbuf *cgnapt_test_pkt0 =
10256                                 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
10257                         if (cgnapt_test_pkt0 == NULL)
10258                                 printf("CGNAPT test pkt 0 alloc failed.");
10259                         struct rte_mbuf *cgnapt_test_pkt1 =
10260                                 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
10261                         if (cgnapt_test_pkt1 == NULL)
10262                                 printf("CGNAPT test pkt 1 alloc failed.");
10263                         struct rte_mbuf *cgnapt_test_pkt2 =
10264                                 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
10265                         if (cgnapt_test_pkt2 == NULL)
10266                                 printf("CGNAPT test pkt 2 alloc failed.");
10267                         struct rte_mbuf *cgnapt_test_pkt3 =
10268                                 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
10269                         if (cgnapt_test_pkt3 == NULL)
10270                                 printf("CGNAPT test pkt 3 alloc failed.");
10271
10272                         struct rte_mbuf *cgnapt_test_pkts[4];
10273
10274                         cgnapt_test_pkts[0] = cgnapt_test_pkt0;
10275                         cgnapt_test_pkts[1] = cgnapt_test_pkt1;
10276                         cgnapt_test_pkts[2] = cgnapt_test_pkt2;
10277                         cgnapt_test_pkts[3] = cgnapt_test_pkt3;
10278
10279                 uint32_t src_addr_offset =
10280                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_SRC_ADR_OFST;
10281                 /* header room + eth hdr size +
10282                 * src_aadr offset in ip header
10283                 */
10284                 uint32_t dst_addr_offset =
10285                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
10286                 /* header room + eth hdr size +
10287                 * dst_aadr offset in ip header
10288                 */
10289                 uint32_t prot_offset =
10290                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_PROTOCOL_OFST;
10291                 /* header room + eth hdr size +
10292                 * srprotocol char offset in ip header
10293                 */
10294                 int pktCnt = 0, entCnt = 0, exCnt = 0;
10295
10296                 for (pktCnt = 0; pktCnt < 4; pktCnt++) {
10297                         uint32_t *src_addr =
10298                                 RTE_MBUF_METADATA_UINT32_PTR
10299                                 (cgnapt_test_pkts[pktCnt], src_addr_offset);
10300                         uint32_t *dst_addr =
10301                                 RTE_MBUF_METADATA_UINT32_PTR
10302                                 (cgnapt_test_pkts[pktCnt], dst_addr_offset);
10303                         uint8_t *protocol =
10304                                 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10305                                                         [pktCnt],
10306                                                         prot_offset);
10307                         uint8_t *phy_port =
10308                                 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10309                                                         [pktCnt], 70);
10310                         uint8_t *eth_dest =
10311                                 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10312                                                         [pktCnt],
10313                                                         MBUF_HDR_ROOM);
10314                         uint8_t *eth_src =
10315                                 RTE_MBUF_METADATA_UINT8_PTR(
10316                                         cgnapt_test_pkts[pktCnt],
10317                                                         MBUF_HDR_ROOM +
10318                                                         6);
10319                         uint16_t *src_port =
10320                                 RTE_MBUF_METADATA_UINT16_PTR
10321                                 (cgnapt_test_pkts[pktCnt],
10322                                  MBUF_HDR_ROOM + ETH_HDR_SIZE +
10323                                  IP_HDR_SIZE);
10324                         uint16_t *dst_port =
10325                                 RTE_MBUF_METADATA_UINT16_PTR
10326                                 (cgnapt_test_pkts[pktCnt],
10327                                  MBUF_HDR_ROOM + ETH_HDR_SIZE +
10328                                  IP_HDR_SIZE + 2);
10329                         *src_addr = 0xc0a80001;
10330                         *dst_addr = 0x90418634;
10331                         *protocol = 0x6;
10332                         *phy_port = 0;
10333                         *src_port = 1234;
10334                         *dst_port = 4000;
10335                         eth_src[0] = 0xAB;
10336                         eth_src[1] = 0xAB;
10337                         eth_src[2] = 0xAB;
10338                         eth_src[3] = 0xAB;
10339                         eth_src[4] = 0xAB;
10340                         eth_src[5] = 0xAB;
10341                         eth_dest[0] = 0x90;
10342                         eth_dest[1] = 0xE2;
10343                         eth_dest[2] = 0xba;
10344                         eth_dest[3] = 0x54;
10345                         eth_dest[4] = 0x67;
10346                         eth_dest[5] = 0xc8;
10347                 }
10348                 struct rte_pipeline_table_entry *table_entries[4];
10349                 struct cgnapt_table_entry ctable_entries[4];
10350                         table_entries[0] = (struct rte_pipeline_table_entry *)
10351                         &ctable_entries[0];
10352                 table_entries[1] = (struct rte_pipeline_table_entry *)
10353                         &ctable_entries[1];
10354                 table_entries[2] = (struct rte_pipeline_table_entry *)
10355                         &ctable_entries[2];
10356                 table_entries[3] = (struct rte_pipeline_table_entry *)
10357                         &ctable_entries[3];
10358                 for (entCnt = 0; entCnt < 4; entCnt++) {
10359                         ctable_entries[entCnt].head.action =
10360                                 RTE_PIPELINE_ACTION_PORT;
10361                         ctable_entries[entCnt].head.port_id = 0;
10362
10363                         ctable_entries[entCnt].data.prv_ip = 0x01020304;
10364                         ctable_entries[entCnt].data.prv_port = 1234;
10365                         ctable_entries[entCnt].data.pub_ip = 0x0a0b0c0d;
10366                         ctable_entries[entCnt].data.pub_port = 4000;
10367                         ctable_entries[entCnt].data.prv_phy_port = 0;
10368                         ctable_entries[entCnt].data.pub_phy_port = 1;
10369                         ctable_entries[entCnt].data.ttl = 500;
10370                 }
10371
10372                 uint64_t time1 = rte_get_tsc_cycles();
10373
10374                 for (exCnt = 0; exCnt < 1000; exCnt++) {
10375                         pkt_work_cgnapt_key(cgnapt_test_pkts[0],
10376                                         instrumentation_port_in_arg);
10377                 }
10378                         uint64_t time2 = rte_get_tsc_cycles();
10379
10380                         printf("times for %d times execution of "
10381                                 "pkt_work_cgnapt_key 0x%jx",
10382                                 exCnt, time1);
10383                         printf(", 0x%jx, diff %" PRIu64 "\n", time2,
10384                                 time2 - time1);
10385
10386                         time1 = rte_get_tsc_cycles();
10387                         for (exCnt = 0; exCnt < 1000000; exCnt++) {
10388                                 pkt_work_cgnapt_key(cgnapt_test_pkts[0],
10389                                         instrumentation_port_in_arg);
10390                         }
10391                         time2 = rte_get_tsc_cycles();
10392                         printf("times for %d times execution of "
10393                                 "pkt_work_cgnapt_key 0x%jx", exCnt, time1);
10394                         printf("0x%jx, diff %" PRIu64 "\n", time2,
10395                                 time2 - time1);
10396
10397                         time1 = rte_get_tsc_cycles();
10398                         for (exCnt = 0; exCnt < 1000; exCnt++) {
10399                                 pkt4_work_cgnapt_key(cgnapt_test_pkts,
10400                                         instrumentation_port_in_arg);
10401                         }
10402                         time2 = rte_get_tsc_cycles();
10403                         printf("times for %d times execution of "
10404                                 "pkt4_work_cgnapt_key 0x%jx",
10405                                 exCnt, time1);
10406                         printf(" 0x%jx, diff %" PRIu64 "\n", time2,
10407                                 time2 - time1);
10408
10409                         time1 = rte_get_tsc_cycles();
10410                         for (exCnt = 0; exCnt < 1000000; exCnt++) {
10411                                 pkt4_work_cgnapt_key(cgnapt_test_pkts,
10412                                         instrumentation_port_in_arg);
10413                         }
10414                         time2 = rte_get_tsc_cycles();
10415                         printf("times for %d times execution of "
10416                                 "pkt4_work_cgnapt_key 0x%jx",
10417                                 exCnt, time1);
10418                         printf("0x%jx, diff %" PRIu64 "\n", time2,
10419                                 time2 - time1);
10420
10421                         uint64_t mask = 0xff;
10422
10423                         time1 = rte_get_tsc_cycles();
10424                         for (exCnt = 0; exCnt < 1000; exCnt++) {
10425                                 pkt_work_cgnapt(cgnapt_test_pkts[0],
10426                                                 table_entries[0], 3, &mask,
10427                                                 NULL);
10428                         }
10429                         time2 = rte_get_tsc_cycles();
10430                         printf("times for %d times execution of "
10431                                 "pkt_work_cgnapt 0x%jx",
10432                                 exCnt, time1);
10433                         printf("0x%jx, diff %" PRIu64 "\n", time2,
10434                                 time2 - time1);
10435
10436                         time1 = rte_get_tsc_cycles();
10437                         for (exCnt = 0; exCnt < 1000000; exCnt++) {
10438                                 pkt_work_cgnapt(cgnapt_test_pkts[0],
10439                                                 table_entries[0], 3, &mask,
10440                                                 NULL);
10441                         }
10442                         time2 = rte_get_tsc_cycles();
10443                         printf("times for %d times execution of "
10444                                 "pkt_work_cgnapt 0x%jx",
10445                                 exCnt, time1);
10446                         printf("0x%jx, diff %" PRIu64 "\n", time2,
10447                                 time2 - time1);
10448
10449                         time1 = rte_get_tsc_cycles();
10450                         for (exCnt = 0; exCnt < 1000; exCnt++) {
10451                                 pkt4_work_cgnapt(cgnapt_test_pkts,
10452                                                  table_entries, 0, &mask, NULL);
10453                         }
10454                         time2 = rte_get_tsc_cycles();
10455                         printf("times for %d times execution of "
10456                                 "pkt4_work_cgnapt 0x%jx",
10457                                 exCnt, time1);
10458                         printf("0x%jx, diff % " PRIu64 "\n", time2,
10459                                 time2 - time1);
10460
10461                         int idummy = ctable_entries[0].data.prv_port;
10462
10463                         idummy++;
10464
10465                 }
10466         }
10467                 return rsp;
10468         }
10469         #endif
10470
10471         if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_LS_ENTRY) {
10472                 printf("CG-NAPT be entries are:\n");
10473                 printf("Pipeline pointer %p\n", p);
10474                 return rsp;
10475         }
10476
10477         if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DYN) {
10478                 printf("Total Number of dynamic napt entries: %" PRIu64 "\n",
10479                                  p_nat->dynCgnaptCount);
10480
10481                 #ifdef CGNAPT_DEBUGGING
10482                 printf("MAX PORT PER CLIENT:");
10483                 printf("%" PRIu64 ",%" PRIu64 ",%" PRIu64 "\n",
10484                                  p_nat->max_port_dec_err1, p_nat->max_port_dec_err2,
10485                                  p_nat->max_port_dec_err3);
10486                 printf("MPPC success : %" PRIu64 "\n",
10487                                  p_nat->max_port_dec_success);
10488
10489                 printf("Release port:err:%" PRIu64 ",ret::%" PRIu64 ",get::%"
10490                                  PRIu64 ",suc::%" PRIu64 "\n", p_nat->pfb_err,
10491                                  p_nat->pfb_ret, p_nat->pfb_get, p_nat->pfb_suc);
10492                 printf("Get port::err:%" PRIu64 ",ret::%" PRIu64 ",get::%"
10493                                  PRIu64 ",suc::%" PRIu64 "\n", p_nat->gfp_err,
10494                                  p_nat->gfp_ret, p_nat->gfp_get, p_nat->gfp_suc);
10495                 printf("Ring Info:\n");
10496                 rte_ring_dump(stdout, p_nat->port_alloc_ring);
10497                 #endif
10498                 return rsp;
10499         }
10500         if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_IPV6) {
10501                 dual_stack_enable = Msg[CGNAPT_DBG_CMD_OFST + 1];
10502                 printf("Dual Stack option set: %x\n", dual_stack_enable);
10503                 return rsp;
10504         }
10505
10506         if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_MAPS_INFO) {
10507                 pipelines_port_info();
10508                 pipelines_map_info();
10509                 return rsp;
10510         }
10511
10512         if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_ITER_COM_TBL) {
10513                 uint32_t count = 0;
10514                 const void *key;
10515                 void *data;
10516                 uint32_t next = 0;
10517                 int32_t index = 0;
10518
10519                 do {
10520                         index =
10521                                 rte_hash_iterate(napt_common_table, &key, &data,
10522                                                  &next);
10523
10524                         if ((index != -EINVAL) && (index != -ENOENT)) {
10525                                 printf("\n%04d  ", count);
10526                                 rte_hexdump(stdout, "KEY", key,
10527                                         sizeof(struct
10528                                                 pipeline_cgnapt_entry_key));
10529
10530                                 //print_key((struct pipeline_cgnapt_entry_key *)
10531                                 //              key);
10532                                 int32_t position =
10533                                         rte_hash_lookup(napt_common_table,
10534                                                 key);
10535                                 print_cgnapt_entry(&napt_hash_tbl_entries
10536                                                          [position]);
10537                         }
10538
10539                         count++;
10540                 } while (index != -ENOENT);
10541                 return rsp;
10542         }
10543
10544         if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_IF_STATS) {
10545
10546                 struct app_params *app =
10547                         (struct app_params *)p_nat->app_params_addr;
10548                 uint8_t cmd[2];
10549
10550                 cmd[0] = Msg[CGNAPT_DBG_CMD_OFST + 1];
10551                 cmd[1] = Msg[CGNAPT_DBG_CMD_OFST + 2];
10552                 switch (cmd[0]) {
10553                 case CGNAPT_IF_STATS_HWQ:
10554                         printf("n_pktq_hwq_int :%d\n", app->n_pktq_hwq_in);
10555                         printf("n_pktq_hwq_out :%d\n", app->n_pktq_hwq_out);
10556                         printf("\n");
10557                         uint8_t i, j;
10558
10559                         for (i = 0; i < app->n_pktq_hwq_in; i++) {
10560                                 struct rte_eth_stats stats;
10561
10562                                 rte_eth_stats_get(p_nat->links_map[i], &stats);
10563
10564                                 if (is_phy_port_privte(i))
10565                                         printf("Private Port Stats %d\n", i);
10566                                 else
10567                                         printf("Public Port Stats  %d\n", i);
10568
10569                                 printf("\n\tipackets : %" PRIu64 "",
10570                                                  stats.ipackets);
10571                                 printf("\n\topackets : %" PRIu64 "",
10572                                                  stats.opackets);
10573                                 printf("\n\tierrors  : %" PRIu64 "",
10574                                                  stats.ierrors);
10575                                 printf("\n\toerrors  : %" PRIu64 "",
10576                                                  stats.oerrors);
10577                                 printf("\n\trx_nombuf: %" PRIu64 "",
10578                                                  stats.rx_nombuf);
10579                                 printf("\n");
10580                                 if (is_phy_port_privte(i))
10581                                         printf("Private Q:");
10582                                 else
10583                                         printf("Public  Q:");
10584                                 for (j = 0; j < RTE_ETHDEV_QUEUE_STAT_CNTRS;
10585                                          j++)
10586                                         printf(" %" PRIu64 ", %" PRIu64 "|",
10587                                                          stats.q_ipackets[j],
10588                                                          stats.q_opackets[j]);
10589
10590                                 printf("\n\n");
10591
10592                         }
10593
10594                         return rsp;
10595
10596                 case CGNAPT_IF_STATS_SWQ:
10597
10598                         printf("n_pktq_swq :%d\n", app->n_pktq_swq);
10599
10600                         if (cmd[1] < app->n_pktq_swq) {
10601                                 rte_ring_dump(stdout, app->swq[cmd[1]]);
10602                                 return rsp;
10603                         }
10604                         printf("SWQ number is invalid\n");
10605                         return rsp;
10606
10607                 case CGNAPT_IF_STATS_OTH:
10608                         printf("\n");
10609                         printf("config_file:%s\n", app->config_file);
10610                         printf("script_file:%s\n", app->script_file);
10611                         printf("parser_file:%s\n", app->parser_file);
10612                         printf("output_file:%s\n", app->output_file);
10613                         printf("n_msgq :%d\n", app->n_msgq);
10614                         printf("n_pktq_tm :%d\n", app->n_pktq_tm);
10615                         printf("n_pktq_source :%d\n", app->n_pktq_source);
10616                         printf("n_pktq_sink :%d\n", app->n_pktq_sink);
10617                         printf("n_pipelines :%d\n", app->n_pipelines);
10618                         printf("\n");
10619                         return rsp;
10620                 default:
10621                         printf("Command does not match\n\n");
10622                         return rsp;
10623
10624                 }               /* switch */
10625
10626                 return rsp;
10627         }
10628
10629         if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_MAX_CLI_PER_PUB_IP) {
10630                 if (nat_only_config_flag) {
10631                         printf("Command not supported for NAT only config.\n");
10632                         return rsp;
10633                 }
10634                 uint16_t ii;
10635
10636                 printf("\tPublic IP:    Num Clients\n");
10637                 for (ii = 0; ii < CGNAPT_MAX_PUB_IP; ii++)
10638                         printf("\t%x : %7d\n", all_public_ip[ii].ip,
10639                                          rte_atomic16_read(&all_public_ip[ii].count));
10640                 return rsp;
10641         }
10642
10643         if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_PUB_IP_LIST) {
10644
10645                 int i;
10646                 for (i = 0; i < p_nat->pub_ip_count; i++)
10647                         printf("%x : (%d,%d)\n", p_nat->pub_ip_port_set[i].ip,
10648                                          p_nat->pub_ip_port_set[i].start_port,
10649                                          p_nat->pub_ip_port_set[i].end_port);
10650                 return rsp;
10651         }
10652
10653         #ifdef CGNAPT_TIMING_INST
10654         if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_TIMING_INST) {
10655                 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 0) {
10656                         p_nat->time_measurements_on = 1;
10657                         p_nat->time_measurements = 0;
10658                         printf("CGNAPT timing instrumentation turned on.\n");
10659                         printf("Max samples %d\n", p_nat->max_time_mesurements);
10660                 }
10661                 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 1) {
10662                         p_nat->time_measurements_on = 0;
10663                         printf("CGNAPT timing instrumentation turned off.\n");
10664                         printf("Cur Samples %d\n", p_nat->time_measurements);
10665                 }
10666                 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 2) {
10667                         uint64_t sum = p_nat->external_time_sum +
10668                                         p_nat->internal_time_sum;
10669                         uint64_t isump = (p_nat->internal_time_sum * 100) / sum;
10670                         uint64_t esump = (p_nat->external_time_sum * 100) / sum;
10671                         printf("CGNAPT timing instrumentation status ...\n");
10672                         printf("Max Count %d, Cur Count %d, Status %d (1=ON)\n",
10673                                          p_nat->max_time_mesurements,
10674                                          p_nat->time_measurements,
10675                                          p_nat->time_measurements_on);
10676                         printf("Internal Time Sum %" PRIu64 " , Ave %" PRIu64
10677                                          ", percent %" PRIu64 "\n",
10678                                          p_nat->internal_time_sum,
10679                                          (p_nat->internal_time_sum /
10680                                 p_nat->time_measurements), isump);
10681                         printf("External Time Sum %" PRIu64 " , Ave %" PRIu64
10682                                          ", percent %" PRIu64 "\n",
10683                                          p_nat->external_time_sum,
10684                                          (p_nat->external_time_sum /
10685                                 p_nat->time_measurements), esump);
10686                 }
10687
10688                 return rsp;
10689         }
10690         #endif
10691
10692         if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_PRINT_NSP) {
10693                 struct cgnapt_nsp_node *ll = nsp_ll;
10694
10695                 while (ll != NULL) {
10696                         fprintf(stderr, "NSP Prefix/Depth=>%x%x:%x%x:%x%x: "
10697                                 "%x%x:%x%x:%x%x:%x%x:%x%x/%d",
10698                                 ll->nsp.prefix[0], ll->nsp.prefix[1],
10699                                 ll->nsp.prefix[2], ll->nsp.prefix[3],
10700                                 ll->nsp.prefix[4], ll->nsp.prefix[5],
10701                                 ll->nsp.prefix[6], ll->nsp.prefix[7],
10702                                 ll->nsp.prefix[8], ll->nsp.prefix[9],
10703                                 ll->nsp.prefix[10], ll->nsp.prefix[11],
10704                                 ll->nsp.prefix[12], ll->nsp.prefix[13],
10705                                 ll->nsp.prefix[14], ll->nsp.prefix[15],
10706                                 ll->nsp.depth);
10707
10708                         ll = ll->next;
10709                 }
10710
10711                 return rsp;
10712         }
10713
10714         printf("CG-NAPT debug handler called with wrong args %x %x\n", Msg[0],
10715                          Msg[1]);
10716         int i = 0;
10717
10718         for (i = 0; i < 20; i++)
10719                 printf("%02x ", Msg[i]);
10720         printf("\n");
10721         return rsp;
10722 }
10723
10724 /**
10725  * Function to print num of clients per IP address
10726  *
10727  */
10728 void print_num_ip_clients(void)
10729 {
10730         if (nat_only_config_flag) {
10731                 printf("Command not supported for NAT only config.\n");
10732                 return;
10733         }
10734
10735         uint16_t ii;
10736         printf("\tPublic IP:    Num Clients\n");
10737         for (ii = 0; ii < CGNAPT_MAX_PUB_IP; ii++)
10738                 printf("\t%08x : %7d\n", all_public_ip[ii].ip,
10739                                  rte_atomic16_read(&all_public_ip[ii].count));
10740 }
10741
10742 /**
10743  * Function to print CGNAPT version info
10744  *
10745  * @param p
10746  *  An unused pointer to struct pipeline
10747  * @param msg
10748  *  void pointer to incoming arguments
10749  */
10750 void *pipeline_cgnapt_msg_req_ver_handler(__rte_unused struct pipeline *p,
10751                                                 void *msg)
10752 {
10753         struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
10754         uint8_t *Msg = msg;
10755
10756         rsp->status = 0;
10757
10758         printf("CG-NAPT debug handler called with args %x %x, offset %d\n",
10759                          Msg[CGNAPT_VER_CMD_OFST], Msg[CGNAPT_VER_CMD_OFST + 1],
10760                          CGNAPT_VER_CMD_OFST);
10761
10762         if (Msg[CGNAPT_VER_CMD_OFST] == CGNAPT_VER_CMD_VER) {
10763                 printf("CGNAPT Version %s\n", CGNAPT_VERSION);
10764                 return rsp;
10765         }
10766         printf("CG-NAPT Version handler called with wrong args %x %x\n",
10767                          Msg[0], Msg[1]);
10768         int i = 0;
10769
10770         for (i = 0; i < 20; i++)
10771                 printf("%02x ", Msg[i]);
10772         printf("\n");
10773         return rsp;
10774 }
10775
10776 /**
10777  * Function to show CGNAPT stats
10778  *
10779  */
10780 void all_cgnapt_stats(void)
10781 {
10782         int i;
10783         struct pipeline_cgnapt *p_nat;
10784         uint64_t receivedPktCount = 0;
10785         uint64_t missedPktCount = 0;
10786         uint64_t naptDroppedPktCount = 0;
10787         uint64_t naptedPktCount = 0;
10788         uint64_t inaptedPktCount = 0;
10789         uint64_t enaptedPktCount = 0;
10790         uint64_t arpicmpPktCount = 0;
10791
10792         printf("\nCG-NAPT Packet Stats:\n");
10793         for (i = 0; i < n_cgnapt_pipeline; i++) {
10794                 p_nat = all_pipeline_cgnapt[i];
10795
10796                 receivedPktCount        += p_nat->receivedPktCount;
10797                 missedPktCount          += p_nat->missedPktCount;
10798                 naptDroppedPktCount     += p_nat->naptDroppedPktCount;
10799                 naptedPktCount          += p_nat->naptedPktCount;
10800                 inaptedPktCount         += p_nat->inaptedPktCount;
10801                 enaptedPktCount         += p_nat->enaptedPktCount;
10802                 arpicmpPktCount         += p_nat->arpicmpPktCount;
10803
10804                 printf("pipeline %d stats:\n", p_nat->pipeline_num);
10805                 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10806                 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10807                 printf("Dropped %" PRIu64 ",",  p_nat->naptDroppedPktCount);
10808                 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10809                 printf("ingress %" PRIu64 ",",  p_nat->inaptedPktCount);
10810                 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10811                 printf("arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10812
10813
10814                 #ifdef CGNAPT_DEBUGGING
10815                 printf("\n Drop detail 1:%" PRIu64 ",",
10816                                 p_nat->naptDroppedPktCount1);
10817                 printf("\n Drop detail 2:%" PRIu64 ",",
10818                                 p_nat->naptDroppedPktCount2);
10819                 printf("\n Drop detail 3:%" PRIu64 ",",
10820                                 p_nat->naptDroppedPktCount3);
10821                 printf("\n Drop detail 4:%" PRIu64 ",",
10822                                 p_nat->naptDroppedPktCount4);
10823                 printf("\n Drop detail 5:%" PRIu64 ",",
10824                                 p_nat->naptDroppedPktCount5);
10825                 printf("\n Drop detail 6:%" PRIu64 "",
10826                                 p_nat->naptDroppedPktCount6);
10827
10828                 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10829                                 p_nat->missedpktcount1,
10830                                 p_nat->missedpktcount2);
10831                 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10832                                 p_nat->missedpktcount3,
10833                                 p_nat->missedpktcount4);
10834                 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10835                                 p_nat->missedpktcount5,
10836                                 p_nat->missedpktcount6);
10837                 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10838                                 p_nat->missedpktcount7,
10839                                 p_nat->missedpktcount8);
10840                 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10841                                 p_nat->missedpktcount9,
10842                                 p_nat->missedpktcount10);
10843
10844                 #endif
10845
10846         }
10847
10848         printf("\nTotal pipeline stats:\n");
10849         printf("Received %" PRIu64 ",", receivedPktCount);
10850         printf("Missed %" PRIu64 ",", missedPktCount);
10851         printf("Dropped %" PRIu64 ",",  naptDroppedPktCount);
10852         printf("Translated %" PRIu64 ",", naptedPktCount);
10853         printf("ingress %" PRIu64 ",",  inaptedPktCount);
10854         printf("egress %" PRIu64 "\n", enaptedPktCount);
10855         printf("arpicmp pkts %" PRIu64 "\n", arpicmpPktCount);
10856 }
10857
10858 void all_cgnapt_clear_stats(void)
10859 {
10860         int i;
10861         struct pipeline_cgnapt *p_nat;
10862                 printf("\nCG-NAPT Packet Stats:\n");
10863         for (i = 0; i < n_cgnapt_pipeline; i++) {
10864                 p_nat = all_pipeline_cgnapt[i];
10865
10866                 printf("pipeline %d stats:\n", p_nat->pipeline_num);
10867                 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10868                 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10869                 printf("Dropped %" PRIu64 ",",  p_nat->naptDroppedPktCount);
10870                 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10871                 printf("ingress %" PRIu64 ",",  p_nat->inaptedPktCount);
10872                 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10873                 printf("arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10874
10875                 p_nat->receivedPktCount = 0;
10876                 p_nat->missedPktCount = 0;
10877                 p_nat->naptDroppedPktCount = 0;
10878                 p_nat->naptedPktCount = 0;
10879                 p_nat->inaptedPktCount = 0;
10880                 p_nat->enaptedPktCount = 0;
10881                 p_nat->arpicmpPktCount = 0;
10882
10883                 #ifdef CGNAPT_DEBUGGING
10884                 printf("\n Drop detail 1:%" PRIu64 ",",
10885                                 p_nat->naptDroppedPktCount1);
10886                 printf("\n Drop detail 2:%" PRIu64 ",",
10887                                 p_nat->naptDroppedPktCount2);
10888                 printf("\n Drop detail 3:%" PRIu64 ",",
10889                                 p_nat->naptDroppedPktCount3);
10890                 printf("\n Drop detail 4:%" PRIu64 ",",
10891                                 p_nat->naptDroppedPktCount4);
10892                 printf("\n Drop detail 5:%" PRIu64 ",",
10893                                 p_nat->naptDroppedPktCount5);
10894                 printf("\n Drop detail 6:%" PRIu64 "",
10895                                 p_nat->naptDroppedPktCount6);
10896
10897                 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10898                                 p_nat->missedpktcount1,
10899                                 p_nat->missedpktcount2);
10900                 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10901                                 p_nat->missedpktcount3,
10902                                 p_nat->missedpktcount4);
10903                 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10904                                 p_nat->missedpktcount5,
10905                                 p_nat->missedpktcount6);
10906                 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10907                                 p_nat->missedpktcount7,
10908                                 p_nat->missedpktcount8);
10909                 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10910                                 p_nat->missedpktcount9,
10911                                 p_nat->missedpktcount10);
10912
10913                 #endif
10914
10915         }
10916 }
10917
10918 /**
10919  * Function to print common CGNAPT table entries
10920  *
10921  */
10922 void print_static_cgnapt_entries(void)
10923 {
10924         uint32_t count = 0;
10925         const void *key;
10926         void *data;
10927         uint32_t next = 0;
10928         int32_t index = 0;
10929         struct cgnapt_table_entry *entry;
10930         do {
10931                 index = rte_hash_iterate(napt_common_table,
10932                                 &key, &data, &next);
10933
10934                 if ((index != -EINVAL) && (index != -ENOENT)) {
10935                         printf("\n%04d  ", count);
10936                         rte_hexdump(stdout, "KEY", key,
10937                                 sizeof(struct pipeline_cgnapt_entry_key));
10938                         int32_t position = rte_hash_lookup(
10939                                         napt_common_table, key);
10940                         entry = &napt_hash_tbl_entries[position];
10941
10942                         if (entry->data.timeout == STATIC_CGNAPT_TIMEOUT)
10943                                 rte_hexdump(stdout, "Entry",
10944                                         (const void *)entry,
10945                                         sizeof(struct cgnapt_table_entry));
10946                 }
10947
10948                 count++;
10949         } while (index != -ENOENT);
10950 }
10951
10952 /**
10953  * Function to show CGNAPT stats
10954  *
10955  */
10956
10957 struct pipeline_be_ops pipeline_cgnapt_be_ops = {
10958         .f_init = pipeline_cgnapt_init,
10959         .f_free = pipeline_cgnapt_free,
10960         .f_run = NULL,
10961         .f_timer = pipeline_cgnapt_timer,
10962         .f_track = pipeline_cgnapt_track,
10963 };