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