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