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