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