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