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