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