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