2 // Copyright (c) 2017 Intel Corporation
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 * Pipeline CG-NAPT BE Implementation.
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.
33 #include <rte_common.h>
34 #include <rte_malloc.h>
40 #include <rte_byteorder.h>
41 #include <rte_table_lpm.h>
42 #include <rte_table_hash.h>
43 #include <rte_table_stub.h>
45 #include <rte_mempool.h>
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>
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"
63 #include "pipeline_common_be.h"
64 #include "vnf_common.h"
65 #include "lib_sip_alg.h"
66 #include "lib_icmpv6.h"
68 #include "pipeline_common_fe.h"
70 #include "rte_ct_tcp.h"
71 #include "rte_cnxn_tracking.h"
74 #include "lib_ftp_alg.h"
77 #include "cgnapt_pcp_be.h"
80 /* To maintain all cgnapt pipeline pointers used for all stats */
81 struct pipeline_cgnapt *all_pipeline_cgnapt[128];
82 uint8_t n_cgnapt_pipeline;
83 struct pipeline_cgnapt *global_pnat;
85 uint64_t arp_pkts_mask;
86 extern struct arp_entry_data *arp_data_ptr[16];
87 /* To know egress or ingress port */
88 static uint8_t cgnapt_in_port_egress_prv[PIPELINE_MAX_PORT_IN];
89 static uint8_t cgnapt_prv_que_port_index[PIPELINE_MAX_PORT_IN];
91 /* Max port per client declarations */
93 struct rte_hash_parameters max_port_per_client_hash_params = {
94 .name = "MAX_PORT_PER_CLIENT",
95 .entries = MAX_DYN_ENTRY,
96 .key_len = sizeof(struct max_port_per_client_key),
97 .hash_func = rte_jhash,
98 .hash_func_init_val = 0,
101 struct rte_ct_cnxn_tracker *cgnat_cnxn_tracker;
104 /***** Common Port Allocation declarations *****/
106 struct rte_ring *port_alloc_ring[MAX_CGNAPT_SETS] = { NULL, NULL, NULL, NULL,
107 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
108 NULL, NULL, NULL, NULL};
109 const char *napt_port_alloc_ring_name[MAX_CGNAPT_SETS] = {
110 "NAPT_PORT_ALLOC_0 ",
111 "NAPT_PORT_ALLOC_1 ",
112 "NAPT_PORT_ALLOC_2 ",
113 "NAPT_PORT_ALLOC_3 ",
114 "NAPT_PORT_ALLOC_4 ",
115 "NAPT_PORT_ALLOC_5 ",
116 "NAPT_PORT_ALLOC_6 ",
117 "NAPT_PORT_ALLOC_7 ",
118 "NAPT_PORT_ALLOC_8 ",
119 "NAPT_PORT_ALLOC_9 ",
120 "NAPT_PORT_ALLOC_10 ",
121 "NAPT_PORT_ALLOC_11 ",
122 "NAPT_PORT_ALLOC_12 ",
123 "NAPT_PORT_ALLOC_13 ",
124 "NAPT_PORT_ALLOC_14 ",
125 "NAPT_PORT_ALLOC_16 "
128 int vnf_set_count = -1;
130 struct app_params *myApp;
132 /***** Common Port Allocation declarations *****/
133 int napt_port_alloc_elem_count;
135 /***** Common Table declarations *****/
136 struct rte_hash_parameters napt_common_table_hash_params = {
137 .name = "NAPT_COM_TBL",
138 .entries = MAX_NAPT_ENTRIES,
139 .key_len = sizeof(struct pipeline_cgnapt_entry_key),
140 .hash_func = rte_jhash,
141 .hash_func_init_val = 0,
145 /***** ARP local cache *****/
147 uint8_t link_hw_laddr_valid[MAX_NUM_LOCAL_MAC_ADDRESS] = {
148 0, 0, 0, 0, 0, 0, 0, 0,
149 0, 0, 0, 0, 0, 0, 0, 0
152 struct ether_addr link_hw_laddr[MAX_NUM_LOCAL_MAC_ADDRESS] = {
153 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
154 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
155 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
156 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
157 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
158 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
159 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
160 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
161 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
162 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
163 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
164 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
165 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
166 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
167 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
168 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }
171 /****** NAT64 declarations *****/
173 uint8_t well_known_prefix[16] = {
174 0x00, 0x64, 0xff, 0x9b,
175 0x00, 0x00, 0x00, 0x00,
176 0x00, 0x00, 0x00, 0x00,
177 0x00, 0x00, 0x00, 0x00
180 static uint32_t local_get_nh_ipv4(
184 struct pipeline_cgnapt *p_nat);
185 static void do_local_nh_ipv4_cache(
187 struct pipeline_cgnapt *p_nat);
189 static uint32_t local_get_nh_ipv6(
193 struct pipeline_cgnapt *p_nat);
195 static void do_local_nh_ipv6_cache(
197 struct pipeline_cgnapt *p_nat);
199 static uint8_t check_arp_icmp(
200 struct rte_mbuf *pkt,
202 struct pipeline_cgnapt *p_nat);
204 /* Finds next power of two for n. If n itself
205 * is a power of two then returns n
208 * Value usually 32-bit value
211 * Value after roundup to power of 2
213 uint64_t nextPowerOf2(uint64_t n)
226 void remove_local_cache(uint8_t port)
228 link_hw_laddr_valid[port] = 0;
232 * Function to get MAC addr of local link
235 * Physical port number
238 * Outport Link MAC addr
241 //struct ether_addr *get_local_link_hw_addr(uint8_t out_port)
243 // return &link_hw_laddr[out_port];
247 * Function to get MAC addr from array instead of hash table
250 * Physical port number
253 * Outport Link MAC addr
256 uint8_t local_dest_mac_present(uint8_t out_port)
258 return link_hw_laddr_valid[out_port];
262 * Function to get IPv4-IP NH from thread local array
271 * CGNAPT pipeline ptr
274 * 1 on success, 0 for failure
277 static uint32_t local_get_nh_ipv4(
281 struct pipeline_cgnapt *p_nat)
284 for (i = 0; i < p_nat->local_lib_arp_route_ent_cnt; i++) {
285 if (((p_nat->local_lib_arp_route_table[i].ip &
286 p_nat->local_lib_arp_route_table[i].mask) ==
287 (ip & p_nat->local_lib_arp_route_table[i].mask))) {
288 *port = p_nat->local_lib_arp_route_table[i].port;
290 *nhip = p_nat->local_lib_arp_route_table[i].nh;
298 * Function to make local copy for NH of type IPv4
301 * Physical port number
303 * CGNAPT pipeline ptr
307 static void do_local_nh_ipv4_cache(
309 struct pipeline_cgnapt *p_nat)
312 /* Search for the entry and do local copy */
315 for (i = 0; i < MAX_ARP_RT_ENTRY; i++) {
316 if (lib_arp_route_table[i].port == dest_if) {
318 struct lib_arp_route_table_entry *lentry =
319 &p_nat->local_lib_arp_route_table
320 [p_nat->local_lib_arp_route_ent_cnt];
322 lentry->ip = lib_arp_route_table[i].ip;
323 lentry->mask = lib_arp_route_table[i].mask;
324 lentry->port = lib_arp_route_table[i].port;
325 lentry->nh = lib_arp_route_table[i].nh;
327 p_nat->local_lib_arp_route_ent_cnt++;
335 * Function to get IPv6-IP NH from thread local array
338 * Pointer to starting addr of IPv6
344 * CGNAPT pipeline ptr
347 * 1 on success, 0 for failure
350 static uint32_t local_get_nh_ipv6(
354 struct pipeline_cgnapt *p_nat)
357 uint8_t netmask_ipv6[16];
358 uint8_t k = 0, l = 0, depthflags = 0, depthflags1 = 0;
360 for (i = 0; i < p_nat->local_lib_nd_route_ent_cnt; i++) {
362 convert_prefixlen_to_netmask_ipv6(
363 p_nat->local_lib_nd_route_table[i].depth,
366 for (k = 0; k < 16; k++)
367 if (p_nat->local_lib_nd_route_table[i].ipv6[k] &
371 for (l = 0; l < 16; l++)
372 if (ip[l] & netmask_ipv6[l])
376 if (depthflags == depthflags1) {
377 *port = p_nat->local_lib_nd_route_table[i].port;
379 for (j = 0; j < 16; j++)
380 nhip[j] = p_nat->local_lib_nd_route_table[i].
393 * Function to make local copy for NH of type IPv6
396 * Physical port number
398 * CGNAPT pipeline ptr
402 static void do_local_nh_ipv6_cache(
404 struct pipeline_cgnapt *p_nat)
406 /* Search for the entry and do local copy */
408 for (i = 0; i < MAX_ND_RT_ENTRY; i++) {
410 if (lib_nd_route_table[i].port == dest_if) {
412 struct lib_nd_route_table_entry *lentry =
413 &p_nat->local_lib_nd_route_table
414 [p_nat->local_lib_nd_route_ent_cnt];
416 for (l = 0; l < 16; l++) {
418 lib_nd_route_table[i].ipv6[l];
420 lib_nd_route_table[i].nhipv6[l];
422 lentry->depth = lib_nd_route_table[i].depth;
423 lentry->port = lib_nd_route_table[i].port;
425 p_nat->local_lib_nd_route_ent_cnt++;
432 /* Commented code may be required for future usage, Please keep it*/
434 static int retrieve_cgnapt_entry_alg(
435 struct pipeline_cgnapt_entry_key *key,
436 struct cgnapt_table_entry **entry_ptr1,
437 struct cgnapt_table_entry **entry_ptr2)
439 #ifdef CGNAPT_DBG_PRNT
440 printf("retrieve_cgnapt_entry key detail Entry:"
441 "0x%x, %d, %d\n", key->ip, key->port,
445 int position = rte_hash_lookup(napt_common_table, key);
447 printf("Invalid cgnapt entry position(first_key): %d\n",
452 *entry_ptr1 = &napt_hash_tbl_entries[position];
454 uint32_t prv_ip = (*entry_ptr1)->data.prv_ip;
455 uint32_t prv_port = (*entry_ptr1)->data.prv_port;
456 uint32_t prv_phy_port = (*entry_ptr1)->data.prv_phy_port;
458 struct pipeline_cgnapt_entry_key second_key;
459 second_key.ip = prv_ip;
460 second_key.port = prv_port;
461 second_key.pid = prv_phy_port;
463 position = rte_hash_lookup(napt_common_table, &second_key);
465 printf("Invalid cgnapt entry position(second_key): %d\n",
470 *entry_ptr2 = &napt_hash_tbl_entries[position];
476 int add_dynamic_cgnapt_entry_alg(
478 struct pipeline_cgnapt_entry_key *key,
479 struct cgnapt_table_entry **entry_ptr1,
480 struct cgnapt_table_entry **entry_ptr2)
482 int port_num = 0, ret;
484 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
486 #ifdef CGNAPT_DBG_PRNT
487 if (CGNAPT_DEBUG >= 1) {
488 printf("Th%d add_dynamic_cgnapt_entry key detail Entry:"
489 "0x%x, %d, %d\n", p_nat->pipeline_num, key->ip, key->port,
494 int32_t position = rte_hash_lookup(napt_common_table, key);
496 #ifdef CGNAPT_DBG_PRNT
497 if (CGNAPT_DEBUG >= 1) {
498 printf("%s: cgnapt entry exists in "
499 "position(first_key): %d\n", __func__, position);
502 *entry_ptr1 = &napt_hash_tbl_entries[position];
503 /* not required, as it is not used in the caller */
509 ret = increment_max_port_counter(key->ip, key->pid, p_nat);
510 if (ret == MAX_PORT_INC_ERROR) {
512 #ifdef CGNAPT_DBG_PRNT
513 if (CGNAPT_DEBUG > 1)
514 printf("add_dynamic_cgnapt_entry:"
515 "increment_max_port_counter-1 failed\n");
521 if (ret == MAX_PORT_INC_REACHED) {
523 #ifdef CGNAPT_DBG_PRNT
524 if (CGNAPT_DEBUG > 1)
525 printf("add_dynamic_cgnapt_entry:"
526 "increment_max_port_counter-2 failed\n");
533 port_num = get_free_iport(p_nat, &public_ip);
535 if (port_num == -1) {
537 #ifdef CGNAPT_DBG_PRNT
538 if (CGNAPT_DEBUG > 2) {
539 printf("add_dynamic_cgnapt_entry: %d\n", port_num);
540 printf("add_dynamic_cgnapt_entry key detail:0x%x, "
541 "%d, %d\n", key->ip, key->port, key->pid);
548 /* check for max_clients_per_ip */
549 if (rte_atomic16_read
551 [rte_jhash(&public_ip, 4, 0) % 16].count) ==
552 p_nat->max_clients_per_ip) {
553 /* For now just bail out
554 * In future we can think about
555 * retrying getting a new iport
557 release_iport(port_num, public_ip, p_nat);
562 rte_atomic16_inc(&all_public_ip
563 [rte_jhash(&public_ip, 4, 0) %
566 #ifdef CGNAPT_DBG_PRNT
567 if ((rte_jhash(&public_ip, 4, 0) % 16) == 8)
568 printf("pub ip:%x coutn:%d\n", public_ip,
569 rte_atomic16_read(&all_public_ip
570 [rte_jhash(&public_ip, 4, 0) % 16].count));
573 #ifdef CGNAPT_DBG_PRNT
574 if (CGNAPT_DEBUG > 0) {
575 printf("add_dynamic_cgnapt_entry: %d\n",
577 printf("add_dynamic_cgnapt_entry key detail: "
578 "0x%x, %d, %d\n", key->ip, key->port, key->pid);
582 struct cgnapt_table_entry entry = {
584 .action = RTE_PIPELINE_ACTION_PORT,
585 /* made it configurable below */
586 {.port_id = p->port_out_id[0]},
590 .prv_port = key->port,
592 .pub_port = port_num,
593 .prv_phy_port = key->pid,
594 .pub_phy_port = get_pub_to_prv_port(
598 /* if(timeout == -1) : static entry
599 * if(timeout == 0 ) : dynamic entry
600 * if(timeout > 0 ) : PCP requested entry
609 entry.data.u.prv_ip = key->ip;
610 entry.data.type = CGNAPT_ENTRY_IPV4;
612 entry.head.port_id = entry.data.pub_phy_port; /* outgoing port info */
614 struct pipeline_cgnapt_entry_key second_key;
615 /* Need to add a second ingress entry */
616 second_key.ip = public_ip;
617 second_key.port = port_num;
618 second_key.pid = 0xffff;
620 #ifdef CGNAPT_DBG_PRNT
621 if (CGNAPT_DEBUG > 2)
622 printf("add_dynamic_cgnapt_entry second key detail:"
623 "0x%x, %d, %d\n", second_key.ip, second_key.port,
627 int32_t position1 = rte_hash_add_key(napt_common_table, (void *)key);
630 printf("CG-NAPT entry add failed ...returning "
631 "without adding ... %d\n", position1);
636 #ifdef CGNAPT_DBG_PRNT
638 printf("add_dynamic_cgnapt_entry:");
640 print_cgnapt_entry(&entry);
644 memcpy(&napt_hash_tbl_entries[position1], &entry,
645 sizeof(struct cgnapt_table_entry));
647 /* this pointer is returned to pkt miss function */
648 *entry_ptr1 = &napt_hash_tbl_entries[position1];
650 p_nat->n_cgnapt_entry_added++;
651 p_nat->dynCgnaptCount++;
653 /* Now modify the forward port for reverse entry */
655 /* outgoing port info */
656 entry.head.port_id = entry.data.prv_phy_port;
658 int32_t position2 = rte_hash_add_key(napt_common_table, &second_key);
661 printf("CG-NAPT entry reverse bulk add failed ..."
662 "returning with fwd add ...%d\n",
667 memcpy(&napt_hash_tbl_entries[position2], &entry,
668 sizeof(struct cgnapt_table_entry));
670 *entry_ptr2 = &napt_hash_tbl_entries[position2];
672 #ifdef CGNAPT_DBG_PRNT
673 if (CGNAPT_DEBUG >= 1) {
674 printf("add_dynamic_cgnapt_entry position: %d, %d\n",
675 position1, position2);
676 printf("add_dynamic_cgnapt_entry: entry_ptr1: %p, "
677 "entry_ptr2: %p\n", *entry_ptr1, *entry_ptr2);
681 timer_thread_enqueue(key, &second_key, *entry_ptr1,
682 *entry_ptr2, (struct pipeline *)p_nat);
684 p_nat->n_cgnapt_entry_added++;
685 p_nat->dynCgnaptCount++;
692 void hw_checksum(struct rte_mbuf *pkt, enum PKT_TYPE ver)
694 struct tcp_hdr *tcp = NULL;
695 struct udp_hdr *udp = NULL;
696 struct icmp_hdr *icmp = NULL;
698 void *ip_header = NULL;
699 uint16_t prot_offset = 0;
700 uint32_t pkt_type_is_ipv4 = 1;
702 pkt->ol_flags |= PKT_TX_IP_CKSUM;
703 pkt->l2_len = ETH_HDR_SIZE;
708 case PKT_TYPE_IPV4to6:
712 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
713 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
715 pkt_type_is_ipv4 = 0;
716 pkt->ol_flags |= PKT_TX_IPV6;
718 sizeof(struct ipv6_hdr);
719 tcp = (struct tcp_hdr *)
720 ((unsigned char *)ip_header +
721 sizeof(struct ipv6_hdr));
722 udp = (struct udp_hdr *)
723 ((unsigned char *)ip_header +
724 sizeof(struct ipv6_hdr));
725 icmp = (struct icmp_hdr *)
726 ((unsigned char *)ip_header +
727 sizeof(struct ipv6_hdr));
729 prot_offset = PROT_OFST_IP6 + temp;
731 case PKT_TYPE_IPV6to4:
735 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
736 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
738 pkt->ol_flags |= PKT_TX_IPV4;
740 sizeof(struct ipv4_hdr);
741 tcp = (struct tcp_hdr *)
742 ((unsigned char *)ip_header +
743 sizeof(struct ipv4_hdr));
744 udp = (struct udp_hdr *)
745 ((unsigned char *)ip_header +
746 sizeof(struct ipv4_hdr));
747 icmp = (struct icmp_hdr *)
748 ((unsigned char *)ip_header +
749 sizeof(struct ipv4_hdr));
750 struct ipv4_hdr *ip_hdr =
751 (struct ipv4_hdr *)ip_header;
752 ip_hdr->hdr_checksum = 0;
754 prot_offset = PROT_OFST_IP4 + temp;
757 printf("hw_checksum: pkt version is invalid\n");
759 protocol = (uint8_t *) RTE_MBUF_METADATA_UINT8_PTR(pkt,
763 case IP_PROTOCOL_TCP: /* 6 */
765 pkt->ol_flags |= PKT_TX_TCP_CKSUM;
766 if (pkt_type_is_ipv4) {
767 tcp->cksum = rte_ipv4_phdr_cksum(
768 (struct ipv4_hdr *)ip_header,
771 tcp->cksum = rte_ipv6_phdr_cksum(
772 (struct ipv6_hdr *)ip_header,
776 case IP_PROTOCOL_UDP: /* 17 */
777 udp->dgram_cksum = 0;
778 pkt->ol_flags |= PKT_TX_UDP_CKSUM;
779 if (pkt_type_is_ipv4) {
782 (struct ipv4_hdr *)ip_header,
787 (struct ipv6_hdr *)ip_header,
791 case IP_PROTOCOL_ICMP: /* 1 */
792 if (pkt_type_is_ipv4) {
793 /* ICMP checksum code */
794 struct ipv4_hdr *ip_hdr =
795 (struct ipv4_hdr *)ip_header;
796 int size = rte_bswap16(ip_hdr->total_length) - 20;
797 icmp->icmp_cksum = 0;
805 printf("hw_checksum() : Neither TCP or UDP pkt\n");
811 void sw_checksum(struct rte_mbuf *pkt, enum PKT_TYPE ver)
813 struct tcp_hdr *tcp = NULL;
814 struct udp_hdr *udp = NULL;
815 struct icmp_hdr *icmp = NULL;
817 void *ip_header = NULL;
818 uint16_t prot_offset = 0;
819 uint32_t pkt_type_is_ipv4 = 1;
823 case PKT_TYPE_IPV4to6:
827 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
828 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
830 pkt_type_is_ipv4 = 0;
831 tcp = (struct tcp_hdr *)
832 ((unsigned char *)ip_header +
833 sizeof(struct ipv6_hdr));
834 udp = (struct udp_hdr *)
835 ((unsigned char *)ip_header +
836 sizeof(struct ipv6_hdr));
837 icmp = (struct icmp_hdr *)
838 ((unsigned char *)ip_header +
839 sizeof(struct ipv6_hdr));
841 prot_offset = PROT_OFST_IP6 + temp;
843 case PKT_TYPE_IPV6to4:
847 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
848 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
850 tcp = (struct tcp_hdr *)
851 ((unsigned char *)ip_header +
852 sizeof(struct ipv4_hdr));
853 udp = (struct udp_hdr *)
854 ((unsigned char *)ip_header +
855 sizeof(struct ipv4_hdr));
856 icmp = (struct icmp_hdr *)
857 ((unsigned char *)ip_header +
858 sizeof(struct ipv4_hdr));
860 prot_offset = PROT_OFST_IP4 + temp;
863 printf("sw_checksum: pkt version is invalid\n");
865 protocol = (uint8_t *) RTE_MBUF_METADATA_UINT8_PTR(pkt,
869 case IP_PROTOCOL_TCP: /* 6 */
871 if (pkt_type_is_ipv4) {
872 struct ipv4_hdr *ip_hdr =
873 (struct ipv4_hdr *)ip_header;
874 tcp->cksum = rte_ipv4_udptcp_cksum(ip_hdr,
876 ip_hdr->hdr_checksum = 0;
877 ip_hdr->hdr_checksum = rte_ipv4_cksum(
878 (struct ipv4_hdr *)ip_hdr);
880 tcp->cksum = rte_ipv6_udptcp_cksum(
882 ip_header, (void *)tcp);
885 case IP_PROTOCOL_UDP: /* 17 */
886 udp->dgram_cksum = 0;
887 if (pkt_type_is_ipv4) {
888 struct ipv4_hdr *ip_hdr =
889 (struct ipv4_hdr *)ip_header;
890 udp->dgram_cksum = rte_ipv4_udptcp_cksum(
891 ip_hdr, (void *)udp);
892 ip_hdr->hdr_checksum = 0;
893 ip_hdr->hdr_checksum = rte_ipv4_cksum(ip_hdr);
895 udp->dgram_cksum = rte_ipv6_udptcp_cksum(
897 ip_header, (void *)udp);
900 case IP_PROTOCOL_ICMP: /* 1 */
901 if (pkt_type_is_ipv4) {
902 /* ICMP checksum code */
903 struct ipv4_hdr *ip_hdr =
904 (struct ipv4_hdr *)ip_header;
905 int size = rte_bswap16(ip_hdr->total_length) - 20;
906 icmp->icmp_cksum = 0;
910 ip_hdr->hdr_checksum = 0;
911 ip_hdr->hdr_checksum = rte_ipv4_cksum(ip_hdr);
916 printf("sw_checksum() : Neither TCP or UDP pkt\n");
921 void print_pkt_info(uint8_t *eth_dest, struct ether_addr *hw_addr,
922 uint32_t dest_address, uint32_t port_id, struct rte_mbuf *pkt)
925 if (CGNAPT_DEBUG > 2) {
926 printf("MAC Found ip 0x%x, port %d - %02x:%02x:%02x:%02x:%02x:%02x \n",
927 dest_address, port_id, hw_addr->addr_bytes[0], hw_addr->addr_bytes[1],
928 hw_addr->addr_bytes[2], hw_addr->addr_bytes[3], hw_addr->addr_bytes[4],
929 hw_addr->addr_bytes[5]);
931 printf("Dest MAC before - %02x:%02x:%02x:%02x:%02x:%02x \n",
932 eth_dest[0], eth_dest[1], eth_dest[2], eth_dest[3], eth_dest[4],
936 if (CGNAPT_DEBUG > 2) {
937 printf("Dest MAC after - "
938 "%02x:%02x:%02x:%02x:%02x:%02x \n",
939 eth_dest[0], eth_dest[1],
940 eth_dest[2], eth_dest[3],
941 eth_dest[4], eth_dest[5]);
944 if (CGNAPT_DEBUG > 4)
948 static uint8_t check_arp_icmp(
949 struct rte_mbuf *pkt,
951 struct pipeline_cgnapt *p_nat)
953 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
954 uint16_t *eth_proto = RTE_MBUF_METADATA_UINT16_PTR(
955 pkt, eth_proto_offset);
956 struct app_link_params *link;
957 uint8_t solicited_node_multicast_addr[16] = {
958 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
959 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00};
961 /* ARP outport number */
962 uint16_t out_port = p_nat->p.n_ports_out - 1;
963 printf("check_arp_icmp called*****\n");
965 uint32_t prot_offset;
967 link = &myApp->link_params[pkt->port];
970 switch (rte_be_to_cpu_16(*eth_proto)) {
974 rte_pipeline_port_out_packet_insert(
980 * Pkt mask should be changed, and not changing the
983 p_nat->invalid_packets |= pkt_mask;
984 p_nat->arpicmpPktCount++;
988 case ETH_TYPE_IPV4: {
989 /* header room + eth hdr size +
990 * src_aadr offset in ip header
992 uint32_t dst_addr_offset = MBUF_HDR_ROOM +
993 ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
995 RTE_MBUF_METADATA_UINT32_PTR(pkt,
997 prot_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
998 IP_HDR_PROTOCOL_OFST;
999 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt,
1001 if ((*protocol == IP_PROTOCOL_ICMP) &&
1002 link->ip == rte_be_to_cpu_32(*dst_addr)) {
1004 if (is_phy_port_privte(pkt->port)) {
1006 rte_pipeline_port_out_packet_insert(
1007 p_nat->p.p, out_port, pkt);
1010 * Pkt mask should be changed,
1011 * and not changing the drop mask
1014 p_nat->invalid_packets |= pkt_mask;
1015 p_nat->arpicmpPktCount++;
1026 if (dual_stack_enable) {
1028 /* Commented code may be required for future usage,
1031 //uint32_t dst_addr_offset = MBUF_HDR_ROOM +
1032 // ETH_HDR_SIZE + IPV6_HDR_DST_ADR_OFST;
1033 //uint32_t *dst_addr =
1034 // RTE_MBUF_METADATA_UINT32_PTR(pkt,
1035 // dst_addr_offset);
1036 uint32_t prot_offset_ipv6 = MBUF_HDR_ROOM +
1037 ETH_HDR_SIZE + IPV6_HDR_PROTOCOL_OFST;
1038 struct ipv6_hdr *ipv6_h;
1040 ipv6_h = (struct ipv6_hdr *) MBUF_HDR_ROOM +
1042 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt,
1045 if (ipv6_h->proto == ICMPV6_PROTOCOL_ID) {
1046 if (!memcmp(ipv6_h->dst_addr, link->ipv6, 16)
1047 || !memcmp(ipv6_h->dst_addr,
1048 solicited_node_multicast_addr, 13)) {
1049 rte_pipeline_port_out_packet_insert(
1050 p_nat->p.p, out_port, pkt);
1052 * Pkt mask should be changed,
1053 * and not changing the drop mask
1055 p_nat->invalid_packets |= pkt_mask;
1056 p_nat->arpicmpPktCount++;
1058 p_nat->invalid_packets |= pkt_mask;
1059 p_nat->naptDroppedPktCount++;
1061 #ifdef CGNAPT_DEBUGGING
1062 p_nat->naptDroppedPktCount1++;
1077 * Function to create common NAPT table
1078 * Called during pipeline initialization
1079 * Creates the common NAPT table
1080 * If it is not already created and stores its pointer
1081 * in global napt_common_table pointer.
1084 * Max number of NAPT flows. This parameter is configurable via config file.
1087 * 0 on success, negative on error.
1089 int create_napt_common_table(uint32_t nFlows)
1091 if (napt_common_table != NULL) {
1092 printf("napt_common_table already exists.\n");
1096 napt_common_table = rte_hash_create(&napt_common_table_hash_params);
1098 if (napt_common_table == NULL) {
1099 printf("napt_common_table creation failed.\n");
1103 uint32_t number_of_entries = nFlows;
1106 RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_table_entry) *
1108 napt_hash_tbl_entries = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1110 if (napt_hash_tbl_entries == NULL) {
1111 printf("napt_hash_tbl_entries creation failed. %d, %d\n",
1112 nFlows, (int)sizeof(struct cgnapt_table_entry));
1120 * Function to initialize bulk port allocation data structures
1121 * Called during pipeline initialization.
1123 * Creates the port alloc ring for the VNF_set this pipeline belongs
1125 * Creates global port allocation buffer pool
1127 * Initializes the port alloc ring according to config data
1130 * A pointer to struct pipeline_cgnapt
1133 * 0 on success, negative on error.
1135 int napt_port_alloc_init(struct pipeline_cgnapt *p_nat)
1137 p_nat->allocated_ports = NULL;
1138 p_nat->free_ports = NULL;
1140 uint32_t vnf_set_num = p_nat->vnf_set;
1141 /*uint32_t vnf_set_num = get_vnf_set_num(p_nat->pipeline_num); */
1143 printf("VNF set number for CGNAPT %d is %d.\n", p_nat->pipeline_num,
1145 if (vnf_set_num == 0xFF) {
1146 printf("VNF set number for CGNAPT %d is invalid %d.\n",
1147 p_nat->pipeline_num, vnf_set_num);
1151 p_nat->port_alloc_ring = port_alloc_ring[vnf_set_num];
1152 if (p_nat->port_alloc_ring != NULL) {
1153 printf("CGNAPT%d port_alloc_ring already exists.\n",
1154 p_nat->pipeline_num);
1158 printf("napt_port_alloc_elem_count :%d\n",
1159 napt_port_alloc_elem_count);
1160 napt_port_alloc_elem_count += 1;
1161 napt_port_alloc_elem_count =
1162 nextPowerOf2(napt_port_alloc_elem_count);
1163 printf("Next power of napt_port_alloc_elem_count: %d\n",
1164 napt_port_alloc_elem_count);
1166 port_alloc_ring[vnf_set_num] =
1167 rte_ring_create(napt_port_alloc_ring_name[vnf_set_num],
1168 napt_port_alloc_elem_count, rte_socket_id(), 0);
1169 p_nat->port_alloc_ring = port_alloc_ring[vnf_set_num];
1170 if (p_nat->port_alloc_ring == NULL) {
1171 printf("CGNAPT%d - Failed to create port_alloc_ring\n",
1172 p_nat->pipeline_num);
1176 /* Create port alloc buffer */
1177 /* Only one pool is enough for all vnf sets */
1178 if (napt_port_pool == NULL) {
1180 napt_port_pool = rte_mempool_create(
1182 napt_port_alloc_elem_count,
1183 sizeof(struct napt_port_alloc_elem),
1184 0, 0, NULL, NULL, NULL,
1185 NULL, rte_socket_id(), 0);
1188 if (napt_port_pool == NULL) {
1189 printf("CGNAPT - Create port pool failed\n");
1193 /* Add all available public IP addresses and ports to the ring */
1196 #ifdef NAT_ONLY_CONFIG_REQ
1197 if (nat_only_config_flag) {
1198 printf("******* pub_ip_range_count:%d ***********\n",
1199 p_nat->pub_ip_range_count);
1200 /* Initialize all public IP's addresses */
1202 uint32_t max_ips_remain;
1204 for (if_addrs = 0; if_addrs < p_nat->pub_ip_range_count;
1206 /* Add all available addresses to the ring */
1208 for (i = p_nat->pub_ip_range[if_addrs].start_ip;
1209 i <= p_nat->pub_ip_range[if_addrs].end_ip;) {
1210 /* 1. Get a port alloc buffer from napt_port_pool */
1214 /* get new napt_port_alloc_elem from pool */
1215 if (rte_mempool_get(napt_port_pool,
1217 printf("CGNAPT - Error in getting port "
1223 /* 2. Populate it with available ports and ip addr */
1224 struct napt_port_alloc_elem *pb =
1225 (struct napt_port_alloc_elem *)portsBuf;
1228 temp = p_nat->pub_ip_range[if_addrs].end_ip -
1231 /* Check if remaining port count is greater
1232 * than or equals to bulk count, if not give
1233 * remaining count ports than giving bulk count
1235 if (temp < NUM_NAPT_PORT_BULK_ALLOC)
1236 max_ips_remain = temp;
1239 NUM_NAPT_PORT_BULK_ALLOC;
1241 for (j = 0; j < max_ips_remain; j++) {
1243 pb->ip_addr[j] = i + j;
1246 p_nat->pub_ip_range[if_addrs].
1251 /* 3. add the port alloc buffer to ring */
1252 if (rte_ring_enqueue(p_nat->port_alloc_ring,
1254 printf("CGNAPT%d - Enqueue error - i %d,",
1255 p_nat->pipeline_num, i);
1256 printf("j %d, if_addrs %d, pb %p\n",
1258 rte_ring_dump(stdout,
1259 p_nat->port_alloc_ring);
1260 rte_mempool_put(napt_port_pool,
1265 /* reset j and advance i */
1267 i += max_ips_remain;
1275 printf("******* p_nat->pub_ip_count:%d ***********\n",
1276 p_nat->pub_ip_count);
1277 /* Initialize all public IP's ports */
1279 uint32_t max_ports_remain;
1281 for (if_ports = 0; if_ports < p_nat->pub_ip_count; if_ports++) {
1282 /* Add all available ports to the ring */
1284 for (i = p_nat->pub_ip_port_set[if_ports].start_port;
1285 i <= p_nat->pub_ip_port_set[if_ports].end_port;) {
1286 /* 1. Get a port alloc buffer from napt_port_pool */
1290 /* get new napt_port_alloc_elem from pool */
1291 if (rte_mempool_get(napt_port_pool, &portsBuf) <
1293 printf("CGNAPT - Error in getting "
1294 "port alloc buffer\n");
1299 /* 2. Populate it with available ports and ip addr */
1300 struct napt_port_alloc_elem *pb =
1301 (struct napt_port_alloc_elem *)portsBuf;
1304 temp = p_nat->pub_ip_port_set[if_ports].end_port -
1306 /* Check if remaining port count is greater
1307 * than or equals to bulk count, if not give
1308 * remaining count ports than giving bulk count
1310 if (temp < NUM_NAPT_PORT_BULK_ALLOC)
1311 max_ports_remain = temp;
1314 NUM_NAPT_PORT_BULK_ALLOC;
1316 for (j = 0; j < max_ports_remain; j++) {
1319 p_nat->pub_ip_port_set[if_ports].ip;
1320 pb->ports[j] = i + j;
1321 if ((i + j) == p_nat->pub_ip_port_set
1322 [if_ports].end_port)
1326 /* 3. add the port alloc buffer to ring */
1327 if (rte_ring_enqueue(p_nat->port_alloc_ring,
1329 printf("CGNAPT%d - Enqueue error - i %d, j %d, "
1330 " if_ports %d, pb %p\n", p_nat->pipeline_num,
1331 i, j, if_ports, pb);
1333 rte_ring_dump(stdout, p_nat->port_alloc_ring);
1334 rte_mempool_put(napt_port_pool, portsBuf);
1338 /* reset j and advance i */
1340 i += max_ports_remain;
1347 static pipeline_msg_req_handler handlers[] = {
1348 [PIPELINE_MSG_REQ_PING] =
1349 pipeline_msg_req_ping_handler,
1350 [PIPELINE_MSG_REQ_STATS_PORT_IN] =
1351 pipeline_msg_req_stats_port_in_handler,
1352 [PIPELINE_MSG_REQ_STATS_PORT_OUT] =
1353 pipeline_msg_req_stats_port_out_handler,
1354 [PIPELINE_MSG_REQ_STATS_TABLE] = pipeline_msg_req_stats_table_handler,
1355 [PIPELINE_MSG_REQ_PORT_IN_ENABLE] =
1356 pipeline_msg_req_port_in_enable_handler,
1357 [PIPELINE_MSG_REQ_PORT_IN_DISABLE] =
1358 pipeline_msg_req_port_in_disable_handler,
1359 [PIPELINE_MSG_REQ_CUSTOM] =
1360 pipeline_cgnapt_msg_req_custom_handler,
1363 static pipeline_msg_req_handler custom_handlers[] = {
1364 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_ADD] =
1365 pipeline_cgnapt_msg_req_entry_add_handler,
1366 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_DEL] =
1367 pipeline_cgnapt_msg_req_entry_del_handler,
1368 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_SYNC] =
1369 pipeline_cgnapt_msg_req_entry_sync_handler,
1370 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_DBG] =
1371 pipeline_cgnapt_msg_req_entry_dbg_handler,
1372 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_ADDM] =
1373 pipeline_cgnapt_msg_req_entry_addm_handler,
1374 [PIPELINE_CGNAPT_MSG_REQ_VER] =
1375 pipeline_cgnapt_msg_req_ver_handler,
1376 [PIPELINE_CGNAPT_MSG_REQ_NSP_ADD] =
1377 pipeline_cgnapt_msg_req_nsp_add_handler,
1378 [PIPELINE_CGNAPT_MSG_REQ_NSP_DEL] =
1379 pipeline_cgnapt_msg_req_nsp_del_handler,
1382 [PIPELINE_CGNAPT_MSG_REQ_PCP] =
1383 pipeline_cgnapt_msg_req_pcp_handler,
1388 * Function to convert an IPv6 packet to IPv4 packet
1391 * A pointer to packet mbuf
1392 * @param in_ipv6_hdr
1393 * A pointer to IPv6 header in the given pkt
1397 convert_ipv6_to_ipv4(struct rte_mbuf *pkt, struct ipv6_hdr *in_ipv6_hdr)
1399 uint32_t ip_hdr_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE;
1401 uint8_t *eth_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1402 uint8_t *ipv6_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, ip_hdr_offset);
1404 struct ether_hdr eth_hdr;
1405 struct ipv4_hdr *ipv4_hdr_p;
1406 uint16_t frag_off = 0x4000;
1407 struct cgnapt_nsp_node *ll = nsp_ll;
1408 uint8_t ipv4_dest[4];
1411 memcpy(ð_hdr, eth_hdr_p, sizeof(struct ether_hdr));
1412 memcpy(in_ipv6_hdr, ipv6_hdr_p, sizeof(struct ipv6_hdr));
1414 eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
1416 char *data_area_p = rte_pktmbuf_adj(pkt, 20);
1417 if (data_area_p == NULL) {
1418 printf("convert_ipv6_to_ipv4:data_area_p is NULL\n");
1421 ipv4_hdr_p = (struct ipv4_hdr *)(data_area_p + ETH_HDR_SIZE);
1422 memset(ipv4_hdr_p, 0, sizeof(struct ipv4_hdr));
1424 memcpy(data_area_p, ð_hdr, sizeof(struct ether_hdr));
1426 #ifdef CGNAPT_DBG_PRNT
1427 if (CGNAPT_DEBUG == 1)
1428 printf("convert_ipv6_to_ipv4: eth_hdr_p(%p), data_area_p(%p), "
1429 "ipv4_hdr_p(%p)\n", eth_hdr_p, data_area_p, ipv4_hdr_p);
1432 ipv4_hdr_p->version_ihl = 0x4 << 4 | 0x5;
1433 ipv4_hdr_p->type_of_service =
1434 rte_be_to_cpu_32(in_ipv6_hdr->vtc_flow) & 0x0ff00000 >> 20;
1435 ipv4_hdr_p->total_length =
1436 rte_cpu_to_be_16(rte_be_to_cpu_16(
1437 in_ipv6_hdr->payload_len) + 20);
1438 ipv4_hdr_p->packet_id = 0;
1439 ipv4_hdr_p->fragment_offset = rte_cpu_to_be_16(frag_off);
1440 ipv4_hdr_p->time_to_live = in_ipv6_hdr->hop_limits;
1441 ipv4_hdr_p->next_proto_id = in_ipv6_hdr->proto;
1442 ipv4_hdr_p->hdr_checksum = 0;
1443 ipv4_hdr_p->src_addr = 0;
1445 while (ll != NULL) {
1447 (&in_ipv6_hdr->dst_addr[0], &ll->nsp.prefix[0],
1448 ll->nsp.depth / 8)) {
1449 if (ll->nsp.depth == 32)
1450 memcpy(&ipv4_dest[0], &in_ipv6_hdr->dst_addr[4],
1452 else if (ll->nsp.depth == 40) {
1453 ipv4_dest[0] = in_ipv6_hdr->dst_addr[5];
1454 ipv4_dest[1] = in_ipv6_hdr->dst_addr[6];
1455 ipv4_dest[2] = in_ipv6_hdr->dst_addr[7];
1456 ipv4_dest[3] = in_ipv6_hdr->dst_addr[9];
1457 } else if (ll->nsp.depth == 48) {
1458 ipv4_dest[0] = in_ipv6_hdr->dst_addr[6];
1459 ipv4_dest[1] = in_ipv6_hdr->dst_addr[7];
1460 ipv4_dest[2] = in_ipv6_hdr->dst_addr[9];
1461 ipv4_dest[3] = in_ipv6_hdr->dst_addr[10];
1462 } else if (ll->nsp.depth == 56) {
1463 ipv4_dest[0] = in_ipv6_hdr->dst_addr[7];
1464 ipv4_dest[1] = in_ipv6_hdr->dst_addr[9];
1465 ipv4_dest[2] = in_ipv6_hdr->dst_addr[10];
1466 ipv4_dest[3] = in_ipv6_hdr->dst_addr[11];
1467 } else if (ll->nsp.depth == 64) {
1468 ipv4_dest[0] = in_ipv6_hdr->dst_addr[9];
1469 ipv4_dest[1] = in_ipv6_hdr->dst_addr[10];
1470 ipv4_dest[2] = in_ipv6_hdr->dst_addr[11];
1471 ipv4_dest[3] = in_ipv6_hdr->dst_addr[12];
1472 } else if (ll->nsp.depth == 96) {
1473 ipv4_dest[0] = in_ipv6_hdr->dst_addr[12];
1474 ipv4_dest[1] = in_ipv6_hdr->dst_addr[13];
1475 ipv4_dest[2] = in_ipv6_hdr->dst_addr[14];
1476 ipv4_dest[3] = in_ipv6_hdr->dst_addr[15];
1487 memcpy(&ipv4_hdr_p->dst_addr, &ipv4_dest[0], 4);
1489 memcpy(&ipv4_hdr_p->dst_addr, &in_ipv6_hdr->dst_addr[12], 4);
1494 * Function to convert an IPv4 packet to IPv6 packet
1497 * A pointer to packet mbuf
1498 * @param in_ipv4_hdr
1499 * A pointer to IPv4 header in the given pkt
1503 convert_ipv4_to_ipv6(struct rte_mbuf *pkt, struct ipv4_hdr *in_ipv4_hdr)
1505 uint32_t ip_hdr_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE;
1507 uint8_t *eth_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1508 uint8_t *ipv4_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, ip_hdr_offset);
1510 struct ether_hdr eth_hdr;
1511 struct ipv6_hdr *ipv6_hdr_p;
1513 memcpy(ð_hdr, eth_hdr_p, sizeof(struct ether_hdr));
1514 memcpy(in_ipv4_hdr, ipv4_hdr_p, sizeof(struct ipv4_hdr));
1516 eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
1518 char *data_area_p = rte_pktmbuf_prepend(pkt, 20);
1519 if (data_area_p == NULL) {
1520 printf("convert_ipv4_to_ipv6:data_area_p is NULL\n");
1523 ipv6_hdr_p = (struct ipv6_hdr *)(data_area_p + ETH_HDR_SIZE);
1524 memset(ipv6_hdr_p, 0, sizeof(struct ipv6_hdr));
1526 memcpy(data_area_p, ð_hdr, sizeof(struct ether_hdr));
1528 ipv6_hdr_p->vtc_flow =
1529 rte_cpu_to_be_32((0x6 << 28) |
1530 (in_ipv4_hdr->type_of_service << 20));
1531 ipv6_hdr_p->payload_len =
1532 rte_cpu_to_be_16(rte_be_to_cpu_16(
1533 in_ipv4_hdr->total_length) - 20);
1534 ipv6_hdr_p->proto = in_ipv4_hdr->next_proto_id;
1535 ipv6_hdr_p->hop_limits = in_ipv4_hdr->time_to_live;
1537 ipv6_hdr_p->src_addr[0] = 0x00;
1538 ipv6_hdr_p->src_addr[1] = 0x64;
1539 ipv6_hdr_p->src_addr[2] = 0xff;
1540 ipv6_hdr_p->src_addr[3] = 0x9b;
1541 ipv6_hdr_p->src_addr[4] = 0x00;
1542 ipv6_hdr_p->src_addr[5] = 0x00;
1543 ipv6_hdr_p->src_addr[6] = 0x00;
1544 ipv6_hdr_p->src_addr[7] = 0x00;
1545 ipv6_hdr_p->src_addr[8] = 0x00;
1546 ipv6_hdr_p->src_addr[9] = 0x00;
1547 ipv6_hdr_p->src_addr[10] = 0x00;
1548 ipv6_hdr_p->src_addr[11] = 0x00;
1549 memcpy(&ipv6_hdr_p->src_addr[12], &in_ipv4_hdr->src_addr, 4);
1551 memset(&ipv6_hdr_p->dst_addr, 0, 16);
1558 * Output port handler
1561 * A pointer to packet mbuf
1563 * Unused void pointer
1566 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1568 pkt_work_cgnapt_out(__rte_unused struct rte_mbuf *pkt, __rte_unused void *arg)
1570 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1571 if ((cgnapt_num_func_to_inst == 5)
1572 && (cgnapt_inst_index < INST_ARRAY_SIZE)) {
1573 if (cgnapt_inst5_flag == 0) {
1574 uint8_t *inst5_sig =
1575 RTE_MBUF_METADATA_UINT8_PTR(pkt,
1577 if (*inst5_sig == CGNAPT_INST5_SIG) {
1578 cgnapt_inst5_flag = 1;
1579 inst_end_time[cgnapt_inst_index] =
1580 rte_get_tsc_cycles();
1581 cgnapt_inst_index++;
1587 /* cgnapt_pkt_out_count++; */
1588 #ifdef CGNAPT_DBG_PRNT
1596 * Output port handler to handle 4 pkts
1599 * A pointer to packet mbuf
1601 * Inport handler argument pointer
1604 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1605 static void pkt4_work_cgnapt_out(struct rte_mbuf **pkt, void *arg)
1609 /* TO BE IMPLEMENTED IF REQUIRED */
1613 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1614 PIPELINE_CGNAPT_PORT_OUT_AH(port_out_ah_cgnapt,
1615 pkt_work_cgnapt_out, pkt4_work_cgnapt_out);
1617 PIPELINE_CGNAPT_PORT_OUT_BAH(port_out_ah_cgnapt_bulk,
1618 pkt_work_cgnapt_out, pkt4_work_cgnapt_out);
1622 * Function to validate the packet and return version
1625 * A pointer to packet mbuf
1628 * IP version of the valid pkt, -1 if invalid pkt
1630 int rte_get_pkt_ver(struct rte_mbuf *pkt)
1632 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
1633 uint16_t *eth_proto =
1634 RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
1636 if (*eth_proto == rte_be_to_cpu_16(ETHER_TYPE_IPv4))
1637 return IP_VERSION_4;
1639 if (dual_stack_enable
1640 && (*eth_proto == rte_be_to_cpu_16(ETHER_TYPE_IPv6)))
1641 return IP_VERSION_6;
1643 /* Check the protocol first, if not UDP or TCP return */
1649 * A method to print the NAPT entry
1652 * A pointer to struct cgnapt_table_entry
1654 void my_print_entry(struct cgnapt_table_entry *ent)
1656 printf("CGNAPT key:\n");
1657 printf("entry_type :%d\n", ent->data.type);
1658 printf("prv_ip: %x %x %x %x\n", ent->data.u.u32_prv_ipv6[0],
1659 ent->data.u.u32_prv_ipv6[1], ent->data.u.u32_prv_ipv6[2],
1660 ent->data.u.u32_prv_ipv6[3]);
1661 printf("prv_port:%d\n", ent->data.prv_port);
1663 printf("pub_ip:%x\n", ent->data.pub_ip);
1664 printf("prv_phy_port:%d\n", ent->data.prv_phy_port);
1665 printf("pub_phy_port:%d\n", ent->data.pub_phy_port);
1669 * Function to print common CGNAPT table entries
1672 void print_common_table(void)
1680 index = rte_hash_iterate(napt_common_table,
1681 &key, &data, &next);
1683 if ((index != -EINVAL) && (index != -ENOENT)) {
1684 printf("\n%04d ", count);
1685 //print_key((struct pipeline_cgnapt_entry_key *)key);
1686 rte_hexdump(stdout, "KEY", key,
1687 sizeof(struct pipeline_cgnapt_entry_key));
1688 int32_t position = rte_hash_lookup(
1689 napt_common_table, key);
1690 print_cgnapt_entry(&napt_hash_tbl_entries[position]);
1694 } while (index != -ENOENT);
1698 * Input port handler for mixed traffic
1699 * This is the main method in this file when running in mixed traffic mode.
1700 * Starting from the packet burst it filters unwanted packets,
1701 * calculates keys, does lookup and then based on the lookup
1702 * updates NAPT table and does packet NAPT translation.
1705 * A pointer to struct rte_pipeline
1707 * A pointer to array of packets mbuf
1709 * Number of packets in the burst
1714 * int that is not checked by caller
1717 static int cgnapt_in_port_ah_mix(struct rte_pipeline *rte_p,
1718 struct rte_mbuf **pkts,
1719 uint32_t n_pkts, void *arg)
1724 * 1. Read packet version, if invalid drop the packet
1725 * 2. Check protocol, if not UDP or TCP drop the packet
1726 * 3. Bring all valid packets together - useful for bulk lookup
1727 * and calculate key for all packets
1728 * a. If IPv4 : calculate key with full IP
1729 * b. If IPv6 : calculate key with last 32-bit of IP
1730 * 4. Do bulk lookup with rte_hash_lookup_bulk(), if something went wrong
1732 * 5. For lookup hit packets, read entry from table
1733 * 6. For lookup miss packets, add dynamic entry to table
1735 * a. If egress pkt, convert to IPv4 and NAPT it
1736 * b. If ingress, drop the pkt
1738 * a. If egress pkt, NAPT it. Get MAC
1739 * b. If first ingress pkt (with no egress entry), drop the pkt
1740 * If not first ingress pkt
1741 * I. If IPv6 converted packet, convert back to IPv6,
1743 * II. If IPv4 packet, NAPT it & get MAC
1744 * 9. Send all packets out to corresponding ports
1746 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
1747 struct pipeline_cgnapt *p_nat = ap->p;
1748 uint8_t compacting_map[RTE_HASH_LOOKUP_BULK_MAX];
1749 uint32_t packets_for_lookup = 0;
1752 p_nat->valid_packets = 0;
1753 p_nat->invalid_packets = 0;
1755 #ifdef CGNAPT_DBG_PRNT
1756 if (CGNAPT_DEBUG > 1)
1757 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
1760 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
1762 uint16_t phy_port = 0;
1763 uint16_t *src_port = NULL;
1764 uint16_t *dst_port = NULL;
1765 uint32_t *src_addr = NULL;
1766 uint32_t *dst_addr = NULL;
1767 uint8_t *protocol = NULL;
1768 uint8_t *eth_dest = NULL;
1769 uint8_t *eth_src = NULL;
1770 uint16_t src_port_offset = 0;
1771 uint16_t dst_port_offset = 0;
1772 uint16_t src_addr_offset = 0;
1773 uint16_t dst_addr_offset = 0;
1774 uint16_t prot_offset = 0;
1775 uint16_t eth_offset = 0;
1778 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
1780 src_port_offset = SRC_PRT_OFST_IP4_TCP;
1781 dst_port_offset = DST_PRT_OFST_IP4_TCP;
1783 for (i = 0; i < n_pkts; i++) {
1784 p_nat->receivedPktCount++;
1786 /* bitmask representing only this packet */
1787 uint64_t pkt_mask = 1LLU << i;
1789 /* remember this pkt as valid pkt */
1790 p_nat->valid_packets |= pkt_mask;
1792 struct rte_mbuf *pkt = pkts[i];
1795 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
1798 int ver = rte_get_pkt_ver(pkt);
1800 #ifdef CGNAPT_DBG_PRNT
1801 printf("ver no. of the pkt:%d\n", ver);
1804 if (unlikely(ver < 0)) {
1805 /* Not a valid pkt , ignore. */
1806 /* remember invalid packets to be dropped */
1807 p_nat->invalid_packets |= pkt_mask;
1808 p_nat->naptDroppedPktCount++;
1810 #ifdef CGNAPT_DEBUGGING
1811 p_nat->naptDroppedPktCount1++;
1816 prot_offset = PROT_OFST_IP4;
1818 prot_offset = PROT_OFST_IP6;
1820 (uint8_t *) RTE_MBUF_METADATA_UINT32_PTR(pkt,
1823 (*protocol == IP_PROTOCOL_TCP
1824 || *protocol == IP_PROTOCOL_UDP
1825 || *protocol == IP_PROTOCOL_ICMP)) {
1826 /* remember invalid packets to be dropped */
1827 p_nat->invalid_packets |= pkt_mask;
1828 p_nat->naptDroppedPktCount++;
1830 #ifdef CGNAPT_DEBUGGING
1831 p_nat->naptDroppedPktCount2++;
1836 #ifdef CGNAPT_DBG_PRNT
1837 if (CGNAPT_DEBUG > 4)
1843 * 1. Handel PCP for egress traffic
1844 * 2. If PCP, then give response (send pkt) from the same port
1845 * 3. Drop the PCP packet, should not be added in the NAPT table
1848 if (*protocol == IP_PROTOCOL_UDP) {
1849 struct udp_hdr *udp;
1851 udp = (struct udp_hdr *)
1852 RTE_MBUF_METADATA_UINT8_PTR(pkt,
1855 udp = (struct udp_hdr *)
1856 RTE_MBUF_METADATA_UINT8_PTR(pkt,
1859 if (rte_bswap16(udp->dst_port) ==
1861 handle_pcp_req(pkt, ver, p_nat);
1862 p_nat->invalid_packets |= pkt_mask;
1872 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1875 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1878 if ((*protocol == IP_PROTOCOL_TCP)
1879 || (*protocol == IP_PROTOCOL_UDP)) {
1881 src_port_offset = SRC_PRT_OFST_IP4_TCP;
1882 dst_port_offset = DST_PRT_OFST_IP4_TCP;
1884 } else if (*protocol == IP_PROTOCOL_ICMP) {
1886 src_port_offset = IDEN_OFST_IP4_ICMP;
1887 /* Sequence number */
1888 dst_port_offset = SEQN_OFST_IP4_ICMP;
1892 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1895 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1900 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1903 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1906 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1909 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1912 /* need to create compacted table of pointers to
1913 * pass to bulk lookup
1916 compacting_map[packets_for_lookup] = i;
1918 //phy_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, phyport_offset);
1919 phy_port = pkt->port;
1921 struct pipeline_cgnapt_entry_key key;
1923 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
1926 if (get_in_port_dir(phy_port)) {
1929 key.ip = rte_bswap32(*src_addr);
1931 key.ip = rte_bswap32(src_addr[3]);
1932 key.port = rte_bswap16(*src_port);
1934 #ifdef NAT_ONLY_CONFIG_REQ
1935 if (nat_only_config_flag)
1940 key.ip = rte_bswap32(*dst_addr);
1942 if (*protocol == IP_PROTOCOL_ICMP) {
1943 /* common table lookupkey preparation from
1944 * incoming ICMP Packet- Indentifier field
1946 key.port = rte_bswap16(*src_port);
1948 key.port = rte_bswap16(*dst_port);
1951 #ifdef NAT_ONLY_CONFIG_REQ
1952 if (nat_only_config_flag)
1959 memcpy(&(p_nat->keys[packets_for_lookup]), &key,
1960 sizeof(struct pipeline_cgnapt_entry_key));
1961 p_nat->key_ptrs[packets_for_lookup] =
1962 &(p_nat->keys[packets_for_lookup]);
1963 packets_for_lookup++;
1966 if (unlikely(packets_for_lookup == 0)) {
1967 /* no suitable packet for lookup */
1968 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
1969 return p_nat->valid_packets;
1972 /* lookup entries in the common napt table */
1974 int lookup_result = rte_hash_lookup_bulk(napt_common_table,
1978 &p_nat->lkup_indx[0]);
1980 if (unlikely(lookup_result < 0)) {
1981 /* unknown error, just discard all packets */
1982 printf("Unexpected hash lookup error %d, discarding all "
1983 "packets", lookup_result);
1984 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
1987 //struct rte_pipeline_table_entry *entries[64];
1988 /* Now one by one check the result of our bulk lookup */
1990 for (i = 0; i < packets_for_lookup; i++) {
1991 /* index into hash table entries */
1992 int hash_table_entry = p_nat->lkup_indx[i];
1993 /* index into packet table of this packet */
1994 uint8_t pkt_index = compacting_map[i];
1995 /*bitmask representing only this packet */
1996 uint64_t pkt_mask = 1LLU << pkt_index;
1998 struct cgnapt_table_entry *entry = NULL;
1999 if (hash_table_entry < 0) {
2001 /* try to add new entry */
2002 struct rte_pipeline_table_entry *table_entry = NULL;
2005 pkt_miss_cgnapt(p_nat->key_ptrs[i],
2008 &p_nat->valid_packets,
2013 /* ICMP Error message generation for
2014 * Destination Host unreachable
2016 if (*protocol == IP_PROTOCOL_ICMP) {
2017 cgnapt_icmp_pkt = pkts[pkt_index];
2018 send_icmp_dest_unreachable_msg();
2021 /* Drop packet by adding to invalid pkt mask */
2023 p_nat->invalid_packets |= dropmask;
2024 #ifdef CGNAPT_DEBUGGING
2025 if (p_nat->kpc2++ < 5) {
2026 printf("in_ah Th: %d",
2027 p_nat->pipeline_num);
2028 print_key(p_nat->key_ptrs[i]);
2032 p_nat->naptDroppedPktCount++;
2034 #ifdef CGNAPT_DEBUGGING
2035 p_nat->naptDroppedPktCount3++;
2040 entry = (struct cgnapt_table_entry *)table_entry;
2042 /* entry found for this packet */
2043 entry = &napt_hash_tbl_entries[hash_table_entry];
2046 /* apply napt and mac changes */
2048 p_nat->entries[pkt_index] = &(entry->head);
2050 phy_port = pkts[pkt_index]->port;
2052 struct ipv6_hdr ipv6_hdr;
2053 struct ipv4_hdr ipv4_hdr;
2055 ver = rte_get_pkt_ver(pkts[pkt_index]);
2056 #ifdef CGNAPT_DEBUGGING
2057 if (CGNAPT_DEBUG >= 1) {
2058 printf("ver:%d\n", ver);
2059 printf("entry->data.type:%d\n", entry->data.type);
2062 if ((ver == 6) && (entry->data.type == CGNAPT_ENTRY_IPV6)
2063 && is_phy_port_privte(phy_port)) {
2064 convert_ipv6_to_ipv4(pkts[pkt_index], &ipv6_hdr);
2066 pkt_type = PKT_TYPE_IPV6to4;
2068 #ifdef CGNAPT_DBG_PRNT
2069 if (CGNAPT_DEBUG >= 1)
2070 printf("pkt_work_cganpt: "
2071 "convert_ipv6_to_ipv4\n");
2074 struct cgnapt_nsp_node *ll = nsp_ll;
2076 while (ll != NULL) {
2077 if (!memcmp(&ipv6_hdr.dst_addr[0],
2079 ll->nsp.depth / 8)) {
2087 && !memcmp(&ipv6_hdr.dst_addr[0],
2088 &well_known_prefix[0], 12)) {
2093 p_nat->invalid_packets |= 1LLU << pkt_index;
2094 p_nat->naptDroppedPktCount++;
2096 #ifdef CGNAPT_DEBUGGING
2097 p_nat->naptDroppedPktCount5++;
2104 /* As packet is already converted into IPv4 we must not operate
2105 * IPv6 offsets on packet
2106 * Only perform IPv4 operations
2111 src_port_offset = SRC_PRT_OFST_IP6t4;
2112 dst_port_offset = DST_PRT_OFST_IP6t4;
2113 src_addr_offset = SRC_ADR_OFST_IP6t4;
2114 dst_addr_offset = DST_ADR_OFST_IP6t4;
2115 prot_offset = PROT_OFST_IP6t4;
2116 eth_offset = ETH_OFST_IP6t4;
2120 if ((*protocol == IP_PROTOCOL_TCP)
2121 || (*protocol == IP_PROTOCOL_UDP)) {
2122 src_port_offset = SRC_PRT_OFST_IP4_TCP;
2123 dst_port_offset = DST_PRT_OFST_IP4_TCP;
2124 } else if (*protocol == IP_PROTOCOL_ICMP) {
2126 src_port_offset = IDEN_OFST_IP4_ICMP;
2127 /* Sequence number */
2128 dst_port_offset = SEQN_OFST_IP4_ICMP;
2131 src_addr_offset = SRC_ADR_OFST_IP4;
2132 dst_addr_offset = DST_ADR_OFST_IP4;
2133 prot_offset = PROT_OFST_IP4;
2134 eth_offset = MBUF_HDR_ROOM;
2139 RTE_MBUF_METADATA_UINT32_PTR(pkts[pkt_index],
2142 RTE_MBUF_METADATA_UINT32_PTR(pkts[pkt_index],
2145 RTE_MBUF_METADATA_UINT16_PTR(pkts[pkt_index],
2148 RTE_MBUF_METADATA_UINT16_PTR(pkts[pkt_index],
2151 RTE_MBUF_METADATA_UINT8_PTR(pkts[pkt_index],
2155 RTE_MBUF_METADATA_UINT8_PTR(pkts[pkt_index],
2158 RTE_MBUF_METADATA_UINT8_PTR(pkts[pkt_index],
2161 if (entry->data.ttl == NAPT_ENTRY_STALE)
2162 entry->data.ttl = NAPT_ENTRY_VALID;
2164 struct ether_addr hw_addr;
2165 uint32_t dest_address = 0;
2166 uint8_t nh_ipv6[16];
2169 uint32_t dest_if = 0xff;
2172 uint16_t *outport_id =
2173 RTE_MBUF_METADATA_UINT16_PTR(pkts[pkt_index],
2174 cgnapt_meta_offset);
2176 if (is_phy_port_privte(phy_port)) {
2178 if (*protocol == IP_PROTOCOL_UDP
2179 && rte_be_to_cpu_16(*dst_port) == 53) {
2180 p_nat->invalid_packets |= 1LLU << pkt_index;
2181 p_nat->naptDroppedPktCount++;
2182 #ifdef CGNAPT_DEBUGGING
2183 p_nat->naptDroppedPktCount6++;
2188 dest_address = rte_bswap32(*dst_addr);
2189 ret = local_get_nh_ipv4(dest_address, &dest_if,
2192 dest_if = get_prv_to_pub_port(&dest_address,
2194 if (dest_if == INVALID_DESTIF) {
2195 p_nat->invalid_packets |=
2197 p_nat->naptDroppedPktCount++;
2198 #ifdef CGNAPT_DEBUGGING
2199 p_nat->naptDroppedPktCount6++;
2203 do_local_nh_ipv4_cache(dest_if, p_nat);
2206 *outport_id = p_nat->outport_id[dest_if];
2207 struct arp_entry_data *ret_arp_data;
2208 ret_arp_data = get_dest_mac_addr_port(dest_address,
2209 &dest_if, (struct ether_addr *)&hw_addr);
2211 if (unlikely(ret_arp_data == NULL)) {
2213 printf("%s: NHIP Not Found, nhip: %x, "
2214 "outport_id: %d\n", __func__, nhip,
2218 p_nat->invalid_packets |= pkt_mask;
2219 p_nat->naptDroppedPktCount++;
2221 #ifdef CGNAPT_DEBUGGING
2222 p_nat->naptDroppedPktCount4++;
2227 if (ret_arp_data->status == COMPLETE) {
2229 if (ret_arp_data->num_pkts) {
2230 p_nat->naptedPktCount += ret_arp_data->num_pkts;
2231 arp_send_buffered_pkts(ret_arp_data,
2232 &hw_addr, *outport_id);
2235 memcpy(eth_dest, &hw_addr,
2236 sizeof(struct ether_addr));
2237 memcpy(eth_src, get_link_hw_addr(dest_if),
2238 sizeof(struct ether_addr));
2239 #ifdef CGNAPT_DBG_PRNT
2240 if (CGNAPT_DEBUG > 2) {
2241 printf("MAC found for ip 0x%x, port %d - "
2242 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2243 dest_address, *outport_id,
2244 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
2245 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
2246 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
2248 printf("Dest MAC before - "
2249 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2250 eth_dest[0], eth_dest[1], eth_dest[2],
2251 eth_dest[3], eth_dest[4], eth_dest[5]);
2255 #ifdef CGNAPT_DBG_PRNT
2256 if (CGNAPT_DEBUG > 2) {
2257 printf("Dest MAC after - "
2258 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2259 eth_dest[0], eth_dest[1], eth_dest[2],
2260 eth_dest[3], eth_dest[4], eth_dest[5]);
2264 #ifdef CGNAPT_DBG_PRNT
2265 if (CGNAPT_DEBUG > 4)
2266 print_pkt(pkts[pkt_index]);
2269 } else if (ret_arp_data->status == INCOMPLETE ||
2270 ret_arp_data->status == PROBE) {
2271 if (ret_arp_data->num_pkts >= NUM_DESC) {
2273 p_nat->invalid_packets |= pkt_mask;
2274 p_nat->naptDroppedPktCount++;
2276 #ifdef CGNAPT_DEBUGGING
2277 p_nat->naptDroppedPktCount4++;
2281 arp_queue_unresolved_packet(ret_arp_data,
2287 #ifdef CGNAPT_DBG_PRNT
2288 if (CGNAPT_DEBUG > 2)
2289 printf("Egress: \tphy_port:%d\t "
2290 "get_prv_to_pub():%d \tout_port:%d\n",
2296 *src_addr = rte_bswap32(entry->data.pub_ip);
2298 #ifdef NAT_ONLY_CONFIG_REQ
2299 if (!nat_only_config_flag) {
2301 *src_port = rte_bswap16(entry->data.pub_port);
2302 #ifdef NAT_ONLY_CONFIG_REQ
2306 p_nat->enaptedPktCount++;
2309 if (*protocol == IP_PROTOCOL_UDP
2310 && rte_be_to_cpu_16(*src_port) == 53) {
2311 p_nat->invalid_packets |= 1LLU << pkt_index;
2312 p_nat->naptDroppedPktCount++;
2313 #ifdef CGNAPT_DEBUGGING
2314 p_nat->naptDroppedPktCount6++;
2319 #ifdef CGNAPT_DBG_PRNT
2320 if (CGNAPT_DEBUG > 2)
2321 printf("Ingress: \tphy_port:%d\t "
2322 "get_pub_to_prv():%d \tout_port%d\n",
2327 if (entry->data.type == CGNAPT_ENTRY_IPV6) {
2328 convert_ipv4_to_ipv6(pkts[pkt_index],
2330 pkt_type = PKT_TYPE_IPV4to6;
2331 /* Ethernet MTU check */
2332 if ((rte_pktmbuf_data_len(pkts[pkt_index]) -
2334 p_nat->invalid_packets |= pkt_mask;
2335 p_nat->naptDroppedPktCount++;
2339 eth_dest = eth_dest - 20;
2340 eth_src = eth_src - 20;
2342 dst_port_offset = DST_PRT_OFST_IP4t6;
2343 dst_addr_offset = DST_ADR_OFST_IP4t6;
2345 RTE_MBUF_METADATA_UINT32_PTR(
2349 RTE_MBUF_METADATA_UINT16_PTR(
2353 memcpy((uint8_t *) &dst_addr[0],
2354 &entry->data.u.prv_ipv6[0], 16);
2355 memset(nh_ipv6, 0, 16);
2357 ret = local_get_nh_ipv6((uint8_t *)&dst_addr[0],
2358 &dest_if, &nh_ipv6[0], p_nat);
2361 dest_if = get_prv_to_pub_port(
2364 if (dest_if == INVALID_DESTIF) {
2365 p_nat->invalid_packets |=
2367 p_nat->naptDroppedPktCount++;
2368 #ifdef CGNAPT_DEBUGGING
2369 p_nat->naptDroppedPktCount6++;
2373 do_local_nh_ipv6_cache(dest_if, p_nat);
2375 *outport_id = p_nat->outport_id[dest_if];
2377 if (get_dest_mac_address_ipv6_port((uint8_t *)
2378 &dst_addr[0], &dest_if,
2379 &hw_addr, &nh_ipv6[0])){
2381 #ifdef CGNAPT_DBG_PRNT
2382 if (CGNAPT_DEBUG > 2) {
2383 printf("MAC found for ip 0x%x, port %d - "
2384 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2385 dest_address, *outport_id,
2386 hw_addr.addr_bytes[0],
2387 hw_addr.addr_bytes[1], hw_addr.addr_bytes[2],
2388 hw_addr.addr_bytes[3], hw_addr.addr_bytes[4],
2389 hw_addr.addr_bytes[5]);
2391 printf("Dest MAC before - "
2392 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2393 eth_dest[0], eth_dest[1], eth_dest[2],
2394 eth_dest[3], eth_dest[4], eth_dest[5]);
2397 memcpy(eth_dest, &hw_addr,
2398 sizeof(struct ether_addr));
2399 memcpy(eth_src, get_link_hw_addr(
2401 sizeof(struct ether_addr));
2403 #ifdef CGNAPT_DBG_PRNT
2404 if (CGNAPT_DEBUG > 2) {
2405 printf("Dest MAC after - "
2406 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2407 eth_dest[0], eth_dest[1], eth_dest[2],
2408 eth_dest[3], eth_dest[4], eth_dest[5]);
2412 #ifdef CGNAPT_DBG_PRNT
2413 if (CGNAPT_DEBUG > 4)
2414 print_pkt(pkts[pkt_index]);
2418 p_nat->invalid_packets |= pkt_mask;
2419 p_nat->naptDroppedPktCount++;
2420 #ifdef CGNAPT_DEBUGGING
2421 p_nat->naptDroppedPktCount4++;
2426 #ifdef NAT_ONLY_CONFIG_REQ
2427 if (!nat_only_config_flag) {
2430 rte_bswap16(entry->data.prv_port);
2431 #ifdef NAT_ONLY_CONFIG_REQ
2436 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
2437 dest_address = entry->data.u.prv_ip;
2438 ret = local_get_nh_ipv4(dest_address, &dest_if,
2441 dest_if = get_pub_to_prv_port(
2442 &dest_address, IP_VERSION_4);
2443 if (dest_if == INVALID_DESTIF) {
2444 p_nat->invalid_packets |=
2446 p_nat->naptDroppedPktCount++;
2447 #ifdef CGNAPT_DEBUGGING
2448 p_nat->naptDroppedPktCount6++;
2452 do_local_nh_ipv4_cache(dest_if, p_nat);
2455 *outport_id = p_nat->outport_id[dest_if];
2456 struct arp_entry_data *ret_arp_data;
2457 ret_arp_data = get_dest_mac_addr_port(dest_address,
2458 &dest_if, (struct ether_addr *)&hw_addr);
2460 if (unlikely(ret_arp_data == NULL)) {
2462 printf("%s: NHIP Not Found, nhip: %x, "
2463 "outport_id: %d\n", __func__, nhip,
2467 p_nat->invalid_packets |= pkt_mask;
2468 p_nat->naptDroppedPktCount++;
2470 #ifdef CGNAPT_DEBUGGING
2471 p_nat->naptDroppedPktCount4++;
2476 if (ret_arp_data->status == COMPLETE) {
2478 if (ret_arp_data->num_pkts) {
2479 p_nat->naptedPktCount +=
2480 ret_arp_data->num_pkts;
2481 arp_send_buffered_pkts(ret_arp_data,
2482 &hw_addr, *outport_id);
2485 memcpy(eth_dest, &hw_addr,
2486 sizeof(struct ether_addr));
2487 memcpy(eth_src, get_link_hw_addr(
2489 sizeof(struct ether_addr));
2490 #ifdef CGNAPT_DBG_PRNT
2491 if (CGNAPT_DEBUG > 2) {
2492 printf("MAC found for ip 0x%x, port %d - "
2493 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2494 dest_address, *outport_id,
2495 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
2496 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
2497 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
2499 printf("Dest MAC before - "
2500 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2501 eth_dest[0], eth_dest[1], eth_dest[2],
2502 eth_dest[3], eth_dest[4], eth_dest[5]);
2506 #ifdef CGNAPT_DBG_PRNT
2507 if (CGNAPT_DEBUG > 2) {
2508 printf("Dest MAC after - "
2509 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2510 eth_dest[0], eth_dest[1], eth_dest[2],
2511 eth_dest[3], eth_dest[4], eth_dest[5]);
2515 #ifdef CGNAPT_DBG_PRNT
2516 if (CGNAPT_DEBUG > 4)
2517 print_pkt(pkts[pkt_index]);
2520 } else if (ret_arp_data->status == INCOMPLETE ||
2521 ret_arp_data->status == PROBE) {
2522 arp_queue_unresolved_packet(ret_arp_data,
2527 if (*protocol == IP_PROTOCOL_ICMP) {
2528 // Query ID reverse translation done here
2530 rte_bswap16(entry->data.prv_port);
2532 #ifdef NAT_ONLY_CONFIG_REQ
2533 if (!nat_only_config_flag) {
2538 #ifdef NAT_ONLY_CONFIG_REQ
2544 p_nat->inaptedPktCount++;
2547 p_nat->naptedPktCount++;
2550 if (p_nat->hw_checksum_reqd)
2551 hw_checksum(pkts[pkt_index], pkt_type);
2553 sw_checksum(pkts[pkt_index], pkt_type);
2557 if (p_nat->invalid_packets) {
2558 /* get rid of invalid packets */
2559 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2561 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2563 #ifdef CGNAPT_DBG_PRNT
2564 if (CGNAPT_DEBUG > 1) {
2565 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
2566 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
2567 printf("invalid_packets:0x%jx\n",
2568 p_nat->invalid_packets);
2569 printf("rte_invalid_packets :0x%jx\n",
2570 rte_p->pkts_drop_mask);
2571 printf("Total pkts dropped :0x%jx\n",
2572 rte_p->n_pkts_ah_drop);
2577 return p_nat->valid_packets;
2581 * Input port handler for IPv4 private traffic
2582 * Starting from the packet burst it filters unwanted packets,
2583 * calculates keys, does lookup and then based on the lookup
2584 * updates NAPT table and does packet NAPT translation.
2587 * A pointer to struct rte_pipeline
2589 * A pointer to array of packets mbuf
2591 * Number of packets in the burst
2596 * int that is not checked by caller
2599 static int cgnapt_in_port_ah_ipv4_prv(struct rte_pipeline *rte_p,
2600 struct rte_mbuf **pkts,
2601 uint32_t n_pkts, void *arg)
2604 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
2605 struct pipeline_cgnapt *p_nat = ap->p;
2607 #ifdef CGNAPT_TIMING_INST
2608 uint64_t entry_timestamp = 0, exit_timestamp;
2610 if (p_nat->time_measurements_on) {
2611 entry_timestamp = rte_get_tsc_cycles();
2612 /* check since exit ts not valid first time through */
2613 if (likely(p_nat->in_port_exit_timestamp))
2614 p_nat->external_time_sum +=
2615 entry_timestamp - p_nat->in_port_exit_timestamp;
2619 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
2620 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
2621 p_nat->invalid_packets = 0;
2623 #ifdef CGNAPT_DBG_PRNT
2624 if (CGNAPT_DEBUG > 1)
2625 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
2628 /* prefetching for mbufs should be done here */
2629 for (j = 0; j < n_pkts; j++)
2630 rte_prefetch0(pkts[j]);
2632 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2633 pkt4_work_cgnapt_key_ipv4_prv(&pkts[i], i, arg, p_nat);
2635 for (; i < n_pkts; i++)
2636 pkt_work_cgnapt_key_ipv4_prv(pkts[i], i, arg, p_nat);
2638 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2640 if (unlikely(p_nat->valid_packets == 0)) {
2641 /* no suitable packet for lookup */
2642 printf("no suitable valid packets\n");
2643 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2644 return p_nat->valid_packets;
2647 /* lookup entries in the common napt table */
2649 int lookup_result = rte_hash_lookup_bulk(
2651 (const void **)&p_nat->key_ptrs,
2652 /* should be minus num invalid pkts */
2654 /*new pipeline data member */
2655 &p_nat->lkup_indx[0]);
2657 if (unlikely(lookup_result < 0)) {
2658 /* unknown error, just discard all packets */
2659 printf("Unexpected hash lookup error %d, discarding "
2660 "all packets", lookup_result);
2661 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
2665 /* Now call second stage of pipeline to one by one
2666 * check the result of our bulk lookup
2669 /* prefetching for table entries should be done here */
2670 for (j = 0; j < n_pkts; j++) {
2671 if (p_nat->lkup_indx[j] >= 0)
2672 rte_prefetch0(&napt_hash_tbl_entries
2673 [p_nat->lkup_indx[j]]);
2679 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2680 pkt4_work_cgnapt_ipv4_prv(pkts, i, arg, p_nat);
2682 for (; i < n_pkts; i++)
2683 pkt_work_cgnapt_ipv4_prv(pkts, i, arg, p_nat);
2685 if (arp_pkts_mask) {
2686 p_nat->valid_packets &= ~(arp_pkts_mask);
2687 rte_pipeline_ah_packet_hijack(rte_p, arp_pkts_mask);
2690 if (p_nat->invalid_packets) {
2691 /* get rid of invalid packets */
2692 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2694 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2696 #ifdef CGNAPT_DBG_PRNT
2697 if (CGNAPT_DEBUG > 1) {
2698 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
2699 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
2700 printf("invalid_packets:0x%jx\n",
2701 p_nat->invalid_packets);
2702 printf("rte_invalid_packets :0x%jx\n",
2703 rte_p->pkts_drop_mask);
2704 printf("Total pkts dropped :0x%jx\n",
2705 rte_p->n_pkts_ah_drop);
2710 #ifdef CGNAPT_TIMING_INST
2711 if (p_nat->time_measurements_on) {
2712 exit_timestamp = rte_get_tsc_cycles();
2713 p_nat->in_port_exit_timestamp = exit_timestamp;
2714 p_nat->internal_time_sum += exit_timestamp - entry_timestamp;
2715 p_nat->time_measurements++;
2716 if (p_nat->time_measurements == p_nat->max_time_mesurements)
2717 p_nat->time_measurements_on = 0;
2721 return p_nat->valid_packets;
2725 * Input port handler for IPv4 public traffic
2726 * Starting from the packet burst it filters unwanted packets,
2727 * calculates keys, does lookup and then based on the lookup
2728 * updates NAPT table and does packet NAPT translation.
2731 * A pointer to struct rte_pipeline
2733 * A pointer to array of packets mbuf
2735 * Number of packets in the burst
2740 * int that is not checked by caller
2742 static int cgnapt_in_port_ah_ipv4_pub(struct rte_pipeline *rte_p,
2743 struct rte_mbuf **pkts,
2744 uint32_t n_pkts, void *arg)
2747 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
2748 struct pipeline_cgnapt *p_nat = ap->p;
2750 #ifdef CGNAPT_TIMING_INST
2751 uint64_t entry_timestamp = 0, exit_timestamp;
2753 if (p_nat->time_measurements_on) {
2754 entry_timestamp = rte_get_tsc_cycles();
2756 /* check since exit ts not valid first time through */
2757 if (likely(p_nat->in_port_exit_timestamp))
2758 p_nat->external_time_sum +=
2759 entry_timestamp - p_nat->in_port_exit_timestamp;
2763 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
2764 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
2765 p_nat->invalid_packets = 0;
2767 #ifdef CGNAPT_DBG_PRNT
2768 if (CGNAPT_DEBUG > 1)
2769 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
2772 /* prefetching for mbufs should be done here */
2773 for (j = 0; j < n_pkts; j++)
2774 rte_prefetch0(pkts[j]);
2776 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2777 pkt4_work_cgnapt_key_ipv4_pub(&pkts[i], i, arg, p_nat);
2779 for (; i < n_pkts; i++)
2780 pkt_work_cgnapt_key_ipv4_pub(pkts[i], i, arg, p_nat);
2782 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2784 if (unlikely(p_nat->valid_packets == 0)) {
2785 printf("no valid packets in pub\n");
2786 /* no suitable packet for lookup */
2787 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2788 return p_nat->valid_packets;
2791 /* lookup entries in the common napt table */
2793 int lookup_result = rte_hash_lookup_bulk(
2795 (const void **)&p_nat->key_ptrs,
2796 /* should be minus num invalid pkts */
2798 /*new pipeline data member */
2799 &p_nat->lkup_indx[0]);
2801 if (unlikely(lookup_result < 0)) {
2802 /* unknown error, just discard all packets */
2803 printf("Unexpected hash lookup error %d, discarding "
2804 "all packets", lookup_result);
2805 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
2809 /* Now call second stage of pipeline to one by one
2810 * check the result of our bulk lookup
2813 /* prefetching for table entries should be done here */
2814 for (j = 0; j < n_pkts; j++) {
2815 if (p_nat->lkup_indx[j] >= 0)
2816 rte_prefetch0(&napt_hash_tbl_entries
2817 [p_nat->lkup_indx[j]]);
2820 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2821 pkt4_work_cgnapt_ipv4_pub(pkts, i, arg, p_nat);
2823 for (; i < n_pkts; i++)
2824 pkt_work_cgnapt_ipv4_pub(pkts, i, arg, p_nat);
2826 if (arp_pkts_mask) {
2827 rte_pipeline_ah_packet_hijack(rte_p, arp_pkts_mask);
2828 p_nat->valid_packets &= ~(arp_pkts_mask);
2831 if (p_nat->invalid_packets) {
2832 /* get rid of invalid packets */
2833 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2835 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2837 #ifdef CGNAPT_DBG_PRNT
2838 if (CGNAPT_DEBUG > 1) {
2839 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
2840 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
2841 printf("invalid_packets:0x%jx\n",
2842 p_nat->invalid_packets);
2843 printf("rte_invalid_packets :0x%jx\n",
2844 rte_p->pkts_drop_mask);
2845 printf("Total pkts dropped :0x%jx\n",
2846 rte_p->n_pkts_ah_drop);
2851 #ifdef CGNAPT_TIMING_INST
2852 if (p_nat->time_measurements_on) {
2853 exit_timestamp = rte_get_tsc_cycles();
2854 p_nat->in_port_exit_timestamp = exit_timestamp;
2856 p_nat->internal_time_sum += exit_timestamp - entry_timestamp;
2857 p_nat->time_measurements++;
2858 if (p_nat->time_measurements == p_nat->max_time_mesurements)
2859 p_nat->time_measurements_on = 0;
2863 return p_nat->valid_packets;
2867 * NAPT key calculation function for IPv4 private traffic
2868 * which handles 4 pkts
2871 * A pointer to array of packets mbuf
2873 * Starting pkt number of pkts
2877 * A pointer to main CGNAPT structure
2881 pkt4_work_cgnapt_key_ipv4_prv(
2882 struct rte_mbuf **pkt,
2884 __rte_unused void *arg,
2885 struct pipeline_cgnapt *p_nat)
2887 p_nat->receivedPktCount += 4;
2888 /* bitmask representing only this packet */
2889 uint64_t pkt_mask0 = 1LLU << pkt_num;
2890 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
2891 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
2892 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
2894 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
2896 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
2898 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
2900 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
2903 uint32_t src_addr0 = RTE_MBUF_METADATA_UINT32(pkt[0],
2905 uint32_t src_addr1 = RTE_MBUF_METADATA_UINT32(pkt[1],
2907 uint32_t src_addr2 = RTE_MBUF_METADATA_UINT32(pkt[2],
2909 uint32_t src_addr3 = RTE_MBUF_METADATA_UINT32(pkt[3],
2912 uint16_t src_port_offset0;
2913 uint16_t src_port_offset1;
2914 uint16_t src_port_offset2;
2915 uint16_t src_port_offset3;
2922 uint16_t phy_port0 = pkt[0]->port;
2923 uint16_t phy_port1 = pkt[1]->port;
2924 uint16_t phy_port2 = pkt[2]->port;
2925 uint16_t phy_port3 = pkt[3]->port;
2927 struct pipeline_cgnapt_entry_key key0;
2928 struct pipeline_cgnapt_entry_key key1;
2929 struct pipeline_cgnapt_entry_key key2;
2930 struct pipeline_cgnapt_entry_key key3;
2932 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
2933 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
2934 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
2935 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
2938 #ifdef CGNAPT_DBG_PRNT
2939 if (CGNAPT_DEBUG > 4)
2944 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
2948 switch (protocol0) {
2949 case IP_PROTOCOL_UDP:
2953 struct udp_hdr *udp;
2955 udp = (struct udp_hdr *)
2956 RTE_MBUF_METADATA_UINT8_PTR(pkt[0],
2959 if (rte_bswap16(udp->dst_port) ==
2961 handle_pcp_req(pkt[0], IPV4_SZ, p_nat);
2962 p_nat->invalid_packets |= pkt_mask0;
2968 case IP_PROTOCOL_TCP:
2970 src_port_offset0 = SRC_PRT_OFST_IP4_TCP;
2971 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
2976 case IP_PROTOCOL_ICMP:
2978 src_port_offset0 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
2980 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
2986 /* remember invalid packets to be dropped */
2987 p_nat->invalid_packets |= pkt_mask0;
2988 p_nat->naptDroppedPktCount++;
2990 #ifdef CGNAPT_DEBUGGING
2991 p_nat->naptDroppedPktCount2++;
2996 key0.pid = phy_port0;
2997 key0.ip = rte_bswap32(src_addr0);
2998 key0.port = rte_bswap16(src_port0);
3000 #ifdef NAT_ONLY_CONFIG_REQ
3001 if (nat_only_config_flag)
3005 memcpy(&p_nat->keys[pkt_num], &key0,
3006 sizeof(struct pipeline_cgnapt_entry_key));
3007 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3012 #ifdef CGNAPT_DBG_PRNT
3013 if (CGNAPT_DEBUG > 4)
3018 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
3021 switch (protocol1) {
3022 case IP_PROTOCOL_UDP:
3026 struct udp_hdr *udp;
3028 udp = (struct udp_hdr *)
3029 RTE_MBUF_METADATA_UINT8_PTR(pkt[1],
3032 if (rte_bswap16(udp->dst_port) ==
3034 handle_pcp_req(pkt[1], IPV4_SZ, p_nat);
3035 p_nat->invalid_packets |= pkt_mask1;
3041 case IP_PROTOCOL_TCP:
3043 src_port_offset1 = SRC_PRT_OFST_IP4_TCP;
3044 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3049 case IP_PROTOCOL_ICMP:
3051 src_port_offset1 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3053 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3059 /* remember invalid packets to be dropped */
3060 p_nat->invalid_packets |= pkt_mask1;
3061 p_nat->naptDroppedPktCount++;
3063 #ifdef CGNAPT_DEBUGGING
3064 p_nat->naptDroppedPktCount2++;
3069 key1.pid = phy_port1;
3070 key1.ip = rte_bswap32(src_addr1);
3071 key1.port = rte_bswap16(src_port1);
3073 #ifdef NAT_ONLY_CONFIG_REQ
3074 if (nat_only_config_flag)
3078 memcpy(&p_nat->keys[pkt_num + 1], &key1,
3079 sizeof(struct pipeline_cgnapt_entry_key));
3080 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
3084 #ifdef CGNAPT_DBG_PRNT
3085 if (CGNAPT_DEBUG > 4)
3090 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
3094 switch (protocol2) {
3095 case IP_PROTOCOL_UDP:
3099 struct udp_hdr *udp;
3101 udp = (struct udp_hdr *)
3102 RTE_MBUF_METADATA_UINT8_PTR(pkt[2],
3105 if (rte_bswap16(udp->dst_port) ==
3107 handle_pcp_req(pkt[2], IPV4_SZ, p_nat);
3108 p_nat->invalid_packets |= pkt_mask2;
3114 case IP_PROTOCOL_TCP:
3116 src_port_offset2 = SRC_PRT_OFST_IP4_TCP;
3117 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3122 case IP_PROTOCOL_ICMP:
3124 src_port_offset2 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3126 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3132 /* remember invalid packets to be dropped */
3133 p_nat->invalid_packets |= pkt_mask2;
3134 p_nat->naptDroppedPktCount++;
3136 #ifdef CGNAPT_DEBUGGING
3137 p_nat->naptDroppedPktCount2++;
3142 key2.pid = phy_port2;
3143 key2.ip = rte_bswap32(src_addr2);
3144 key2.port = rte_bswap16(src_port2);
3146 #ifdef NAT_ONLY_CONFIG_REQ
3147 if (nat_only_config_flag)
3151 memcpy(&p_nat->keys[pkt_num + 2], &key2,
3152 sizeof(struct pipeline_cgnapt_entry_key));
3153 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
3157 #ifdef CGNAPT_DBG_PRNT
3158 if (CGNAPT_DEBUG > 4)
3162 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
3166 switch (protocol3) {
3167 case IP_PROTOCOL_UDP:
3171 struct udp_hdr *udp;
3173 udp = (struct udp_hdr *)
3174 RTE_MBUF_METADATA_UINT8_PTR(pkt[3],
3177 if (rte_bswap16(udp->dst_port) ==
3179 handle_pcp_req(pkt[3], IPV4_SZ, p_nat);
3180 p_nat->invalid_packets |= pkt_mask3;
3186 case IP_PROTOCOL_TCP:
3188 src_port_offset3 = SRC_PRT_OFST_IP4_TCP;
3189 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3194 case IP_PROTOCOL_ICMP:
3196 src_port_offset3 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3198 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3204 /* remember invalid packets to be dropped */
3205 p_nat->invalid_packets |= pkt_mask3;
3206 p_nat->naptDroppedPktCount++;
3208 #ifdef CGNAPT_DEBUGGING
3209 p_nat->naptDroppedPktCount2++;
3214 key3.pid = phy_port3;
3215 key3.ip = rte_bswap32(src_addr3);
3216 key3.port = rte_bswap16(src_port3);
3218 #ifdef NAT_ONLY_CONFIG_REQ
3219 if (nat_only_config_flag)
3223 memcpy(&p_nat->keys[pkt_num + 3], &key3,
3224 sizeof(struct pipeline_cgnapt_entry_key));
3225 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
3229 * NAPT key calculation function for IPv4 public traffic
3230 * which handles 4 pkts
3233 * A pointer to array of packets mbuf
3235 * Starting pkt number of pkts
3239 * A pointer to main CGNAPT structure
3243 pkt4_work_cgnapt_key_ipv4_pub(
3244 struct rte_mbuf **pkt,
3246 __rte_unused void *arg,
3247 struct pipeline_cgnapt *p_nat)
3249 p_nat->receivedPktCount += 4;
3250 /* bitmask representing only this packet */
3251 uint64_t pkt_mask0 = 1LLU << pkt_num;
3252 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
3253 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
3254 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
3256 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
3258 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
3260 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
3262 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
3265 uint32_t dst_addr0 = RTE_MBUF_METADATA_UINT32(pkt[0],
3267 uint32_t dst_addr1 = RTE_MBUF_METADATA_UINT32(pkt[1],
3269 uint32_t dst_addr2 = RTE_MBUF_METADATA_UINT32(pkt[2],
3271 uint32_t dst_addr3 = RTE_MBUF_METADATA_UINT32(pkt[3],
3274 uint16_t src_port_offset0;
3275 uint16_t src_port_offset1;
3276 uint16_t src_port_offset2;
3277 uint16_t src_port_offset3;
3279 uint16_t dst_port_offset0;
3280 uint16_t dst_port_offset1;
3281 uint16_t dst_port_offset2;
3282 uint16_t dst_port_offset3;
3294 struct pipeline_cgnapt_entry_key key0;
3295 struct pipeline_cgnapt_entry_key key1;
3296 struct pipeline_cgnapt_entry_key key2;
3297 struct pipeline_cgnapt_entry_key key3;
3299 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
3300 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
3301 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
3302 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
3305 #ifdef CGNAPT_DBG_PRNT
3306 if (CGNAPT_DEBUG > 4)
3311 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
3315 switch (protocol0) {
3316 case IP_PROTOCOL_UDP:
3317 case IP_PROTOCOL_TCP:
3319 src_port_offset0 = SRC_PRT_OFST_IP4_TCP;
3320 dst_port_offset0 = DST_PRT_OFST_IP4_TCP;
3322 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3324 dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3327 key0.port = rte_bswap16(dst_port0);
3331 case IP_PROTOCOL_ICMP:
3333 src_port_offset0 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3335 /*Sequence number */
3336 dst_port_offset0 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3339 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3341 dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3344 key0.port = rte_bswap16(src_port0);
3349 /* remember invalid packets to be dropped */
3350 p_nat->invalid_packets |= pkt_mask0;
3351 p_nat->naptDroppedPktCount++;
3353 #ifdef CGNAPT_DEBUGGING
3354 p_nat->naptDroppedPktCount2++;
3360 key0.ip = rte_bswap32(dst_addr0);
3362 #ifdef NAT_ONLY_CONFIG_REQ
3363 if (nat_only_config_flag)
3367 memcpy(&p_nat->keys[pkt_num], &key0,
3368 sizeof(struct pipeline_cgnapt_entry_key));
3369 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3374 #ifdef CGNAPT_DBG_PRNT
3375 if (CGNAPT_DEBUG > 4)
3380 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
3384 switch (protocol1) {
3385 case IP_PROTOCOL_UDP:
3386 case IP_PROTOCOL_TCP:
3388 src_port_offset1 = SRC_PRT_OFST_IP4_TCP;
3389 dst_port_offset1 = DST_PRT_OFST_IP4_TCP;
3391 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3393 dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3396 key1.port = rte_bswap16(dst_port1);
3400 case IP_PROTOCOL_ICMP:
3402 src_port_offset1 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3404 /*Sequence number */
3405 dst_port_offset1 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3408 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3410 dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3413 key1.port = rte_bswap16(src_port1);
3417 /* remember invalid packets to be dropped */
3418 p_nat->invalid_packets |= pkt_mask1;
3419 p_nat->naptDroppedPktCount++;
3421 #ifdef CGNAPT_DEBUGGING
3422 p_nat->naptDroppedPktCount2++;
3428 key1.ip = rte_bswap32(dst_addr1);
3430 #ifdef NAT_ONLY_CONFIG_REQ
3431 if (nat_only_config_flag)
3435 memcpy(&p_nat->keys[pkt_num + 1], &key1,
3436 sizeof(struct pipeline_cgnapt_entry_key));
3437 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
3441 #ifdef CGNAPT_DBG_PRNT
3442 if (CGNAPT_DEBUG > 4)
3447 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
3451 switch (protocol2) {
3452 case IP_PROTOCOL_UDP:
3453 case IP_PROTOCOL_TCP:
3455 src_port_offset2 = SRC_PRT_OFST_IP4_TCP;
3456 dst_port_offset2 = DST_PRT_OFST_IP4_TCP;
3458 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3460 dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3463 key2.port = rte_bswap16(dst_port2);
3467 case IP_PROTOCOL_ICMP:
3469 src_port_offset2 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3471 /*Sequence number */
3472 dst_port_offset2 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3475 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3477 dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3480 key2.port = rte_bswap16(src_port2);
3485 /* remember invalid packets to be dropped */
3486 p_nat->invalid_packets |= pkt_mask2;
3487 p_nat->naptDroppedPktCount++;
3489 #ifdef CGNAPT_DEBUGGING
3490 p_nat->naptDroppedPktCount2++;
3496 key2.ip = rte_bswap32(dst_addr2);
3498 #ifdef NAT_ONLY_CONFIG_REQ
3499 if (nat_only_config_flag)
3503 memcpy(&p_nat->keys[pkt_num + 2], &key2,
3504 sizeof(struct pipeline_cgnapt_entry_key));
3505 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
3509 #ifdef CGNAPT_DBG_PRNT
3510 if (CGNAPT_DEBUG > 4)
3515 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
3519 switch (protocol3) {
3520 case IP_PROTOCOL_UDP:
3521 case IP_PROTOCOL_TCP:
3523 src_port_offset3 = SRC_PRT_OFST_IP4_TCP;
3524 dst_port_offset3 = DST_PRT_OFST_IP4_TCP;
3526 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3528 dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3531 key3.port = rte_bswap16(dst_port3);
3535 case IP_PROTOCOL_ICMP:
3537 src_port_offset3 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3539 /*Sequence number */
3540 dst_port_offset3 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3543 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3545 dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3548 key3.port = rte_bswap16(src_port3);
3553 /* remember invalid packets to be dropped */
3554 p_nat->invalid_packets |= pkt_mask3;
3555 p_nat->naptDroppedPktCount++;
3557 #ifdef CGNAPT_DEBUGGING
3558 p_nat->naptDroppedPktCount2++;
3564 key3.ip = rte_bswap32(dst_addr3);
3566 #ifdef NAT_ONLY_CONFIG_REQ
3567 if (nat_only_config_flag)
3571 memcpy(&p_nat->keys[pkt_num + 3], &key3,
3572 sizeof(struct pipeline_cgnapt_entry_key));
3573 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
3577 * NAPT key calculation function for IPv4 private traffic
3578 * which handles 1 pkt
3581 * A pointer to array of packets mbuf
3583 * Pkt number of pkts
3587 * A pointer to main CGNAPT structure
3591 pkt_work_cgnapt_key_ipv4_prv(
3592 struct rte_mbuf *pkt,
3594 __rte_unused void *arg,
3595 struct pipeline_cgnapt *p_nat)
3598 p_nat->receivedPktCount++;
3600 /* bitmask representing only this packet */
3601 uint64_t pkt_mask = 1LLU << pkt_num;
3602 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3604 uint32_t src_addr = RTE_MBUF_METADATA_UINT32(pkt, SRC_ADR_OFST_IP4);
3606 uint16_t src_port_offset;
3610 uint16_t phy_port = pkt->port;
3611 struct pipeline_cgnapt_entry_key key;
3613 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
3616 #ifdef CGNAPT_DBG_PRNT
3617 if (CGNAPT_DEBUG > 4)
3622 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
3627 case IP_PROTOCOL_UDP:
3631 struct udp_hdr *udp;
3633 udp = (struct udp_hdr *)
3634 RTE_MBUF_METADATA_UINT8_PTR(pkt,
3637 if (rte_bswap16(udp->dst_port) ==
3639 handle_pcp_req(pkt, IPV4_SZ, p_nat);
3640 p_nat->invalid_packets |= pkt_mask;
3646 case IP_PROTOCOL_TCP:
3648 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3649 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3651 key.port = rte_bswap16(src_port);
3654 case IP_PROTOCOL_ICMP:
3656 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3658 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3660 key.port = rte_bswap16(src_port);
3664 /* remember invalid packets to be dropped */
3665 p_nat->invalid_packets |= pkt_mask;
3666 p_nat->naptDroppedPktCount++;
3668 #ifdef CGNAPT_DEBUGGING
3669 p_nat->naptDroppedPktCount2++;
3675 key.ip = rte_bswap32(src_addr);
3677 #ifdef NAT_ONLY_CONFIG_REQ
3678 if (nat_only_config_flag)
3682 memcpy(&p_nat->keys[pkt_num], &key,
3683 sizeof(struct pipeline_cgnapt_entry_key));
3684 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3688 * NAPT key calculation function for IPv4 public traffic
3689 * which handles 1 pkt
3692 * A pointer to array of packets mbuf
3694 * Pkt number of pkts
3698 * A pointer to main CGNAPT structure
3702 pkt_work_cgnapt_key_ipv4_pub(
3703 struct rte_mbuf *pkt,
3705 __rte_unused void *arg,
3706 struct pipeline_cgnapt *p_nat)
3708 p_nat->receivedPktCount++;
3710 /* bitmask representing only this packet */
3711 uint64_t pkt_mask = 1LLU << pkt_num;
3712 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3713 uint32_t dst_addr = RTE_MBUF_METADATA_UINT32(pkt, DST_ADR_OFST_IP4);
3714 uint16_t src_port_offset;
3715 uint16_t dst_port_offset;
3718 struct pipeline_cgnapt_entry_key key;
3719 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
3721 #ifdef CGNAPT_DBG_PRNT
3722 if (CGNAPT_DEBUG > 4)
3727 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
3732 case IP_PROTOCOL_UDP:
3733 case IP_PROTOCOL_TCP:
3734 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3735 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3737 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3738 dst_port = RTE_MBUF_METADATA_UINT16(pkt, dst_port_offset);
3740 key.port = rte_bswap16(dst_port);
3742 case IP_PROTOCOL_ICMP:
3744 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3746 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3749 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3750 dst_port = RTE_MBUF_METADATA_UINT16(pkt, dst_port_offset);
3752 /* common table lookupkey preparation from incoming
3753 * ICMP Packet- Indentifier field
3755 key.port = rte_bswap16(src_port);
3758 /* remember invalid packets to be dropped */
3759 p_nat->invalid_packets |= pkt_mask;
3760 p_nat->naptDroppedPktCount++;
3762 #ifdef CGNAPT_DEBUGGING
3763 p_nat->naptDroppedPktCount2++;
3768 key.ip = rte_bswap32(dst_addr);
3770 #ifdef NAT_ONLY_CONFIG_REQ
3771 if (nat_only_config_flag)
3777 memcpy(&p_nat->keys[pkt_num], &key,
3778 sizeof(struct pipeline_cgnapt_entry_key));
3779 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3784 * NAPT function for IPv4 private traffic which handles 1 pkt
3787 * A pointer to array of packet mbuf
3793 * A pointer to main CGNAPT structure
3796 uint64_t last_update;
3798 pkt_work_cgnapt_ipv4_prv(
3799 struct rte_mbuf **pkts,
3801 __rte_unused void *arg,
3802 struct pipeline_cgnapt *p_nat)
3805 struct rte_CT_helper ct_helper;
3806 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
3809 /* index into hash table entries */
3810 int hash_table_entry = p_nat->lkup_indx[pkt_num];
3811 /*bitmask representing only this packet */
3812 uint64_t pkt_mask = 1LLU << pkt_num;
3813 struct rte_mbuf *pkt = pkts[pkt_num];
3815 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3817 uint32_t dest_if = 0xff; /* Added for Multiport */
3818 uint16_t *outport_id =
3819 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
3821 struct cgnapt_table_entry *entry = NULL;
3823 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
3825 if (hash_table_entry < 0) {
3827 /* try to add new entry */
3828 struct rte_pipeline_table_entry *table_entry = NULL;
3830 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
3832 &p_nat->valid_packets, pkt_num,
3836 /* ICMP Error message generation for Destination
3839 if (protocol == IP_PROTOCOL_ICMP) {
3840 cgnapt_icmp_pkt = pkt;
3841 send_icmp_dest_unreachable_msg();
3844 /* Drop packet by adding to invalid pkt mask */
3846 p_nat->invalid_packets |= dropmask;
3847 #ifdef CGNAPT_DEBUGGING
3848 if (p_nat->kpc2++ < 5) {
3849 printf("in_ah Th: %d", p_nat->pipeline_num);
3850 print_key(p_nat->key_ptrs[pkt_num]);
3854 p_nat->naptDroppedPktCount++;
3856 #ifdef CGNAPT_DEBUGGING
3857 p_nat->naptDroppedPktCount3++;
3862 entry = (struct cgnapt_table_entry *)table_entry;
3864 /* entry found for this packet */
3865 entry = &napt_hash_tbl_entries[hash_table_entry];
3868 /* apply napt and mac changes */
3870 p_nat->entries[pkt_num] = &(entry->head);
3872 uint32_t *src_addr =
3873 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP4);
3874 uint32_t *dst_addr =
3875 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
3876 uint16_t src_port_offset = 0;
3877 uint16_t dst_port_offset = 0;
3882 case IP_PROTOCOL_TCP:
3883 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3884 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3885 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3886 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3889 if ((rte_be_to_cpu_16(*src_port) == 21) ||
3890 rte_be_to_cpu_16(*dst_port) == 21) {
3893 printf("cgnapt_ct_process: pkt_mask: % "PRIu64", "
3894 "pkt_num: %d\n", pkt_mask, pkt_num);
3897 pkt_mask = cgnapt_ct_process(cgnat_cnxn_tracker, pkts,
3898 pkt_mask, &ct_helper);
3902 case IP_PROTOCOL_UDP:
3903 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3904 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3905 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3906 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3908 case IP_PROTOCOL_ICMP:
3910 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3912 /*Sequence number */
3913 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3915 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3916 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3920 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
3921 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
3923 if (entry->data.ttl == NAPT_ENTRY_STALE)
3924 entry->data.ttl = NAPT_ENTRY_VALID;
3926 struct ether_addr hw_addr;
3927 uint32_t dest_address = 0;
3930 if (unlikely(protocol == IP_PROTOCOL_UDP
3931 && rte_be_to_cpu_16(*dst_port) == 53)) {
3932 p_nat->invalid_packets |= pkt_mask;
3933 p_nat->naptDroppedPktCount++;
3935 #ifdef CGNAPT_DEBUGGING
3936 p_nat->naptDroppedPktCount6++;
3940 last_update = rte_rdtsc();
3941 dest_address = rte_bswap32(*dst_addr);
3943 struct arp_entry_data *ret_arp_data = NULL;
3944 ret_arp_data = get_dest_mac_addr_port(dest_address, &dest_if, (struct ether_addr *)eth_dest);
3945 *outport_id = p_nat->outport_id[dest_if];
3947 if (arp_cache_dest_mac_present(dest_if)) {
3948 ether_addr_copy(get_link_hw_addr(dest_if),(struct ether_addr *)eth_src);
3949 arp_data_ptr[dest_if]->n_last_update = time(NULL);
3951 if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) {
3952 printf("sending buffered packets\n");
3953 p_nat->naptedPktCount += ret_arp_data->num_pkts;
3954 arp_send_buffered_pkts(ret_arp_data,
3955 (struct ether_addr *)eth_dest, *outport_id);
3960 if (unlikely(ret_arp_data == NULL)) {
3962 printf("%s: NHIP Not Found, nhip:%x , "
3963 "outport_id: %d\n", __func__, nhip,
3967 p_nat->invalid_packets |= pkt_mask;
3968 p_nat->naptDroppedPktCount++;
3970 #ifdef CGNAPT_DEBUGGING
3971 p_nat->naptDroppedPktCount4++;
3976 if (ret_arp_data->status == INCOMPLETE ||
3977 ret_arp_data->status == PROBE) {
3978 if (ret_arp_data->num_pkts >= NUM_DESC) {
3980 p_nat->invalid_packets |= pkt_mask;
3981 p_nat->naptDroppedPktCount++;
3983 #ifdef CGNAPT_DEBUGGING
3984 p_nat->naptDroppedPktCount4++;
3988 arp_pkts_mask |= pkt_mask;
3989 arp_queue_unresolved_packet(ret_arp_data, pkt);
3998 *src_addr = rte_bswap32(entry->data.pub_ip);
4001 #ifdef NAT_ONLY_CONFIG_REQ
4002 if (!nat_only_config_flag) {
4004 *src_port = rte_bswap16(entry->data.pub_port);
4005 #ifdef NAT_ONLY_CONFIG_REQ
4010 uint16_t rtp_port = 0, rtcp_port = 0;
4011 struct cgnapt_table_entry *entry_ptr1 = NULL,
4012 *entry_ptr2 = NULL, *entry_ptr3 = NULL,
4015 if (unlikely(protocol == IP_PROTOCOL_UDP
4016 && (rte_be_to_cpu_16(*dst_port) == 5060
4017 || rte_be_to_cpu_16(*src_port) == 5060))) {
4019 int ret = natSipAlgGetAudioPorts(pkt, &rtp_port,
4021 /* Commented code may be required for debug
4022 * and future use, Please keep it*/
4025 printf("%s: Wrong SIP ALG packet1\n",
4027 p_nat->invalid_packets |= pkt_mask;
4029 p_nat->naptDroppedPktCount++;
4031 #ifdef CGNAPT_DEBUGGING
4032 p_nat->naptDroppedPktCount4++;
4038 if (ret >= 0 && rtp_port != 0) {
4039 struct pipeline_cgnapt_entry_key rtp_key;
4040 rtp_key.ip = entry->data.u.prv_ip;
4041 rtp_key.port = rtp_port;
4042 rtp_key.pid = entry->data.prv_phy_port;
4044 if (add_dynamic_cgnapt_entry_alg(
4045 (struct pipeline *)p_nat, &rtp_key,
4046 &entry_ptr1, &entry_ptr2) == 0) {
4047 printf("%s: Wrong SIP ALG packet2\n",
4049 p_nat->invalid_packets |= pkt_mask;
4051 p_nat->naptDroppedPktCount++;
4053 #ifdef CGNAPT_DEBUGGING
4054 p_nat->naptDroppedPktCount4++;
4060 if (ret >= 0 && rtcp_port != 0) {
4061 struct pipeline_cgnapt_entry_key rtcp_key;
4062 rtcp_key.ip = entry->data.u.prv_ip;
4063 rtcp_key.port = rtcp_port;
4064 rtcp_key.pid = entry->data.prv_phy_port;
4066 if (add_dynamic_cgnapt_entry_alg(
4067 (struct pipeline *)p_nat, &rtcp_key,
4068 &entry_ptr3, &entry_ptr4) == 0) {
4069 printf("%s: Wrong SIP ALG packet3\n",
4071 p_nat->invalid_packets |= pkt_mask;
4073 p_nat->naptDroppedPktCount++;
4075 #ifdef CGNAPT_DEBUGGING
4076 p_nat->naptDroppedPktCount4++;
4082 //if(entry_ptr1 != NULL && entry_ptr3 != NULL)
4083 if (sip_alg_dpi(pkt, PRIVATE, entry->data.pub_ip,
4084 entry->data.pub_port, entry->data.u.prv_ip,
4085 entry->data.prv_port, (rtp_port == 0) ? 0 :
4086 entry_ptr1->data.pub_port,
4087 (rtcp_port == 0) ? 0 :
4088 entry_ptr3->data.pub_port) == 0) {
4090 printf("%s: Wrong SIP ALG packet4\n",
4092 p_nat->invalid_packets |= pkt_mask;
4094 p_nat->naptDroppedPktCount++;
4096 #ifdef CGNAPT_DEBUGGING
4097 p_nat->naptDroppedPktCount4++;
4102 #endif /* SIP_ALG */
4107 printf("@CGNAT-pktwork ct_position :%d, pkt_num %d pkt_mask= "
4108 "%" PRIu64 "\n", ct_position, pkt_num, pkt_mask);
4111 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4112 rte_be_to_cpu_16(*dst_port) == 21) {
4114 int32_t ct_position = cgnat_cnxn_tracker->positions[pkt_num];
4115 if (ct_position < 0){
4116 p_nat->invalid_packets |= pkt_mask;
4117 p_nat->naptDroppedPktCount++;
4120 /* Commented code may be required for future usage,
4123 //if (cgnat_cnxn_tracker->hash_table_entries
4124 // [ct_position].alg_bypass_flag != BYPASS)
4126 struct pipeline_cgnapt_entry_key data_channel_entry_key;
4128 data_channel_entry_key.ip = entry->data.pub_ip;
4129 data_channel_entry_key.port = entry->data.pub_port;
4130 data_channel_entry_key.pid = pkt->port;
4131 ftp_alg_dpi(p_nat, &data_channel_entry_key, pkt,
4132 cgnat_cnxn_tracker, ct_position, PRIVATE);
4135 #endif /* FTP_ALG */
4137 p_nat->enaptedPktCount++;
4140 p_nat->naptedPktCount++;
4143 if (p_nat->hw_checksum_reqd)
4144 hw_checksum(pkt, pkt_type);
4146 sw_checksum(pkt, pkt_type);
4153 * NAPT function for IPv4 public traffic which handles 1 pkt
4156 * A pointer to array of packet mbuf
4162 * A pointer to main CGNAPT structure
4166 pkt_work_cgnapt_ipv4_pub(
4167 struct rte_mbuf **pkts,
4169 __rte_unused void *arg,
4170 struct pipeline_cgnapt *p_nat)
4174 struct rte_CT_helper ct_helper;
4175 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4178 /* index into hash table entries */
4179 int hash_table_entry = p_nat->lkup_indx[pkt_num];
4180 /*bitmask representing only this packet */
4181 uint64_t pkt_mask = 1LLU << pkt_num;
4182 struct rte_mbuf *pkt = pkts[pkt_num];
4184 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
4186 uint32_t dest_if = 0xff; /* Added for Multiport */
4187 uint16_t *outport_id =
4188 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
4190 struct cgnapt_table_entry *entry = NULL;
4192 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4194 if (hash_table_entry < 0) {
4196 /* try to add new entry */
4197 struct rte_pipeline_table_entry *table_entry = NULL;
4199 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
4201 &p_nat->valid_packets, pkt_num,
4205 /* ICMP Error message generation for
4206 * Destination Host unreachable
4208 if (protocol == IP_PROTOCOL_ICMP) {
4209 cgnapt_icmp_pkt = pkt;
4210 send_icmp_dest_unreachable_msg();
4213 /* Drop packet by adding to invalid pkt mask */
4215 p_nat->invalid_packets |= dropmask;
4216 #ifdef CGNAPT_DEBUGGING
4217 if (p_nat->kpc2++ < 5) {
4218 printf("in_ah Th: %d", p_nat->pipeline_num);
4219 print_key(p_nat->key_ptrs[pkt_num]);
4223 p_nat->naptDroppedPktCount++;
4225 #ifdef CGNAPT_DEBUGGING
4226 p_nat->naptDroppedPktCount3++;
4231 entry = (struct cgnapt_table_entry *)table_entry;
4233 /* entry found for this packet */
4234 entry = &napt_hash_tbl_entries[hash_table_entry];
4237 /* apply napt and mac changes */
4239 p_nat->entries[pkt_num] = &(entry->head);
4241 uint32_t *dst_addr =
4242 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4243 uint16_t src_port_offset = 0;
4244 uint16_t dst_port_offset = 0;
4246 if ((protocol == IP_PROTOCOL_TCP) || (protocol == IP_PROTOCOL_UDP)) {
4247 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4248 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4249 } else if (protocol == IP_PROTOCOL_ICMP) {
4251 src_port_offset = MBUF_HDR_ROOM +
4254 /*Sequence number */
4255 dst_port_offset = MBUF_HDR_ROOM +
4260 uint16_t *src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
4261 uint16_t *dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
4263 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4264 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4266 if (entry->data.ttl == NAPT_ENTRY_STALE)
4267 entry->data.ttl = NAPT_ENTRY_VALID;
4269 struct ether_addr hw_addr;
4270 uint32_t dest_address = 0;
4272 /* Multiport Changes */
4278 if (unlikely(protocol == IP_PROTOCOL_UDP
4279 && rte_be_to_cpu_16(*src_port) == 53)) {
4280 p_nat->invalid_packets |= pkt_mask;
4281 p_nat->naptDroppedPktCount++;
4282 #ifdef CGNAPT_DEBUGGING
4283 p_nat->naptDroppedPktCount6++;
4289 dest_address = entry->data.u.prv_ip;
4290 struct arp_entry_data *ret_arp_data = NULL;
4291 ret_arp_data = get_dest_mac_addr_port(dest_address, &dest_if, (struct ether_addr *)eth_dest);
4292 *outport_id = p_nat->outport_id[dest_if];
4294 if (arp_cache_dest_mac_present(dest_if)) {
4295 ether_addr_copy(get_link_hw_addr(dest_if), (struct ether_addr *)eth_src);
4296 arp_data_ptr[dest_if]->n_last_update = time(NULL);
4298 if (ret_arp_data && ret_arp_data->num_pkts) {
4299 printf("sending buffered packets\n");
4300 p_nat->naptedPktCount += ret_arp_data->num_pkts;
4301 arp_send_buffered_pkts(ret_arp_data,
4302 (struct ether_addr *)eth_dest, *outport_id);
4307 if (unlikely(ret_arp_data == NULL)) {
4309 /* Commented code may be required for debug
4310 * and future use, Please keep it */
4311 printf("%s: NHIP Not Found, nhip: %x, "
4312 "outport_id: %d\n", __func__, nhip,
4316 p_nat->invalid_packets |= pkt_mask;
4317 p_nat->naptDroppedPktCount++;
4319 #ifdef CGNAPT_DEBUGGING
4320 p_nat->naptDroppedPktCount4++;
4326 if (ret_arp_data->status == INCOMPLETE ||
4327 ret_arp_data->status == PROBE) {
4328 if (ret_arp_data->num_pkts >= NUM_DESC) {
4330 p_nat->invalid_packets |= pkt_mask;
4331 p_nat->naptDroppedPktCount++;
4333 #ifdef CGNAPT_DEBUGGING
4334 p_nat->naptDroppedPktCount4++;
4338 arp_pkts_mask |= pkt_mask;
4339 arp_queue_unresolved_packet(ret_arp_data, pkt);
4348 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
4349 if (protocol == IP_PROTOCOL_ICMP) {
4350 /* Query ID reverse translation done here */
4351 /* dont care sequence num */
4352 *src_port = rte_bswap16(entry->data.prv_port);
4355 #ifdef NAT_ONLY_CONFIG_REQ
4356 if (!nat_only_config_flag) {
4358 *dst_port = rte_bswap16(entry->data.prv_port);
4360 #ifdef NAT_ONLY_CONFIG_REQ
4364 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4365 rte_be_to_cpu_16(*dst_port) == 21) {
4366 pkt_mask = cgnapt_ct_process(cgnat_cnxn_tracker, pkts,
4367 pkt_mask, &ct_helper);
4373 uint16_t rtp_port = 0, rtcp_port = 0;
4374 struct cgnapt_table_entry *entry_ptr1 = NULL,
4377 /* Commented code may be required for debug
4378 * and future use, Please keep it */
4380 struct cgnapt_table_entry *entry_ptr2 = NULL,
4384 if (unlikely(protocol == IP_PROTOCOL_UDP
4385 && (rte_be_to_cpu_16(*dst_port) == 5060
4386 || rte_be_to_cpu_16(*src_port) == 5060))) {
4387 /* Commented code may be required for future usage,
4391 int ret = natSipAlgGetAudioPorts(pkt, &rtp_port,
4394 printf("%s: Wrong SIP ALG packet1\n",
4396 p_nat->invalid_packets |= pkt_mask;
4398 p_nat->naptDroppedPktCount++;
4400 #ifdef CGNAPT_DEBUGGING
4401 p_nat->naptDroppedPktCount4++;
4405 if (rtp_port != 0) {
4406 struct pipeline_cgnapt_entry_key rtp_key;
4407 rtp_key.ip = entry->data.pub_ip;
4408 rtp_key.port = rtp_port;
4409 rtp_key.pid = 0xffff;
4411 if (retrieve_cgnapt_entry_alg(&rtp_key,
4412 &entry_ptr1, &entry_ptr2) == 0) {
4413 printf("%s: Wrong SIP ALG packet2\n",
4415 p_nat->invalid_packets |= pkt_mask;
4417 p_nat->naptDroppedPktCount++;
4419 #ifdef CGNAPT_DEBUGGING
4420 p_nat->naptDroppedPktCount4++;
4426 if (rtcp_port != 0) {
4427 struct pipeline_cgnapt_entry_key rtcp_key;
4428 rtcp_key.ip = entry->data.pub_ip;
4429 rtcp_key.port = rtcp_port;
4430 rtcp_key.pid = 0xffff;
4432 if (retrieve_cgnapt_entry_alg(&rtcp_key,
4433 &entry_ptr3, &entry_ptr4) == 0) {
4434 printf("%s: Wrong SIP ALG packet3\n",
4436 p_nat->invalid_packets |= pkt_mask;
4438 p_nat->naptDroppedPktCount++;
4440 #ifdef CGNAPT_DEBUGGING
4441 p_nat->naptDroppedPktCount4++;
4449 if (sip_alg_dpi(pkt, PUBLIC, entry->data.u.prv_ip,
4450 entry->data.prv_port, entry->data.pub_ip,
4451 entry->data.pub_port, (rtp_port == 0) ? 0 :
4452 entry_ptr1->data.prv_port,
4453 (rtcp_port == 0) ? 0 :
4454 entry_ptr3->data.prv_port) == 0) {
4456 printf("%s: Wrong SIP ALG packet4\n",
4458 p_nat->invalid_packets |= pkt_mask;
4460 p_nat->naptDroppedPktCount++;
4462 #ifdef CGNAPT_DEBUGGING
4463 p_nat->naptDroppedPktCount4++;
4469 #endif /* SIP_ALG */
4472 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4473 rte_be_to_cpu_16(*dst_port) == 21) {
4474 int32_t ct_position = cgnat_cnxn_tracker->
4476 if (ct_position < 0){
4477 p_nat->invalid_packets |= pkt_mask;
4479 p_nat->naptDroppedPktCount++;
4483 rte_hexdump(stdout, "CT Entry", &cgnat_cnxn_tracker->
4484 hash_table_entries[ct_position].key, 40);
4487 /* Commented code may be required for debug
4488 * and future use, Please keep it*/
4489 //if (cgnat_cnxn_tracker->hash_table_entries
4490 // [ct_position].alg_bypass_flag != BYPASS)
4493 struct pipeline_cgnapt_entry_key
4494 data_channel_entry_key;
4496 data_channel_entry_key.ip = entry->data.pub_ip;
4497 data_channel_entry_key.port = entry->data.pub_port;
4498 data_channel_entry_key.pid = 0xffff;
4499 //printf("pkt_work_pub ftp_alg_dpi\n");
4500 ftp_alg_dpi(p_nat, &data_channel_entry_key, pkt,
4501 cgnat_cnxn_tracker, ct_position, PUBLIC);
4507 p_nat->inaptedPktCount++;
4510 p_nat->naptedPktCount++;
4513 if (p_nat->hw_checksum_reqd)
4514 hw_checksum(pkt, pkt_type);
4516 sw_checksum(pkt, pkt_type);
4522 * NAPT function for IPv4 private traffic which handles 4 pkts
4525 * A pointer to array of packets mbuf
4527 * Starting pkt number of pkts
4531 * A pointer to main CGNAPT structure
4535 pkt4_work_cgnapt_ipv4_prv(
4536 struct rte_mbuf **pkts,
4537 uint32_t in_pkt_num,
4538 __rte_unused void *arg,
4539 struct pipeline_cgnapt *p_nat)
4541 uint32_t dest_if = 0xff; /* Added for Multiport */
4542 struct rte_mbuf *pkt;
4545 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4548 struct rte_CT_helper ct_helper;
4549 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4552 for (i = 0; i < 4; i++) {
4553 pkt_num = in_pkt_num + i;
4554 pkt = pkts[pkt_num];
4556 /* index into hash table entries */
4557 int hash_table_entry = p_nat->lkup_indx[pkt_num];
4558 /*bitmask representing only this packet */
4559 uint64_t pkt_mask = 1LLU << pkt_num;
4561 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
4563 uint16_t *outport_id =
4564 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
4566 struct cgnapt_table_entry *entry = NULL;
4568 if (hash_table_entry < 0) {
4570 /* try to add new entry */
4571 struct rte_pipeline_table_entry *table_entry = NULL;
4574 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
4576 &p_nat->valid_packets, pkt_num,
4580 /* ICMP Error message generation for
4581 * Destination Host unreachable
4583 if (protocol == IP_PROTOCOL_ICMP) {
4584 cgnapt_icmp_pkt = pkt;
4585 send_icmp_dest_unreachable_msg();
4588 /* Drop packet by adding to invalid pkt mask */
4590 p_nat->invalid_packets |= dropmask;
4592 #ifdef CGNAPT_DEBUGGING
4593 if (p_nat->kpc2++ < 5) {
4594 printf("in_ah Th: %d",
4595 p_nat->pipeline_num);
4596 print_key(p_nat->key_ptrs[pkt_num]);
4600 p_nat->naptDroppedPktCount++;
4602 #ifdef CGNAPT_DEBUGGING
4603 p_nat->naptDroppedPktCount3++;
4608 entry = (struct cgnapt_table_entry *)table_entry;
4610 /* entry found for this packet */
4611 entry = &napt_hash_tbl_entries[hash_table_entry];
4614 /* apply napt and mac changes */
4616 p_nat->entries[pkt_num] = &(entry->head);
4618 uint32_t *src_addr =
4619 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP4);
4620 uint32_t *dst_addr =
4621 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4622 uint16_t src_port_offset = 0;
4623 uint16_t dst_port_offset = 0;
4628 if ((protocol == IP_PROTOCOL_TCP)
4629 || (protocol == IP_PROTOCOL_UDP)) {
4630 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4631 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4632 } else if (protocol == IP_PROTOCOL_ICMP) {
4634 src_port_offset = MBUF_HDR_ROOM +
4637 /*Sequence number */
4638 dst_port_offset = MBUF_HDR_ROOM +
4645 case IP_PROTOCOL_TCP:
4646 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4647 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4648 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4650 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4654 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4655 rte_be_to_cpu_16(*dst_port) == 21) {
4657 //To process CT , pkt_mask does it need
4658 //to be complemented ??
4660 printf("cgnapt_ct_process: pkt_mask: "
4661 "% "PRIu64", pkt_num: %d\n",
4665 pkt_mask = cgnapt_ct_process(
4666 cgnat_cnxn_tracker, pkts,
4667 pkt_mask, &ct_helper);
4671 case IP_PROTOCOL_UDP:
4672 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4673 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4674 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4676 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4679 case IP_PROTOCOL_ICMP:
4681 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
4683 /*Sequence number */
4684 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
4686 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4688 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4695 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4697 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4699 if (entry->data.ttl == NAPT_ENTRY_STALE)
4700 entry->data.ttl = NAPT_ENTRY_VALID;
4702 struct ether_addr hw_addr;
4703 uint32_t dest_address = 0;
4704 /*Multiport Changes */
4711 if (unlikely(protocol == IP_PROTOCOL_UDP
4712 && rte_be_to_cpu_16(*dst_port) == 53)) {
4713 p_nat->invalid_packets |= pkt_mask;
4714 p_nat->naptDroppedPktCount++;
4716 #ifdef CGNAPT_DEBUGGING
4717 p_nat->naptDroppedPktCount6++;
4723 dest_address = rte_bswap32(*dst_addr);
4724 struct arp_entry_data *ret_arp_data = NULL;
4725 uint64_t start, end;
4726 ret_arp_data = get_dest_mac_addr_port(dest_address, &dest_if, (struct ether_addr *)eth_dest);
4727 *outport_id = p_nat->outport_id[dest_if];
4728 if (arp_cache_dest_mac_present(dest_if)) {
4729 ether_addr_copy(get_link_hw_addr(dest_if), (struct ether_addr *)eth_src);
4730 arp_data_ptr[dest_if]->n_last_update = time(NULL);
4732 if (ret_arp_data && ret_arp_data->num_pkts) {
4733 printf("sending buffered packets\n");
4734 p_nat->naptedPktCount += ret_arp_data->num_pkts;
4735 arp_send_buffered_pkts(ret_arp_data,
4736 (struct ether_addr *)eth_dest, *outport_id);
4741 if (unlikely(ret_arp_data == NULL)) {
4743 printf("%s: ARP Not Found, nhip: %x, "
4744 "outport_id: %d\n", __func__, nhip,
4748 p_nat->invalid_packets |= pkt_mask;
4749 p_nat->naptDroppedPktCount++;
4751 #ifdef CGNAPT_DEBUGGING
4752 p_nat->naptDroppedPktCount4++;
4758 if (ret_arp_data->status == INCOMPLETE ||
4759 ret_arp_data->status == PROBE) {
4760 if (ret_arp_data->num_pkts >= NUM_DESC) {
4762 p_nat->invalid_packets |= pkt_mask;
4763 p_nat->naptDroppedPktCount++;
4765 #ifdef CGNAPT_DEBUGGING
4766 p_nat->naptDroppedPktCount4++;
4770 arp_pkts_mask |= pkt_mask;
4771 arp_queue_unresolved_packet(ret_arp_data, pkt);
4779 *src_addr = rte_bswap32(entry->data.pub_ip);
4781 #ifdef NAT_ONLY_CONFIG_REQ
4782 if (!nat_only_config_flag) {
4784 *src_port = rte_bswap16(entry->data.pub_port);
4785 #ifdef NAT_ONLY_CONFIG_REQ
4790 uint16_t rtp_port = 0, rtcp_port = 0;
4791 struct cgnapt_table_entry *entry_ptr1 = NULL,
4792 *entry_ptr2 = NULL, *entry_ptr3 = NULL,
4795 if (unlikely(protocol == IP_PROTOCOL_UDP
4796 && (rte_be_to_cpu_16(*dst_port) == 5060
4797 || rte_be_to_cpu_16(*src_port) == 5060))) {
4799 int ret = natSipAlgGetAudioPorts(pkt,
4800 &rtp_port, &rtcp_port);
4801 /* Commented code may be required for future usage,
4806 printf("%s: Wrong SIP ALG packet1\n",
4808 p_nat->invalid_packets |= pkt_mask;
4810 p_nat->naptDroppedPktCount++;
4812 #ifdef CGNAPT_DEBUGGING
4813 p_nat->naptDroppedPktCount4++;
4819 if (ret >= 0 && rtp_port != 0) {
4820 struct pipeline_cgnapt_entry_key rtp_key;
4821 rtp_key.ip = entry->data.u.prv_ip;
4822 rtp_key.port = rtp_port;
4823 rtp_key.pid = entry->data.prv_phy_port;
4825 if (add_dynamic_cgnapt_entry_alg(
4826 (struct pipeline *)p_nat, &rtp_key,
4827 &entry_ptr1, &entry_ptr2) == 0) {
4828 printf("%s: Wrong SIP ALG packet2\n",
4830 p_nat->invalid_packets |= pkt_mask;
4832 p_nat->naptDroppedPktCount++;
4834 #ifdef CGNAPT_DEBUGGING
4835 p_nat->naptDroppedPktCount4++;
4841 if (ret >= 0 && rtcp_port != 0) {
4842 struct pipeline_cgnapt_entry_key rtcp_key;
4843 rtcp_key.ip = entry->data.u.prv_ip;
4844 rtcp_key.port = rtcp_port;
4845 rtcp_key.pid = entry->data.prv_phy_port;
4847 if (add_dynamic_cgnapt_entry_alg(
4848 (struct pipeline *)p_nat, &rtcp_key,
4849 &entry_ptr3, &entry_ptr4) == 0) {
4851 printf("%s: Wrong SIP ALG packet3\n",
4853 p_nat->invalid_packets |= pkt_mask;
4855 p_nat->naptDroppedPktCount++;
4857 #ifdef CGNAPT_DEBUGGING
4858 p_nat->naptDroppedPktCount4++;
4864 //if(entry_ptr1 != NULL && entry_ptr3 != NULL)
4865 if (sip_alg_dpi(pkt, PRIVATE,
4867 entry->data.pub_port,
4868 entry->data.u.prv_ip,
4869 entry->data.prv_port,
4870 (rtp_port == 0) ? 0 :
4871 entry_ptr1->data.pub_port,
4872 (rtcp_port == 0) ? 0 :
4873 entry_ptr3->data.pub_port) == 0) {
4875 printf("%s: Wrong SIP ALG packet4\n",
4877 p_nat->invalid_packets |= pkt_mask;
4879 p_nat->naptDroppedPktCount++;
4881 #ifdef CGNAPT_DEBUGGING
4882 p_nat->naptDroppedPktCount4++;
4887 #endif /* SIP_ALG */
4890 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4891 rte_be_to_cpu_16(*dst_port) == 21) {
4893 int32_t ct_position =
4894 cgnat_cnxn_tracker->positions[pkt_num];
4896 printf("@CGNAT-pkt4work ct_position :%d, pkt_num %d "
4897 "pkt_mask = %" PRIu64 "\n", ct_position,
4901 if (ct_position < 0){
4902 p_nat->invalid_packets |= pkt_mask;
4903 p_nat->naptDroppedPktCount++;
4906 if (cgnat_cnxn_tracker->hash_table_entries[ct_position].
4907 alg_bypass_flag != BYPASS){
4909 struct pipeline_cgnapt_entry_key
4910 data_channel_entry_key;
4912 data_channel_entry_key.ip =
4914 data_channel_entry_key.port =
4915 entry->data.pub_port;
4916 data_channel_entry_key.pid = 0xffff;
4918 ftp_alg_dpi(p_nat, &data_channel_entry_key,
4919 pkt, cgnat_cnxn_tracker, ct_position,
4925 p_nat->enaptedPktCount++;
4928 p_nat->naptedPktCount++;
4931 if (p_nat->hw_checksum_reqd)
4932 hw_checksum(pkt, pkt_type);
4934 sw_checksum(pkt, pkt_type);
4940 * NAPT function for IPv4 public traffic which handles 4 pkts
4943 * A pointer to array of packets mbuf
4945 * Starting pkt number of pkts
4949 * A pointer to main CGNAPT structure
4953 pkt4_work_cgnapt_ipv4_pub(
4954 struct rte_mbuf **pkts,
4955 uint32_t in_pkt_num,
4956 __rte_unused void *arg,
4957 struct pipeline_cgnapt *p_nat)
4960 struct rte_CT_helper ct_helper;
4961 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4963 struct rte_mbuf *pkt;
4966 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4968 for (i = 0; i < 4; i++) {
4969 pkt_num = in_pkt_num + i;
4970 pkt = pkts[pkt_num];
4972 /* index into hash table entries */
4973 int hash_table_entry = p_nat->lkup_indx[pkt_num];
4974 /*bitmask representing only this packet */
4975 uint64_t pkt_mask = 1LLU << pkt_num;
4977 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
4979 uint32_t dest_if = 0xff; /* Added for Multiport */
4980 uint16_t *outport_id =
4981 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
4983 struct cgnapt_table_entry *entry = NULL;
4985 if (hash_table_entry < 0) {
4987 /* try to add new entry */
4988 struct rte_pipeline_table_entry *table_entry = NULL;
4991 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
4993 &p_nat->valid_packets, pkt_num,
4997 /* ICMP Error message generation for
4998 * Destination Host unreachable
5000 if (protocol == IP_PROTOCOL_ICMP) {
5001 cgnapt_icmp_pkt = pkt;
5002 send_icmp_dest_unreachable_msg();
5005 /* Drop packet by adding to invalid pkt mask */
5007 p_nat->invalid_packets |= dropmask;
5009 #ifdef CGNAPT_DEBUGGING
5010 if (p_nat->kpc2++ < 5) {
5011 printf("in_ah Th: %d",
5012 p_nat->pipeline_num);
5013 print_key(p_nat->key_ptrs[pkt_num]);
5017 p_nat->naptDroppedPktCount++;
5019 #ifdef CGNAPT_DEBUGGING
5020 p_nat->naptDroppedPktCount3++;
5022 printf("causing p_nat->naptDroppedPktCount3\n");
5026 entry = (struct cgnapt_table_entry *)table_entry;
5028 /* entry found for this packet */
5029 entry = &napt_hash_tbl_entries[hash_table_entry];
5032 /* apply napt and mac changes */
5034 p_nat->entries[pkt_num] = &(entry->head);
5036 uint32_t *dst_addr =
5037 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
5038 uint16_t src_port_offset = 0;
5039 uint16_t dst_port_offset = 0;
5041 if ((protocol == IP_PROTOCOL_TCP)
5042 || (protocol == IP_PROTOCOL_UDP)) {
5043 src_port_offset = SRC_PRT_OFST_IP4_TCP;
5044 dst_port_offset = DST_PRT_OFST_IP4_TCP;
5045 } else if (protocol == IP_PROTOCOL_ICMP) {
5047 src_port_offset = MBUF_HDR_ROOM +
5050 /*Sequence number */
5051 dst_port_offset = MBUF_HDR_ROOM +
5056 uint16_t *src_port =
5057 RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
5058 uint16_t *dst_port =
5059 RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
5062 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
5064 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
5066 if (entry->data.ttl == NAPT_ENTRY_STALE)
5067 entry->data.ttl = NAPT_ENTRY_VALID;
5069 struct ether_addr hw_addr;
5070 uint32_t dest_address = 0;
5071 /* Multiport Changes */
5077 if (unlikely(protocol == IP_PROTOCOL_UDP
5078 && rte_be_to_cpu_16(*src_port) == 53)) {
5079 p_nat->invalid_packets |= pkt_mask;
5080 p_nat->naptDroppedPktCount++;
5081 #ifdef CGNAPT_DEBUGGING
5082 p_nat->naptDroppedPktCount6++;
5087 dest_address = entry->data.u.prv_ip;
5088 struct arp_entry_data *ret_arp_data = NULL;
5089 ret_arp_data = get_dest_mac_addr_port(dest_address, &dest_if, (struct ether_addr *)eth_dest);
5090 *outport_id = p_nat->outport_id[dest_if];
5092 if (arp_cache_dest_mac_present(dest_if)) {
5093 ether_addr_copy(get_link_hw_addr(dest_if), (struct ether_addr *)eth_src);
5094 arp_data_ptr[dest_if]->n_last_update = time(NULL);
5096 if (ret_arp_data && ret_arp_data->num_pkts) {
5097 printf("sending buffered packets\n");
5098 p_nat->naptedPktCount += ret_arp_data->num_pkts;
5099 arp_send_buffered_pkts(ret_arp_data,
5100 (struct ether_addr *)eth_dest, *outport_id);
5105 if (unlikely(ret_arp_data == NULL)) {
5107 printf("%s: NHIP Not Found, nhip: %x, "
5108 "outport_id: %d\n", __func__, nhip,
5112 p_nat->invalid_packets |= pkt_mask;
5113 p_nat->naptDroppedPktCount++;
5115 #ifdef CGNAPT_DEBUGGING
5116 p_nat->naptDroppedPktCount4++;
5121 if (ret_arp_data->status == INCOMPLETE ||
5122 ret_arp_data->status == PROBE) {
5123 if (ret_arp_data->num_pkts >= NUM_DESC) {
5125 p_nat->invalid_packets |= pkt_mask;
5126 p_nat->naptDroppedPktCount++;
5128 #ifdef CGNAPT_DEBUGGING
5129 p_nat->naptDroppedPktCount4++;
5133 arp_pkts_mask |= pkt_mask;
5134 arp_queue_unresolved_packet(ret_arp_data, pkt);
5143 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
5144 if (protocol == IP_PROTOCOL_ICMP) {
5145 /* Query ID reverse translation done here */
5146 *src_port = rte_bswap16(entry->data.prv_port);
5147 /* dont care sequence num */
5149 #ifdef NAT_ONLY_CONFIG_REQ
5150 if (!nat_only_config_flag) {
5153 rte_bswap16(entry->data.prv_port);
5154 #ifdef NAT_ONLY_CONFIG_REQ
5159 if ((rte_be_to_cpu_16(*src_port) == 21) ||
5160 rte_be_to_cpu_16(*dst_port) == 21) {
5161 pkt_mask = cgnapt_ct_process(
5162 cgnat_cnxn_tracker, pkts,
5163 pkt_mask, &ct_helper);
5169 uint16_t rtp_port = 0, rtcp_port = 0;
5170 struct cgnapt_table_entry *entry_ptr1 = NULL,
5172 /* Commented code may be required for future usage,
5176 struct cgnapt_table_entry *entry_ptr2 = NULL,
5180 if (unlikely(protocol == IP_PROTOCOL_UDP
5181 && (rte_be_to_cpu_16(*dst_port) == 5060
5182 || rte_be_to_cpu_16(*src_port) == 5060))) {
5183 /* Commented code may be required for future usage,
5187 int ret = natSipAlgGetAudioPorts(pkt,
5188 &rtp_port, &rtcp_port);
5190 printf("%s: Wrong SIP ALG packet1\n",
5192 p_nat->invalid_packets |= pkt_mask;
5194 p_nat->naptDroppedPktCount++;
5196 #ifdef CGNAPT_DEBUGGING
5197 p_nat->naptDroppedPktCount4++;
5202 if (rtp_port != 0) {
5203 struct pipeline_cgnapt_entry_key rtp_key;
5204 rtp_key.ip = entry->data.pub_ip;
5205 rtp_key.port = rtp_port;
5206 rtp_key.pid = 0xffff;
5208 if (retrieve_cgnapt_entry_alg(&rtp_key,
5209 &entry_ptr1, &entry_ptr2) == 0) {
5210 printf("%s: Wrong SIP ALG packet2\n",
5212 p_nat->invalid_packets |= pkt_mask;
5214 p_nat->naptDroppedPktCount++;
5216 #ifdef CGNAPT_DEBUGGING
5217 p_nat->naptDroppedPktCount4++;
5223 if (rtcp_port != 0) {
5224 struct pipeline_cgnapt_entry_key rtcp_key;
5225 rtcp_key.ip = entry->data.pub_ip;
5226 rtcp_key.port = rtcp_port;
5227 rtcp_key.pid = 0xffff;
5229 if (retrieve_cgnapt_entry_alg(&rtcp_key,
5230 &entry_ptr3, &entry_ptr4) == 0) {
5231 printf("%s: Wrong SIP ALG packet3\n",
5233 p_nat->invalid_packets |= pkt_mask;
5234 p_nat->naptDroppedPktCount++;
5236 #ifdef CGNAPT_DEBUGGING
5237 p_nat->naptDroppedPktCount4++;
5244 if (sip_alg_dpi(pkt, PUBLIC,
5245 entry->data.u.prv_ip,
5246 entry->data.prv_port,
5248 entry->data.pub_port,
5249 (rtp_port == 0) ? 0 :
5250 entry_ptr1->data.prv_port,
5251 (rtcp_port == 0) ? 0 :
5252 entry_ptr3->data.prv_port) == 0) {
5254 printf("%s: Wrong SIP ALG packet4\n",
5256 p_nat->invalid_packets |= pkt_mask;
5258 p_nat->naptDroppedPktCount++;
5260 #ifdef CGNAPT_DEBUGGING
5261 p_nat->naptDroppedPktCount4++;
5266 #endif /* SIP_ALG */
5269 if ((rte_be_to_cpu_16(*src_port) == 21) ||
5270 rte_be_to_cpu_16(*dst_port) == 21) {
5272 int32_t ct_position =
5273 cgnat_cnxn_tracker->positions[pkt_num];
5274 if (ct_position < 0){
5275 p_nat->invalid_packets |= pkt_mask;
5277 p_nat->naptDroppedPktCount++;
5280 if (cgnat_cnxn_tracker->hash_table_entries
5281 [ct_position].alg_bypass_flag != BYPASS){
5283 struct pipeline_cgnapt_entry_key
5284 data_channel_entry_key;
5287 data_channel_entry_key.ip =
5289 data_channel_entry_key.port =
5290 entry->data.pub_port;
5291 data_channel_entry_key.pid = 0xffff;
5293 ftp_alg_dpi(p_nat, &data_channel_entry_key,
5294 pkt, cgnat_cnxn_tracker,
5295 ct_position, PUBLIC);
5300 p_nat->inaptedPktCount++;
5303 p_nat->naptedPktCount++;
5306 if (p_nat->hw_checksum_reqd)
5307 hw_checksum(pkt, pkt_type);
5309 sw_checksum(pkt, pkt_type);
5315 * NAPT key calculation function for IPv6 private traffic
5316 * which handles 1 pkt
5319 * A pointer to array of packets mbuf
5321 * Pkt number of pkts
5325 * A pointer to main CGNAPT structure
5329 pkt_work_cgnapt_key_ipv6_prv(
5330 struct rte_mbuf *pkt,
5332 __rte_unused void *arg,
5333 struct pipeline_cgnapt *p_nat)
5336 p_nat->receivedPktCount++;
5338 /* bitmask representing only this packet */
5339 uint64_t pkt_mask = 1LLU << pkt_num;
5341 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
5342 uint32_t *src_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
5344 uint16_t src_port = RTE_MBUF_METADATA_UINT16(pkt, SRC_PRT_OFST_IP6);
5346 uint16_t phy_port = pkt->port;
5347 struct pipeline_cgnapt_entry_key key;
5349 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
5351 #ifdef CGNAPT_DBG_PRNT
5352 if (CGNAPT_DEBUG > 4)
5357 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
5362 case IP_PROTOCOL_UDP:
5366 struct udp_hdr *udp;
5368 udp = (struct udp_hdr *)
5369 RTE_MBUF_METADATA_UINT8_PTR(pkt,
5372 if (rte_bswap16(udp->dst_port) ==
5374 handle_pcp_req(pkt, IPV6_SZ, p_nat);
5375 p_nat->invalid_packets |= pkt_mask;
5381 case IP_PROTOCOL_TCP:
5382 case IP_PROTOCOL_ICMP:
5383 /*we don't need icmp check in ipv6 */
5387 printf("wrong protocol: %d\n", protocol);
5388 /* remember invalid packets to be dropped */
5389 p_nat->invalid_packets |= pkt_mask;
5390 p_nat->naptDroppedPktCount++;
5392 #ifdef CGNAPT_DEBUGGING
5393 p_nat->naptDroppedPktCount2++;
5399 key.ip = rte_bswap32(src_addr[3]);
5400 key.port = rte_bswap16(src_port);
5402 #ifdef NAT_ONLY_CONFIG_REQ
5403 if (nat_only_config_flag)
5407 memcpy(&p_nat->keys[pkt_num], &key,
5408 sizeof(struct pipeline_cgnapt_entry_key));
5409 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5413 * NAPT key calculation function for IPv6 public traffic
5414 * which handles 1 pkt
5417 * A pointer to array of packets mbuf
5419 * Pkt number of pkts
5423 * A pointer to main CGNAPT structure
5427 pkt_work_cgnapt_key_ipv6_pub(
5428 struct rte_mbuf *pkt,
5430 __rte_unused void *arg,
5431 struct pipeline_cgnapt *p_nat)
5435 p_nat->receivedPktCount++;
5437 /* bitmask representing only this packet */
5438 uint64_t pkt_mask = 1LLU << pkt_num;
5440 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
5442 uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
5444 uint16_t dst_port = RTE_MBUF_METADATA_UINT16(pkt,
5445 DST_PRT_OFST_IP4_TCP);
5447 struct pipeline_cgnapt_entry_key key;
5449 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
5451 #ifdef CGNAPT_DBG_PRNT
5452 if (CGNAPT_DEBUG > 4)
5457 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
5463 case IP_PROTOCOL_UDP:
5464 case IP_PROTOCOL_TCP:
5465 case IP_PROTOCOL_ICMP:
5466 /*we don't need icmp check in ipv6 */
5470 /* remember invalid packets to be dropped */
5471 p_nat->invalid_packets |= pkt_mask;
5472 p_nat->naptDroppedPktCount++;
5474 #ifdef CGNAPT_DEBUGGING
5475 p_nat->naptDroppedPktCount2++;
5481 key.ip = rte_bswap32(dst_addr[0]);
5482 key.port = rte_bswap16(dst_port);
5484 #ifdef NAT_ONLY_CONFIG_REQ
5485 if (nat_only_config_flag)
5489 memcpy(&p_nat->keys[pkt_num], &key,
5490 sizeof(struct pipeline_cgnapt_entry_key));
5491 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5495 * NAPT key calculation function for IPv6 private traffic
5496 * which handles 4 pkts
5499 * A pointer to array of packets mbuf
5501 * Starting pkt number of pkts
5505 * A pointer to main CGNAPT structure
5509 pkt4_work_cgnapt_key_ipv6_prv(
5510 struct rte_mbuf **pkt,
5512 __rte_unused void *arg,
5513 struct pipeline_cgnapt *p_nat)
5515 p_nat->receivedPktCount += 4;
5517 /* bitmask representing only this packet */
5518 uint64_t pkt_mask0 = 1LLU << pkt_num;
5519 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
5520 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
5521 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
5523 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
5525 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
5527 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
5529 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
5532 uint32_t *src_addr0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0],
5534 uint32_t *src_addr1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1],
5536 uint32_t *src_addr2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2],
5538 uint32_t *src_addr3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3],
5541 uint16_t src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
5543 uint16_t src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
5545 uint16_t src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
5547 uint16_t src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
5550 uint16_t phy_port0 = pkt[0]->port;
5551 uint16_t phy_port1 = pkt[1]->port;
5552 uint16_t phy_port2 = pkt[2]->port;
5553 uint16_t phy_port3 = pkt[3]->port;
5555 struct pipeline_cgnapt_entry_key key0;
5556 struct pipeline_cgnapt_entry_key key1;
5557 struct pipeline_cgnapt_entry_key key2;
5558 struct pipeline_cgnapt_entry_key key3;
5560 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
5561 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
5562 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
5563 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
5567 #ifdef CGNAPT_DBG_PRNT
5568 if (CGNAPT_DEBUG > 4)
5573 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
5577 switch (protocol0) {
5579 case IP_PROTOCOL_UDP:
5583 struct udp_hdr *udp;
5585 udp = (struct udp_hdr *)
5586 RTE_MBUF_METADATA_UINT8_PTR(pkt[0],
5589 if (rte_bswap16(udp->dst_port) ==
5591 handle_pcp_req(pkt[0], IPV6_SZ, p_nat);
5592 p_nat->invalid_packets |= pkt_mask0;
5598 case IP_PROTOCOL_TCP:
5599 case IP_PROTOCOL_ICMP:
5600 /*we don't need icmp check in ipv6 */
5604 /* remember invalid packets to be dropped */
5605 p_nat->invalid_packets |= pkt_mask0;
5606 p_nat->naptDroppedPktCount++;
5608 #ifdef CGNAPT_DEBUGGING
5609 p_nat->naptDroppedPktCount2++;
5616 key0.pid = phy_port0;
5617 key0.ip = rte_bswap32(src_addr0[3]);
5618 key0.port = rte_bswap16(src_port0);
5620 #ifdef NAT_ONLY_CONFIG_REQ
5621 if (nat_only_config_flag)
5625 memcpy(&p_nat->keys[pkt_num], &key0,
5626 sizeof(struct pipeline_cgnapt_entry_key));
5627 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5630 #ifdef CGNAPT_DBG_PRNT
5631 if (CGNAPT_DEBUG > 4)
5636 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
5640 switch (protocol1) {
5641 case IP_PROTOCOL_UDP:
5645 struct udp_hdr *udp;
5647 udp = (struct udp_hdr *)
5648 RTE_MBUF_METADATA_UINT8_PTR(pkt[1],
5651 if (rte_bswap16(udp->dst_port) ==
5653 handle_pcp_req(pkt[1], IPV6_SZ, p_nat);
5654 p_nat->invalid_packets |= pkt_mask1;
5660 case IP_PROTOCOL_TCP:
5661 case IP_PROTOCOL_ICMP:
5662 /*we don't need icmp check in ipv6 */
5666 /* remember invalid packets to be dropped */
5667 p_nat->invalid_packets |= pkt_mask1;
5668 p_nat->naptDroppedPktCount++;
5670 #ifdef CGNAPT_DEBUGGING
5671 p_nat->naptDroppedPktCount2++;
5677 key1.pid = phy_port1;
5678 key1.ip = rte_bswap32(src_addr1[3]);
5679 key1.port = rte_bswap16(src_port1);
5681 #ifdef NAT_ONLY_CONFIG_REQ
5682 if (nat_only_config_flag)
5686 memcpy(&p_nat->keys[pkt_num + 1], &key1,
5687 sizeof(struct pipeline_cgnapt_entry_key));
5688 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
5691 #ifdef CGNAPT_DBG_PRNT
5692 if (CGNAPT_DEBUG > 4)
5697 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
5701 switch (protocol2) {
5702 case IP_PROTOCOL_UDP:
5706 struct udp_hdr *udp;
5708 udp = (struct udp_hdr *)
5709 RTE_MBUF_METADATA_UINT8_PTR(pkt[2],
5712 if (rte_bswap16(udp->dst_port) ==
5714 handle_pcp_req(pkt[2], IPV6_SZ, p_nat);
5715 p_nat->invalid_packets |= pkt_mask2;
5721 case IP_PROTOCOL_TCP:
5722 case IP_PROTOCOL_ICMP:
5723 /*we don't need icmp check in ipv6 */
5727 /* remember invalid packets to be dropped */
5728 p_nat->invalid_packets |= pkt_mask2;
5729 p_nat->naptDroppedPktCount++;
5731 #ifdef CGNAPT_DEBUGGING
5732 p_nat->naptDroppedPktCount2++;
5738 key2.pid = phy_port2;
5739 key2.ip = rte_bswap32(src_addr2[3]);
5740 key2.port = rte_bswap16(src_port2);
5742 #ifdef NAT_ONLY_CONFIG_REQ
5743 if (nat_only_config_flag)
5747 memcpy(&p_nat->keys[pkt_num + 2], &key2,
5748 sizeof(struct pipeline_cgnapt_entry_key));
5749 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
5752 #ifdef CGNAPT_DBG_PRNT
5753 if (CGNAPT_DEBUG > 4)
5758 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
5762 switch (protocol3) {
5763 case IP_PROTOCOL_UDP:
5767 struct udp_hdr *udp;
5769 udp = (struct udp_hdr *)
5770 RTE_MBUF_METADATA_UINT8_PTR(pkt[3],
5773 if (rte_bswap16(udp->dst_port) ==
5775 handle_pcp_req(pkt[3], IPV6_SZ, p_nat);
5776 p_nat->invalid_packets |= pkt_mask3;
5782 case IP_PROTOCOL_TCP:
5783 case IP_PROTOCOL_ICMP:
5784 /*we don't need icmp check in ipv6 */
5788 /* remember invalid packets to be dropped */
5789 p_nat->invalid_packets |= pkt_mask2;
5790 p_nat->naptDroppedPktCount++;
5792 #ifdef CGNAPT_DEBUGGING
5793 p_nat->naptDroppedPktCount2++;
5799 key3.pid = phy_port3;
5800 key3.ip = rte_bswap32(src_addr3[3]);
5801 key3.port = rte_bswap16(src_port3);
5803 #ifdef NAT_ONLY_CONFIG_REQ
5804 if (nat_only_config_flag)
5808 memcpy(&p_nat->keys[pkt_num + 3], &key3,
5809 sizeof(struct pipeline_cgnapt_entry_key));
5810 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
5816 * NAPT key calculation function for IPv4 public traffic
5817 * which handles 4 pkts
5820 * A pointer to array of packets mbuf
5822 * Starting pkt number of pkts
5826 * A pointer to main CGNAPT structure
5830 pkt4_work_cgnapt_key_ipv6_pub(
5831 struct rte_mbuf **pkt,
5833 __rte_unused void *arg,
5834 struct pipeline_cgnapt *p_nat)
5836 p_nat->receivedPktCount += 4;
5838 /* bitmask representing only this packet */
5839 uint64_t pkt_mask0 = 1LLU << pkt_num;
5840 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
5841 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
5842 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
5844 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
5846 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
5848 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
5850 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
5853 uint32_t *dst_addr0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0],
5855 uint32_t *dst_addr1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1],
5857 uint32_t *dst_addr2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2],
5859 uint32_t *dst_addr3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3],
5862 uint16_t dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
5863 DST_PRT_OFST_IP4_TCP);
5864 uint16_t dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
5865 DST_PRT_OFST_IP4_TCP);
5866 uint16_t dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
5867 DST_PRT_OFST_IP4_TCP);
5868 uint16_t dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
5869 DST_PRT_OFST_IP4_TCP);
5871 struct pipeline_cgnapt_entry_key key0;
5872 struct pipeline_cgnapt_entry_key key1;
5873 struct pipeline_cgnapt_entry_key key2;
5874 struct pipeline_cgnapt_entry_key key3;
5876 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
5877 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
5878 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
5879 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
5883 #ifdef CGNAPT_DBG_PRNT
5884 if (CGNAPT_DEBUG > 4)
5889 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
5893 switch (protocol0) {
5895 case IP_PROTOCOL_TCP:
5896 case IP_PROTOCOL_UDP:
5897 case IP_PROTOCOL_ICMP:
5898 /*we don't need icmp check in ipv6 */
5902 /* remember invalid packets to be dropped */
5903 p_nat->invalid_packets |= pkt_mask0;
5904 p_nat->naptDroppedPktCount++;
5906 #ifdef CGNAPT_DEBUGGING
5907 p_nat->naptDroppedPktCount2++;
5913 key0.ip = rte_bswap32(dst_addr0[0]);
5914 key0.port = rte_bswap16(dst_port0);
5916 #ifdef NAT_ONLY_CONFIG_REQ
5917 if (nat_only_config_flag)
5921 memcpy(&p_nat->keys[pkt_num], &key0,
5922 sizeof(struct pipeline_cgnapt_entry_key));
5923 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5929 #ifdef CGNAPT_DBG_PRNT
5930 if (CGNAPT_DEBUG > 4)
5935 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
5939 switch (protocol1) {
5941 case IP_PROTOCOL_TCP:
5942 case IP_PROTOCOL_UDP:
5943 case IP_PROTOCOL_ICMP:
5944 /*we don't need icmp check in ipv6 */
5948 /* remember invalid packets to be dropped */
5949 p_nat->invalid_packets |= pkt_mask1;
5950 p_nat->naptDroppedPktCount++;
5952 #ifdef CGNAPT_DEBUGGING
5953 p_nat->naptDroppedPktCount2++;
5959 key1.ip = rte_bswap32(dst_addr1[0]);
5960 key1.port = rte_bswap16(dst_port1);
5962 #ifdef NAT_ONLY_CONFIG_REQ
5963 if (nat_only_config_flag)
5967 memcpy(&p_nat->keys[pkt_num + 1], &key1,
5968 sizeof(struct pipeline_cgnapt_entry_key));
5969 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
5975 #ifdef CGNAPT_DBG_PRNT
5976 if (CGNAPT_DEBUG > 4)
5981 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
5985 switch (protocol2) {
5987 case IP_PROTOCOL_TCP:
5988 case IP_PROTOCOL_UDP:
5989 case IP_PROTOCOL_ICMP:
5990 /*we don't need icmp check in ipv6 */
5994 /* remember invalid packets to be dropped */
5995 p_nat->invalid_packets |= pkt_mask2;
5996 p_nat->naptDroppedPktCount++;
5998 #ifdef CGNAPT_DEBUGGING
5999 p_nat->naptDroppedPktCount2++;
6005 key2.ip = rte_bswap32(dst_addr2[0]);
6006 key2.port = rte_bswap16(dst_port2);
6008 #ifdef NAT_ONLY_CONFIG_REQ
6009 if (nat_only_config_flag)
6013 memcpy(&p_nat->keys[pkt_num + 2], &key2,
6014 sizeof(struct pipeline_cgnapt_entry_key));
6016 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
6022 #ifdef CGNAPT_DBG_PRNT
6023 if (CGNAPT_DEBUG > 4)
6028 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
6032 switch (protocol3) {
6034 case IP_PROTOCOL_TCP:
6035 case IP_PROTOCOL_UDP:
6036 case IP_PROTOCOL_ICMP:
6037 /*we don't need icmp check in ipv6 */
6041 /* remember invalid packets to be dropped */
6042 p_nat->invalid_packets |= pkt_mask3;
6043 p_nat->naptDroppedPktCount++;
6045 #ifdef CGNAPT_DEBUGGING
6046 p_nat->naptDroppedPktCount2++;
6052 key3.ip = rte_bswap32(dst_addr3[0]);
6053 key3.port = rte_bswap16(dst_port3);
6055 #ifdef NAT_ONLY_CONFIG_REQ
6056 if (nat_only_config_flag)
6060 memcpy(&p_nat->keys[pkt_num + 3], &key3,
6061 sizeof(struct pipeline_cgnapt_entry_key));
6063 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
6067 * NAPT function for IPv6 private traffic which handles 1 pkt
6070 * A pointer to array of packet mbuf
6076 * A pointer to main CGNAPT structure
6080 pkt_work_cgnapt_ipv6_prv(
6081 struct rte_mbuf *pkt,
6083 __rte_unused void *arg,
6084 struct pipeline_cgnapt *p_nat)
6086 /* index into hash table entries */
6087 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6089 /*bitmask representing only this packet */
6090 uint64_t pkt_mask = 1LLU << pkt_num;
6092 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
6094 /* Added for Multiport */
6095 uint32_t dest_if = INVALID_DESTIF;
6096 uint16_t *outport_id = RTE_MBUF_METADATA_UINT16_PTR(pkt,
6097 cgnapt_meta_offset);
6099 struct cgnapt_table_entry *entry = NULL;
6100 enum PKT_TYPE pkt_type = PKT_TYPE_IPV6to4;
6102 if (hash_table_entry < 0) {
6104 /* try to add new entry */
6105 struct rte_pipeline_table_entry *table_entry = NULL;
6107 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
6109 &p_nat->valid_packets, pkt_num,
6113 /* ICMP Error message generation for
6114 * Destination Host unreachable
6116 /* Do we need this check for ipv6? */
6117 if (protocol == IP_PROTOCOL_ICMP) {
6118 cgnapt_icmp_pkt = pkt;
6119 send_icmp_dest_unreachable_msg();
6122 /* Drop packet by adding to invalid pkt mask */
6124 p_nat->invalid_packets |= dropmask;
6126 #ifdef CGNAPT_DEBUGGING
6127 if (p_nat->kpc2++ < 5) {
6128 printf("in_ah Th: %d", p_nat->pipeline_num);
6129 print_key(p_nat->key_ptrs[pkt_num]);
6133 p_nat->naptDroppedPktCount++;
6135 #ifdef CGNAPT_DEBUGGING
6136 p_nat->naptDroppedPktCount3++;
6142 entry = (struct cgnapt_table_entry *)table_entry;
6144 /* entry found for this packet */
6145 entry = &napt_hash_tbl_entries[hash_table_entry];
6148 /* apply napt and mac changes */
6150 p_nat->entries[pkt_num] = &(entry->head);
6152 struct ipv6_hdr ipv6_hdr;
6154 struct ether_addr hw_addr;
6155 uint32_t dest_address = 0;
6160 convert_ipv6_to_ipv4(pkt, &ipv6_hdr);
6162 #ifdef CGNAPT_DBG_PRNT
6163 if (CGNAPT_DEBUG == 1)
6164 printf("pkt_work_cganpt: convert_ipv6_to_ipv4\n");
6167 struct cgnapt_nsp_node *ll = nsp_ll;
6170 while (ll != NULL) {
6172 (&ipv6_hdr.dst_addr[0], &ll->nsp.prefix[0],
6173 ll->nsp.depth / 8)) {
6181 && !memcmp(&ipv6_hdr.dst_addr[0], &well_known_prefix[0],
6187 p_nat->invalid_packets |= pkt_mask;
6188 p_nat->naptDroppedPktCount++;
6190 #ifdef CGNAPT_DEBUGGING
6191 p_nat->naptDroppedPktCount5++;
6199 /* As packet is already converted into IPv4 we must not
6200 * operate IPv6 offsets on packet
6201 * Only perform IPv4 operations
6204 uint32_t *src_addr =
6205 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP6t4);
6206 uint32_t *dst_addr =
6207 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP6t4);
6208 uint16_t *src_port =
6209 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP6t4);
6210 uint16_t *dst_port =
6211 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP6t4);
6213 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt,
6215 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt,
6216 ETH_OFST_IP6t4 + 6);
6218 if (entry->data.ttl == NAPT_ENTRY_STALE)
6219 entry->data.ttl = NAPT_ENTRY_VALID;
6222 if (unlikely(protocol == IP_PROTOCOL_UDP
6223 && rte_be_to_cpu_16(*dst_port) == 53)) {
6224 p_nat->invalid_packets |= pkt_mask;
6225 p_nat->naptDroppedPktCount++;
6227 #ifdef CGNAPT_DEBUGGING
6228 p_nat->naptDroppedPktCount6++;
6234 dest_address = rte_bswap32(*dst_addr);
6235 /*Multiport Changes */
6238 ret = local_get_nh_ipv4(dest_address, &dest_if, &nhip, p_nat);
6240 dest_if = get_prv_to_pub_port(&dest_address, IP_VERSION_4);
6242 if (dest_if == INVALID_DESTIF) {
6243 p_nat->invalid_packets |= pkt_mask;
6244 p_nat->naptDroppedPktCount++;
6245 #ifdef CGNAPT_DEBUGGING
6246 p_nat->naptDroppedPktCount6++;
6251 do_local_nh_ipv4_cache(dest_if, p_nat);
6253 *outport_id = p_nat->outport_id[dest_if];
6255 #ifdef CGNAPT_DBG_PRNT
6256 if (CGNAPT_DEBUG > 2)
6257 printf("Egress: \tphy_port:%d\t get_prv_to_pub():%d "
6258 "\tout_port:%d\n", pkt->port,
6259 dest_if, *outport_id);
6263 #ifdef CGNAPT_DBG_PRNT
6264 static int static_count;
6266 if (static_count++ < 10) {
6268 my_print_entry(entry);
6269 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6270 printf("dest_add:%x\n", entry->data.u.prv_ip);
6271 printf("dest_add:%x\n", *dst_addr);
6272 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6276 if (local_dest_mac_present(dest_if)) {
6277 memcpy(eth_src, get_link_hw_addr(dest_if),
6278 sizeof(struct ether_addr));
6280 struct arp_entry_data *ret_arp_data;
6281 ret_arp_data = get_dest_mac_addr_port(dest_address, &dest_if, (struct ether_addr *)&hw_addr);
6283 if (unlikely(ret_arp_data == NULL)) {
6285 printf("%s: NHIP Not Found, nhip: %x, "
6286 "outport_id: %d\n", __func__, nhip,
6290 p_nat->invalid_packets |= pkt_mask;
6291 p_nat->naptDroppedPktCount++;
6293 #ifdef CGNAPT_DEBUGGING
6294 p_nat->naptDroppedPktCount4++;
6299 if (ret_arp_data->status == COMPLETE) {
6301 #ifdef CGNAPT_DBG_PRNT
6302 if (CGNAPT_DEBUG > 2) {
6303 printf("MAC found for ip 0x%x, port %d - %02x:%02x: "
6304 "%02x:%02x:%02x:%02x\n", dest_address,
6306 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
6307 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
6308 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
6310 printf("Dest MAC before - %02x:%02x:%02x:%02x: "
6311 "%02x:%02x\n", eth_dest[0], eth_dest[1],
6312 eth_dest[2], eth_dest[3],
6313 eth_dest[4], eth_dest[5]);
6317 //memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
6319 #ifdef CGNAPT_DBG_PRNT
6320 if (CGNAPT_DEBUG > 2) {
6321 printf("Dest MAC after - "
6322 "%02x:%02x:%02x:%02x:%02x:%02x\n",
6323 eth_dest[0], eth_dest[1], eth_dest[2], eth_dest[3],
6324 eth_dest[4], eth_dest[5]);
6328 memcpy(eth_src, get_link_hw_addr(dest_if),
6329 sizeof(struct ether_addr));
6330 } else if (ret_arp_data->status == INCOMPLETE ||
6331 ret_arp_data->status == PROBE) {
6332 arp_queue_unresolved_packet(ret_arp_data,
6340 *src_addr = rte_bswap32(entry->data.pub_ip);
6342 #ifdef NAT_ONLY_CONFIG_REQ
6343 if (!nat_only_config_flag) {
6345 *src_port = rte_bswap16(entry->data.pub_port);
6347 #ifdef NAT_ONLY_CONFIG_REQ
6351 p_nat->enaptedPktCount++;
6354 p_nat->naptedPktCount++;
6357 if (p_nat->hw_checksum_reqd)
6358 hw_checksum(pkt, pkt_type);
6360 sw_checksum(pkt, pkt_type);
6366 * NAPT function for IPv6 public traffic which handles 1 pkt
6369 * A pointer to array of packet mbuf
6375 * A pointer to main CGNAPT structure
6379 pkt_work_cgnapt_ipv6_pub(
6380 struct rte_mbuf *pkt,
6382 __rte_unused void *arg,
6383 struct pipeline_cgnapt *p_nat)
6386 /* index into hash table entries */
6387 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6388 /*bitmask representing only this packet */
6389 uint64_t pkt_mask = 1LLU << pkt_num;
6391 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
6393 uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */
6394 uint16_t *outport_id =
6395 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6396 struct cgnapt_table_entry *entry = NULL;
6398 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4to6;
6400 if (hash_table_entry < 0) {
6402 /* Drop ingress initial traffic */
6404 p_nat->invalid_packets |= pkt_mask;
6405 p_nat->naptDroppedPktCount++;
6407 #ifdef CGNAPT_DEBUGGING
6408 p_nat->naptDroppedPktCount3++;
6409 if (p_nat->kpc2++ < 5) {
6410 printf("in_ah Th: %d", p_nat->pipeline_num);
6411 print_key(p_nat->key_ptrs[pkt_num]);
6418 /* entry found for this packet */
6419 entry = &napt_hash_tbl_entries[hash_table_entry];
6422 /* apply napt and mac changes */
6424 p_nat->entries[pkt_num] = &(entry->head);
6425 if (entry->data.type != CGNAPT_ENTRY_IPV6) {
6426 p_nat->invalid_packets |= pkt_mask;
6427 p_nat->naptDroppedPktCount++;
6431 struct ipv4_hdr ipv4_hdr;
6432 uint16_t *src_port =
6433 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP4_TCP);
6435 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
6436 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
6438 if (entry->data.ttl == NAPT_ENTRY_STALE)
6439 entry->data.ttl = NAPT_ENTRY_VALID;
6441 struct ether_addr hw_addr;
6442 uint8_t dest_addr_ipv6[16];
6443 uint8_t nh_ipv6[16];
6448 if (unlikely(protocol == IP_PROTOCOL_UDP
6449 && rte_be_to_cpu_16(*src_port) == 53)) {
6450 p_nat->invalid_packets |= pkt_mask;
6451 p_nat->naptDroppedPktCount++;
6452 #ifdef CGNAPT_DEBUGGING
6453 p_nat->naptDroppedPktCount6++;
6458 memcpy(&dest_addr_ipv6[0], &entry->data.u.prv_ipv6[0], 16);
6461 ret = local_get_nh_ipv6(&dest_addr_ipv6[0], &dest_if,
6464 dest_if = get_prv_to_pub_port((uint32_t *)
6468 if (dest_if == INVALID_DESTIF) {
6469 p_nat->invalid_packets |= pkt_mask;
6470 p_nat->naptDroppedPktCount++;
6471 #ifdef CGNAPT_DEBUGGING
6472 p_nat->naptDroppedPktCount6++;
6477 do_local_nh_ipv6_cache(dest_if, p_nat);
6479 *outport_id = p_nat->outport_id[dest_if];
6482 #ifdef CGNAPT_DEBUGGING
6483 static int static_count;
6485 if (static_count++ < 10) {
6487 my_print_entry(entry);
6488 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6489 printf("dest_add:%x\n", entry->data.u.prv_ip);
6490 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6494 memset(nh_ipv6, 0, 16);
6495 if (get_dest_mac_address_ipv6_port(
6501 #ifdef CGNAPT_DBG_PRNT
6502 if (CGNAPT_DEBUG > 2) {
6503 printf("MAC found for ip 0x%x, port %d - "
6504 "%02x:%02x:%02x:%02x:%02x:%02x\n",
6505 *((uint32_t *)dest_addr_ipv6 + 12),
6507 hw_addr.addr_bytes[0],
6508 hw_addr.addr_bytes[1], hw_addr.addr_bytes[2],
6509 hw_addr.addr_bytes[3], hw_addr.addr_bytes[4],
6510 hw_addr.addr_bytes[5]);
6512 printf("Dest MAC before - "
6513 "%02x:%02x:%02x:%02x:%02x:%02x\n",
6514 eth_dest[0], eth_dest[1], eth_dest[2],
6515 eth_dest[3], eth_dest[4], eth_dest[5]);
6519 memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
6521 #ifdef CGNAPT_DBG_PRNT
6522 if (CGNAPT_DEBUG > 2) {
6523 printf("Dest MAC after - "
6524 "%02x:%02x:%02x:%02x:%02x:%02x\n",
6525 eth_dest[0], eth_dest[1], eth_dest[2], eth_dest[3],
6526 eth_dest[4], eth_dest[5]);
6530 memcpy(eth_src, get_link_hw_addr(dest_if),
6531 sizeof(struct ether_addr));
6533 p_nat->invalid_packets |= pkt_mask;
6534 p_nat->naptDroppedPktCount++;
6536 #ifdef CGNAPT_DEBUGGING
6537 p_nat->naptDroppedPktCount4++;
6545 convert_ipv4_to_ipv6(pkt, &ipv4_hdr);
6547 /* Ethernet MTU check */
6548 if ((rte_pktmbuf_data_len(pkt) - 14) > 1500) {
6549 p_nat->invalid_packets |= pkt_mask;
6550 p_nat->naptDroppedPktCount++;
6553 uint32_t *dst_addr =
6554 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4t6);
6555 uint16_t *dst_port =
6556 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP4t6);
6558 memcpy((uint8_t *) &dst_addr[0], &entry->data.u.prv_ipv6[0],
6561 #ifdef NAT_ONLY_CONFIG_REQ
6562 if (!nat_only_config_flag) {
6564 *dst_port = rte_bswap16(entry->data.prv_port);
6566 #ifdef NAT_ONLY_CONFIG_REQ
6570 p_nat->inaptedPktCount++;
6573 p_nat->naptedPktCount++;
6576 if (p_nat->hw_checksum_reqd)
6577 hw_checksum(pkt, pkt_type);
6579 sw_checksum(pkt, pkt_type);
6585 * NAPT function for IPv6 private traffic which handles 4 pkts
6588 * A pointer to array of packets mbuf
6590 * Starting pkt number of pkts
6594 * A pointer to main CGNAPT structure
6598 pkt4_work_cgnapt_ipv6_prv(
6599 struct rte_mbuf **pkts,
6600 uint32_t in_pkt_num,
6601 __rte_unused void *arg,
6602 struct pipeline_cgnapt *p_nat)
6604 struct rte_mbuf *pkt;
6608 enum PKT_TYPE pkt_type = PKT_TYPE_IPV6to4;
6610 for (i = 0; i < 4; i++) {
6611 pkt_num = in_pkt_num + i;
6614 /* index into hash table entries */
6615 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6616 /*bitmask representing only this packet */
6617 uint64_t pkt_mask = 1LLU << pkt_num;
6619 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
6620 uint32_t dest_if = INVALID_DESTIF;
6621 uint16_t *outport_id =
6622 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6623 struct cgnapt_table_entry *entry = NULL;
6625 if (hash_table_entry < 0) {
6627 /* try to add new entry */
6628 struct rte_pipeline_table_entry *table_entry = NULL;
6631 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
6633 &p_nat->valid_packets, pkt_num,
6637 /* ICMP Error message generation for
6638 * Destination Host unreachable
6640 /* Do we need this check for ipv6? */
6641 if (protocol == IP_PROTOCOL_ICMP) {
6642 cgnapt_icmp_pkt = pkt;
6643 send_icmp_dest_unreachable_msg();
6646 /* Drop packet by adding to invalid pkt mask */
6648 p_nat->invalid_packets |= dropmask;
6650 #ifdef CGNAPT_DEBUGGING
6651 if (p_nat->kpc2++ < 5) {
6652 printf("in_ah Th: %d",
6653 p_nat->pipeline_num);
6654 print_key(p_nat->key_ptrs[pkt_num]);
6658 p_nat->naptDroppedPktCount++;
6660 #ifdef CGNAPT_DEBUGGING
6661 p_nat->naptDroppedPktCount3++;
6667 entry = (struct cgnapt_table_entry *)table_entry;
6669 /* entry found for this packet */
6670 entry = &napt_hash_tbl_entries[hash_table_entry];
6673 /* apply napt and mac changes */
6675 p_nat->entries[pkt_num] = &(entry->head);
6677 struct ipv6_hdr ipv6_hdr;
6678 struct ether_addr hw_addr;
6679 uint32_t dest_address = 0;
6680 uint8_t nh_ipv6[16];
6685 convert_ipv6_to_ipv4(pkt, &ipv6_hdr);
6687 #ifdef CGNAPT_DBG_PRNT
6688 if (CGNAPT_DEBUG >= 1)
6689 printf("pkt_work_cganpt: "
6690 "convert_ipv6_to_ipv4\n");
6693 struct cgnapt_nsp_node *ll = nsp_ll;
6696 while (ll != NULL) {
6697 if (!memcmp(&ipv6_hdr.dst_addr[0],
6699 ll->nsp.depth / 8)) {
6707 && !memcmp(&ipv6_hdr.dst_addr[0],
6708 &well_known_prefix[0], 12)) {
6713 p_nat->invalid_packets |= pkt_mask;
6714 p_nat->naptDroppedPktCount++;
6716 #ifdef CGNAPT_DEBUGGING
6717 p_nat->naptDroppedPktCount5++;
6724 /* As packet is already converted into IPv4 we must not
6725 * operate IPv6 offsets on packet only perform IPv4 operations
6728 uint32_t *src_addr =
6729 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP6t4);
6730 uint32_t *dst_addr =
6731 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP6t4);
6732 uint16_t *src_port =
6733 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP6t4);
6734 uint16_t *dst_port =
6735 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP6t4);
6738 RTE_MBUF_METADATA_UINT8_PTR(pkt, ETH_OFST_IP6t4);
6740 RTE_MBUF_METADATA_UINT8_PTR(pkt, ETH_OFST_IP6t4 + 6);
6742 if (entry->data.ttl == NAPT_ENTRY_STALE)
6743 entry->data.ttl = NAPT_ENTRY_VALID;
6748 if (unlikely(protocol == IP_PROTOCOL_UDP
6749 && rte_be_to_cpu_16(*dst_port) == 53)) {
6750 p_nat->invalid_packets |= pkt_mask;
6751 p_nat->naptDroppedPktCount++;
6753 #ifdef CGNAPT_DEBUGGING
6754 p_nat->naptDroppedPktCount6++;
6759 dest_address = rte_bswap32(*dst_addr);
6762 ret = local_get_nh_ipv4(dest_address, &dest_if, &nhip, p_nat);
6764 dest_if = get_prv_to_pub_port(&dest_address, IP_VERSION_4);
6766 if (dest_if == INVALID_DESTIF) {
6767 p_nat->invalid_packets |= pkt_mask;
6768 p_nat->naptDroppedPktCount++;
6769 #ifdef CGNAPT_DEBUGGING
6770 p_nat->naptDroppedPktCount6++;
6775 do_local_nh_ipv4_cache(dest_if, p_nat);
6777 *outport_id = p_nat->outport_id[dest_if];
6779 #ifdef CGNAPT_DBG_PRNT
6780 if (CGNAPT_DEBUG > 2)
6781 printf("Egress: \tphy_port:%d\t"
6782 "get_prv_to_pub():%d \tout_port:%d\n",
6783 pkt->port, dest_if, *outport_id);
6787 #ifdef CGNAPT_DEBUGGING
6788 static int static_count;
6790 if (static_count++ < 10) {
6792 my_print_entry(entry);
6793 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6794 printf("dest_add:%x\n", entry->data.u.prv_ip);
6795 printf("dest_add:%x\n", *dst_addr);
6796 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6800 memset(nh_ipv6, 0, 16);
6803 struct arp_entry_data *ret_arp_data;
6804 ret_arp_data = get_dest_mac_addr_port(dest_address, &dest_if, (struct ether_addr *)&hw_addr);
6806 if (unlikely(ret_arp_data == NULL)) {
6808 printf("%s: NHIP Not Found, nhip: %x, "
6809 "outport_id: %d\n", __func__, nhip,
6813 p_nat->invalid_packets |= pkt_mask;
6814 p_nat->naptDroppedPktCount++;
6816 #ifdef CGNAPT_DEBUGGING
6817 p_nat->naptDroppedPktCount4++;
6822 if (ret_arp_data->status == COMPLETE) {
6824 #ifdef CGNAPT_DBG_PRNT
6825 if (CGNAPT_DEBUG > 2) {
6826 printf("MAC found for ip 0x%x, port %d - "
6827 "%02x:%02x:%02x:%02x:%02x:%02x\n",
6828 dest_address, *outport_id,
6829 hw_addr.addr_bytes[0],
6830 hw_addr.addr_bytes[1],
6831 hw_addr.addr_bytes[2],
6832 hw_addr.addr_bytes[3],
6833 hw_addr.addr_bytes[4],
6834 hw_addr.addr_bytes[5]
6837 printf("Dest MAC before - "
6838 "%02x:%02x:%02x:%02x:%02x:%02x\n",
6839 eth_dest[0], eth_dest[1], eth_dest[2],
6840 eth_dest[3], eth_dest[4], eth_dest[5]);
6844 //memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
6846 #ifdef CGNAPT_DBG_PRNT
6847 if (CGNAPT_DEBUG > 2) {
6848 printf("Dest MAC after - "
6849 "%02x:%02x:%02x:%02x:%02x:%02x\n",
6850 eth_dest[0], eth_dest[1], eth_dest[2],
6851 eth_dest[3], eth_dest[4], eth_dest[5]);
6855 memcpy(eth_src, get_link_hw_addr(dest_if),
6856 sizeof(struct ether_addr));
6857 } else if (ret_arp_data->status == INCOMPLETE ||
6858 ret_arp_data->status == PROBE) {
6859 arp_queue_unresolved_packet(ret_arp_data,
6867 *src_addr = rte_bswap32(entry->data.pub_ip);
6869 #ifdef NAT_ONLY_CONFIG_REQ
6870 if (!nat_only_config_flag) {
6872 *src_port = rte_bswap16(entry->data.pub_port);
6874 #ifdef NAT_ONLY_CONFIG_REQ
6878 p_nat->enaptedPktCount++;
6881 p_nat->naptedPktCount++;
6884 if (p_nat->hw_checksum_reqd)
6885 hw_checksum(pkt, pkt_type);
6887 sw_checksum(pkt, pkt_type);
6893 * NAPT function for IPv6 public traffic which handles 4 pkts
6896 * A pointer to array of packets mbuf
6898 * Starting pkt number of pkts
6902 * A pointer to main CGNAPT structure
6906 pkt4_work_cgnapt_ipv6_pub(
6907 struct rte_mbuf **pkts,
6908 uint32_t in_pkt_num,
6909 __rte_unused void *arg,
6910 struct pipeline_cgnapt *p_nat)
6912 struct rte_mbuf *pkt;
6916 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4to6;
6918 for (i = 0; i < 4; i++) {
6919 pkt_num = in_pkt_num + i;
6922 /* index into hash table entries */
6923 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6924 /*bitmask representing only this packet */
6925 uint64_t pkt_mask = 1LLU << pkt_num;
6927 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
6928 uint16_t *outport_id =
6929 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6930 struct cgnapt_table_entry *entry = NULL;
6932 if (hash_table_entry < 0) {
6934 /* Drop ingress initial traffic */
6936 p_nat->invalid_packets |= pkt_mask;
6937 p_nat->naptDroppedPktCount++;
6938 #ifdef CGNAPT_DEBUGGING
6939 p_nat->naptDroppedPktCount3++;
6940 if (p_nat->kpc2++ < 5) {
6941 printf("in_ah Th: %d", p_nat->pipeline_num);
6942 print_key(p_nat->key_ptrs[pkt_num]);
6949 /* entry found for this packet */
6950 entry = &napt_hash_tbl_entries[hash_table_entry];
6953 /* apply napt and mac changes */
6955 p_nat->entries[pkt_num] = &(entry->head);
6956 if (entry->data.type != CGNAPT_ENTRY_IPV6) {
6957 p_nat->invalid_packets |= pkt_mask;
6958 p_nat->naptDroppedPktCount++;
6962 struct ipv4_hdr ipv4_hdr;
6964 uint16_t *src_port =
6965 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP4_TCP);
6968 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
6970 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
6972 if (entry->data.ttl == NAPT_ENTRY_STALE)
6973 entry->data.ttl = NAPT_ENTRY_VALID;
6975 struct ether_addr hw_addr;
6976 uint8_t dest_addr_ipv6[16];
6977 uint8_t nh_ipv6[16];
6978 uint32_t dest_if = INVALID_DESTIF;
6979 { /*start of Ingress */
6981 if (unlikely(protocol == IP_PROTOCOL_UDP
6982 && rte_be_to_cpu_16(*src_port) == 53)) {
6983 p_nat->invalid_packets |= pkt_mask;
6984 p_nat->naptDroppedPktCount++;
6985 #ifdef CGNAPT_DEBUGGING
6986 p_nat->naptDroppedPktCount6++;
6991 memcpy(&dest_addr_ipv6[0], &entry->data.u.prv_ipv6[0],
6995 ret = local_get_nh_ipv6(&dest_addr_ipv6[0], &dest_if,
6998 dest_if = get_prv_to_pub_port((uint32_t *)
6999 &dest_addr_ipv6[0], IP_VERSION_6);
7001 if (dest_if == INVALID_DESTIF) {
7002 p_nat->invalid_packets |= pkt_mask;
7003 p_nat->naptDroppedPktCount++;
7004 #ifdef CGNAPT_DEBUGGING
7005 p_nat->naptDroppedPktCount6++;
7010 do_local_nh_ipv6_cache(dest_if, p_nat);
7013 *outport_id = p_nat->outport_id[dest_if];
7014 }/* end of ingress */
7016 #ifdef CGNAPT_DEBUGGING
7017 static int static_count;
7019 if (static_count++ < 10) {
7021 my_print_entry(entry);
7022 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
7023 printf("dest_add:%x\n", entry->data.u.prv_ip);
7024 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
7028 memset(nh_ipv6, 0, 16);
7029 if (get_dest_mac_address_ipv6
7030 (&dest_addr_ipv6[0], &dest_if,
7031 &hw_addr, &nh_ipv6[0])) {
7032 #ifdef CGNAPT_DBG_PRNT
7033 if (CGNAPT_DEBUG > 2) {
7034 printf("MAC found for ip 0x%x, port %d - "
7035 "%02x:%02x:%02x:%02x:%02x:%02x\n",
7036 *((uint32_t *)dest_addr_ipv6 + 12),
7038 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
7039 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
7040 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
7042 printf("Dest MAC before - "
7043 "%02x:%02x:%02x:%02x:%02x:%02x\n",
7044 eth_dest[0], eth_dest[1], eth_dest[2],
7045 eth_dest[3], eth_dest[4], eth_dest[5]);
7049 memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
7051 #ifdef CGNAPT_DBG_PRNT
7052 if (CGNAPT_DEBUG > 2) {
7053 printf("Dest MAC after - "
7054 "%02x:%02x:%02x:%02x:%02x:%02x\n",
7055 eth_dest[0], eth_dest[1], eth_dest[2],
7056 eth_dest[3], eth_dest[4], eth_dest[5]);
7061 get_link_hw_addr(dest_if),
7062 sizeof(struct ether_addr));
7064 p_nat->invalid_packets |= pkt_mask;
7065 p_nat->naptDroppedPktCount++;
7067 #ifdef CGNAPT_DEBUGGING
7068 p_nat->naptDroppedPktCount4++;
7075 /* start of Ingress */
7077 convert_ipv4_to_ipv6(pkt, &ipv4_hdr);
7079 /* Ethernet MTU check */
7080 if ((rte_pktmbuf_data_len(pkt) - 14) > 1500) {
7081 p_nat->invalid_packets |= pkt_mask;
7082 p_nat->naptDroppedPktCount++;
7085 uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
7086 DST_ADR_OFST_IP4t6);
7087 uint16_t *dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
7088 DST_PRT_OFST_IP4t6);
7090 memcpy((uint8_t *) &dst_addr[0],
7091 &entry->data.u.prv_ipv6[0], 16);
7093 #ifdef NAT_ONLY_CONFIG_REQ
7094 if (!nat_only_config_flag) {
7096 *dst_port = rte_bswap16(entry->data.prv_port);
7098 #ifdef NAT_ONLY_CONFIG_REQ
7102 p_nat->inaptedPktCount++;
7103 } /* end of ingress */
7105 p_nat->naptedPktCount++;
7108 if (p_nat->hw_checksum_reqd)
7109 hw_checksum(pkt, pkt_type);
7111 sw_checksum(pkt, pkt_type);
7113 } /* end of for loop */
7117 * Input port handler for IPv6 private traffic
7118 * Starting from the packet burst it filters unwanted packets,
7119 * calculates keys, does lookup and then based on the lookup
7120 * updates NAPT table and does packet NAPT translation.
7123 * A pointer to struct rte_pipeline
7125 * A pointer to array of packets mbuf
7127 * Number of packets in the burst
7132 * int that is not checked by caller
7134 static int cgnapt_in_port_ah_ipv6_prv(struct rte_pipeline *rte_p,
7135 struct rte_mbuf **pkts,
7136 uint32_t n_pkts, void *arg)
7139 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
7140 struct pipeline_cgnapt *p_nat = ap->p;
7142 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
7143 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
7144 p_nat->invalid_packets = 0;
7146 #ifdef CGNAPT_DBG_PRNT
7147 if (CGNAPT_DEBUG > 1)
7148 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
7151 /* prefetching for mbufs should be done here */
7152 for (j = 0; j < n_pkts; j++)
7153 rte_prefetch0(pkts[j]);
7155 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7156 pkt4_work_cgnapt_key_ipv6_prv(&pkts[i], i, arg, p_nat);
7158 for (; i < n_pkts; i++)
7159 pkt_work_cgnapt_key_ipv6_prv(pkts[i], i, arg, p_nat);
7161 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7163 if (unlikely(p_nat->valid_packets == 0)) {
7164 /* no suitable packet for lookup */
7165 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7166 return p_nat->valid_packets;
7169 /* lookup entries in the common napt table */
7171 int lookup_result = rte_hash_lookup_bulk(
7173 (const void **) &p_nat->key_ptrs,
7174 /* should be minus num invalid pkts */
7176 /*new pipeline data member */
7177 &p_nat->lkup_indx[0]);
7179 if (unlikely(lookup_result < 0)) {
7180 /* unknown error, just discard all packets */
7181 printf("Unexpected hash lookup error %d, "
7182 "discarding all packets",
7184 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
7188 /* Now call second stage of pipeline to one by one
7189 * check the result of our bulk lookup
7192 /* prefetching for table entries should be done here */
7193 for (j = 0; j < n_pkts; j++) {
7194 if (p_nat->lkup_indx[j] >= 0)
7195 rte_prefetch0(&napt_hash_tbl_entries
7196 [p_nat->lkup_indx[j]]);
7199 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7200 pkt4_work_cgnapt_ipv6_prv(&pkts[i], i, arg, p_nat);
7202 for (; i < n_pkts; i++)
7203 pkt_work_cgnapt_ipv6_prv(pkts[i], i, arg, p_nat);
7205 if (p_nat->invalid_packets) {
7206 /* get rid of invalid packets */
7207 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7209 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7211 #ifdef CGNAPT_DBG_PRNT
7212 if (CGNAPT_DEBUG > 1) {
7213 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
7214 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
7215 printf("invalid_packets:0x%jx\n",
7216 p_nat->invalid_packets);
7217 printf("rte_invalid_packets :0x%jx\n",
7218 rte_p->pkts_drop_mask);
7219 printf("Total pkts dropped :0x%jx\n",
7220 rte_p->n_pkts_ah_drop);
7225 return p_nat->valid_packets;
7230 * Input port handler for IPv6 public traffic
7231 * Starting from the packet burst it filters unwanted packets,
7232 * calculates keys, does lookup and then based on the lookup
7233 * updates NAPT table and does packet NAPT translation.
7236 * A pointer to struct rte_pipeline
7238 * A pointer to array of packets mbuf
7240 * Number of packets in the burst
7245 * int that is not checked by caller
7247 static int cgnapt_in_port_ah_ipv6_pub(struct rte_pipeline *rte_p,
7248 struct rte_mbuf **pkts,
7249 uint32_t n_pkts, void *arg)
7252 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
7253 struct pipeline_cgnapt *p_nat = ap->p;
7255 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
7256 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
7257 p_nat->invalid_packets = 0;
7259 #ifdef CGNAPT_DBG_PRNT
7260 if (CGNAPT_DEBUG > 1)
7261 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
7264 /* prefetching for mbufs should be done here */
7265 for (j = 0; j < n_pkts; j++)
7266 rte_prefetch0(pkts[j]);
7268 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7269 pkt4_work_cgnapt_key_ipv6_pub(&pkts[i], i, arg, p_nat);
7271 for (; i < n_pkts; i++)
7272 pkt_work_cgnapt_key_ipv6_pub(pkts[i], i, arg, p_nat);
7274 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7276 if (unlikely(p_nat->valid_packets == 0)) {
7277 /* no suitable packet for lookup */
7278 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7279 return p_nat->valid_packets;
7282 /* lookup entries in the common napt table */
7284 int lookup_result = rte_hash_lookup_bulk(
7286 (const void **) &p_nat->key_ptrs,
7287 /* should be minus num invalid pkts */
7289 /*new pipeline data member */
7290 &p_nat->lkup_indx[0]);
7292 if (unlikely(lookup_result < 0)) {
7293 /* unknown error, just discard all packets */
7294 printf("Unexpected hash lookup error %d, "
7295 "discarding all packets",
7297 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
7301 /* Now call second stage of pipeline to one by one
7302 * check the result of our bulk lookup
7305 /* prefetching for table entries should be done here */
7306 for (j = 0; j < n_pkts; j++) {
7307 if (p_nat->lkup_indx[j] >= 0)
7308 rte_prefetch0(&napt_hash_tbl_entries
7309 [p_nat->lkup_indx[j]]);
7312 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7313 pkt4_work_cgnapt_ipv6_pub(&pkts[i], i, arg, p_nat);
7315 for (; i < n_pkts; i++)
7316 pkt_work_cgnapt_ipv6_pub(pkts[i], i, arg, p_nat);
7318 if (p_nat->invalid_packets) {
7319 /* get rid of invalid packets */
7320 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7322 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7324 #ifdef CGNAPT_DBG_PRNT
7325 if (CGNAPT_DEBUG > 1) {
7326 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
7327 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
7328 printf("invalid_packets:0x%jx\n",
7329 p_nat->invalid_packets);
7330 printf("rte_invalid_packets :0x%jx\n",
7331 rte_p->pkts_drop_mask);
7332 printf("Total pkts dropped :0x%jx\n",
7333 rte_p->n_pkts_ah_drop);
7338 return p_nat->valid_packets;
7342 * Function to send ICMP dest unreachable msg
7345 void send_icmp_dest_unreachable_msg(void)
7348 struct ether_hdr *eth_h;
7349 struct ipv4_hdr *ip_h;
7350 struct icmp_hdr *icmp_h;
7351 struct rte_mbuf *icmp_pkt = cgnapt_icmp_pkt;
7353 if (icmp_pkt == NULL) {
7355 printf("Error allocating icmp_pkt rte_mbuf\n");
7359 port_id = icmp_pkt->port;
7361 struct app_link_params *link;
7362 link = &mylink[port_id];
7363 eth_h = rte_pktmbuf_mtod(icmp_pkt, struct ether_hdr *);
7364 ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
7365 icmp_h = (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
7367 struct ether_addr gw_addr;
7368 struct ether_addr dst_addr;
7369 ether_addr_copy(ð_h->s_addr, &dst_addr);
7370 rte_eth_macaddr_get(port_id, &gw_addr);
7371 ether_addr_copy(&gw_addr, ð_h->s_addr);
7372 ether_addr_copy(&dst_addr, ð_h->d_addr);
7374 eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
7375 ip_h->version_ihl = IP_VHL_DEF;
7376 ip_h->type_of_service = 0;
7377 ip_h->total_length = rte_cpu_to_be_16(sizeof(struct ipv4_hdr) +
7378 sizeof(struct icmp_hdr));
7379 ip_h->packet_id = 0xaabb;
7380 ip_h->fragment_offset = 0x0000;
7381 ip_h->time_to_live = 64;
7382 ip_h->next_proto_id = 1;
7385 uint32_t src_addr_offset =
7386 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_SRC_ADR_OFST;
7388 RTE_MBUF_METADATA_UINT32_PTR(cgnapt_icmp_pkt, src_addr_offset);
7390 ip_h->dst_addr = *src_addr;
7391 ip_h->src_addr = rte_bswap32(link->ip);
7393 ip_h->dst_addr = *src_addr;
7394 ip_h->src_addr = rte_bswap32(link->ip);
7396 ip_h->hdr_checksum = 0;
7397 ip_h->hdr_checksum = rte_ipv4_cksum(ip_h);
7398 icmp_h->icmp_type = 3; /* Destination Unreachable */
7399 icmp_h->icmp_code = 13; /* Communication administratively prohibited */
7401 icmp_h->icmp_cksum = ~rte_raw_cksum(icmp_h, sizeof(struct icmp_hdr));
7403 icmp_pkt->pkt_len = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
7404 sizeof(struct icmp_hdr);
7405 icmp_pkt->data_len = icmp_pkt->pkt_len;
7406 if (ARPICMP_DEBUG) {
7407 printf("Sending ICMP error message - "
7408 "Destination Unreachable\n");
7410 rte_pipeline_port_out_packet_insert(myP, port_id, icmp_pkt);
7414 * Function to add a dynamic NAPT entry pair
7417 * A pointer to struct pipeline
7419 * A pointer to struct pipeline_cgnapt_entry_key
7421 * expairy time of an dynamic or PCP req entry
7423 * uint8_t pointer of source address
7426 * A pointer to struct cgnapt_table_entry for added entry
7429 struct cgnapt_table_entry *add_dynamic_cgnapt_entry(
7431 struct pipeline_cgnapt_entry_key *key,
7438 void *entry_ptr, *ret_ptr;
7441 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
7443 #ifdef CGNAPT_DBG_PRNT
7444 if (CGNAPT_DEBUG >= 1) {
7445 printf("Th%d add_dynamic_cgnapt_entry key detail Entry:"
7446 "0x%x, %d, %d\n", p_nat->pipeline_num, key->ip, key->port,
7451 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX && i < p_nat->pkt_burst_cnt;
7453 if (p_nat->cgnapt_dyn_ent_table[i].ip == key->ip
7454 && p_nat->cgnapt_dyn_ent_table[i].port == key->port
7455 && p_nat->cgnapt_dyn_ent_table[i].pid == key->pid) {
7457 #ifdef CGNAPT_DBG_PRNT
7458 if (CGNAPT_DEBUG > 1)
7459 printf("add_dynamic_cgnapt_entry:pkt_burst "
7460 "array key matched!!!\n");
7463 return &napt_hash_tbl_entries
7464 [p_nat->cgnapt_dyn_ent_index[i]];
7468 #ifdef NAT_ONLY_CONFIG_REQ
7469 if (!nat_only_config_flag) {
7472 ret = increment_max_port_counter(key->ip, key->pid, p_nat);
7473 if (ret == MAX_PORT_INC_ERROR) {
7475 #ifdef CGNAPT_DEBUGGING
7476 p_nat->missedpktcount5++;
7479 #ifdef CGNAPT_DBG_PRNT
7480 if (CGNAPT_DEBUG > 1)
7481 printf("add_dynamic_cgnapt_entry:"
7482 "increment_max_port_counter-1 failed\n");
7489 if (ret == MAX_PORT_INC_REACHED) {
7491 #ifdef CGNAPT_DEBUGGING
7492 p_nat->missedpktcount6++;
7495 #ifdef CGNAPT_DBG_PRNT
7496 if (CGNAPT_DEBUG > 1)
7497 printf("add_dynamic_cgnapt_entry:"
7498 "increment_max_port_counter-2 failed\n");
7505 #ifdef NAT_ONLY_CONFIG_REQ
7510 port_num = get_free_iport(p_nat, &public_ip);
7512 if (port_num == -1) {
7514 #ifdef CGNAPT_DBG_PRNT
7515 if (CGNAPT_DEBUG > 2) {
7516 printf("add_dynamic_cgnapt_entry: %d\n", port_num);
7517 printf("add_dynamic_cgnapt_entry key detail:0x%x, "
7518 "%d, %d\n", key->ip, key->port, key->pid);
7522 #ifdef CGNAPT_DEBUGGING
7523 p_nat->missedpktcount7++;
7530 #ifdef NAT_ONLY_CONFIG_REQ
7531 if (!nat_only_config_flag) {
7534 if (ret == 2) { //MPPC_NEW_ENTRY
7536 /* check for max_clients_per_ip */
7537 if (rte_atomic16_read
7539 [rte_jhash(&public_ip, 4, 0) %
7540 CGNAPT_MAX_PUB_IP].count) ==
7541 p_nat->max_clients_per_ip) {
7543 /* For now just bail out
7544 * In future we can think about
7545 * retrying getting a new iport
7548 release_iport(port_num, public_ip, p_nat);
7550 #ifdef CGNAPT_DEBUGGING
7551 p_nat->missedpktcount10++;
7557 rte_atomic16_inc(&all_public_ip
7558 [rte_jhash(&public_ip, 4, 0) %
7559 CGNAPT_MAX_PUB_IP].count);
7561 #ifdef CGNAPT_DBG_PRNT
7562 if ((rte_jhash(&public_ip, 4, 0) %
7563 CGNAPT_MAX_PUB_IP) == 8)
7564 printf("pub ip:%x coutn:%d\n", public_ip,
7565 rte_atomic16_read(&all_public_ip
7566 [rte_jhash(&public_ip, 4, 0) %
7567 CGNAPT_MAX_PUB_IP].count));
7571 #ifdef NAT_ONLY_CONFIG_REQ
7575 #ifdef CGNAPT_DBG_PRNT
7576 if (CGNAPT_DEBUG > 0) {
7577 printf("add_dynamic_cgnapt_entry: %d\n",
7579 printf("add_dynamic_cgnapt_entry key detail: "
7580 "0x%x, %d, %d\n", key->ip, key->port, key->pid);
7584 struct cgnapt_table_entry entry = {
7586 .action = RTE_PIPELINE_ACTION_PORT,
7587 /* made it configurable below */
7588 {.port_id = p->port_out_id[0]},
7592 .prv_port = key->port,
7593 .pub_ip = public_ip,
7594 .pub_port = port_num,
7595 .prv_phy_port = key->pid,
7596 .pub_phy_port = get_pub_to_prv_port(
7600 /* if(timeout == -1) : static entry
7601 * if(timeout == 0 ) : dynamic entry
7602 * if(timeout > 0 ) : PCP requested entry
7604 .timeout = timeout > 0 ? timeout : 0,
7611 #ifdef NAT_ONLY_CONFIG_REQ
7612 if (nat_only_config_flag) {
7613 entry.data.prv_port = 0xffff;
7614 entry.data.pub_port = 0xffff;
7618 if (pkt_type == CGNAPT_ENTRY_IPV6) {
7619 entry.data.type = CGNAPT_ENTRY_IPV6;
7620 memcpy(&entry.data.u.prv_ipv6[0], src_addr, 16);
7622 entry.data.u.prv_ip = key->ip;
7623 entry.data.type = CGNAPT_ENTRY_IPV4;
7626 //entry.head.port_id = CGNAPT_PUB_PORT_ID; /* outgoing port info */
7627 entry.head.port_id = entry.data.pub_phy_port; /* outgoing port info */
7629 struct pipeline_cgnapt_entry_key second_key;
7630 /* Need to add a second ingress entry */
7631 second_key.ip = public_ip;
7632 second_key.port = port_num;
7633 second_key.pid = 0xffff;
7635 #ifdef NAT_ONLY_CONFIG_REQ
7636 if (nat_only_config_flag)
7637 second_key.port = 0xffff;
7640 #ifdef CGNAPT_DBG_PRNT
7641 if (CGNAPT_DEBUG > 2)
7642 printf("add_dynamic_cgnapt_entry second key detail:"
7643 "0x%x, %d, %d\n", second_key.ip, second_key.port,
7647 int32_t position = rte_hash_add_key(napt_common_table, (void *)key);
7650 #ifdef CGNAPT_DEBUGGING
7651 p_nat->missedpktcount8++;
7654 printf("CG-NAPT entry add failed ...returning "
7655 "without adding ... %d\n", position);
7660 #ifdef CGNAPT_DBG_PRNT
7662 printf("add_dynamic_cgnapt_entry\n");
7664 print_cgnapt_entry(&entry);
7668 memcpy(&napt_hash_tbl_entries[position], &entry,
7669 sizeof(struct cgnapt_table_entry));
7671 /* this pointer is returned to pkt miss function */
7672 ret_ptr = &napt_hash_tbl_entries[position];
7674 p_nat->n_cgnapt_entry_added++;
7675 p_nat->dynCgnaptCount++;
7677 /* Now modify the forward port for reverse entry */
7679 /* outgoing port info */
7680 //entry.head.port_id = CGNAPT_PRV_PORT_ID;
7681 /* outgoing port info */
7682 entry.head.port_id = entry.data.prv_phy_port;
7684 int32_t position2 = rte_hash_add_key(napt_common_table, &second_key);
7686 if (position2 < 0) {
7687 #ifdef CGNAPT_DEBUGGING
7688 p_nat->missedpktcount9++;
7690 printf("CG-NAPT entry reverse bulk add failed ..."
7691 "returning with fwd add ...%d\n",
7697 memcpy(&napt_hash_tbl_entries[position2], &entry,
7698 sizeof(struct cgnapt_table_entry));
7700 entry_ptr = &napt_hash_tbl_entries[position2];
7702 timer_thread_enqueue(key, &second_key, ret_ptr,
7703 entry_ptr, (struct pipeline *)p_nat);
7705 p_nat->n_cgnapt_entry_added++;
7706 p_nat->dynCgnaptCount++;
7708 if (p_nat->pkt_burst_cnt < RTE_PORT_IN_BURST_SIZE_MAX) {
7709 memcpy(&p_nat->cgnapt_dyn_ent_table[p_nat->pkt_burst_cnt], key,
7710 sizeof(struct pipeline_cgnapt_entry_key));
7711 p_nat->cgnapt_dyn_ent_index[p_nat->pkt_burst_cnt] = position;
7712 p_nat->pkt_burst_cnt++;
7717 int pkt_miss_cgnapt_count;
7719 * Function handle a missed NAPT entry lookup
7720 * Will attempt to add a dynamic entry pair.
7723 * A pointer to struct pipeline
7725 * A pointer to struct pipeline_cgnapt_entry_key
7727 * A pointer to pkt struct rte_mbuf
7729 * uint64_t pointer to pkt mask
7730 * @param table_entry
7731 * A pointer to struct rte_pipeline_table_entry to be created and returned
7733 * number of this pkt in current burst
7736 * A uint64_t mask for drop packets
7739 pkt_miss_cgnapt(struct pipeline_cgnapt_entry_key *key,
7740 struct rte_mbuf *pkt,
7741 struct rte_pipeline_table_entry **table_entry,
7742 __rte_unused uint64_t *pkts_mask,
7743 uint32_t pkt_num, void *arg)
7746 #ifdef CGNAPT_DBG_PRNT
7747 if (CGNAPT_DEBUG > 0)
7748 printf("\n pkt_miss_cgnapt\n");
7752 * see if get_port passes for this src address
7753 * if passed add a new egress entry and a
7754 * corresponding new ingress entry
7755 * return the fwd entry to calling function using input pointer
7756 * else if get_port fails drop packet
7759 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)arg;
7761 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
7762 uint32_t src_addr_offset_ipv6 =
7763 MBUF_HDR_ROOM + ETH_HDR_SIZE + IPV6_HDR_SRC_ADR_OFST;
7764 uint16_t phy_port = pkt->port;
7766 uint16_t *eth_proto =
7767 RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
7769 uint8_t *src_addr = NULL;
7770 uint8_t src_addr_ipv6[16];
7771 uint8_t pkt_type = CGNAPT_ENTRY_IPV4;
7772 /* To drop the packet */
7773 uint64_t drop_mask = 0;
7775 if (p_nat->is_static_cgnapt) {
7776 drop_mask |= 1LLU << pkt_num;
7777 p_nat->missedPktCount++;
7779 #ifdef CGNAPT_DEBUGGING
7780 p_nat->missedpktcount1++;
7785 if (rte_be_to_cpu_16(*eth_proto) == ETHER_TYPE_IPv6) {
7787 RTE_MBUF_METADATA_UINT8_PTR(pkt, src_addr_offset_ipv6);
7788 pkt_type = CGNAPT_ENTRY_IPV6;
7789 memcpy(src_addr_ipv6, src_addr, 16);
7794 /* some validation first */
7795 if (is_phy_port_privte(phy_port)) {
7796 /* dynamic NAPT entry creation */
7797 *table_entry = (struct rte_pipeline_table_entry *)
7798 add_dynamic_cgnapt_entry(
7799 (struct pipeline *)&p_nat->p,
7801 DYNAMIC_CGNAPT_TIMEOUT,
7803 src_addr_ipv6, &err);
7805 if (!(*table_entry)) {
7807 drop_mask |= 1LLU << pkt_num;
7808 p_nat->missedPktCount++;
7810 #ifdef CGNAPT_DEBUGGING
7811 p_nat->missedpktcount2++;
7814 #ifdef CGNAPT_DBG_PRNT
7815 if (CGNAPT_DEBUG > 1)
7816 printf("Add Dynamic NAT entry failed "
7820 #ifdef CGNAPT_DEBUGGING
7821 p_nat->missedpktcount11++;
7826 } else if (!is_phy_port_privte(phy_port)) {
7828 #ifdef CGNAPT_DBG_PRNT
7829 if (CGNAPT_DEBUG >= 2) {
7830 printf("Initial Ingress entry creation NOT ALLOWED "
7835 drop_mask |= 1LLU << pkt_num;
7836 p_nat->missedPktCount++;
7838 #ifdef CGNAPT_DEBUGGING
7839 p_nat->missedpktcount3++;
7843 #ifdef CGNAPT_DBG_PRNT
7844 if (CGNAPT_DEBUG > 1)
7845 printf("NOT a PRIVATE or PUBLIC port!!!!!\n");
7848 drop_mask |= 1LLU << pkt_num;
7849 p_nat->missedPktCount++;
7851 #ifdef CGNAPT_DEBUGGING
7852 p_nat->missedpktcount4++;
7856 #ifdef CGNAPT_DBG_PRNT
7857 if (CGNAPT_DEBUG > 5)
7867 * Function to print the contents of a packet
7870 * A pointer to pkt struct rte_mbuf
7872 void print_pkt(struct rte_mbuf *pkt)
7876 printf("\nPacket Contents:\n");
7878 uint8_t *rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
7880 for (i = 0; i < 20; i++) {
7881 for (j = 0; j < 20; j++)
7882 printf("%02x ", rd[(20 * i) + j]);
7888 rte_table_hash_op_hash cgnapt_hash_func[] = {
7900 * Function to parse incoming pipeline arguments
7901 * Called during pipeline initialization
7904 * A pointer to struct pipeline_cgnapt
7906 * A pointer to struct pipeline_params
7909 * 0 if success, negative if failure
7912 pipeline_cgnapt_parse_args(struct pipeline_cgnapt *p,
7913 struct pipeline_params *params)
7915 uint32_t n_flows_present = 0;
7916 uint32_t key_offset_present = 0;
7917 uint32_t key_size_present = 0;
7918 uint32_t hash_offset_present = 0;
7919 uint32_t n_entries_present = 0;
7920 uint32_t max_port_present = 0;
7921 uint32_t max_client_present = 0;
7922 uint32_t public_ip_range_present = 0;
7923 uint32_t public_ip_port_range_present = 0;
7925 uint8_t public_ip_count = 0;
7926 uint8_t public_ip_range_count = 0;
7927 uint8_t dest_if_offset_present = 0;
7928 uint8_t cgnapt_meta_offset_present = 0;
7929 uint8_t prv_que_handler_present = 0;
7930 uint8_t n_prv_in_port = 0;
7932 if (CGNAPT_DEBUG > 2) {
7933 printf("CGNAPT pipeline_cgnapt_parse_args params->n_args: %d\n",
7936 for (i = 0; i < params->n_args; i++) {
7937 char *arg_name = params->args_name[i];
7938 char *arg_value = params->args_value[i];
7940 if (CGNAPT_DEBUG > 2) {
7941 printf("CGNAPT args[%d]: %s %d, %s\n", i, arg_name,
7942 atoi(arg_value), arg_value);
7944 if (strcmp(arg_name, "prv_que_handler") == 0) {
7946 if (prv_que_handler_present) {
7947 printf("Duplicate pktq_in_prv ..\n\n");
7950 prv_que_handler_present = 1;
7955 /* get the first token */
7956 token = strtok(arg_value, "(");
7957 token = strtok(token, ")");
7958 token = strtok(token, ",");
7959 printf("***** prv_que_handler *****\n");
7961 if (token == NULL) {
7962 printf("string is null\n");
7963 printf("invalid prv_que_handler value/n");
7966 printf("string is :%s\n", token);
7968 /* walk through other tokens */
7969 while (token != NULL) {
7970 printf(" %s\n", token);
7971 rxport = atoi(token);
7972 cgnapt_prv_que_port_index[n_prv_in_port++] =
7974 if (rxport < PIPELINE_MAX_PORT_IN)
7975 cgnapt_in_port_egress_prv[rxport] = 1;
7976 token = strtok(NULL, ",");
7979 if (n_prv_in_port == 0) {
7980 printf("VNF common parse err - "
7981 "no prv RX phy port\n");
7987 if (strcmp(arg_name, "cgnapt_meta_offset") == 0) {
7988 if (cgnapt_meta_offset_present) {
7989 printf("CG-NAPT parse error:");
7990 printf("cgnapt_meta_offset initizlized "
7991 "mulitple times\n");
7994 cgnapt_meta_offset_present = 1;
7996 temp = atoi(arg_value);
7999 printf("cgnapt_meta_offset is invalid :");
8000 printf("Not be more than metadata size\n");
8003 cgnapt_meta_offset = (uint16_t) temp;
8005 if (strcmp(arg_name, "vnf_set") == 0)
8008 if (strcmp(arg_name, "public_ip_range") == 0) {
8009 public_ip_range_present = 1;
8010 if (public_ip_port_range_present) {
8011 printf("CG-NAPT parse error:");
8012 printf("public_ip_range with "
8013 "public_ip_port_range_present\n");
8017 p->pub_ip_range = rte_realloc(p->pub_ip_range,
8020 RTE_CACHE_LINE_SIZE);
8022 if (!p->pub_ip_range) {
8023 printf("Memory allocation failed for "
8028 uint32_t sip = 0, eip = 0;
8030 if (sscanf(arg_value, "(%x,%x)", &sip, &eip) != 2) {
8031 printf("public_ip_range is invalid\n");
8035 if (sip <= 0 || eip <= 0 || sip >= eip) {
8036 printf("public_ip_range is invalid %x-%x\n",
8041 printf("public_ip_range: %d-%d\n",
8042 p->pub_ip_range[public_ip_range_count].
8044 p->pub_ip_range[public_ip_range_count].
8047 p->pub_ip_range_count = ++public_ip_range_count;
8051 if (strcmp(arg_name, "public_ip_port_range") == 0) {
8052 public_ip_port_range_present = 1;
8053 if (nat_only_config_flag || public_ip_range_present) {
8055 printf("CG-NAPT parse error:");
8056 printf("nat_only_config_flag OR ");
8057 printf("public_ip_range_present with "
8058 "public_ip_port_range_present\n");
8062 p->pub_ip_port_set = rte_realloc(
8064 sizeof(struct pub_ip_port_set),
8065 RTE_CACHE_LINE_SIZE);
8067 if (!p->pub_ip_port_set) {
8068 printf("Memory allocation failed for "
8076 if (sscanf(arg_value, "%x:(%d,%d)",
8077 &ip, &sp, &ep) != 3) {
8078 printf("Public IP or Port-range is invalid\n");
8082 if (ip <= 0 || sp <= 0 || ep <= 0 || sp > ep) {
8083 printf("Public IP or Port-range is invalid "
8084 "%x:%d-%d\n", ip, sp, ep);
8088 printf("public_ip: 0x%x Range:%d-%d\n",
8089 p->pub_ip_port_set[public_ip_count].ip = ip,
8090 p->pub_ip_port_set[public_ip_count].start_port = sp,
8091 p->pub_ip_port_set[public_ip_count].end_port = ep);
8093 napt_port_alloc_elem_count += (ep - sp + 1);
8094 printf("parse - napt_port_alloc_elem_count :%d\n",
8095 napt_port_alloc_elem_count);
8097 /* Store all public IPs of all CGNAPT threads
8098 * in the global variable
8100 /* to revisit indexing */
8101 all_public_ip[rte_jhash(&ip, 4, 0) %
8102 CGNAPT_MAX_PUB_IP].ip = ip;
8103 p->pub_ip_count = ++public_ip_count;
8104 printf("public_ip_count:%d hash:%d\n", public_ip_count,
8105 rte_jhash(&ip, 4, 0) % CGNAPT_MAX_PUB_IP);
8109 /* hw_checksum_reqd */
8110 if (strcmp(arg_name, "hw_checksum_reqd") == 0) {
8112 temp = atoi(arg_value);
8113 if ((temp != 0) && (temp != 1)) {
8114 printf("hw_checksum_reqd is invalid\n");
8117 p->hw_checksum_reqd = temp;
8121 /* nat_only_config_flag */
8122 if (strcmp(arg_name, "nat_only_config_flag") == 0) {
8123 nat_only_config_flag = 1;
8124 if (public_ip_port_range_present) {
8126 printf("CG-NAPT parse error:");
8127 printf("nat_only_config_flag with "
8128 "public_ip_port_range_present\n");
8134 /* max_port_per_client */
8135 if (strcmp(arg_name, "max_port_per_client") == 0) {
8136 if (max_port_present) {
8137 printf("CG-NAPT Parse Error: "
8138 "duplicate max_port_per_client\n");
8141 max_port_present = 1;
8144 max = atoi(arg_value);
8146 printf("max_port_per_client is invalid !!!\n");
8150 p->max_port_per_client = (uint16_t) max;
8152 if (p->max_port_per_client <= 0) {
8153 printf("max port per client is invalid\n");
8157 printf("max_port_per_client comp: %d\n",
8158 p->max_port_per_client);
8162 /* max_clients_per_ip */
8163 if (strcmp(arg_name, "max_clients_per_ip") == 0) {
8164 if (max_client_present) {
8165 printf("CG-NAPT parse Error: duplicate "
8166 "max_clients_per_ip\n");
8169 max_client_present = 1;
8171 if (nat_only_config_flag) {
8172 printf("CG-NAPT parse error:");
8173 printf("nat_only_config_flag with "
8174 "max_clients_per_ip\n");
8179 max = atoi(arg_value);
8181 printf("max_clients_per_ip is invalid !!!\n");
8185 p->max_clients_per_ip = (uint16_t) max;
8187 if (p->max_clients_per_ip <= 0) {
8188 printf("max_clients_per_ip is invalid\n");
8192 printf("max_clients_per_ip: %d\n",
8193 p->max_clients_per_ip);
8198 if (strcmp(arg_name, "n_entries") == 0) {
8199 if (n_entries_present)
8201 n_entries_present = 1;
8203 p->n_entries = atoi(arg_value);
8204 if (p->n_entries == 0)
8211 if (strcmp(arg_name, "n_flows") == 0) {
8212 if (n_flows_present)
8214 n_flows_present = 1;
8216 p->n_flows = atoi(arg_value);
8217 if (p->n_flows == 0)
8220 napt_common_table_hash_params.entries = p->n_flows;
8223 /* dest_if_offset Multiport Changes */
8224 if (strcmp(arg_name, "dest_if_offset") == 0) {
8225 if (dest_if_offset_present)
8227 //dest_if_offset_present = 1;
8229 dest_if_offset = atoi(arg_value);
8235 if (strcmp(arg_name, "key_offset") == 0) {
8236 if (key_offset_present)
8238 key_offset_present = 1;
8240 p->key_offset = atoi(arg_value);
8246 if (strcmp(arg_name, "key_size") == 0) {
8247 if (key_size_present)
8249 key_size_present = 1;
8251 p->key_size = atoi(arg_value);
8252 if ((p->key_size == 0) ||
8253 (p->key_size > PIPELINE_CGNAPT_KEY_MAX_SIZE) ||
8261 if (strcmp(arg_name, "hash_offset") == 0) {
8262 if (hash_offset_present)
8264 hash_offset_present = 1;
8266 p->hash_offset = atoi(arg_value);
8272 if (strcmp(arg_name, "pkt_type") == 0) {
8273 if (strcmp(arg_value, "ipv4") == 0) {
8274 p->traffic_type = TRAFFIC_TYPE_IPV4;
8275 printf("Traffic is set to IPv4\n");
8276 } else if (strcmp(arg_value, "ipv6") == 0) {
8277 p->traffic_type = TRAFFIC_TYPE_IPV6;
8278 printf("Traffic is set to IPv6\n");
8284 if (strcmp(arg_name, "cgnapt_debug") == 0) {
8285 CGNAPT_DEBUG = atoi(arg_value);
8290 /* any other Unknown argument return -1 */
8293 #ifdef NAT_ONLY_CONFIG_REQ
8294 if (nat_only_config_flag) {
8295 if (!public_ip_range_count) {
8296 printf("No public_ip_range %d for NAT only config.\n",
8297 public_ip_range_count);
8298 printf("Running static NAT only configuration\n");
8299 p->is_static_cgnapt = 1;
8304 if (!p->max_port_per_client)
8305 p->is_static_cgnapt = 1;
8308 /* Check that mandatory arguments are present */
8309 if ((n_flows_present == 0) ||
8310 (cgnapt_meta_offset_present == 0))
8317 * Function to initialize the pipeline
8320 * A pointer to struct pipeline_params
8322 * Void pointer - points to app params
8325 * void pointer to the pipeline, NULL 0 if failure
8327 static void *pipeline_cgnapt_init(struct pipeline_params *params, void *arg)
8328 /* (struct app_params *app) save it for use in port in handler */
8331 struct pipeline_cgnapt *p_nat;
8332 uint32_t size, i, in_ports_arg_size;
8334 /* Check input arguments */
8335 if ((params == NULL) ||
8336 (params->n_ports_in == 0) || (params->n_ports_out == 0))
8339 /* Memory allocation */
8340 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_cgnapt));
8341 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8342 p_nat = (struct pipeline_cgnapt *)p;
8343 global_pnat = p_nat;
8347 all_pipeline_cgnapt[n_cgnapt_pipeline++] = p_nat;
8349 strcpy(p->name, params->name);
8350 p->log_level = params->log_level;
8352 PLOG(p, HIGH, "CG-NAPT");
8353 /* Initialize all counters and arrays */
8355 p_nat->n_cgnapt_entry_deleted = 0;
8356 p_nat->n_cgnapt_entry_added = 0;
8357 p_nat->naptedPktCount = 0;
8358 p_nat->naptDroppedPktCount = 0;
8359 p_nat->inaptedPktCount = 0;
8360 p_nat->enaptedPktCount = 0;
8361 p_nat->receivedPktCount = 0;
8362 p_nat->missedPktCount = 0;
8363 p_nat->dynCgnaptCount = 0;
8364 p_nat->arpicmpPktCount = 0;
8366 p_nat->app_params_addr = (uint64_t) arg;
8367 for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
8368 p_nat->links_map[i] = 0xff;
8369 p_nat->outport_id[i] = 0xff;
8370 cgnapt_in_port_egress_prv[i] = 0;
8371 cgnapt_prv_que_port_index[i] = 0;
8373 p_nat->pipeline_num = 0xff;
8374 p_nat->hw_checksum_reqd = 0;
8375 p_nat->pub_ip_port_set = NULL;
8376 p_nat->pub_ip_count = 0;
8377 p_nat->traffic_type = TRAFFIC_TYPE_MIX;
8378 p_nat->vnf_set = 0xff;
8380 /* For every init it should be reset */
8381 napt_port_alloc_elem_count = 0;
8383 #ifdef CGNAPT_TIMING_INST
8384 p_nat->in_port_exit_timestamp = 0;
8385 p_nat->external_time_sum = 0;
8386 p_nat->internal_time_sum = 0;
8387 p_nat->time_measurements = 0;
8388 p_nat->max_time_mesurements = 10000;
8389 p_nat->time_measurements_on = 0;
8392 #ifdef CGNAPT_DEBUGGING
8394 p_nat->naptDebugCount = 0;
8396 p_nat->naptDroppedPktCount1 = 0;
8397 p_nat->naptDroppedPktCount2 = 0;
8398 p_nat->naptDroppedPktCount3 = 0;
8399 p_nat->naptDroppedPktCount4 = 0;
8400 p_nat->naptDroppedPktCount5 = 0;
8401 p_nat->naptDroppedPktCount6 = 0;
8403 p_nat->missedpktcount1 = 0;
8404 p_nat->missedpktcount2 = 0;
8405 p_nat->missedpktcount3 = 0;
8406 p_nat->missedpktcount4 = 0;
8407 p_nat->missedpktcount5 = 0;
8408 p_nat->missedpktcount6 = 0;
8409 p_nat->missedpktcount7 = 0;
8410 p_nat->missedpktcount8 = 0;
8411 p_nat->missedpktcount9 = 0;
8412 p_nat->missedpktcount10 = 0;
8413 p_nat->missedpktcount11 = 0;
8414 p_nat->missedpktcount12 = 0;
8416 p_nat->max_port_dec_err1 = 0;
8417 p_nat->max_port_dec_err2 = 0;
8418 p_nat->max_port_dec_err3 = 0;
8419 p_nat->max_port_dec_success = 0;
8435 static int sip_enabled;
8439 #endif /* SIP_ALG */
8441 /*struct rte_pipeline_table_entry *entries[RTE_HASH_LOOKUP_BULK_MAX];*/
8442 /* bitmap of valid packets */
8443 p_nat->valid_packets = 0;
8444 /* bitmap of invalid packets to be dropped */
8445 p_nat->invalid_packets = 0;
8447 for (i = 0; i < RTE_HASH_LOOKUP_BULK_MAX; i++)
8448 p_nat->key_ptrs[i] = &(p_nat->keys[i]);
8450 p_nat->port_alloc_ring = NULL;
8452 /* Parse arguments */
8453 if (pipeline_cgnapt_parse_args(p_nat, params))
8456 p_nat->vnf_set = vnf_set_count;
8460 struct rte_pipeline_params pipeline_params = {
8461 .name = params->name,
8462 .socket_id = params->socket_id,
8463 .offset_port_id = cgnapt_meta_offset,
8466 p->p = rte_pipeline_create(&pipeline_params);
8474 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8476 uint32_t instr_size =
8477 RTE_CACHE_LINE_ROUNDUP((sizeof(uint64_t)) *
8480 (uint64_t *) rte_zmalloc(NULL, instr_size,
8481 RTE_CACHE_LINE_SIZE);
8483 (uint64_t *) rte_zmalloc(NULL, instr_size,
8484 RTE_CACHE_LINE_SIZE);
8486 (uint32_t *) rte_zmalloc(NULL, instr_size / 2,
8487 RTE_CACHE_LINE_SIZE);
8488 if ((inst_start_time == NULL) || (inst_end_time == NULL)
8489 || (inst_diff_time == NULL)) {
8490 printf("Inst array alloc failed .... ");
8495 /* Memory allocation for in_port_h_arg */
8496 in_ports_arg_size = RTE_CACHE_LINE_ROUNDUP(
8497 (sizeof(struct pipeline_cgnapt_in_port_h_arg)) *
8498 (params->n_ports_in));
8499 struct pipeline_cgnapt_in_port_h_arg *ap =
8500 (struct pipeline_cgnapt_in_port_h_arg *)
8503 RTE_CACHE_LINE_SIZE);
8507 myApp = (struct app_params *) arg;
8510 p->n_ports_in = params->n_ports_in;
8511 for (i = 0; i < p->n_ports_in; i++) {
8512 /* passing our cgnapt pipeline in call back arg */
8514 (ap[i]).in_port_id = i;
8516 struct rte_pipeline_port_in_params port_params = {
8518 pipeline_port_in_params_get_ops(¶ms->port_in
8521 pipeline_port_in_params_convert(¶ms->port_in
8523 .f_action = cgnapt_in_port_ah_mix,
8525 .burst_size = params->port_in[i].burst_size,
8528 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8530 instrumentation_port_in_arg = &(ap[i]);
8533 if (p_nat->traffic_type == TRAFFIC_TYPE_IPV4) {
8534 /* Private in-port handler */
8535 /* Multiport changes */
8536 if (cgnapt_in_port_egress_prv[i]) {
8537 port_params.f_action =
8538 cgnapt_in_port_ah_ipv4_prv;
8539 printf("CGNAPT port %d is IPv4 Prv\n", i);
8541 port_params.f_action =
8542 cgnapt_in_port_ah_ipv4_pub;
8543 printf("CGNAPT port %d is IPv4 Pub\n", i);
8547 if (p_nat->traffic_type == TRAFFIC_TYPE_IPV6) {
8548 if (cgnapt_in_port_egress_prv[i]) {
8549 port_params.f_action =
8550 cgnapt_in_port_ah_ipv6_prv;
8551 printf("CGNAPT port %d is IPv6 Prv\n", i);
8553 port_params.f_action =
8554 cgnapt_in_port_ah_ipv6_pub;
8555 printf("CGNAPT port %d is IPv6 Pub\n", i);
8559 int status = rte_pipeline_port_in_create(p->p,
8564 rte_pipeline_free(p->p);
8572 p->n_ports_out = params->n_ports_out;
8573 for (i = 0; i < p->n_ports_out; i++) {
8574 struct rte_pipeline_port_out_params port_params = {
8575 .ops = pipeline_port_out_params_get_ops(
8576 ¶ms->port_out[i]),
8577 .arg_create = pipeline_port_out_params_convert(
8578 ¶ms->port_out[i]),
8579 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8580 .f_action = port_out_ah_cgnapt,
8587 int status = rte_pipeline_port_out_create(p->p,
8589 &p->port_out_id[i]);
8592 rte_pipeline_free(p->p);
8598 int pipeline_num = 0;
8600 ignore = sscanf(params->name, "PIPELINE%d", &pipeline_num);
8602 printf("Not able to read pipeline number\n");
8605 p_nat->pipeline_num = (uint8_t) pipeline_num;
8606 register_pipeline_Qs(p_nat->pipeline_num, p);
8607 set_link_map(p_nat->pipeline_num, p, p_nat->links_map);
8608 set_outport_id(p_nat->pipeline_num, p, p_nat->outport_id);
8614 if (napt_common_table == NULL) {
8615 if (create_napt_common_table(p_nat->n_flows)) {
8617 "CG-NAPT create_napt_common_table failed.");
8622 struct rte_pipeline_table_params table_params = {
8623 .ops = &rte_table_stub_ops,
8625 .f_action_hit = NULL,
8626 .f_action_miss = NULL,
8628 .action_data_size = 0,
8631 int status = rte_pipeline_table_create(p->p,
8636 rte_pipeline_free(p->p);
8640 struct rte_pipeline_table_entry default_entry = {
8641 .action = RTE_PIPELINE_ACTION_PORT_META
8643 struct rte_pipeline_table_entry *default_entry_ptr;
8644 status = rte_pipeline_table_default_entry_add(
8648 &default_entry_ptr);
8650 rte_pipeline_free(p->p);
8656 /* Connecting input ports to tables */
8657 for (i = 0; i < p->n_ports_in; i++) {
8658 int status = rte_pipeline_port_in_connect_to_table(p->p,
8665 rte_pipeline_free(p->p);
8671 /* Enable input ports */
8672 for (i = 0; i < p->n_ports_in; i++) {
8673 int status = rte_pipeline_port_in_enable(p->p,
8677 rte_pipeline_free(p->p);
8683 /* Check pipeline consistency */
8684 if (rte_pipeline_check(p->p) < 0) {
8685 rte_pipeline_free(p->p);
8690 /* Message queues */
8691 p->n_msgq = params->n_msgq;
8692 for (i = 0; i < p->n_msgq; i++)
8693 p->msgq_in[i] = params->msgq_in[i];
8694 for (i = 0; i < p->n_msgq; i++)
8695 p->msgq_out[i] = params->msgq_out[i];
8697 /* Message handlers */
8698 memcpy(p->handlers, handlers, sizeof(p->handlers));
8699 memcpy(p_nat->custom_handlers,
8700 custom_handlers, sizeof(p_nat->custom_handlers));
8702 if (!p_nat->is_static_cgnapt) {
8703 printf("Initializing dyn napt components ... %d\n",
8704 p_nat->pipeline_num);
8705 if (napt_port_alloc_init(p_nat) == -1) {
8706 printf("Error - napt_port_alloc_init failed - %d\n",
8707 p_nat->pipeline_num);
8712 if (max_port_per_client_hash == NULL) {
8713 rc = init_max_port_per_client(p_nat);
8715 printf("CGNAPT Error - "
8716 "init_max_port_per_client failed %d", rc);
8723 if (!icmp_pool_init) {
8725 /* create the arp_icmp mbuf rx pool */
8726 cgnapt_icmp_pktmbuf_tx_pool =
8727 rte_pktmbuf_pool_create("icmp_mbuf_tx_pool", 63, 32, 0,
8728 RTE_MBUF_DEFAULT_BUF_SIZE,
8730 if (cgnapt_icmp_pktmbuf_tx_pool == NULL) {
8731 PLOG(p, HIGH, "ICMP mbuf pool create failed.");
8736 rte_pktmbuf_alloc(cgnapt_icmp_pktmbuf_tx_pool);
8738 if (cgnapt_icmp_pkt == NULL) {
8739 printf("Failed to allocate cgnapt_icmp_pkt\n");
8746 cgnat_cnxn_tracker = rte_zmalloc(NULL, rte_ct_get_cnxn_tracker_size(),
8747 RTE_CACHE_LINE_SIZE);
8749 if (cgnat_cnxn_tracker == NULL) {
8750 printf("CGNAPT CT memory not allocated\n");
8753 rte_ct_initialize_default_timeouts(cgnat_cnxn_tracker);
8755 printf("CGNAPT CT Flows %d\n", p_nat->n_flows);
8757 ret = rte_ct_initialize_cnxn_tracker(cgnat_cnxn_tracker,
8759 "CGNAT_CT_COMMON_TABLE");
8769 if (pcp_init() == PCP_INIT_SUCCESS)
8770 printf("PCP contents are initialized successfully\n");
8772 printf("Error in initializing PCP contents\n");
8779 * Function for pipeline cleanup
8782 * A void pointer to pipeline
8787 static int pipeline_cgnapt_free(void *pipeline)
8789 struct pipeline *p = (struct pipeline *)pipeline;
8791 /* Check input arguments */
8795 /* Free resources */
8796 rte_pipeline_free(p->p);
8802 pipeline_cgnapt_track(void *pipeline, __rte_unused uint32_t port_in,
8805 struct pipeline *p = (struct pipeline *)pipeline;
8807 /* Check input arguments */
8808 if ((p == NULL) || (port_in >= p->n_ports_in) || (port_out == NULL))
8811 if (p->n_ports_in == 1) {
8820 * Function for pipeline timers
8823 * A void pointer to pipeline
8828 static int pipeline_cgnapt_timer(void *pipeline)
8830 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)pipeline;
8832 pipeline_msg_req_handle(&p_nat->p);
8834 rte_pipeline_flush(((struct pipeline *)p_nat)->p);
8840 * Function for pipeline custom handlers
8843 * A void pointer to pipeline
8845 * void pointer for incoming data
8848 * void pointer of response
8850 void *pipeline_cgnapt_msg_req_custom_handler(struct pipeline *p, void *msg)
8852 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
8853 struct pipeline_custom_msg_req *req = msg;
8854 pipeline_msg_req_handler f_handle;
8856 f_handle = (req->subtype < PIPELINE_CGNAPT_MSG_REQS) ?
8857 p_nat->custom_handlers[req->subtype] :
8858 pipeline_msg_req_invalid_handler;
8860 if (f_handle == NULL)
8861 f_handle = pipeline_msg_req_invalid_handler;
8863 return f_handle(p, req);
8867 * Function for adding NSP data
8870 * A void pointer to pipeline
8872 * void pointer for incoming data
8875 * void pointer of response
8877 void *pipeline_cgnapt_msg_req_nsp_add_handler(
8878 __rte_unused struct pipeline *p,
8881 struct pipeline_cgnapt_nsp_add_msg_req *req = msg;
8882 struct pipeline_cgnapt_nsp_add_msg_rsp *rsp = msg;
8884 struct cgnapt_nsp_node *node = NULL, *ll = nsp_ll;
8887 (req->nsp.depth == 32 || req->nsp.depth == 40
8888 || req->nsp.depth == 48 || req->nsp.depth == 56
8889 || req->nsp.depth == 64 || req->nsp.depth == 96)) {
8895 printf("be initial cond\n");
8896 if (nsp_ll == NULL) {
8897 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_nsp_node));
8898 node = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8900 printf("be 1st cond\n");
8906 memcpy(&node->nsp, &req->nsp,
8907 sizeof(struct pipeline_cgnapt_nsp_t));
8911 while (ll != NULL) {
8912 if (!memcmp(ll->nsp.prefix, req->nsp.prefix, 16)
8913 && ll->nsp.depth == req->nsp.depth) {
8914 printf("be 2st cond\n");
8922 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_nsp_node));
8923 node = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8925 printf("be 3st cond\n");
8931 memcpy(&node->nsp, &req->nsp,
8932 sizeof(struct pipeline_cgnapt_nsp_t));
8933 node->next = nsp_ll;
8940 printf("be 4st cond\n");
8945 * Function for deleting NSP data
8948 * A void pointer to pipeline
8950 * void pointer for incoming data
8953 * void pointer of response
8955 void *pipeline_cgnapt_msg_req_nsp_del_handler(
8956 __rte_unused struct pipeline *p,
8959 struct pipeline_cgnapt_nsp_del_msg_req *req = msg;
8960 struct pipeline_cgnapt_nsp_del_msg_rsp *rsp = msg;
8961 struct cgnapt_nsp_node *prev = NULL, *ll = nsp_ll;
8963 while (ll != NULL) {
8964 if (!memcmp(ll->nsp.prefix, req->nsp.prefix, 16)
8965 && ll->nsp.depth == req->nsp.depth) {
8967 prev->next = ll->next;
8990 * Function for adding NAPT entry
8993 * A void pointer to pipeline
8995 * void pointer for incoming data
8998 * void pointer of response
9000 void *pipeline_cgnapt_msg_req_entry_add_handler(struct pipeline *p, void *msg)
9002 struct pipeline_cgnapt_entry_add_msg_req *req = msg;
9003 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9004 uint8_t type = req->data.type;
9005 uint32_t src_ip = (type == CGNAPT_ENTRY_IPV4) ?
9006 req->data.u.prv_ip :
9007 rte_bswap32(req->data.u.u32_prv_ipv6[3]);
9009 uint8_t src_ipv6[16];
9011 uint32_t dest_ip = req->data.pub_ip;
9012 uint16_t src_port = req->data.prv_port;
9013 uint16_t dest_port = req->data.pub_port;
9014 uint16_t rx_port = req->data.prv_phy_port;
9015 uint32_t ttl = req->data.ttl;
9017 if (type == CGNAPT_ENTRY_IPV6)
9018 memcpy(src_ipv6, req->data.u.prv_ipv6, 16);
9020 printf("CG-NAPT addm - PrvIP %x, PrvPort %d,", src_ip, src_port);
9021 printf("PubIP %x, PubPort %d,", dest_ip, dest_port);
9023 printf("PhyPort %d, ttl %u,", rx_port, ttl);
9024 printf("entry_type %d\n", type);
9026 #ifdef NAT_ONLY_CONFIG_REQ
9027 if (nat_only_config_flag) {
9028 if (!p_nat->is_static_cgnapt) {
9031 for (i = 0; i < p_nat->pub_ip_range_count; i++) {
9032 if (((dest_ip >= p_nat->pub_ip_range[i].start_ip)
9033 && (dest_ip <= p_nat->pub_ip_range[i].end_ip))) {
9034 printf("Error - static port cannot be in Dynamic "
9036 printf("%x-%x\n", p_nat->pub_ip_range[i].start_ip,
9037 p_nat->pub_ip_range[i].end_ip);
9043 if (pipeline_cgnapt_msg_req_entry_addm_pair(p, msg,
9049 printf("pipeline_cgnapt_msg_req_entry_addm_handler\n");
9053 printf("Success - pipeline_cgnapt_msg_req_entry_addm_handler");
9054 printf("added %d rule pairs.\n", count);
9060 if (!p_nat->is_static_cgnapt) {
9063 for (i = 0; i < p_nat->pub_ip_count; i++) {
9064 /* Check port range if same Public-IP */
9065 if (dest_ip != p_nat->pub_ip_port_set[i].ip)
9067 if (((dest_port >= p_nat->pub_ip_port_set[i].start_port) &&
9068 (dest_port <= p_nat->pub_ip_port_set[i].end_port))) {
9069 printf("Error - port cannot be in Dynamic "
9070 "port range %d-%d\n",
9071 p_nat->pub_ip_port_set[i].start_port,
9072 p_nat->pub_ip_port_set[i].end_port);
9078 if (pipeline_cgnapt_msg_req_entry_addm_pair
9079 (p, msg, src_ip, src_port, dest_ip, dest_port, rx_port,
9080 ttl, type, src_ipv6)) {
9081 printf("Error - pipeline_cgnapt_msg_req_entry_add_handler\n");
9086 printf("\nSuccess - pipeline_cgnapt_msg_req_entry_add_handler "
9093 * Function for adding a NAPT entry pair
9096 * A void pointer to pipeline
9098 * void pointer for incoming data
9104 * destination ip address
9108 * Physical receive port
9110 * time to live value
9112 * type of entry IPv4 vs IPv6
9114 * uint8_t array of IPv6 address
9117 * 0 if success, negative if fails
9120 pipeline_cgnapt_msg_req_entry_addm_pair(
9121 struct pipeline *p, __rte_unused void *msg,
9122 uint32_t src_ip, uint16_t src_port,
9123 uint32_t dest_ip, uint16_t dest_port,
9124 uint16_t rx_port, uint32_t ttl,
9125 uint8_t type, uint8_t src_ipv6[16])
9128 struct pipeline_cgnapt_entry_key key;
9129 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9132 key.port = src_port;
9135 struct cgnapt_table_entry entry = {
9137 .action = RTE_PIPELINE_ACTION_PORT,
9138 .port_id = CGNAPT_PUB_PORT_ID,
9142 /*.prv_ip = src_ip, */
9143 .prv_port = src_port,
9145 .pub_port = dest_port,
9146 .prv_phy_port = rx_port,
9147 .pub_phy_port = get_prv_to_pub_port(&dest_ip,
9150 .timeout = STATIC_CGNAPT_TIMEOUT,
9157 if (type == CGNAPT_ENTRY_IPV4) {
9158 entry.data.type = CGNAPT_ENTRY_IPV4;
9159 entry.data.u.prv_ip = src_ip;
9161 entry.data.type = CGNAPT_ENTRY_IPV6;
9162 memcpy(entry.data.u.prv_ipv6, src_ipv6, 16);
9165 /* Also need to add a paired entry on our own */
9167 * Need to change key
9168 * Need to change entry header
9169 * Will keep the same entry and take care
9170 * of translation in table hit handler
9172 struct pipeline_cgnapt_entry_key second_key;
9174 /* Need to add a second ingress entry */
9175 second_key.ip = dest_ip;
9176 second_key.port = dest_port;
9177 second_key.pid = 0xffff;
9179 #ifdef NAT_ONLY_CONFIG_REQ
9180 if (nat_only_config_flag) {
9182 entry.data.pub_port = 0xffff;
9183 second_key.port = 0xffff;
9187 //if (CGNAPT_DEBUG > 2)
9188 //printf("key.ip %x, key.port %d", key.ip, key.port);
9189 //printf("key.pid %d, in_type %d,", key.pid, type);
9190 //printf("entry_type %d\n", entry.data.type);
9192 int32_t position = rte_hash_add_key(napt_common_table, &key);
9195 printf("CG-NAPT entry bulk add failed");
9196 printf(" ... returning without adding ...\n");
9200 memcpy(&napt_hash_tbl_entries[position], &entry,
9201 sizeof(struct cgnapt_table_entry));
9203 #ifdef CGNAPT_DEBUGGING
9204 if (p_nat->kpc1++ < 5)
9208 p_nat->n_cgnapt_entry_added++;
9210 /* Now modify the forward port for reverse entry */
9211 entry.head.port_id = CGNAPT_PRV_PORT_ID;
9213 position = rte_hash_add_key(napt_common_table, &second_key);
9216 printf("CG-NAPT entry reverse bulk add failed");
9217 printf(" ... returning with fwd add ...%d\n", position);
9221 memcpy(&napt_hash_tbl_entries[position], &entry,
9222 sizeof(struct cgnapt_table_entry));
9224 #ifdef CGNAPT_DEBUGGING
9225 if (p_nat->kpc1 < 5)
9226 print_key(&second_key);
9229 p_nat->n_cgnapt_entry_added++;
9234 * Function for adding multiple NAPT entries
9237 * A void pointer to pipeline
9239 * void pointer for incoming data
9242 * void pointer of response
9244 void *pipeline_cgnapt_msg_req_entry_addm_handler(struct pipeline *p, void *msg)
9246 struct pipeline_cgnapt_entry_addm_msg_req *req = msg;
9247 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9249 uint32_t max_ue = req->data.num_ue;
9250 uint8_t type = req->data.type;
9251 uint32_t src_ip = (type == CGNAPT_ENTRY_IPV4) ?
9252 req->data.u.prv_ip :
9253 rte_bswap32(req->data.u.u32_prv_ipv6[3]);
9255 uint8_t src_ipv6[16];
9257 uint32_t dest_ip = req->data.pub_ip;
9258 uint16_t src_port = req->data.prv_port;
9259 uint16_t dest_port = req->data.pub_port;
9260 uint16_t rx_port = req->data.prv_phy_port;
9261 uint32_t ttl = req->data.ttl;
9262 uint16_t max_src_port = req->data.prv_port_max;
9263 uint16_t max_dest_port = req->data.pub_port_max;
9265 uint16_t src_port_start = src_port;
9266 uint16_t dest_port_start = dest_port;
9267 uint32_t src_ip_temp;
9269 if (type == CGNAPT_ENTRY_IPV6)
9270 memcpy(src_ipv6, req->data.u.prv_ipv6, 16);
9272 printf("CG-NAPT addm - PrvIP %x, PrvPort %d,", src_ip, src_port);
9273 printf("PubIP %x, PubPort %d,", dest_ip, dest_port);
9274 printf("PhyPort %d, ttl %u, NumUe %d,", rx_port, ttl, max_ue);
9275 printf("mPrvPort %d, mPubPort %d,", max_src_port, max_dest_port);
9276 printf("entry_type %d\n", type);
9278 #ifdef NAT_ONLY_CONFIG_REQ
9279 if (nat_only_config_flag) {
9280 if (!p_nat->is_static_cgnapt) {
9283 for (i = 0; i < p_nat->pub_ip_range_count; i++) {
9284 if (((dest_ip >= p_nat->pub_ip_range[i].start_ip)
9285 && (dest_ip <= p_nat->pub_ip_range[i].end_ip)) ||
9286 (((dest_ip + max_ue) >=
9287 p_nat->pub_ip_range[i].start_ip) &&
9288 ((dest_ip + max_ue) <=
9289 p_nat->pub_ip_range[i].end_ip))) {
9290 printf("Error - static port cannot be in Dynamic "
9292 printf("%x-%x\n", p_nat->pub_ip_range[i].start_ip,
9293 p_nat->pub_ip_range[i].end_ip);
9300 for (uenum = 0; uenum < max_ue; uenum++) {
9302 if (pipeline_cgnapt_msg_req_entry_addm_pair(p, msg,
9308 printf("pipeline_cgnapt_msg_req_entry_addm_handler\n");
9318 printf("Success - pipeline_cgnapt_msg_req_entry_addm_handler");
9319 printf("added %d rule pairs.\n", count);
9325 if (!p_nat->is_static_cgnapt) {
9328 for (i = 0; i < p_nat->pub_ip_count; i++) {
9329 /* Check port range if same Public-IP */
9330 if (dest_ip != p_nat->pub_ip_port_set[i].ip)
9332 if (((dest_port >= p_nat->pub_ip_port_set[i].start_port) &&
9333 (dest_port <= p_nat->pub_ip_port_set[i].end_port)) ||
9334 ((max_dest_port >= p_nat->pub_ip_port_set[i].start_port)
9335 && max_dest_port <= p_nat->pub_ip_port_set[i].end_port)) {
9336 printf("Error - port cannot be in Dynamic port range %d-%d\n",
9337 p_nat->pub_ip_port_set[i].start_port,
9338 p_nat->pub_ip_port_set[i].end_port);
9344 for (uenum = 0; uenum < max_ue; uenum++) {
9345 if (pipeline_cgnapt_msg_req_entry_addm_pair
9346 (p, msg, src_ip, src_port, dest_ip, dest_port, rx_port,
9347 ttl, type, src_ipv6)) {
9348 printf("Error - pipeline_cgnapt_msg_req_entry_addm_handler\n");
9355 if (src_port > max_src_port) {
9356 src_port = src_port_start;
9358 if (req->data.type == CGNAPT_ENTRY_IPV6) {
9359 src_ip_temp = rte_bswap32(src_ip);
9360 memcpy(&src_ipv6[12], &src_ip_temp, 4);
9364 if (dest_port > max_dest_port) {
9365 dest_port = dest_port_start;
9370 printf("\nSuccess - pipeline_cgnapt_msg_req_entry_addm_handler added");
9371 printf("%d rule pairs.\n", count);
9377 * Function for deleting NAPT entry
9380 * A void pointer to pipeline
9382 * void pointer for incoming data
9385 * void pointer of response
9387 void *pipeline_cgnapt_msg_req_entry_del_handler(struct pipeline *p, void *msg)
9389 struct pipeline_cgnapt_entry_delete_msg_req *req = msg;
9390 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9391 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9394 uint8_t *KeyP = (void *)(&req->key);
9397 printf("pipeline_cgnapt_msg_req_entry_del_handler - Key: ");
9398 for (i = 0; i < (int)sizeof(struct pipeline_cgnapt_entry_key);
9400 printf(" %02x", KeyP[i]);
9401 printf(" ,KeySize %u\n",
9402 (int)sizeof(struct pipeline_cgnapt_entry_key));
9405 struct cgnapt_table_entry entry;
9407 /* If ingress key */
9408 if (!is_phy_port_privte(req->key.pid))
9409 req->key.pid = 0xffff;
9411 #ifdef NAT_ONLY_CONFIG_REQ
9412 if (nat_only_config_flag)
9413 req->key.port = 0xffff;
9417 position = rte_hash_lookup(napt_common_table, &req->key);
9418 if (position == -ENOENT) {
9419 printf("Entry not found\n");
9422 memcpy(&entry, &napt_hash_tbl_entries[position],
9423 sizeof(struct cgnapt_table_entry));
9424 position = rte_hash_del_key(napt_common_table, &req->key);
9425 p_nat->n_cgnapt_entry_deleted++;
9427 struct pipeline_cgnapt_entry_key second_key;
9429 if (is_phy_port_privte(req->key.pid)) {
9430 /* key is for egress - make second key for ingress */
9431 second_key.ip = entry.data.pub_ip;
9432 second_key.port = entry.data.pub_port;
9433 second_key.pid = 0xffff;
9436 /* key is for ingress - make second key for egress */
9437 second_key.ip = entry.data.u.prv_ip;
9438 second_key.port = entry.data.prv_port;
9439 second_key.pid = entry.data.prv_phy_port;
9442 #ifdef NAT_ONLY_CONFIG_REQ
9443 if (nat_only_config_flag)
9444 second_key.port = 0xffff;
9447 position = rte_hash_del_key(napt_common_table, &second_key);
9448 p_nat->n_cgnapt_entry_deleted++;
9453 void *pipeline_cgnapt_msg_req_entry_sync_handler(struct pipeline *p, void *msg)
9455 struct pipeline_cgnapt_entry_delete_msg_req *req = msg;
9456 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9458 rsp->status = rte_pipeline_table_entry_delete(
9462 &rsp->key_found, NULL);
9468 * Function to print the NAPT key
9471 * A pointer to struct pipeline_cgnapt_entry_key
9473 void print_key(struct pipeline_cgnapt_entry_key *key)
9475 uint8_t *KeyP = (void *)(key);
9479 for (i = 0; i < (int)sizeof(struct pipeline_cgnapt_entry_key); i++)
9480 printf(" %02x", KeyP[i]);
9484 * Function to print the table entry
9487 * A pointer to struct rte_pipeline_table_entry
9489 void print_entry1(struct rte_pipeline_table_entry *entry)
9491 uint8_t *entryP = (void *)(entry);
9495 for (i = 0; i < (int)sizeof(struct rte_pipeline_table_entry); i++)
9496 printf(" %02x", entryP[i]);
9500 * Function to print the NAPT table entry
9503 * A pointer to struct cgnapt_table_entry
9505 void print_cgnapt_entry(struct cgnapt_table_entry *entry)
9507 uint8_t *entryP = (void *)(entry);
9510 printf("CGNAPT Entry: ");
9511 for (i = 0; i < (int)sizeof(struct cgnapt_table_entry); i++)
9512 printf(" %02x", entryP[i]);
9513 printf(" size:%d\n", (int)sizeof(struct cgnapt_table_entry));
9517 * Function to get a free port
9520 * A pointer to struct pipeline_cgnapt
9522 * A uint32_t pointer to return corresponding ip address
9525 * free port number, 0 if error
9527 int get_free_iport(struct pipeline_cgnapt *p_nat, uint32_t *public_ip)
9530 /* If we don't have a valid napt_port_alloc_elem get one from
9533 if (p_nat->allocated_ports == NULL) {
9537 ret = rte_ring_dequeue(p_nat->port_alloc_ring, &ports);
9539 p_nat->allocated_ports =
9540 (struct napt_port_alloc_elem *)ports;
9542 #ifdef CGNAPT_DEBUGGING
9546 #ifdef CGNAPT_DBG_PRNT
9547 if (CGNAPT_DEBUG > 3)
9548 printf("p_nat->allocated_ports %p\n",
9549 p_nat->allocated_ports);
9552 printf("CGNAPT Err - get_free_iport rte_ring_dequeue "
9554 printf("%d, %d, %d\n", rte_ring_count(
9555 p_nat->port_alloc_ring), rte_ring_free_count(
9556 p_nat->port_alloc_ring), ret);
9558 #ifdef CGNAPT_DEBUGGING
9559 #ifdef CGNAPT_DBG_PRNT
9560 printf("Th%d GFP:: %" PRIu64 ", %" PRIu64 ", "
9561 "%" PRIu64", %" PRIu64 ",\n", p_nat->pipeline_num,
9562 p_nat->gfp_get, p_nat->gfp_ret, p_nat->gfp_suc,
9572 /* get the port from index count-1 and decrease count */
9573 port = p_nat->allocated_ports->ports
9574 [p_nat->allocated_ports->count - 1];
9575 *public_ip = p_nat->allocated_ports->ip_addr
9576 [p_nat->allocated_ports->count - 1];
9578 p_nat->allocated_ports->count -= 1;
9580 /* if count is zero, return buffer to mem pool */
9581 if (p_nat->allocated_ports->count == 0) {
9582 rte_mempool_put(napt_port_pool, p_nat->allocated_ports);
9584 #ifdef CGNAPT_DEBUGGING
9586 #ifdef CGNAPT_DBG_PRNT
9587 printf("Th%d Returned to pool p_nat->allocated_ports %p,",
9588 p_nat->pipeline_num, p_nat->allocated_ports);
9589 printf("%" PRIu64 ", %" PRIu64 ",",
9590 p_nat->gfp_get, p_nat->gfp_ret);
9591 printf("%" PRIu64 ", %" PRIu64 ",\n",
9592 p_nat->gfp_suc, p_nat->gfp_err);
9596 p_nat->allocated_ports = NULL;
9599 #ifdef CGNAPT_DEBUGGING
9607 * Function to free a port
9610 * Port number to free
9612 * Corresponding ip address
9614 * A pointer to struct pipeline_cgnapt
9617 void release_iport(uint16_t port_num, uint32_t public_ip,
9618 struct pipeline_cgnapt *p_nat)
9620 /* If we don't have a valid napt_port_alloc_elem get one
9623 if (p_nat->free_ports == NULL) {
9626 #ifdef CGNAPT_DEBUGGING
9630 if (rte_mempool_get(napt_port_pool, &ports) < 0) {
9631 #ifdef CGNAPT_DEBUGGING
9634 printf("CGNAPT release_iport error in getting "
9635 "port alloc buffer\n");
9639 p_nat->free_ports = (struct napt_port_alloc_elem *)ports;
9640 p_nat->free_ports->count = 0;
9643 /* put the port at index count and increase count */
9644 p_nat->free_ports->ip_addr[p_nat->free_ports->count] = public_ip;
9645 p_nat->free_ports->ports[p_nat->free_ports->count] = port_num;
9646 p_nat->free_ports->count += 1;
9648 /* if napt_port_alloc_elem is full add it to ring */
9651 #ifdef CGNAPT_DEBUGGING
9655 #ifdef CGNAPT_DBG_PRNT
9656 if (CGNAPT_DEBUG >= 2) {
9657 printf("CGNAPT port_alloc_ring before EnQ Cnt %d, Free %d\n",
9658 rte_ring_count(p_nat->port_alloc_ring),
9659 rte_ring_free_count(p_nat->port_alloc_ring));
9663 if (rte_ring_enqueue(p_nat->port_alloc_ring,
9664 (void *)p_nat->free_ports) != 0) {
9665 printf("CGNAPT release_iport Enqueue error %p\n",
9668 #ifdef CGNAPT_DEBUGGING
9673 #ifdef CGNAPT_DBG_PRNT
9674 if (CGNAPT_DEBUG >= 2) {
9675 printf("CGNAPT port_alloc_ring after EnQ Cnt %d",
9676 rte_ring_count(p_nat->port_alloc_ring));
9678 rte_ring_free_count(p_nat->port_alloc_ring));
9682 p_nat->free_ports = NULL;
9685 #ifdef CGNAPT_DEBUGGING
9691 * Function to initialize max ports per client data structures
9692 * Called during dynamic NAPT initialization.
9695 * A pointer to struct pipeline_cgnapt
9698 * 0 if success, negative if error
9700 int init_max_port_per_client(
9701 __rte_unused struct pipeline_cgnapt *p_nat)
9703 if (max_port_per_client_hash)
9706 /*MPPC_ALREADY_EXISTS */
9710 max_port_per_client_hash =
9711 rte_hash_create(&max_port_per_client_hash_params);
9712 if (!max_port_per_client_hash)
9715 /*MPPC_HASH_CREATE_ERROR */
9717 max_port_per_client_array =
9719 sizeof(struct max_port_per_client) * MAX_DYN_ENTRY,
9720 RTE_CACHE_LINE_SIZE);
9721 if (!max_port_per_client_array)
9724 /*MPPC_ARRAY_CREATE_ERROR */
9726 for (i = 0; i < MAX_DYN_ENTRY; i++) {
9727 max_port_per_client_array[i].prv_ip = 0;
9728 max_port_per_client_array[i].prv_phy_port = 0;
9729 max_port_per_client_array[i].max_port_cnt = 0;
9737 * Function to check if max ports for a client is reached
9739 * @param prv_ip_param
9740 * A uint32_t ip address of client
9741 * @param prv_phy_port_param
9742 * A uint32_t physical port id of the client
9744 * A pointer to struct pipeline_cgnapt
9747 * 0 if max port not reached, 1 if reached, -1 if error
9749 int is_max_port_per_client_reached(uint32_t prv_ip_param,
9750 uint32_t prv_phy_port_param,
9751 struct pipeline_cgnapt *p_nat)
9753 int index = MAX_PORT_INVALID_KEY;
9755 struct max_port_per_client_key key = {
9756 .prv_ip = prv_ip_param,
9757 .prv_phy_port = prv_phy_port_param,
9760 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9763 return MAX_PORT_INVALID_KEY;
9765 if (max_port_per_client_array[index].max_port_cnt >=
9766 p_nat->max_port_per_client)
9767 return MAX_PORT_REACHED;
9769 return MAX_PORT_NOT_REACHED;
9773 * Function to increase max ports for a client
9775 * @param prv_ip_param
9776 * A uint32_t ip address of client
9777 * @param prv_phy_port_param
9778 * A uint32_t physical port id of the client
9780 * A pointer to struct pipeline_cgnapt
9783 * 0 if max port reached, 1 if success, 2 if new entry, -1 if error
9785 int increment_max_port_counter(uint32_t prv_ip_param,
9786 uint32_t prv_phy_port_param,
9787 struct pipeline_cgnapt *p_nat)
9789 int index = MAX_PORT_INC_ERROR;
9791 struct max_port_per_client_key key = {
9792 .prv_ip = prv_ip_param,
9793 .prv_phy_port = prv_phy_port_param,
9796 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9798 if (index == -EINVAL)
9799 return MAX_PORT_INC_ERROR;
9801 if (index == -ENOENT) {
9802 if (max_port_per_client_add_entry(prv_ip_param,
9805 return MAX_PORT_INC_ERROR;
9807 return 2; /*return MAX_PORT_NEW_ENTRY; */
9810 if (CGNAPT_DEBUG > 2)
9811 printf("%s: max_port_cnt(%d), p_nat_max(%d)\n", __func__,
9812 max_port_per_client_array[index].max_port_cnt,
9813 p_nat->max_port_per_client);
9815 if (max_port_per_client_array[index].max_port_cnt <
9816 p_nat->max_port_per_client) {
9817 max_port_per_client_array[index].max_port_cnt++;
9818 return MAX_PORT_INC_SUCCESS;
9821 return MAX_PORT_INC_REACHED;
9825 * Function to decrease max ports for a client
9827 * @param prv_ip_param
9828 * A uint32_t ip address of client
9829 * @param prv_phy_port_param
9830 * A uint32_t physical port id of the client
9832 * A pointer to struct pipeline_cgnapt
9835 * 0 if count already 0, 1 if success, -1 if error
9837 int decrement_max_port_counter(uint32_t prv_ip_param,
9838 uint32_t prv_phy_port_param,
9839 struct pipeline_cgnapt *p_nat)
9841 int index = MAX_PORT_DEC_ERROR;
9843 struct max_port_per_client_key key = {
9844 .prv_ip = prv_ip_param,
9845 .prv_phy_port = prv_phy_port_param,
9848 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9851 #ifdef CGNAPT_DEBUGGING
9852 p_nat->max_port_dec_err1++;
9854 return MAX_PORT_DEC_ERROR;
9858 if (max_port_per_client_array[index].max_port_cnt > 0) {
9859 /* If it is the last port,ret this info which is used for
9860 * max_cli_per_pub_ip
9863 max_port_per_client_array[index].max_port_cnt--;
9864 /* Count should be atomic but we are good as we have only
9865 * one task handling this counter at a time (core affinity)
9869 if (max_port_per_client_array[index].max_port_cnt <= 0) {
9870 if (max_port_per_client_del_entry
9871 (prv_ip_param, prv_phy_port_param, p_nat) <= 0) {
9873 #ifdef CGNAPT_DEBUGGING
9874 p_nat->max_port_dec_err2++;
9876 return MAX_PORT_DEC_ERROR;
9879 #ifdef CGNAPT_DEBUGGING
9880 p_nat->max_port_dec_err3++;
9883 return MAX_PORT_DEC_REACHED;
9886 #ifdef CGNAPT_DEBUGGING
9887 p_nat->max_port_dec_success++;
9890 return MAX_PORT_DEC_SUCCESS;
9894 * Function to add a max ports per client entry
9896 * @param prv_ip_param
9897 * A uint32_t ip address of client
9898 * @param prv_phy_port_param
9899 * A uint32_t physical port id of the client
9901 * A pointer to struct pipeline_cgnapt
9904 * 0 no success, 1 if success, -1 if error
9906 int max_port_per_client_add_entry(
9907 uint32_t prv_ip_param,
9908 uint32_t prv_phy_port_param,
9909 __rte_unused struct pipeline_cgnapt *p_nat)
9911 int index = MAX_PORT_ADD_ERROR;
9913 struct max_port_per_client_key key = {
9914 .prv_ip = prv_ip_param,
9915 .prv_phy_port = prv_phy_port_param,
9918 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9919 if (index == -EINVAL)
9920 return MAX_PORT_ADD_ERROR;
9923 return MAX_PORT_ADD_UNSUCCESS;
9925 if (index == -ENOENT) {
9927 #ifdef CGNAPT_DBG_PRNT
9928 if (CGNAPT_DEBUG > 2)
9929 printf("max_port_per_client_add_entry fn: "
9930 "Entry does not exist\n");
9934 rte_hash_add_key(max_port_per_client_hash,
9935 (const void *)&key);
9936 if (index == -ENOSPC)
9937 return MAX_PORT_ADD_UNSUCCESS;
9939 #ifdef CGNAPT_DBG_PRNT
9940 if (CGNAPT_DEBUG > 2)
9941 printf("max_port_per_client_add_entry fn:"
9942 "Add entry index(%d)\n", index);
9945 max_port_per_client_array[index].prv_ip = prv_ip_param;
9946 max_port_per_client_array[index].prv_phy_port =
9950 max_port_per_client_array[index].max_port_cnt++;
9951 return MAX_PORT_ADD_SUCCESS;
9955 * Function to delete a max ports per client entry
9957 * @param prv_ip_param
9958 * A uint32_t ip address of client
9959 * @param prv_phy_port_param
9960 * A uint32_t physical port id of the client
9962 * A pointer to struct pipeline_cgnapt
9965 * 0 no success, 1 if success, -1 if error
9967 int max_port_per_client_del_entry(
9968 uint32_t prv_ip_param,
9969 uint32_t prv_phy_port_param,
9970 __rte_unused struct pipeline_cgnapt *p_nat)
9972 int index = MAX_PORT_DEL_ERROR;
9974 struct max_port_per_client_key key = {
9975 .prv_ip = prv_ip_param,
9976 .prv_phy_port = prv_phy_port_param,
9979 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9981 if (index == -EINVAL)
9982 return MAX_PORT_DEL_ERROR;
9984 if (index == -ENOENT)
9985 return MAX_PORT_DEL_UNSUCCESS;
9987 index = rte_hash_del_key(max_port_per_client_hash, (const void *)&key);
9988 max_port_per_client_array[index].prv_ip = 0;
9989 max_port_per_client_array[index].prv_phy_port = 0;
9990 max_port_per_client_array[index].max_port_cnt = 0;
9992 return MAX_PORT_DEL_SUCCESS;
9996 * Function to execute debug commands
9999 * A pointer to struct pipeline
10001 * void pointer to incoming arguments
10003 void *pipeline_cgnapt_msg_req_entry_dbg_handler(struct pipeline *p, void *msg)
10005 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
10006 uint8_t *Msg = msg;
10007 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
10011 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_STATS_SHOW) {
10012 printf("\nCG-NAPT Packet Stats:\n");
10013 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10014 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10015 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10016 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10017 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10018 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10019 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10021 #ifdef CGNAPT_DEBUGGING
10022 printf("\n Drop detail 1:%" PRIu64 ",",
10023 p_nat->naptDroppedPktCount1);
10024 printf("\n Drop detail 2:%" PRIu64 ",",
10025 p_nat->naptDroppedPktCount2);
10026 printf("\n Drop detail 3:%" PRIu64 ",",
10027 p_nat->naptDroppedPktCount3);
10028 printf("\n Drop detail 4:%" PRIu64 ",",
10029 p_nat->naptDroppedPktCount4);
10030 printf("\n Drop detail 5:%" PRIu64 ",",
10031 p_nat->naptDroppedPktCount5);
10032 printf("\n Drop detail 6:%" PRIu64 "",
10033 p_nat->naptDroppedPktCount6);
10035 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10036 p_nat->missedpktcount1,
10037 p_nat->missedpktcount2);
10038 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10039 p_nat->missedpktcount3,
10040 p_nat->missedpktcount4);
10041 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10042 p_nat->missedpktcount5,
10043 p_nat->missedpktcount6);
10044 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10045 p_nat->missedpktcount7,
10046 p_nat->missedpktcount8);
10047 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10048 p_nat->missedpktcount9,
10049 p_nat->missedpktcount10);
10056 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_STATS_CLEAR) {
10057 printf("\nCG-NAPT Packet Stats:\n");
10058 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10059 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10060 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10061 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10062 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10063 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10064 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10066 p_nat->naptedPktCount = 0;
10067 p_nat->naptDroppedPktCount = 0;
10068 p_nat->inaptedPktCount = 0;
10069 p_nat->enaptedPktCount = 0;
10070 p_nat->receivedPktCount = 0;
10071 p_nat->missedPktCount = 0;
10072 p_nat->arpicmpPktCount = 0;
10073 printf("CG-NAPT Packet Stats cleared\n");
10077 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DBG_LEVEL) {
10078 CGNAPT_DEBUG = Msg[CGNAPT_DBG_CMD_OFST + 1];
10079 printf("CG-NAPT debug level set to %d\n", CGNAPT_DEBUG);
10083 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DBG_SHOW) {
10085 printf("\nNAPT entries - added %" PRIu64 ",",
10086 p_nat->n_cgnapt_entry_added);
10087 printf("deleted %" PRIu64 ",", p_nat->n_cgnapt_entry_deleted);
10088 printf("current %" PRIu64 "", p_nat->n_cgnapt_entry_added -
10089 p_nat->n_cgnapt_entry_deleted);
10091 printf("\nCG-NAPT Packet Stats:\n");
10092 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10093 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10094 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10095 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10096 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10097 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10098 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10102 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
10103 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_INSTRUMENTATION) {
10104 if (Msg[CGNAPT_DBG_CMD_OFST1] ==
10105 CGNAPT_CMD_INSTRUMENTATION_SUB0) {
10108 uint32_t diff_sum = 0;
10110 printf("CG-NAPT Instrumentation ...\n");
10111 printf("Instrumentation data collected for fn# %d\n",
10112 cgnapt_num_func_to_inst);
10113 printf("Current collection index %d\n",
10114 cgnapt_inst_index);
10116 if (Msg[CGNAPT_DBG_CMD_OFST + 2] == 2) {
10117 printf("Timer Start:\n");
10119 for (index = 0; index < INST_ARRAY_SIZE; index++) {
10120 if ((index % 5) == 0)
10122 printf(" 0x%jx", inst_start_time[index]);
10124 printf("\n\nTimer End:\n");
10126 for (index = 0; index < INST_ARRAY_SIZE; index++) {
10127 if ((index % 5) == 0)
10129 printf(" 0x%jx", inst_end_time[index]);
10133 for (index = 0; index < INST_ARRAY_SIZE; index++) {
10134 inst_diff_time[index] = (uint32_t) (inst_end_time[index] -
10135 inst_start_time[index]);
10138 if (Msg[CGNAPT_DBG_CMD_OFST + 2] ==
10139 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
10140 printf("\n\nTimer Diff:\n");
10142 for (index = 0; index < INST_ARRAY_SIZE; index++) {
10143 if (Msg[CGNAPT_DBG_CMD_OFST + 2] ==
10144 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
10145 if ((index % 5) == 0)
10147 printf(" 0x%08x", inst_diff_time[index]);
10150 diff_sum += inst_diff_time[index];
10153 printf("\ndiff_sum %u, INST_ARRAY_SIZE %d, Ave Time %u\n",
10154 diff_sum, INST_ARRAY_SIZE, (diff_sum / INST_ARRAY_SIZE));
10155 } else if (Msg[CGNAPT_DBG_CMD_OFST + 1] ==
10156 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
10157 /* p plid entry dbg 7 1 0
10158 * p plid entry dbg 7 1 1 <--- pkt_work_cgnapt
10159 * p plid entry dbg 7 1 2 <--- pkt4_work_cgnapt
10160 * p plid entry dbg 7 1 3 <--- pkt_work_cgnapt_key
10161 * p plid entry dbg 7 1 4 <--- pkt4_work_cgnapt_key
10162 * p plid entry dbg 7 1 5 <--- in port ah to out port ah
10163 * - pkt life in the system
10164 * p plid entry dbg 7 1 6 <--- how long this instrumentation
10167 cgnapt_inst_index = 0;
10168 cgnapt_num_func_to_inst = Msg[CGNAPT_DBG_CMD_OFST + 2];
10169 printf("Instrumentation data collection started for fn# %d\n",
10170 cgnapt_num_func_to_inst);
10171 } else if (Msg[CGNAPT_DBG_CMD_OFST + 1] ==
10172 CGNAPT_CMD_INSTRUMENTATION_SUB2) {
10173 /* p plid entry dbg 7 2 0
10174 * Test all major functions by calling them multiple times
10175 * pkt_work_cgnapt, pkt4_work_cgnapt, pkt_work_cgnapt_key,
10176 * pkt4_work_cgnapt_key
10178 if (cgnapt_test_pktmbuf_pool == NULL) {
10179 cgnapt_test_pktmbuf_pool = rte_pktmbuf_pool_create(
10180 "cgnapt_test_pktmbuf_pool", 63, 32, 0,
10181 RTE_MBUF_DEFAULT_BUF_SIZE,
10185 if (cgnapt_test_pktmbuf_pool == NULL)
10186 printf("CGNAPT test mbuf pool create failed.\n");
10188 struct rte_mbuf *cgnapt_test_pkt0 =
10189 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
10190 if (cgnapt_test_pkt0 == NULL)
10191 printf("CGNAPT test pkt 0 alloc failed.");
10192 struct rte_mbuf *cgnapt_test_pkt1 =
10193 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
10194 if (cgnapt_test_pkt1 == NULL)
10195 printf("CGNAPT test pkt 1 alloc failed.");
10196 struct rte_mbuf *cgnapt_test_pkt2 =
10197 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
10198 if (cgnapt_test_pkt2 == NULL)
10199 printf("CGNAPT test pkt 2 alloc failed.");
10200 struct rte_mbuf *cgnapt_test_pkt3 =
10201 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
10202 if (cgnapt_test_pkt3 == NULL)
10203 printf("CGNAPT test pkt 3 alloc failed.");
10205 struct rte_mbuf *cgnapt_test_pkts[4];
10207 cgnapt_test_pkts[0] = cgnapt_test_pkt0;
10208 cgnapt_test_pkts[1] = cgnapt_test_pkt1;
10209 cgnapt_test_pkts[2] = cgnapt_test_pkt2;
10210 cgnapt_test_pkts[3] = cgnapt_test_pkt3;
10212 uint32_t src_addr_offset =
10213 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_SRC_ADR_OFST;
10214 /* header room + eth hdr size +
10215 * src_aadr offset in ip header
10217 uint32_t dst_addr_offset =
10218 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
10219 /* header room + eth hdr size +
10220 * dst_aadr offset in ip header
10222 uint32_t prot_offset =
10223 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_PROTOCOL_OFST;
10224 /* header room + eth hdr size +
10225 * srprotocol char offset in ip header
10227 int pktCnt = 0, entCnt = 0, exCnt = 0;
10229 for (pktCnt = 0; pktCnt < 4; pktCnt++) {
10230 uint32_t *src_addr =
10231 RTE_MBUF_METADATA_UINT32_PTR
10232 (cgnapt_test_pkts[pktCnt], src_addr_offset);
10233 uint32_t *dst_addr =
10234 RTE_MBUF_METADATA_UINT32_PTR
10235 (cgnapt_test_pkts[pktCnt], dst_addr_offset);
10236 uint8_t *protocol =
10237 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10240 uint8_t *phy_port =
10241 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10243 uint8_t *eth_dest =
10244 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10248 RTE_MBUF_METADATA_UINT8_PTR(
10249 cgnapt_test_pkts[pktCnt],
10252 uint16_t *src_port =
10253 RTE_MBUF_METADATA_UINT16_PTR
10254 (cgnapt_test_pkts[pktCnt],
10255 MBUF_HDR_ROOM + ETH_HDR_SIZE +
10257 uint16_t *dst_port =
10258 RTE_MBUF_METADATA_UINT16_PTR
10259 (cgnapt_test_pkts[pktCnt],
10260 MBUF_HDR_ROOM + ETH_HDR_SIZE +
10262 *src_addr = 0xc0a80001;
10263 *dst_addr = 0x90418634;
10274 eth_dest[0] = 0x90;
10275 eth_dest[1] = 0xE2;
10276 eth_dest[2] = 0xba;
10277 eth_dest[3] = 0x54;
10278 eth_dest[4] = 0x67;
10279 eth_dest[5] = 0xc8;
10281 struct rte_pipeline_table_entry *table_entries[4];
10282 struct cgnapt_table_entry ctable_entries[4];
10283 table_entries[0] = (struct rte_pipeline_table_entry *)
10284 &ctable_entries[0];
10285 table_entries[1] = (struct rte_pipeline_table_entry *)
10286 &ctable_entries[1];
10287 table_entries[2] = (struct rte_pipeline_table_entry *)
10288 &ctable_entries[2];
10289 table_entries[3] = (struct rte_pipeline_table_entry *)
10290 &ctable_entries[3];
10291 for (entCnt = 0; entCnt < 4; entCnt++) {
10292 ctable_entries[entCnt].head.action =
10293 RTE_PIPELINE_ACTION_PORT;
10294 ctable_entries[entCnt].head.port_id = 0;
10296 ctable_entries[entCnt].data.prv_ip = 0x01020304;
10297 ctable_entries[entCnt].data.prv_port = 1234;
10298 ctable_entries[entCnt].data.pub_ip = 0x0a0b0c0d;
10299 ctable_entries[entCnt].data.pub_port = 4000;
10300 ctable_entries[entCnt].data.prv_phy_port = 0;
10301 ctable_entries[entCnt].data.pub_phy_port = 1;
10302 ctable_entries[entCnt].data.ttl = 500;
10305 uint64_t time1 = rte_get_tsc_cycles();
10307 for (exCnt = 0; exCnt < 1000; exCnt++) {
10308 pkt_work_cgnapt_key(cgnapt_test_pkts[0],
10309 instrumentation_port_in_arg);
10311 uint64_t time2 = rte_get_tsc_cycles();
10313 printf("times for %d times execution of "
10314 "pkt_work_cgnapt_key 0x%jx",
10316 printf(", 0x%jx, diff %" PRIu64 "\n", time2,
10319 time1 = rte_get_tsc_cycles();
10320 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10321 pkt_work_cgnapt_key(cgnapt_test_pkts[0],
10322 instrumentation_port_in_arg);
10324 time2 = rte_get_tsc_cycles();
10325 printf("times for %d times execution of "
10326 "pkt_work_cgnapt_key 0x%jx", exCnt, time1);
10327 printf("0x%jx, diff %" PRIu64 "\n", time2,
10330 time1 = rte_get_tsc_cycles();
10331 for (exCnt = 0; exCnt < 1000; exCnt++) {
10332 pkt4_work_cgnapt_key(cgnapt_test_pkts,
10333 instrumentation_port_in_arg);
10335 time2 = rte_get_tsc_cycles();
10336 printf("times for %d times execution of "
10337 "pkt4_work_cgnapt_key 0x%jx",
10339 printf(" 0x%jx, diff %" PRIu64 "\n", time2,
10342 time1 = rte_get_tsc_cycles();
10343 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10344 pkt4_work_cgnapt_key(cgnapt_test_pkts,
10345 instrumentation_port_in_arg);
10347 time2 = rte_get_tsc_cycles();
10348 printf("times for %d times execution of "
10349 "pkt4_work_cgnapt_key 0x%jx",
10351 printf("0x%jx, diff %" PRIu64 "\n", time2,
10354 uint64_t mask = 0xff;
10356 time1 = rte_get_tsc_cycles();
10357 for (exCnt = 0; exCnt < 1000; exCnt++) {
10358 pkt_work_cgnapt(cgnapt_test_pkts[0],
10359 table_entries[0], 3, &mask,
10362 time2 = rte_get_tsc_cycles();
10363 printf("times for %d times execution of "
10364 "pkt_work_cgnapt 0x%jx",
10366 printf("0x%jx, diff %" PRIu64 "\n", time2,
10369 time1 = rte_get_tsc_cycles();
10370 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10371 pkt_work_cgnapt(cgnapt_test_pkts[0],
10372 table_entries[0], 3, &mask,
10375 time2 = rte_get_tsc_cycles();
10376 printf("times for %d times execution of "
10377 "pkt_work_cgnapt 0x%jx",
10379 printf("0x%jx, diff %" PRIu64 "\n", time2,
10382 time1 = rte_get_tsc_cycles();
10383 for (exCnt = 0; exCnt < 1000; exCnt++) {
10384 pkt4_work_cgnapt(cgnapt_test_pkts,
10385 table_entries, 0, &mask, NULL);
10387 time2 = rte_get_tsc_cycles();
10388 printf("times for %d times execution of "
10389 "pkt4_work_cgnapt 0x%jx",
10391 printf("0x%jx, diff % " PRIu64 "\n", time2,
10394 int idummy = ctable_entries[0].data.prv_port;
10404 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_LS_ENTRY) {
10405 printf("CG-NAPT be entries are:\n");
10406 printf("Pipeline pointer %p\n", p);
10410 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DYN) {
10411 printf("Total Number of dynamic napt entries: %" PRIu64 "\n",
10412 p_nat->dynCgnaptCount);
10414 #ifdef CGNAPT_DEBUGGING
10415 printf("MAX PORT PER CLIENT:");
10416 printf("%" PRIu64 ",%" PRIu64 ",%" PRIu64 "\n",
10417 p_nat->max_port_dec_err1, p_nat->max_port_dec_err2,
10418 p_nat->max_port_dec_err3);
10419 printf("MPPC success : %" PRIu64 "\n",
10420 p_nat->max_port_dec_success);
10422 printf("Release port:err:%" PRIu64 ",ret::%" PRIu64 ",get::%"
10423 PRIu64 ",suc::%" PRIu64 "\n", p_nat->pfb_err,
10424 p_nat->pfb_ret, p_nat->pfb_get, p_nat->pfb_suc);
10425 printf("Get port::err:%" PRIu64 ",ret::%" PRIu64 ",get::%"
10426 PRIu64 ",suc::%" PRIu64 "\n", p_nat->gfp_err,
10427 p_nat->gfp_ret, p_nat->gfp_get, p_nat->gfp_suc);
10428 printf("Ring Info:\n");
10429 rte_ring_dump(stdout, p_nat->port_alloc_ring);
10433 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_IPV6) {
10434 dual_stack_enable = Msg[CGNAPT_DBG_CMD_OFST + 1];
10435 printf("Dual Stack option set: %x\n", dual_stack_enable);
10439 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_MAPS_INFO) {
10440 pipelines_port_info();
10441 pipelines_map_info();
10445 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_ITER_COM_TBL) {
10446 uint32_t count = 0;
10454 rte_hash_iterate(napt_common_table, &key, &data,
10457 if ((index != -EINVAL) && (index != -ENOENT)) {
10458 printf("\n%04d ", count);
10459 rte_hexdump(stdout, "KEY", key,
10461 pipeline_cgnapt_entry_key));
10463 //print_key((struct pipeline_cgnapt_entry_key *)
10466 rte_hash_lookup(napt_common_table,
10468 print_cgnapt_entry(&napt_hash_tbl_entries
10473 } while (index != -ENOENT);
10477 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_IF_STATS) {
10479 struct app_params *app =
10480 (struct app_params *)p_nat->app_params_addr;
10483 cmd[0] = Msg[CGNAPT_DBG_CMD_OFST + 1];
10484 cmd[1] = Msg[CGNAPT_DBG_CMD_OFST + 2];
10486 case CGNAPT_IF_STATS_HWQ:
10487 printf("n_pktq_hwq_int :%d\n", app->n_pktq_hwq_in);
10488 printf("n_pktq_hwq_out :%d\n", app->n_pktq_hwq_out);
10492 for (i = 0; i < app->n_pktq_hwq_in; i++) {
10493 struct rte_eth_stats stats;
10495 rte_eth_stats_get(p_nat->links_map[i], &stats);
10497 if (is_phy_port_privte(i))
10498 printf("Private Port Stats %d\n", i);
10500 printf("Public Port Stats %d\n", i);
10502 printf("\n\tipackets : %" PRIu64 "",
10504 printf("\n\topackets : %" PRIu64 "",
10506 printf("\n\tierrors : %" PRIu64 "",
10508 printf("\n\toerrors : %" PRIu64 "",
10510 printf("\n\trx_nombuf: %" PRIu64 "",
10513 if (is_phy_port_privte(i))
10514 printf("Private Q:");
10516 printf("Public Q:");
10517 for (j = 0; j < RTE_ETHDEV_QUEUE_STAT_CNTRS;
10519 printf(" %" PRIu64 ", %" PRIu64 "|",
10520 stats.q_ipackets[j],
10521 stats.q_opackets[j]);
10529 case CGNAPT_IF_STATS_SWQ:
10531 printf("n_pktq_swq :%d\n", app->n_pktq_swq);
10533 if (cmd[1] < app->n_pktq_swq) {
10534 rte_ring_dump(stdout, app->swq[cmd[1]]);
10537 printf("SWQ number is invalid\n");
10540 case CGNAPT_IF_STATS_OTH:
10542 printf("config_file:%s\n", app->config_file);
10543 printf("script_file:%s\n", app->script_file);
10544 printf("parser_file:%s\n", app->parser_file);
10545 printf("output_file:%s\n", app->output_file);
10546 printf("n_msgq :%d\n", app->n_msgq);
10547 printf("n_pktq_tm :%d\n", app->n_pktq_tm);
10548 printf("n_pktq_source :%d\n", app->n_pktq_source);
10549 printf("n_pktq_sink :%d\n", app->n_pktq_sink);
10550 printf("n_pipelines :%d\n", app->n_pipelines);
10554 printf("Command does not match\n\n");
10562 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_MAX_CLI_PER_PUB_IP) {
10563 if (nat_only_config_flag) {
10564 printf("Command not supported for NAT only config.\n");
10569 printf("\tPublic IP: Num Clients\n");
10570 for (ii = 0; ii < CGNAPT_MAX_PUB_IP; ii++)
10571 printf("\t%x : %7d\n", all_public_ip[ii].ip,
10572 rte_atomic16_read(&all_public_ip[ii].count));
10576 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_PUB_IP_LIST) {
10579 for (i = 0; i < p_nat->pub_ip_count; i++)
10580 printf("%x : (%d,%d)\n", p_nat->pub_ip_port_set[i].ip,
10581 p_nat->pub_ip_port_set[i].start_port,
10582 p_nat->pub_ip_port_set[i].end_port);
10586 #ifdef CGNAPT_TIMING_INST
10587 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_TIMING_INST) {
10588 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 0) {
10589 p_nat->time_measurements_on = 1;
10590 p_nat->time_measurements = 0;
10591 printf("CGNAPT timing instrumentation turned on.\n");
10592 printf("Max samples %d\n", p_nat->max_time_mesurements);
10594 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 1) {
10595 p_nat->time_measurements_on = 0;
10596 printf("CGNAPT timing instrumentation turned off.\n");
10597 printf("Cur Samples %d\n", p_nat->time_measurements);
10599 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 2) {
10600 uint64_t sum = p_nat->external_time_sum +
10601 p_nat->internal_time_sum;
10602 uint64_t isump = (p_nat->internal_time_sum * 100) / sum;
10603 uint64_t esump = (p_nat->external_time_sum * 100) / sum;
10604 printf("CGNAPT timing instrumentation status ...\n");
10605 printf("Max Count %d, Cur Count %d, Status %d (1=ON)\n",
10606 p_nat->max_time_mesurements,
10607 p_nat->time_measurements,
10608 p_nat->time_measurements_on);
10609 printf("Internal Time Sum %" PRIu64 " , Ave %" PRIu64
10610 ", percent %" PRIu64 "\n",
10611 p_nat->internal_time_sum,
10612 (p_nat->internal_time_sum /
10613 p_nat->time_measurements), isump);
10614 printf("External Time Sum %" PRIu64 " , Ave %" PRIu64
10615 ", percent %" PRIu64 "\n",
10616 p_nat->external_time_sum,
10617 (p_nat->external_time_sum /
10618 p_nat->time_measurements), esump);
10625 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_PRINT_NSP) {
10626 struct cgnapt_nsp_node *ll = nsp_ll;
10628 while (ll != NULL) {
10629 fprintf(stderr, "NSP Prefix/Depth=>%x%x:%x%x:%x%x: "
10630 "%x%x:%x%x:%x%x:%x%x:%x%x/%d",
10631 ll->nsp.prefix[0], ll->nsp.prefix[1],
10632 ll->nsp.prefix[2], ll->nsp.prefix[3],
10633 ll->nsp.prefix[4], ll->nsp.prefix[5],
10634 ll->nsp.prefix[6], ll->nsp.prefix[7],
10635 ll->nsp.prefix[8], ll->nsp.prefix[9],
10636 ll->nsp.prefix[10], ll->nsp.prefix[11],
10637 ll->nsp.prefix[12], ll->nsp.prefix[13],
10638 ll->nsp.prefix[14], ll->nsp.prefix[15],
10647 printf("CG-NAPT debug handler called with wrong args %x %x\n", Msg[0],
10651 for (i = 0; i < 20; i++)
10652 printf("%02x ", Msg[i]);
10658 * Function to print num of clients per IP address
10661 void print_num_ip_clients(void)
10663 if (nat_only_config_flag) {
10664 printf("Command not supported for NAT only config.\n");
10669 printf("\tPublic IP: Num Clients\n");
10670 for (ii = 0; ii < CGNAPT_MAX_PUB_IP; ii++)
10671 printf("\t%08x : %7d\n", all_public_ip[ii].ip,
10672 rte_atomic16_read(&all_public_ip[ii].count));
10676 * Function to print CGNAPT version info
10679 * An unused pointer to struct pipeline
10681 * void pointer to incoming arguments
10683 void *pipeline_cgnapt_msg_req_ver_handler(__rte_unused struct pipeline *p,
10686 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
10687 uint8_t *Msg = msg;
10691 printf("CG-NAPT debug handler called with args %x %x, offset %d\n",
10692 Msg[CGNAPT_VER_CMD_OFST], Msg[CGNAPT_VER_CMD_OFST + 1],
10693 CGNAPT_VER_CMD_OFST);
10695 if (Msg[CGNAPT_VER_CMD_OFST] == CGNAPT_VER_CMD_VER) {
10696 printf("CGNAPT Version %s\n", CGNAPT_VERSION);
10699 printf("CG-NAPT Version handler called with wrong args %x %x\n",
10703 for (i = 0; i < 20; i++)
10704 printf("%02x ", Msg[i]);
10710 * Function to show CGNAPT stats
10713 void all_cgnapt_stats(void)
10716 struct pipeline_cgnapt *p_nat;
10717 uint64_t receivedPktCount = 0;
10718 uint64_t missedPktCount = 0;
10719 uint64_t naptDroppedPktCount = 0;
10720 uint64_t naptedPktCount = 0;
10721 uint64_t inaptedPktCount = 0;
10722 uint64_t enaptedPktCount = 0;
10723 uint64_t arpicmpPktCount = 0;
10725 printf("\nCG-NAPT Packet Stats:\n");
10726 for (i = 0; i < n_cgnapt_pipeline; i++) {
10727 p_nat = all_pipeline_cgnapt[i];
10729 receivedPktCount += p_nat->receivedPktCount;
10730 missedPktCount += p_nat->missedPktCount;
10731 naptDroppedPktCount += p_nat->naptDroppedPktCount;
10732 naptedPktCount += p_nat->naptedPktCount;
10733 inaptedPktCount += p_nat->inaptedPktCount;
10734 enaptedPktCount += p_nat->enaptedPktCount;
10735 arpicmpPktCount += p_nat->arpicmpPktCount;
10737 printf("pipeline %d stats:\n", p_nat->pipeline_num);
10738 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10739 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10740 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10741 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10742 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10743 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10744 printf("arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10747 #ifdef CGNAPT_DEBUGGING
10748 printf("\n Drop detail 1:%" PRIu64 ",",
10749 p_nat->naptDroppedPktCount1);
10750 printf("\n Drop detail 2:%" PRIu64 ",",
10751 p_nat->naptDroppedPktCount2);
10752 printf("\n Drop detail 3:%" PRIu64 ",",
10753 p_nat->naptDroppedPktCount3);
10754 printf("\n Drop detail 4:%" PRIu64 ",",
10755 p_nat->naptDroppedPktCount4);
10756 printf("\n Drop detail 5:%" PRIu64 ",",
10757 p_nat->naptDroppedPktCount5);
10758 printf("\n Drop detail 6:%" PRIu64 "",
10759 p_nat->naptDroppedPktCount6);
10761 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10762 p_nat->missedpktcount1,
10763 p_nat->missedpktcount2);
10764 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10765 p_nat->missedpktcount3,
10766 p_nat->missedpktcount4);
10767 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10768 p_nat->missedpktcount5,
10769 p_nat->missedpktcount6);
10770 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10771 p_nat->missedpktcount7,
10772 p_nat->missedpktcount8);
10773 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10774 p_nat->missedpktcount9,
10775 p_nat->missedpktcount10);
10781 printf("\nTotal pipeline stats:\n");
10782 printf("Received %" PRIu64 ",", receivedPktCount);
10783 printf("Missed %" PRIu64 ",", missedPktCount);
10784 printf("Dropped %" PRIu64 ",", naptDroppedPktCount);
10785 printf("Translated %" PRIu64 ",", naptedPktCount);
10786 printf("ingress %" PRIu64 ",", inaptedPktCount);
10787 printf("egress %" PRIu64 "\n", enaptedPktCount);
10788 printf("arpicmp pkts %" PRIu64 "\n", arpicmpPktCount);
10791 void all_cgnapt_clear_stats(void)
10794 struct pipeline_cgnapt *p_nat;
10795 printf("\nCG-NAPT Packet Stats:\n");
10796 for (i = 0; i < n_cgnapt_pipeline; i++) {
10797 p_nat = all_pipeline_cgnapt[i];
10799 printf("pipeline %d stats:\n", p_nat->pipeline_num);
10800 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10801 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10802 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10803 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10804 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10805 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10806 printf("arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10808 p_nat->receivedPktCount = 0;
10809 p_nat->missedPktCount = 0;
10810 p_nat->naptDroppedPktCount = 0;
10811 p_nat->naptedPktCount = 0;
10812 p_nat->inaptedPktCount = 0;
10813 p_nat->enaptedPktCount = 0;
10814 p_nat->arpicmpPktCount = 0;
10816 #ifdef CGNAPT_DEBUGGING
10817 printf("\n Drop detail 1:%" PRIu64 ",",
10818 p_nat->naptDroppedPktCount1);
10819 printf("\n Drop detail 2:%" PRIu64 ",",
10820 p_nat->naptDroppedPktCount2);
10821 printf("\n Drop detail 3:%" PRIu64 ",",
10822 p_nat->naptDroppedPktCount3);
10823 printf("\n Drop detail 4:%" PRIu64 ",",
10824 p_nat->naptDroppedPktCount4);
10825 printf("\n Drop detail 5:%" PRIu64 ",",
10826 p_nat->naptDroppedPktCount5);
10827 printf("\n Drop detail 6:%" PRIu64 "",
10828 p_nat->naptDroppedPktCount6);
10830 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10831 p_nat->missedpktcount1,
10832 p_nat->missedpktcount2);
10833 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10834 p_nat->missedpktcount3,
10835 p_nat->missedpktcount4);
10836 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10837 p_nat->missedpktcount5,
10838 p_nat->missedpktcount6);
10839 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10840 p_nat->missedpktcount7,
10841 p_nat->missedpktcount8);
10842 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10843 p_nat->missedpktcount9,
10844 p_nat->missedpktcount10);
10852 * Function to print common CGNAPT table entries
10855 void print_static_cgnapt_entries(void)
10857 uint32_t count = 0;
10862 struct cgnapt_table_entry *entry;
10864 index = rte_hash_iterate(napt_common_table,
10865 &key, &data, &next);
10867 if ((index != -EINVAL) && (index != -ENOENT)) {
10868 printf("\n%04d ", count);
10869 rte_hexdump(stdout, "KEY", key,
10870 sizeof(struct pipeline_cgnapt_entry_key));
10871 int32_t position = rte_hash_lookup(
10872 napt_common_table, key);
10873 entry = &napt_hash_tbl_entries[position];
10875 if (entry->data.timeout == STATIC_CGNAPT_TIMEOUT)
10876 rte_hexdump(stdout, "Entry",
10877 (const void *)entry,
10878 sizeof(struct cgnapt_table_entry));
10882 } while (index != -ENOENT);
10886 * Function to show CGNAPT stats
10890 struct pipeline_be_ops pipeline_cgnapt_be_ops = {
10891 .f_init = pipeline_cgnapt_init,
10892 .f_free = pipeline_cgnapt_free,
10894 .f_timer = pipeline_cgnapt_timer,
10895 .f_track = pipeline_cgnapt_track,