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;
84 /* To know egress or ingress port */
85 static uint8_t cgnapt_in_port_egress_prv[PIPELINE_MAX_PORT_IN];
86 static uint8_t cgnapt_prv_que_port_index[PIPELINE_MAX_PORT_IN];
88 /* Max port per client declarations */
90 struct rte_hash_parameters max_port_per_client_hash_params = {
91 .name = "MAX_PORT_PER_CLIENT",
92 .entries = MAX_DYN_ENTRY,
93 .key_len = sizeof(struct max_port_per_client_key),
94 .hash_func = rte_jhash,
95 .hash_func_init_val = 0,
98 struct rte_ct_cnxn_tracker *cgnat_cnxn_tracker;
101 /***** Common Port Allocation declarations *****/
103 struct rte_ring *port_alloc_ring[MAX_CGNAPT_SETS] = { NULL, NULL, NULL, NULL,
104 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
105 NULL, NULL, NULL, NULL};
106 const char *napt_port_alloc_ring_name[MAX_CGNAPT_SETS] = {
107 "NAPT_PORT_ALLOC_0 ",
108 "NAPT_PORT_ALLOC_1 ",
109 "NAPT_PORT_ALLOC_2 ",
110 "NAPT_PORT_ALLOC_3 ",
111 "NAPT_PORT_ALLOC_4 ",
112 "NAPT_PORT_ALLOC_5 ",
113 "NAPT_PORT_ALLOC_6 ",
114 "NAPT_PORT_ALLOC_7 ",
115 "NAPT_PORT_ALLOC_8 ",
116 "NAPT_PORT_ALLOC_9 ",
117 "NAPT_PORT_ALLOC_10 ",
118 "NAPT_PORT_ALLOC_11 ",
119 "NAPT_PORT_ALLOC_12 ",
120 "NAPT_PORT_ALLOC_13 ",
121 "NAPT_PORT_ALLOC_14 ",
122 "NAPT_PORT_ALLOC_16 "
125 int vnf_set_count = -1;
127 struct app_params *myApp;
129 /***** Common Port Allocation declarations *****/
130 int napt_port_alloc_elem_count;
132 /***** Common Table declarations *****/
133 struct rte_hash_parameters napt_common_table_hash_params = {
134 .name = "NAPT_COM_TBL",
135 .entries = MAX_NAPT_ENTRIES,
136 .key_len = sizeof(struct pipeline_cgnapt_entry_key),
137 .hash_func = rte_jhash,
138 .hash_func_init_val = 0,
142 /***** ARP local cache *****/
143 uint8_t link_hw_laddr_valid[MAX_NUM_LOCAL_MAC_ADDRESS] = {
144 0, 0, 0, 0, 0, 0, 0, 0,
145 0, 0, 0, 0, 0, 0, 0, 0
148 struct ether_addr link_hw_laddr[MAX_NUM_LOCAL_MAC_ADDRESS] = {
149 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
150 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
151 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
152 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
153 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
154 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
155 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
156 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
157 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
158 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
159 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
160 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
161 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
162 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
163 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
164 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }
167 /****** NAT64 declarations *****/
169 uint8_t well_known_prefix[16] = {
170 0x00, 0x64, 0xff, 0x9b,
171 0x00, 0x00, 0x00, 0x00,
172 0x00, 0x00, 0x00, 0x00,
173 0x00, 0x00, 0x00, 0x00
176 static uint32_t local_get_nh_ipv4(
180 struct pipeline_cgnapt *p_nat);
182 static void do_local_nh_ipv4_cache(
184 struct pipeline_cgnapt *p_nat);
186 static uint32_t local_get_nh_ipv6(
190 struct pipeline_cgnapt *p_nat);
192 static void do_local_nh_ipv6_cache(
194 struct pipeline_cgnapt *p_nat);
196 static uint8_t check_arp_icmp(
197 struct rte_mbuf *pkt,
199 struct pipeline_cgnapt *p_nat);
201 /* Finds next power of two for n. If n itself
202 * is a power of two then returns n
205 * Value usually 32-bit value
208 * Value after roundup to power of 2
210 uint64_t nextPowerOf2(uint64_t n)
224 * Function to get MAC addr of local link
227 * Physical port number
230 * Outport Link MAC addr
233 struct ether_addr *get_local_link_hw_addr(uint8_t out_port)
235 return &link_hw_laddr[out_port];
239 * Function to get MAC addr from array instead of hash table
242 * Physical port number
245 * Outport Link MAC addr
248 uint8_t local_dest_mac_present(uint8_t out_port)
250 return link_hw_laddr_valid[out_port];
254 * Function to get IPv4-IP NH from thread local array
263 * CGNAPT pipeline ptr
266 * 1 on success, 0 for failure
269 static uint32_t local_get_nh_ipv4(
273 struct pipeline_cgnapt *p_nat)
276 for (i = 0; i < p_nat->local_lib_arp_route_ent_cnt; i++) {
277 if (((p_nat->local_lib_arp_route_table[i].ip &
278 p_nat->local_lib_arp_route_table[i].mask) ==
279 (ip & p_nat->local_lib_arp_route_table[i].mask))) {
280 *port = p_nat->local_lib_arp_route_table[i].port;
282 *nhip = p_nat->local_lib_arp_route_table[i].nh;
290 * Function to make local copy for NH of type IPv4
293 * Physical port number
295 * CGNAPT pipeline ptr
299 static void do_local_nh_ipv4_cache(
301 struct pipeline_cgnapt *p_nat)
304 /* Search for the entry and do local copy */
307 for (i = 0; i < MAX_ARP_RT_ENTRY; i++) {
308 if (lib_arp_route_table[i].port == dest_if) {
310 struct lib_arp_route_table_entry *lentry =
311 &p_nat->local_lib_arp_route_table
312 [p_nat->local_lib_arp_route_ent_cnt];
314 lentry->ip = lib_arp_route_table[i].ip;
315 lentry->mask = lib_arp_route_table[i].mask;
316 lentry->port = lib_arp_route_table[i].port;
317 lentry->nh = lib_arp_route_table[i].nh;
319 p_nat->local_lib_arp_route_ent_cnt++;
327 * Function to get IPv6-IP NH from thread local array
330 * Pointer to starting addr of IPv6
336 * CGNAPT pipeline ptr
339 * 1 on success, 0 for failure
342 static uint32_t local_get_nh_ipv6(
346 struct pipeline_cgnapt *p_nat)
349 uint8_t netmask_ipv6[16];
350 uint8_t k = 0, l = 0, depthflags = 0, depthflags1 = 0;
352 for (i = 0; i < p_nat->local_lib_nd_route_ent_cnt; i++) {
354 convert_prefixlen_to_netmask_ipv6(
355 p_nat->local_lib_nd_route_table[i].depth,
358 for (k = 0; k < 16; k++)
359 if (p_nat->local_lib_nd_route_table[i].ipv6[k] &
363 for (l = 0; l < 16; l++)
364 if (ip[l] & netmask_ipv6[l])
368 if (depthflags == depthflags1) {
369 *port = p_nat->local_lib_nd_route_table[i].port;
371 for (j = 0; j < 16; j++)
372 nhip[j] = p_nat->local_lib_nd_route_table[i].
385 * Function to make local copy for NH of type IPv6
388 * Physical port number
390 * CGNAPT pipeline ptr
394 static void do_local_nh_ipv6_cache(
396 struct pipeline_cgnapt *p_nat)
398 /* Search for the entry and do local copy */
400 for (i = 0; i < MAX_ND_RT_ENTRY; i++) {
402 if (lib_nd_route_table[i].port == dest_if) {
404 struct lib_nd_route_table_entry *lentry =
405 &p_nat->local_lib_nd_route_table
406 [p_nat->local_lib_nd_route_ent_cnt];
408 for (l = 0; l < 16; l++) {
410 lib_nd_route_table[i].ipv6[l];
412 lib_nd_route_table[i].nhipv6[l];
414 lentry->depth = lib_nd_route_table[i].depth;
415 lentry->port = lib_nd_route_table[i].port;
417 p_nat->local_lib_nd_route_ent_cnt++;
424 /* Commented code may be required for future usage, Please keep it*/
426 static int retrieve_cgnapt_entry_alg(
427 struct pipeline_cgnapt_entry_key *key,
428 struct cgnapt_table_entry **entry_ptr1,
429 struct cgnapt_table_entry **entry_ptr2)
431 #ifdef CGNAPT_DBG_PRNT
432 printf("retrieve_cgnapt_entry key detail Entry:"
433 "0x%x, %d, %d\n", key->ip, key->port,
437 int position = rte_hash_lookup(napt_common_table, key);
439 printf("Invalid cgnapt entry position(first_key): %d\n",
444 *entry_ptr1 = &napt_hash_tbl_entries[position];
446 uint32_t prv_ip = (*entry_ptr1)->data.prv_ip;
447 uint32_t prv_port = (*entry_ptr1)->data.prv_port;
448 uint32_t prv_phy_port = (*entry_ptr1)->data.prv_phy_port;
450 struct pipeline_cgnapt_entry_key second_key;
451 second_key.ip = prv_ip;
452 second_key.port = prv_port;
453 second_key.pid = prv_phy_port;
455 position = rte_hash_lookup(napt_common_table, &second_key);
457 printf("Invalid cgnapt entry position(second_key): %d\n",
462 *entry_ptr2 = &napt_hash_tbl_entries[position];
468 int add_dynamic_cgnapt_entry_alg(
470 struct pipeline_cgnapt_entry_key *key,
471 struct cgnapt_table_entry **entry_ptr1,
472 struct cgnapt_table_entry **entry_ptr2)
474 int port_num = 0, ret;
476 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
478 #ifdef CGNAPT_DBG_PRNT
479 if (CGNAPT_DEBUG >= 1) {
480 printf("Th%d add_dynamic_cgnapt_entry key detail Entry:"
481 "0x%x, %d, %d\n", p_nat->pipeline_num, key->ip, key->port,
486 int32_t position = rte_hash_lookup(napt_common_table, key);
488 #ifdef CGNAPT_DBG_PRNT
489 if (CGNAPT_DEBUG >= 1) {
490 printf("%s: cgnapt entry exists in "
491 "position(first_key): %d\n", __func__, position);
494 *entry_ptr1 = &napt_hash_tbl_entries[position];
495 /* not required, as it is not used in the caller */
501 ret = increment_max_port_counter(key->ip, key->pid, p_nat);
502 if (ret == MAX_PORT_INC_ERROR) {
504 #ifdef CGNAPT_DBG_PRNT
505 if (CGNAPT_DEBUG > 1)
506 printf("add_dynamic_cgnapt_entry:"
507 "increment_max_port_counter-1 failed\n");
513 if (ret == MAX_PORT_INC_REACHED) {
515 #ifdef CGNAPT_DBG_PRNT
516 if (CGNAPT_DEBUG > 1)
517 printf("add_dynamic_cgnapt_entry:"
518 "increment_max_port_counter-2 failed\n");
525 port_num = get_free_iport(p_nat, &public_ip);
527 if (port_num == -1) {
529 #ifdef CGNAPT_DBG_PRNT
530 if (CGNAPT_DEBUG > 2) {
531 printf("add_dynamic_cgnapt_entry: %d\n", port_num);
532 printf("add_dynamic_cgnapt_entry key detail:0x%x, "
533 "%d, %d\n", key->ip, key->port, key->pid);
540 /* check for max_clients_per_ip */
541 if (rte_atomic16_read
543 [rte_jhash(&public_ip, 4, 0) % 16].count) ==
544 p_nat->max_clients_per_ip) {
545 /* For now just bail out
546 * In future we can think about
547 * retrying getting a new iport
549 release_iport(port_num, public_ip, p_nat);
554 rte_atomic16_inc(&all_public_ip
555 [rte_jhash(&public_ip, 4, 0) %
558 #ifdef CGNAPT_DBG_PRNT
559 if ((rte_jhash(&public_ip, 4, 0) % 16) == 8)
560 printf("pub ip:%x coutn:%d\n", public_ip,
561 rte_atomic16_read(&all_public_ip
562 [rte_jhash(&public_ip, 4, 0) % 16].count));
565 #ifdef CGNAPT_DBG_PRNT
566 if (CGNAPT_DEBUG > 0) {
567 printf("add_dynamic_cgnapt_entry: %d\n",
569 printf("add_dynamic_cgnapt_entry key detail: "
570 "0x%x, %d, %d\n", key->ip, key->port, key->pid);
574 struct cgnapt_table_entry entry = {
576 .action = RTE_PIPELINE_ACTION_PORT,
577 /* made it configurable below */
578 {.port_id = p->port_out_id[0]},
582 .prv_port = key->port,
584 .pub_port = port_num,
585 .prv_phy_port = key->pid,
586 .pub_phy_port = get_pub_to_prv_port(
590 /* if(timeout == -1) : static entry
591 * if(timeout == 0 ) : dynamic entry
592 * if(timeout > 0 ) : PCP requested entry
601 entry.data.u.prv_ip = key->ip;
602 entry.data.type = CGNAPT_ENTRY_IPV4;
604 entry.head.port_id = entry.data.pub_phy_port; /* outgoing port info */
606 struct pipeline_cgnapt_entry_key second_key;
607 /* Need to add a second ingress entry */
608 second_key.ip = public_ip;
609 second_key.port = port_num;
610 second_key.pid = 0xffff;
612 #ifdef CGNAPT_DBG_PRNT
613 if (CGNAPT_DEBUG > 2)
614 printf("add_dynamic_cgnapt_entry second key detail:"
615 "0x%x, %d, %d\n", second_key.ip, second_key.port,
619 int32_t position1 = rte_hash_add_key(napt_common_table, (void *)key);
622 printf("CG-NAPT entry add failed ...returning "
623 "without adding ... %d\n", position1);
628 #ifdef CGNAPT_DBG_PRNT
630 printf("add_dynamic_cgnapt_entry:");
632 print_cgnapt_entry(&entry);
636 memcpy(&napt_hash_tbl_entries[position1], &entry,
637 sizeof(struct cgnapt_table_entry));
639 /* this pointer is returned to pkt miss function */
640 *entry_ptr1 = &napt_hash_tbl_entries[position1];
642 p_nat->n_cgnapt_entry_added++;
643 p_nat->dynCgnaptCount++;
645 /* Now modify the forward port for reverse entry */
647 /* outgoing port info */
648 entry.head.port_id = entry.data.prv_phy_port;
650 int32_t position2 = rte_hash_add_key(napt_common_table, &second_key);
653 printf("CG-NAPT entry reverse bulk add failed ..."
654 "returning with fwd add ...%d\n",
659 memcpy(&napt_hash_tbl_entries[position2], &entry,
660 sizeof(struct cgnapt_table_entry));
662 *entry_ptr2 = &napt_hash_tbl_entries[position2];
664 #ifdef CGNAPT_DBG_PRNT
665 if (CGNAPT_DEBUG >= 1) {
666 printf("add_dynamic_cgnapt_entry position: %d, %d\n",
667 position1, position2);
668 printf("add_dynamic_cgnapt_entry: entry_ptr1: %p, "
669 "entry_ptr2: %p\n", *entry_ptr1, *entry_ptr2);
673 timer_thread_enqueue(key, &second_key, *entry_ptr1,
674 *entry_ptr2, (struct pipeline *)p_nat);
676 p_nat->n_cgnapt_entry_added++;
677 p_nat->dynCgnaptCount++;
684 void hw_checksum(struct rte_mbuf *pkt, enum PKT_TYPE ver)
686 struct tcp_hdr *tcp = NULL;
687 struct udp_hdr *udp = NULL;
688 struct icmp_hdr *icmp = NULL;
690 void *ip_header = NULL;
691 uint16_t prot_offset = 0;
692 uint32_t pkt_type_is_ipv4 = 1;
694 pkt->ol_flags |= PKT_TX_IP_CKSUM;
695 pkt->l2_len = ETH_HDR_SIZE;
700 case PKT_TYPE_IPV4to6:
704 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
705 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
707 pkt_type_is_ipv4 = 0;
708 pkt->ol_flags |= PKT_TX_IPV6;
710 sizeof(struct ipv6_hdr);
711 tcp = (struct tcp_hdr *)
712 ((unsigned char *)ip_header +
713 sizeof(struct ipv6_hdr));
714 udp = (struct udp_hdr *)
715 ((unsigned char *)ip_header +
716 sizeof(struct ipv6_hdr));
717 icmp = (struct icmp_hdr *)
718 ((unsigned char *)ip_header +
719 sizeof(struct ipv6_hdr));
721 prot_offset = PROT_OFST_IP6 + temp;
723 case PKT_TYPE_IPV6to4:
727 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
728 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
730 pkt->ol_flags |= PKT_TX_IPV4;
732 sizeof(struct ipv4_hdr);
733 tcp = (struct tcp_hdr *)
734 ((unsigned char *)ip_header +
735 sizeof(struct ipv4_hdr));
736 udp = (struct udp_hdr *)
737 ((unsigned char *)ip_header +
738 sizeof(struct ipv4_hdr));
739 icmp = (struct icmp_hdr *)
740 ((unsigned char *)ip_header +
741 sizeof(struct ipv4_hdr));
742 struct ipv4_hdr *ip_hdr =
743 (struct ipv4_hdr *)ip_header;
744 ip_hdr->hdr_checksum = 0;
746 prot_offset = PROT_OFST_IP4 + temp;
749 printf("hw_checksum: pkt version is invalid\n");
751 protocol = (uint8_t *) RTE_MBUF_METADATA_UINT8_PTR(pkt,
755 case IP_PROTOCOL_TCP: /* 6 */
757 pkt->ol_flags |= PKT_TX_TCP_CKSUM;
758 if (pkt_type_is_ipv4) {
759 tcp->cksum = rte_ipv4_phdr_cksum(
760 (struct ipv4_hdr *)ip_header,
763 tcp->cksum = rte_ipv6_phdr_cksum(
764 (struct ipv6_hdr *)ip_header,
768 case IP_PROTOCOL_UDP: /* 17 */
769 udp->dgram_cksum = 0;
770 pkt->ol_flags |= PKT_TX_UDP_CKSUM;
771 if (pkt_type_is_ipv4) {
774 (struct ipv4_hdr *)ip_header,
779 (struct ipv6_hdr *)ip_header,
783 case IP_PROTOCOL_ICMP: /* 1 */
784 if (pkt_type_is_ipv4) {
785 /* ICMP checksum code */
786 struct ipv4_hdr *ip_hdr =
787 (struct ipv4_hdr *)ip_header;
788 int size = rte_bswap16(ip_hdr->total_length) - 20;
789 icmp->icmp_cksum = 0;
797 printf("hw_checksum() : Neither TCP or UDP pkt\n");
803 void sw_checksum(struct rte_mbuf *pkt, enum PKT_TYPE ver)
805 struct tcp_hdr *tcp = NULL;
806 struct udp_hdr *udp = NULL;
807 struct icmp_hdr *icmp = NULL;
809 void *ip_header = NULL;
810 uint16_t prot_offset = 0;
811 uint32_t pkt_type_is_ipv4 = 1;
815 case PKT_TYPE_IPV4to6:
819 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
820 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
822 pkt_type_is_ipv4 = 0;
823 tcp = (struct tcp_hdr *)
824 ((unsigned char *)ip_header +
825 sizeof(struct ipv6_hdr));
826 udp = (struct udp_hdr *)
827 ((unsigned char *)ip_header +
828 sizeof(struct ipv6_hdr));
829 icmp = (struct icmp_hdr *)
830 ((unsigned char *)ip_header +
831 sizeof(struct ipv6_hdr));
833 prot_offset = PROT_OFST_IP6 + temp;
835 case PKT_TYPE_IPV6to4:
839 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
840 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
842 tcp = (struct tcp_hdr *)
843 ((unsigned char *)ip_header +
844 sizeof(struct ipv4_hdr));
845 udp = (struct udp_hdr *)
846 ((unsigned char *)ip_header +
847 sizeof(struct ipv4_hdr));
848 icmp = (struct icmp_hdr *)
849 ((unsigned char *)ip_header +
850 sizeof(struct ipv4_hdr));
852 prot_offset = PROT_OFST_IP4 + temp;
855 printf("sw_checksum: pkt version is invalid\n");
857 protocol = (uint8_t *) RTE_MBUF_METADATA_UINT8_PTR(pkt,
861 case IP_PROTOCOL_TCP: /* 6 */
863 if (pkt_type_is_ipv4) {
864 struct ipv4_hdr *ip_hdr =
865 (struct ipv4_hdr *)ip_header;
866 tcp->cksum = rte_ipv4_udptcp_cksum(ip_hdr,
868 ip_hdr->hdr_checksum = 0;
869 ip_hdr->hdr_checksum = rte_ipv4_cksum(
870 (struct ipv4_hdr *)ip_hdr);
872 tcp->cksum = rte_ipv6_udptcp_cksum(
874 ip_header, (void *)tcp);
877 case IP_PROTOCOL_UDP: /* 17 */
878 udp->dgram_cksum = 0;
879 if (pkt_type_is_ipv4) {
880 struct ipv4_hdr *ip_hdr =
881 (struct ipv4_hdr *)ip_header;
882 udp->dgram_cksum = rte_ipv4_udptcp_cksum(
883 ip_hdr, (void *)udp);
884 ip_hdr->hdr_checksum = 0;
885 ip_hdr->hdr_checksum = rte_ipv4_cksum(ip_hdr);
887 udp->dgram_cksum = rte_ipv6_udptcp_cksum(
889 ip_header, (void *)udp);
892 case IP_PROTOCOL_ICMP: /* 1 */
893 if (pkt_type_is_ipv4) {
894 /* ICMP checksum code */
895 struct ipv4_hdr *ip_hdr =
896 (struct ipv4_hdr *)ip_header;
897 int size = rte_bswap16(ip_hdr->total_length) - 20;
898 icmp->icmp_cksum = 0;
902 ip_hdr->hdr_checksum = 0;
903 ip_hdr->hdr_checksum = rte_ipv4_cksum(ip_hdr);
908 printf("sw_checksum() : Neither TCP or UDP pkt\n");
913 static uint8_t check_arp_icmp(
914 struct rte_mbuf *pkt,
916 struct pipeline_cgnapt *p_nat)
918 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
919 uint16_t *eth_proto = RTE_MBUF_METADATA_UINT16_PTR(
920 pkt, eth_proto_offset);
921 struct app_link_params *link;
922 uint8_t solicited_node_multicast_addr[16] = {
923 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
924 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00};
926 /* ARP outport number */
927 uint16_t out_port = p_nat->p.n_ports_out - 1;
930 uint32_t prot_offset;
932 link = &myApp->link_params[pkt->port];
935 switch (rte_be_to_cpu_16(*eth_proto)) {
939 rte_pipeline_port_out_packet_insert(
945 * Pkt mask should be changed, and not changing the
948 p_nat->invalid_packets |= pkt_mask;
949 p_nat->arpicmpPktCount++;
953 case ETH_TYPE_IPV4: {
954 /* header room + eth hdr size +
955 * src_aadr offset in ip header
957 uint32_t dst_addr_offset = MBUF_HDR_ROOM +
958 ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
960 RTE_MBUF_METADATA_UINT32_PTR(pkt,
962 prot_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
963 IP_HDR_PROTOCOL_OFST;
964 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt,
966 if ((*protocol == IP_PROTOCOL_ICMP) &&
967 link->ip == rte_be_to_cpu_32(*dst_addr)) {
969 if (is_phy_port_privte(pkt->port)) {
971 rte_pipeline_port_out_packet_insert(
972 p_nat->p.p, out_port, pkt);
975 * Pkt mask should be changed,
976 * and not changing the drop mask
979 p_nat->invalid_packets |= pkt_mask;
980 p_nat->arpicmpPktCount++;
991 if (dual_stack_enable) {
993 /* Commented code may be required for future usage,
996 //uint32_t dst_addr_offset = MBUF_HDR_ROOM +
997 // ETH_HDR_SIZE + IPV6_HDR_DST_ADR_OFST;
998 //uint32_t *dst_addr =
999 // RTE_MBUF_METADATA_UINT32_PTR(pkt,
1000 // dst_addr_offset);
1001 uint32_t prot_offset_ipv6 = MBUF_HDR_ROOM +
1002 ETH_HDR_SIZE + IPV6_HDR_PROTOCOL_OFST;
1003 struct ipv6_hdr *ipv6_h;
1005 ipv6_h = (struct ipv6_hdr *) MBUF_HDR_ROOM +
1007 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt,
1010 if (ipv6_h->proto == ICMPV6_PROTOCOL_ID) {
1011 if (!memcmp(ipv6_h->dst_addr, link->ipv6, 16)
1012 || !memcmp(ipv6_h->dst_addr,
1013 solicited_node_multicast_addr, 13)) {
1014 rte_pipeline_port_out_packet_insert(
1015 p_nat->p.p, out_port, pkt);
1017 * Pkt mask should be changed,
1018 * and not changing the drop mask
1020 p_nat->invalid_packets |= pkt_mask;
1021 p_nat->arpicmpPktCount++;
1023 p_nat->invalid_packets |= pkt_mask;
1024 p_nat->naptDroppedPktCount++;
1026 #ifdef CGNAPT_DEBUGGING
1027 p_nat->naptDroppedPktCount1++;
1042 * Function to create common NAPT table
1043 * Called during pipeline initialization
1044 * Creates the common NAPT table
1045 * If it is not already created and stores its pointer
1046 * in global napt_common_table pointer.
1049 * Max number of NAPT flows. This parameter is configurable via config file.
1052 * 0 on success, negative on error.
1054 int create_napt_common_table(uint32_t nFlows)
1056 if (napt_common_table != NULL) {
1057 printf("napt_common_table already exists.\n");
1061 napt_common_table = rte_hash_create(&napt_common_table_hash_params);
1063 if (napt_common_table == NULL) {
1064 printf("napt_common_table creation failed.\n");
1068 uint32_t number_of_entries = nFlows;
1071 RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_table_entry) *
1073 napt_hash_tbl_entries = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1075 if (napt_hash_tbl_entries == NULL) {
1076 printf("napt_hash_tbl_entries creation failed. %d, %d\n",
1077 nFlows, (int)sizeof(struct cgnapt_table_entry));
1085 * Function to initialize bulk port allocation data structures
1086 * Called during pipeline initialization.
1088 * Creates the port alloc ring for the VNF_set this pipeline belongs
1090 * Creates global port allocation buffer pool
1092 * Initializes the port alloc ring according to config data
1095 * A pointer to struct pipeline_cgnapt
1098 * 0 on success, negative on error.
1100 int napt_port_alloc_init(struct pipeline_cgnapt *p_nat)
1102 p_nat->allocated_ports = NULL;
1103 p_nat->free_ports = NULL;
1105 uint32_t vnf_set_num = p_nat->vnf_set;
1106 /*uint32_t vnf_set_num = get_vnf_set_num(p_nat->pipeline_num); */
1108 printf("VNF set number for CGNAPT %d is %d.\n", p_nat->pipeline_num,
1110 if (vnf_set_num == 0xFF) {
1111 printf("VNF set number for CGNAPT %d is invalid %d.\n",
1112 p_nat->pipeline_num, vnf_set_num);
1116 p_nat->port_alloc_ring = port_alloc_ring[vnf_set_num];
1117 if (p_nat->port_alloc_ring != NULL) {
1118 printf("CGNAPT%d port_alloc_ring already exists.\n",
1119 p_nat->pipeline_num);
1123 printf("napt_port_alloc_elem_count :%d\n",
1124 napt_port_alloc_elem_count);
1125 napt_port_alloc_elem_count += 1;
1126 napt_port_alloc_elem_count =
1127 nextPowerOf2(napt_port_alloc_elem_count);
1128 printf("Next power of napt_port_alloc_elem_count: %d\n",
1129 napt_port_alloc_elem_count);
1131 port_alloc_ring[vnf_set_num] =
1132 rte_ring_create(napt_port_alloc_ring_name[vnf_set_num],
1133 napt_port_alloc_elem_count, rte_socket_id(), 0);
1134 p_nat->port_alloc_ring = port_alloc_ring[vnf_set_num];
1135 if (p_nat->port_alloc_ring == NULL) {
1136 printf("CGNAPT%d - Failed to create port_alloc_ring\n",
1137 p_nat->pipeline_num);
1141 /* Create port alloc buffer */
1142 /* Only one pool is enough for all vnf sets */
1143 if (napt_port_pool == NULL) {
1145 napt_port_pool = rte_mempool_create(
1147 napt_port_alloc_elem_count,
1148 sizeof(struct napt_port_alloc_elem),
1149 0, 0, NULL, NULL, NULL,
1150 NULL, rte_socket_id(), 0);
1153 if (napt_port_pool == NULL) {
1154 printf("CGNAPT - Create port pool failed\n");
1158 /* Add all available public IP addresses and ports to the ring */
1161 #ifdef NAT_ONLY_CONFIG_REQ
1162 if (nat_only_config_flag) {
1163 printf("******* pub_ip_range_count:%d ***********\n",
1164 p_nat->pub_ip_range_count);
1165 /* Initialize all public IP's addresses */
1167 uint32_t max_ips_remain;
1169 for (if_addrs = 0; if_addrs < p_nat->pub_ip_range_count;
1171 /* Add all available addresses to the ring */
1173 for (i = p_nat->pub_ip_range[if_addrs].start_ip;
1174 i <= p_nat->pub_ip_range[if_addrs].end_ip;) {
1175 /* 1. Get a port alloc buffer from napt_port_pool */
1179 /* get new napt_port_alloc_elem from pool */
1180 if (rte_mempool_get(napt_port_pool,
1182 printf("CGNAPT - Error in getting port "
1188 /* 2. Populate it with available ports and ip addr */
1189 struct napt_port_alloc_elem *pb =
1190 (struct napt_port_alloc_elem *)portsBuf;
1193 temp = p_nat->pub_ip_range[if_addrs].end_ip -
1196 /* Check if remaining port count is greater
1197 * than or equals to bulk count, if not give
1198 * remaining count ports than giving bulk count
1200 if (temp < NUM_NAPT_PORT_BULK_ALLOC)
1201 max_ips_remain = temp;
1204 NUM_NAPT_PORT_BULK_ALLOC;
1206 for (j = 0; j < max_ips_remain; j++) {
1208 pb->ip_addr[j] = i + j;
1211 p_nat->pub_ip_range[if_addrs].
1216 /* 3. add the port alloc buffer to ring */
1217 if (rte_ring_enqueue(p_nat->port_alloc_ring,
1219 printf("CGNAPT%d - Enqueue error - i %d,",
1220 p_nat->pipeline_num, i);
1221 printf("j %d, if_addrs %d, pb %p\n",
1223 rte_ring_dump(stdout,
1224 p_nat->port_alloc_ring);
1225 rte_mempool_put(napt_port_pool,
1230 /* reset j and advance i */
1232 i += max_ips_remain;
1240 printf("******* p_nat->pub_ip_count:%d ***********\n",
1241 p_nat->pub_ip_count);
1242 /* Initialize all public IP's ports */
1244 uint32_t max_ports_remain;
1246 for (if_ports = 0; if_ports < p_nat->pub_ip_count; if_ports++) {
1247 /* Add all available ports to the ring */
1249 for (i = p_nat->pub_ip_port_set[if_ports].start_port;
1250 i <= p_nat->pub_ip_port_set[if_ports].end_port;) {
1251 /* 1. Get a port alloc buffer from napt_port_pool */
1255 /* get new napt_port_alloc_elem from pool */
1256 if (rte_mempool_get(napt_port_pool, &portsBuf) <
1258 printf("CGNAPT - Error in getting "
1259 "port alloc buffer\n");
1264 /* 2. Populate it with available ports and ip addr */
1265 struct napt_port_alloc_elem *pb =
1266 (struct napt_port_alloc_elem *)portsBuf;
1269 temp = p_nat->pub_ip_port_set[if_ports].end_port -
1271 /* Check if remaining port count is greater
1272 * than or equals to bulk count, if not give
1273 * remaining count ports than giving bulk count
1275 if (temp < NUM_NAPT_PORT_BULK_ALLOC)
1276 max_ports_remain = temp;
1279 NUM_NAPT_PORT_BULK_ALLOC;
1281 for (j = 0; j < max_ports_remain; j++) {
1284 p_nat->pub_ip_port_set[if_ports].ip;
1285 pb->ports[j] = i + j;
1286 if ((i + j) == p_nat->pub_ip_port_set
1287 [if_ports].end_port)
1291 /* 3. add the port alloc buffer to ring */
1292 if (rte_ring_enqueue(p_nat->port_alloc_ring,
1294 printf("CGNAPT%d - Enqueue error - i %d, j %d, "
1295 " if_ports %d, pb %p\n", p_nat->pipeline_num,
1296 i, j, if_ports, pb);
1298 rte_ring_dump(stdout, p_nat->port_alloc_ring);
1299 rte_mempool_put(napt_port_pool, portsBuf);
1303 /* reset j and advance i */
1305 i += max_ports_remain;
1312 static pipeline_msg_req_handler handlers[] = {
1313 [PIPELINE_MSG_REQ_PING] =
1314 pipeline_msg_req_ping_handler,
1315 [PIPELINE_MSG_REQ_STATS_PORT_IN] =
1316 pipeline_msg_req_stats_port_in_handler,
1317 [PIPELINE_MSG_REQ_STATS_PORT_OUT] =
1318 pipeline_msg_req_stats_port_out_handler,
1319 [PIPELINE_MSG_REQ_STATS_TABLE] = pipeline_msg_req_stats_table_handler,
1320 [PIPELINE_MSG_REQ_PORT_IN_ENABLE] =
1321 pipeline_msg_req_port_in_enable_handler,
1322 [PIPELINE_MSG_REQ_PORT_IN_DISABLE] =
1323 pipeline_msg_req_port_in_disable_handler,
1324 [PIPELINE_MSG_REQ_CUSTOM] =
1325 pipeline_cgnapt_msg_req_custom_handler,
1328 static pipeline_msg_req_handler custom_handlers[] = {
1329 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_ADD] =
1330 pipeline_cgnapt_msg_req_entry_add_handler,
1331 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_DEL] =
1332 pipeline_cgnapt_msg_req_entry_del_handler,
1333 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_SYNC] =
1334 pipeline_cgnapt_msg_req_entry_sync_handler,
1335 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_DBG] =
1336 pipeline_cgnapt_msg_req_entry_dbg_handler,
1337 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_ADDM] =
1338 pipeline_cgnapt_msg_req_entry_addm_handler,
1339 [PIPELINE_CGNAPT_MSG_REQ_VER] =
1340 pipeline_cgnapt_msg_req_ver_handler,
1341 [PIPELINE_CGNAPT_MSG_REQ_NSP_ADD] =
1342 pipeline_cgnapt_msg_req_nsp_add_handler,
1343 [PIPELINE_CGNAPT_MSG_REQ_NSP_DEL] =
1344 pipeline_cgnapt_msg_req_nsp_del_handler,
1347 [PIPELINE_CGNAPT_MSG_REQ_PCP] =
1348 pipeline_cgnapt_msg_req_pcp_handler,
1353 * Function to convert an IPv6 packet to IPv4 packet
1356 * A pointer to packet mbuf
1357 * @param in_ipv6_hdr
1358 * A pointer to IPv6 header in the given pkt
1362 convert_ipv6_to_ipv4(struct rte_mbuf *pkt, struct ipv6_hdr *in_ipv6_hdr)
1364 uint32_t ip_hdr_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE;
1366 uint8_t *eth_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1367 uint8_t *ipv6_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, ip_hdr_offset);
1369 struct ether_hdr eth_hdr;
1370 struct ipv4_hdr *ipv4_hdr_p;
1371 uint16_t frag_off = 0x4000;
1372 struct cgnapt_nsp_node *ll = nsp_ll;
1373 uint8_t ipv4_dest[4];
1376 memcpy(ð_hdr, eth_hdr_p, sizeof(struct ether_hdr));
1377 memcpy(in_ipv6_hdr, ipv6_hdr_p, sizeof(struct ipv6_hdr));
1379 eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
1381 char *data_area_p = rte_pktmbuf_adj(pkt, 20);
1382 if (data_area_p == NULL) {
1383 printf("convert_ipv6_to_ipv4:data_area_p is NULL\n");
1386 ipv4_hdr_p = (struct ipv4_hdr *)(data_area_p + ETH_HDR_SIZE);
1387 memset(ipv4_hdr_p, 0, sizeof(struct ipv4_hdr));
1389 memcpy(data_area_p, ð_hdr, sizeof(struct ether_hdr));
1391 #ifdef CGNAPT_DBG_PRNT
1392 if (CGNAPT_DEBUG == 1)
1393 printf("convert_ipv6_to_ipv4: eth_hdr_p(%p), data_area_p(%p), "
1394 "ipv4_hdr_p(%p)\n", eth_hdr_p, data_area_p, ipv4_hdr_p);
1397 ipv4_hdr_p->version_ihl = 0x4 << 4 | 0x5;
1398 ipv4_hdr_p->type_of_service =
1399 rte_be_to_cpu_32(in_ipv6_hdr->vtc_flow) & 0x0ff00000 >> 20;
1400 ipv4_hdr_p->total_length =
1401 rte_cpu_to_be_16(rte_be_to_cpu_16(
1402 in_ipv6_hdr->payload_len) + 20);
1403 ipv4_hdr_p->packet_id = 0;
1404 ipv4_hdr_p->fragment_offset = rte_cpu_to_be_16(frag_off);
1405 ipv4_hdr_p->time_to_live = in_ipv6_hdr->hop_limits;
1406 ipv4_hdr_p->next_proto_id = in_ipv6_hdr->proto;
1407 ipv4_hdr_p->hdr_checksum = 0;
1408 ipv4_hdr_p->src_addr = 0;
1410 while (ll != NULL) {
1412 (&in_ipv6_hdr->dst_addr[0], &ll->nsp.prefix[0],
1413 ll->nsp.depth / 8)) {
1414 if (ll->nsp.depth == 32)
1415 memcpy(&ipv4_dest[0], &in_ipv6_hdr->dst_addr[4],
1417 else if (ll->nsp.depth == 40) {
1418 ipv4_dest[0] = in_ipv6_hdr->dst_addr[5];
1419 ipv4_dest[1] = in_ipv6_hdr->dst_addr[6];
1420 ipv4_dest[2] = in_ipv6_hdr->dst_addr[7];
1421 ipv4_dest[3] = in_ipv6_hdr->dst_addr[9];
1422 } else if (ll->nsp.depth == 48) {
1423 ipv4_dest[0] = in_ipv6_hdr->dst_addr[6];
1424 ipv4_dest[1] = in_ipv6_hdr->dst_addr[7];
1425 ipv4_dest[2] = in_ipv6_hdr->dst_addr[9];
1426 ipv4_dest[3] = in_ipv6_hdr->dst_addr[10];
1427 } else if (ll->nsp.depth == 56) {
1428 ipv4_dest[0] = in_ipv6_hdr->dst_addr[7];
1429 ipv4_dest[1] = in_ipv6_hdr->dst_addr[9];
1430 ipv4_dest[2] = in_ipv6_hdr->dst_addr[10];
1431 ipv4_dest[3] = in_ipv6_hdr->dst_addr[11];
1432 } else if (ll->nsp.depth == 64) {
1433 ipv4_dest[0] = in_ipv6_hdr->dst_addr[9];
1434 ipv4_dest[1] = in_ipv6_hdr->dst_addr[10];
1435 ipv4_dest[2] = in_ipv6_hdr->dst_addr[11];
1436 ipv4_dest[3] = in_ipv6_hdr->dst_addr[12];
1437 } else if (ll->nsp.depth == 96) {
1438 ipv4_dest[0] = in_ipv6_hdr->dst_addr[12];
1439 ipv4_dest[1] = in_ipv6_hdr->dst_addr[13];
1440 ipv4_dest[2] = in_ipv6_hdr->dst_addr[14];
1441 ipv4_dest[3] = in_ipv6_hdr->dst_addr[15];
1452 memcpy(&ipv4_hdr_p->dst_addr, &ipv4_dest[0], 4);
1454 memcpy(&ipv4_hdr_p->dst_addr, &in_ipv6_hdr->dst_addr[12], 4);
1459 * Function to convert an IPv4 packet to IPv6 packet
1462 * A pointer to packet mbuf
1463 * @param in_ipv4_hdr
1464 * A pointer to IPv4 header in the given pkt
1468 convert_ipv4_to_ipv6(struct rte_mbuf *pkt, struct ipv4_hdr *in_ipv4_hdr)
1470 uint32_t ip_hdr_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE;
1472 uint8_t *eth_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1473 uint8_t *ipv4_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, ip_hdr_offset);
1475 struct ether_hdr eth_hdr;
1476 struct ipv6_hdr *ipv6_hdr_p;
1478 memcpy(ð_hdr, eth_hdr_p, sizeof(struct ether_hdr));
1479 memcpy(in_ipv4_hdr, ipv4_hdr_p, sizeof(struct ipv4_hdr));
1481 eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
1483 char *data_area_p = rte_pktmbuf_prepend(pkt, 20);
1484 if (data_area_p == NULL) {
1485 printf("convert_ipv4_to_ipv6:data_area_p is NULL\n");
1488 ipv6_hdr_p = (struct ipv6_hdr *)(data_area_p + ETH_HDR_SIZE);
1489 memset(ipv6_hdr_p, 0, sizeof(struct ipv6_hdr));
1491 memcpy(data_area_p, ð_hdr, sizeof(struct ether_hdr));
1493 ipv6_hdr_p->vtc_flow =
1494 rte_cpu_to_be_32((0x6 << 28) |
1495 (in_ipv4_hdr->type_of_service << 20));
1496 ipv6_hdr_p->payload_len =
1497 rte_cpu_to_be_16(rte_be_to_cpu_16(
1498 in_ipv4_hdr->total_length) - 20);
1499 ipv6_hdr_p->proto = in_ipv4_hdr->next_proto_id;
1500 ipv6_hdr_p->hop_limits = in_ipv4_hdr->time_to_live;
1502 ipv6_hdr_p->src_addr[0] = 0x00;
1503 ipv6_hdr_p->src_addr[1] = 0x64;
1504 ipv6_hdr_p->src_addr[2] = 0xff;
1505 ipv6_hdr_p->src_addr[3] = 0x9b;
1506 ipv6_hdr_p->src_addr[4] = 0x00;
1507 ipv6_hdr_p->src_addr[5] = 0x00;
1508 ipv6_hdr_p->src_addr[6] = 0x00;
1509 ipv6_hdr_p->src_addr[7] = 0x00;
1510 ipv6_hdr_p->src_addr[8] = 0x00;
1511 ipv6_hdr_p->src_addr[9] = 0x00;
1512 ipv6_hdr_p->src_addr[10] = 0x00;
1513 ipv6_hdr_p->src_addr[11] = 0x00;
1514 memcpy(&ipv6_hdr_p->src_addr[12], &in_ipv4_hdr->src_addr, 4);
1516 memset(&ipv6_hdr_p->dst_addr, 0, 16);
1523 * Output port handler
1526 * A pointer to packet mbuf
1528 * Unused void pointer
1531 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1533 pkt_work_cgnapt_out(__rte_unused struct rte_mbuf *pkt, __rte_unused void *arg)
1535 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1536 if ((cgnapt_num_func_to_inst == 5)
1537 && (cgnapt_inst_index < INST_ARRAY_SIZE)) {
1538 if (cgnapt_inst5_flag == 0) {
1539 uint8_t *inst5_sig =
1540 RTE_MBUF_METADATA_UINT8_PTR(pkt,
1542 if (*inst5_sig == CGNAPT_INST5_SIG) {
1543 cgnapt_inst5_flag = 1;
1544 inst_end_time[cgnapt_inst_index] =
1545 rte_get_tsc_cycles();
1546 cgnapt_inst_index++;
1552 /* cgnapt_pkt_out_count++; */
1553 #ifdef CGNAPT_DBG_PRNT
1561 * Output port handler to handle 4 pkts
1564 * A pointer to packet mbuf
1566 * Inport handler argument pointer
1569 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1570 static void pkt4_work_cgnapt_out(struct rte_mbuf **pkt, void *arg)
1574 /* TO BE IMPLEMENTED IF REQUIRED */
1578 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1579 PIPELINE_CGNAPT_PORT_OUT_AH(port_out_ah_cgnapt,
1580 pkt_work_cgnapt_out, pkt4_work_cgnapt_out);
1582 PIPELINE_CGNAPT_PORT_OUT_BAH(port_out_ah_cgnapt_bulk,
1583 pkt_work_cgnapt_out, pkt4_work_cgnapt_out);
1587 * Function to validate the packet and return version
1590 * A pointer to packet mbuf
1593 * IP version of the valid pkt, -1 if invalid pkt
1595 int rte_get_pkt_ver(struct rte_mbuf *pkt)
1597 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
1598 uint16_t *eth_proto =
1599 RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
1601 if (*eth_proto == rte_be_to_cpu_16(ETHER_TYPE_IPv4))
1602 return IP_VERSION_4;
1604 if (dual_stack_enable
1605 && (*eth_proto == rte_be_to_cpu_16(ETHER_TYPE_IPv6)))
1606 return IP_VERSION_6;
1608 /* Check the protocol first, if not UDP or TCP return */
1614 * A method to print the NAPT entry
1617 * A pointer to struct cgnapt_table_entry
1619 void my_print_entry(struct cgnapt_table_entry *ent)
1621 printf("CGNAPT key:\n");
1622 printf("entry_type :%d\n", ent->data.type);
1623 printf("prv_ip: %x %x %x %x\n", ent->data.u.u32_prv_ipv6[0],
1624 ent->data.u.u32_prv_ipv6[1], ent->data.u.u32_prv_ipv6[2],
1625 ent->data.u.u32_prv_ipv6[3]);
1626 printf("prv_port:%d\n", ent->data.prv_port);
1628 printf("pub_ip:%x\n", ent->data.pub_ip);
1629 printf("prv_phy_port:%d\n", ent->data.prv_phy_port);
1630 printf("pub_phy_port:%d\n", ent->data.pub_phy_port);
1634 * Function to print common CGNAPT table entries
1637 void print_common_table(void)
1645 index = rte_hash_iterate(napt_common_table,
1646 &key, &data, &next);
1648 if ((index != -EINVAL) && (index != -ENOENT)) {
1649 printf("\n%04d ", count);
1650 //print_key((struct pipeline_cgnapt_entry_key *)key);
1651 rte_hexdump(stdout, "KEY", key,
1652 sizeof(struct pipeline_cgnapt_entry_key));
1653 int32_t position = rte_hash_lookup(
1654 napt_common_table, key);
1655 print_cgnapt_entry(&napt_hash_tbl_entries[position]);
1659 } while (index != -ENOENT);
1663 * Input port handler for mixed traffic
1664 * This is the main method in this file when running in mixed traffic mode.
1665 * Starting from the packet burst it filters unwanted packets,
1666 * calculates keys, does lookup and then based on the lookup
1667 * updates NAPT table and does packet NAPT translation.
1670 * A pointer to struct rte_pipeline
1672 * A pointer to array of packets mbuf
1674 * Number of packets in the burst
1679 * int that is not checked by caller
1682 static int cgnapt_in_port_ah_mix(struct rte_pipeline *rte_p,
1683 struct rte_mbuf **pkts,
1684 uint32_t n_pkts, void *arg)
1689 * 1. Read packet version, if invalid drop the packet
1690 * 2. Check protocol, if not UDP or TCP drop the packet
1691 * 3. Bring all valid packets together - useful for bulk lookup
1692 * and calculate key for all packets
1693 * a. If IPv4 : calculate key with full IP
1694 * b. If IPv6 : calculate key with last 32-bit of IP
1695 * 4. Do bulk lookup with rte_hash_lookup_bulk(), if something went wrong
1697 * 5. For lookup hit packets, read entry from table
1698 * 6. For lookup miss packets, add dynamic entry to table
1700 * a. If egress pkt, convert to IPv4 and NAPT it
1701 * b. If ingress, drop the pkt
1703 * a. If egress pkt, NAPT it. Get MAC
1704 * b. If first ingress pkt (with no egress entry), drop the pkt
1705 * If not first ingress pkt
1706 * I. If IPv6 converted packet, convert back to IPv6,
1708 * II. If IPv4 packet, NAPT it & get MAC
1709 * 9. Send all packets out to corresponding ports
1711 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
1712 struct pipeline_cgnapt *p_nat = ap->p;
1713 uint8_t compacting_map[RTE_HASH_LOOKUP_BULK_MAX];
1714 uint32_t packets_for_lookup = 0;
1717 p_nat->valid_packets = 0;
1718 p_nat->invalid_packets = 0;
1720 #ifdef CGNAPT_DBG_PRNT
1721 if (CGNAPT_DEBUG > 1)
1722 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
1725 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
1727 uint16_t phy_port = 0;
1728 uint16_t *src_port = NULL;
1729 uint16_t *dst_port = NULL;
1730 uint32_t *src_addr = NULL;
1731 uint32_t *dst_addr = NULL;
1732 uint8_t *protocol = NULL;
1733 uint8_t *eth_dest = NULL;
1734 uint8_t *eth_src = NULL;
1735 uint16_t src_port_offset = 0;
1736 uint16_t dst_port_offset = 0;
1737 uint16_t src_addr_offset = 0;
1738 uint16_t dst_addr_offset = 0;
1739 uint16_t prot_offset = 0;
1740 uint16_t eth_offset = 0;
1743 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
1745 src_port_offset = SRC_PRT_OFST_IP4_TCP;
1746 dst_port_offset = DST_PRT_OFST_IP4_TCP;
1748 for (i = 0; i < n_pkts; i++) {
1749 p_nat->receivedPktCount++;
1751 /* bitmask representing only this packet */
1752 uint64_t pkt_mask = 1LLU << i;
1754 /* remember this pkt as valid pkt */
1755 p_nat->valid_packets |= pkt_mask;
1757 struct rte_mbuf *pkt = pkts[i];
1760 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
1763 int ver = rte_get_pkt_ver(pkt);
1765 #ifdef CGNAPT_DBG_PRNT
1766 printf("ver no. of the pkt:%d\n", ver);
1769 if (unlikely(ver < 0)) {
1770 /* Not a valid pkt , ignore. */
1771 /* remember invalid packets to be dropped */
1772 p_nat->invalid_packets |= pkt_mask;
1773 p_nat->naptDroppedPktCount++;
1775 #ifdef CGNAPT_DEBUGGING
1776 p_nat->naptDroppedPktCount1++;
1781 prot_offset = PROT_OFST_IP4;
1783 prot_offset = PROT_OFST_IP6;
1785 (uint8_t *) RTE_MBUF_METADATA_UINT32_PTR(pkt,
1788 (*protocol == IP_PROTOCOL_TCP
1789 || *protocol == IP_PROTOCOL_UDP
1790 || *protocol == IP_PROTOCOL_ICMP)) {
1791 /* remember invalid packets to be dropped */
1792 p_nat->invalid_packets |= pkt_mask;
1793 p_nat->naptDroppedPktCount++;
1795 #ifdef CGNAPT_DEBUGGING
1796 p_nat->naptDroppedPktCount2++;
1801 #ifdef CGNAPT_DBG_PRNT
1802 if (CGNAPT_DEBUG > 4)
1808 * 1. Handel PCP for egress traffic
1809 * 2. If PCP, then give response (send pkt) from the same port
1810 * 3. Drop the PCP packet, should not be added in the NAPT table
1813 if (*protocol == IP_PROTOCOL_UDP) {
1814 struct udp_hdr *udp;
1816 udp = (struct udp_hdr *)
1817 RTE_MBUF_METADATA_UINT8_PTR(pkt,
1820 udp = (struct udp_hdr *)
1821 RTE_MBUF_METADATA_UINT8_PTR(pkt,
1824 if (rte_bswap16(udp->dst_port) ==
1826 handle_pcp_req(pkt, ver, p_nat);
1827 p_nat->invalid_packets |= pkt_mask;
1837 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1840 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1843 if ((*protocol == IP_PROTOCOL_TCP)
1844 || (*protocol == IP_PROTOCOL_UDP)) {
1846 src_port_offset = SRC_PRT_OFST_IP4_TCP;
1847 dst_port_offset = DST_PRT_OFST_IP4_TCP;
1849 } else if (*protocol == IP_PROTOCOL_ICMP) {
1851 src_port_offset = IDEN_OFST_IP4_ICMP;
1852 /* Sequence number */
1853 dst_port_offset = SEQN_OFST_IP4_ICMP;
1857 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1860 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1865 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1868 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1871 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1874 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1877 /* need to create compacted table of pointers to
1878 * pass to bulk lookup
1881 compacting_map[packets_for_lookup] = i;
1883 //phy_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, phyport_offset);
1884 phy_port = pkt->port;
1886 struct pipeline_cgnapt_entry_key key;
1888 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
1891 if (get_in_port_dir(phy_port)) {
1894 key.ip = rte_bswap32(*src_addr);
1896 key.ip = rte_bswap32(src_addr[3]);
1897 key.port = rte_bswap16(*src_port);
1899 #ifdef NAT_ONLY_CONFIG_REQ
1900 if (nat_only_config_flag)
1905 key.ip = rte_bswap32(*dst_addr);
1907 if (*protocol == IP_PROTOCOL_ICMP) {
1908 /* common table lookupkey preparation from
1909 * incoming ICMP Packet- Indentifier field
1911 key.port = rte_bswap16(*src_port);
1913 key.port = rte_bswap16(*dst_port);
1916 #ifdef NAT_ONLY_CONFIG_REQ
1917 if (nat_only_config_flag)
1924 memcpy(&(p_nat->keys[packets_for_lookup]), &key,
1925 sizeof(struct pipeline_cgnapt_entry_key));
1926 p_nat->key_ptrs[packets_for_lookup] =
1927 &(p_nat->keys[packets_for_lookup]);
1928 packets_for_lookup++;
1931 if (unlikely(packets_for_lookup == 0)) {
1932 /* no suitable packet for lookup */
1933 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
1934 return p_nat->valid_packets;
1937 /* lookup entries in the common napt table */
1939 int lookup_result = rte_hash_lookup_bulk(napt_common_table,
1943 &p_nat->lkup_indx[0]);
1945 if (unlikely(lookup_result < 0)) {
1946 /* unknown error, just discard all packets */
1947 printf("Unexpected hash lookup error %d, discarding all "
1948 "packets", lookup_result);
1949 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
1952 //struct rte_pipeline_table_entry *entries[64];
1953 /* Now one by one check the result of our bulk lookup */
1955 for (i = 0; i < packets_for_lookup; i++) {
1956 /* index into hash table entries */
1957 int hash_table_entry = p_nat->lkup_indx[i];
1958 /* index into packet table of this packet */
1959 uint8_t pkt_index = compacting_map[i];
1960 /*bitmask representing only this packet */
1961 uint64_t pkt_mask = 1LLU << pkt_index;
1963 struct cgnapt_table_entry *entry = NULL;
1964 if (hash_table_entry < 0) {
1966 /* try to add new entry */
1967 struct rte_pipeline_table_entry *table_entry = NULL;
1970 pkt_miss_cgnapt(p_nat->key_ptrs[i],
1973 &p_nat->valid_packets,
1978 /* ICMP Error message generation for
1979 * Destination Host unreachable
1981 if (*protocol == IP_PROTOCOL_ICMP) {
1982 cgnapt_icmp_pkt = pkts[pkt_index];
1983 send_icmp_dest_unreachable_msg();
1986 /* Drop packet by adding to invalid pkt mask */
1988 p_nat->invalid_packets |= dropmask;
1989 #ifdef CGNAPT_DEBUGGING
1990 if (p_nat->kpc2++ < 5) {
1991 printf("in_ah Th: %d",
1992 p_nat->pipeline_num);
1993 print_key(p_nat->key_ptrs[i]);
1997 p_nat->naptDroppedPktCount++;
1999 #ifdef CGNAPT_DEBUGGING
2000 p_nat->naptDroppedPktCount3++;
2005 entry = (struct cgnapt_table_entry *)table_entry;
2007 /* entry found for this packet */
2008 entry = &napt_hash_tbl_entries[hash_table_entry];
2011 /* apply napt and mac changes */
2013 p_nat->entries[pkt_index] = &(entry->head);
2015 phy_port = pkts[pkt_index]->port;
2017 struct ipv6_hdr ipv6_hdr;
2018 struct ipv4_hdr ipv4_hdr;
2020 ver = rte_get_pkt_ver(pkts[pkt_index]);
2021 #ifdef CGNAPT_DEBUGGING
2022 if (CGNAPT_DEBUG >= 1) {
2023 printf("ver:%d\n", ver);
2024 printf("entry->data.type:%d\n", entry->data.type);
2027 if ((ver == 6) && (entry->data.type == CGNAPT_ENTRY_IPV6)
2028 && is_phy_port_privte(phy_port)) {
2029 convert_ipv6_to_ipv4(pkts[pkt_index], &ipv6_hdr);
2031 pkt_type = PKT_TYPE_IPV6to4;
2033 #ifdef CGNAPT_DBG_PRNT
2034 if (CGNAPT_DEBUG >= 1)
2035 printf("pkt_work_cganpt: "
2036 "convert_ipv6_to_ipv4\n");
2039 struct cgnapt_nsp_node *ll = nsp_ll;
2041 while (ll != NULL) {
2042 if (!memcmp(&ipv6_hdr.dst_addr[0],
2044 ll->nsp.depth / 8)) {
2052 && !memcmp(&ipv6_hdr.dst_addr[0],
2053 &well_known_prefix[0], 12)) {
2058 p_nat->invalid_packets |= 1LLU << pkt_index;
2059 p_nat->naptDroppedPktCount++;
2061 #ifdef CGNAPT_DEBUGGING
2062 p_nat->naptDroppedPktCount5++;
2069 /* As packet is already converted into IPv4 we must not operate
2070 * IPv6 offsets on packet
2071 * Only perform IPv4 operations
2076 src_port_offset = SRC_PRT_OFST_IP6t4;
2077 dst_port_offset = DST_PRT_OFST_IP6t4;
2078 src_addr_offset = SRC_ADR_OFST_IP6t4;
2079 dst_addr_offset = DST_ADR_OFST_IP6t4;
2080 prot_offset = PROT_OFST_IP6t4;
2081 eth_offset = ETH_OFST_IP6t4;
2085 if ((*protocol == IP_PROTOCOL_TCP)
2086 || (*protocol == IP_PROTOCOL_UDP)) {
2087 src_port_offset = SRC_PRT_OFST_IP4_TCP;
2088 dst_port_offset = DST_PRT_OFST_IP4_TCP;
2089 } else if (*protocol == IP_PROTOCOL_ICMP) {
2091 src_port_offset = IDEN_OFST_IP4_ICMP;
2092 /* Sequence number */
2093 dst_port_offset = SEQN_OFST_IP4_ICMP;
2096 src_addr_offset = SRC_ADR_OFST_IP4;
2097 dst_addr_offset = DST_ADR_OFST_IP4;
2098 prot_offset = PROT_OFST_IP4;
2099 eth_offset = MBUF_HDR_ROOM;
2104 RTE_MBUF_METADATA_UINT32_PTR(pkts[pkt_index],
2107 RTE_MBUF_METADATA_UINT32_PTR(pkts[pkt_index],
2110 RTE_MBUF_METADATA_UINT16_PTR(pkts[pkt_index],
2113 RTE_MBUF_METADATA_UINT16_PTR(pkts[pkt_index],
2116 RTE_MBUF_METADATA_UINT8_PTR(pkts[pkt_index],
2120 RTE_MBUF_METADATA_UINT8_PTR(pkts[pkt_index],
2123 RTE_MBUF_METADATA_UINT8_PTR(pkts[pkt_index],
2126 if (entry->data.ttl == NAPT_ENTRY_STALE)
2127 entry->data.ttl = NAPT_ENTRY_VALID;
2129 struct ether_addr hw_addr;
2130 uint32_t dest_address = 0;
2131 uint8_t nh_ipv6[16];
2134 uint32_t dest_if = 0xff;
2137 uint16_t *outport_id =
2138 RTE_MBUF_METADATA_UINT16_PTR(pkts[pkt_index],
2139 cgnapt_meta_offset);
2141 if (is_phy_port_privte(phy_port)) {
2143 if (*protocol == IP_PROTOCOL_UDP
2144 && rte_be_to_cpu_16(*dst_port) == 53) {
2145 p_nat->invalid_packets |= 1LLU << pkt_index;
2146 p_nat->naptDroppedPktCount++;
2147 #ifdef CGNAPT_DEBUGGING
2148 p_nat->naptDroppedPktCount6++;
2153 dest_address = rte_bswap32(*dst_addr);
2154 ret = local_get_nh_ipv4(dest_address, &dest_if,
2157 dest_if = get_prv_to_pub_port(&dest_address,
2159 if (dest_if == INVALID_DESTIF) {
2160 p_nat->invalid_packets |=
2162 p_nat->naptDroppedPktCount++;
2163 #ifdef CGNAPT_DEBUGGING
2164 p_nat->naptDroppedPktCount6++;
2168 do_local_nh_ipv4_cache(dest_if, p_nat);
2171 *outport_id = p_nat->outport_id[dest_if];
2173 ret = get_dest_mac_addr_port(dest_address,
2174 &dest_if, &hw_addr);
2176 if (ret == ARP_FOUND) {
2177 memcpy(eth_dest, &hw_addr,
2178 sizeof(struct ether_addr));
2179 memcpy(eth_src, get_link_hw_addr(dest_if),
2180 sizeof(struct ether_addr));
2181 #ifdef CGNAPT_DBG_PRNT
2182 if (CGNAPT_DEBUG > 2) {
2183 printf("MAC found for ip 0x%x, port %d - "
2184 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2185 dest_address, *outport_id,
2186 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
2187 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
2188 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
2190 printf("Dest MAC before - "
2191 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2192 eth_dest[0], eth_dest[1], eth_dest[2],
2193 eth_dest[3], eth_dest[4], eth_dest[5]);
2197 #ifdef CGNAPT_DBG_PRNT
2198 if (CGNAPT_DEBUG > 2) {
2199 printf("Dest MAC after - "
2200 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2201 eth_dest[0], eth_dest[1], eth_dest[2],
2202 eth_dest[3], eth_dest[4], eth_dest[5]);
2206 #ifdef CGNAPT_DBG_PRNT
2207 if (CGNAPT_DEBUG > 4)
2208 print_pkt(pkts[pkt_index]);
2212 if (ret == ARP_NOT_FOUND) {
2213 /* Commented code may be required
2214 * for future use, Please keep it */
2215 //request_arp(*outport_id, nhip,
2217 printf("%s: ARP Not Found, nhip: %x, "
2218 "outport_id: %d\n", __func__, nhip,
2222 p_nat->invalid_packets |= pkt_mask;
2223 p_nat->naptDroppedPktCount++;
2224 #ifdef CGNAPT_DEBUGGING
2225 p_nat->naptDroppedPktCount4++;
2230 #ifdef CGNAPT_DBG_PRNT
2231 if (CGNAPT_DEBUG > 2)
2232 printf("Egress: \tphy_port:%d\t "
2233 "get_prv_to_pub():%d \tout_port:%d\n",
2239 *src_addr = rte_bswap32(entry->data.pub_ip);
2241 #ifdef NAT_ONLY_CONFIG_REQ
2242 if (!nat_only_config_flag) {
2244 *src_port = rte_bswap16(entry->data.pub_port);
2245 #ifdef NAT_ONLY_CONFIG_REQ
2249 p_nat->enaptedPktCount++;
2252 if (*protocol == IP_PROTOCOL_UDP
2253 && rte_be_to_cpu_16(*src_port) == 53) {
2254 p_nat->invalid_packets |= 1LLU << pkt_index;
2255 p_nat->naptDroppedPktCount++;
2256 #ifdef CGNAPT_DEBUGGING
2257 p_nat->naptDroppedPktCount6++;
2262 #ifdef CGNAPT_DBG_PRNT
2263 if (CGNAPT_DEBUG > 2)
2264 printf("Ingress: \tphy_port:%d\t "
2265 "get_pub_to_prv():%d \tout_port%d\n",
2270 if (entry->data.type == CGNAPT_ENTRY_IPV6) {
2271 convert_ipv4_to_ipv6(pkts[pkt_index],
2273 pkt_type = PKT_TYPE_IPV4to6;
2274 /* Ethernet MTU check */
2275 if ((rte_pktmbuf_data_len(pkts[pkt_index]) -
2277 p_nat->invalid_packets |= pkt_mask;
2278 p_nat->naptDroppedPktCount++;
2282 eth_dest = eth_dest - 20;
2283 eth_src = eth_src - 20;
2285 dst_port_offset = DST_PRT_OFST_IP4t6;
2286 dst_addr_offset = DST_ADR_OFST_IP4t6;
2288 RTE_MBUF_METADATA_UINT32_PTR(
2292 RTE_MBUF_METADATA_UINT16_PTR(
2296 memcpy((uint8_t *) &dst_addr[0],
2297 &entry->data.u.prv_ipv6[0], 16);
2298 memset(nh_ipv6, 0, 16);
2300 ret = local_get_nh_ipv6((uint8_t *)&dst_addr[0],
2301 &dest_if, &nh_ipv6[0], p_nat);
2304 dest_if = get_prv_to_pub_port(
2307 if (dest_if == INVALID_DESTIF) {
2308 p_nat->invalid_packets |=
2310 p_nat->naptDroppedPktCount++;
2311 #ifdef CGNAPT_DEBUGGING
2312 p_nat->naptDroppedPktCount6++;
2316 do_local_nh_ipv6_cache(dest_if, p_nat);
2318 *outport_id = p_nat->outport_id[dest_if];
2320 if (get_dest_mac_address_ipv6_port((uint8_t *)
2321 &dst_addr[0], &dest_if,
2322 &hw_addr, &nh_ipv6[0])){
2324 #ifdef CGNAPT_DBG_PRNT
2325 if (CGNAPT_DEBUG > 2) {
2326 printf("MAC found for ip 0x%x, port %d - "
2327 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2328 dest_address, *outport_id,
2329 hw_addr.addr_bytes[0],
2330 hw_addr.addr_bytes[1], hw_addr.addr_bytes[2],
2331 hw_addr.addr_bytes[3], hw_addr.addr_bytes[4],
2332 hw_addr.addr_bytes[5]);
2334 printf("Dest MAC before - "
2335 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2336 eth_dest[0], eth_dest[1], eth_dest[2],
2337 eth_dest[3], eth_dest[4], eth_dest[5]);
2340 memcpy(eth_dest, &hw_addr,
2341 sizeof(struct ether_addr));
2342 memcpy(eth_src, get_link_hw_addr(
2344 sizeof(struct ether_addr));
2346 #ifdef CGNAPT_DBG_PRNT
2347 if (CGNAPT_DEBUG > 2) {
2348 printf("Dest MAC after - "
2349 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2350 eth_dest[0], eth_dest[1], eth_dest[2],
2351 eth_dest[3], eth_dest[4], eth_dest[5]);
2355 #ifdef CGNAPT_DBG_PRNT
2356 if (CGNAPT_DEBUG > 4)
2357 print_pkt(pkts[pkt_index]);
2361 p_nat->invalid_packets |= pkt_mask;
2362 p_nat->naptDroppedPktCount++;
2363 #ifdef CGNAPT_DEBUGGING
2364 p_nat->naptDroppedPktCount4++;
2369 #ifdef NAT_ONLY_CONFIG_REQ
2370 if (!nat_only_config_flag) {
2373 rte_bswap16(entry->data.prv_port);
2374 #ifdef NAT_ONLY_CONFIG_REQ
2379 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
2380 dest_address = entry->data.u.prv_ip;
2381 ret = local_get_nh_ipv4(dest_address, &dest_if,
2384 dest_if = get_pub_to_prv_port(
2385 &dest_address, IP_VERSION_4);
2386 if (dest_if == INVALID_DESTIF) {
2387 p_nat->invalid_packets |=
2389 p_nat->naptDroppedPktCount++;
2390 #ifdef CGNAPT_DEBUGGING
2391 p_nat->naptDroppedPktCount6++;
2395 do_local_nh_ipv4_cache(dest_if, p_nat);
2398 *outport_id = p_nat->outport_id[dest_if];
2400 ret = get_dest_mac_addr_port(dest_address,
2401 &dest_if, &hw_addr);
2403 if (ret == ARP_FOUND) {
2404 memcpy(eth_dest, &hw_addr,
2405 sizeof(struct ether_addr));
2406 memcpy(eth_src, get_link_hw_addr(
2408 sizeof(struct ether_addr));
2409 #ifdef CGNAPT_DBG_PRNT
2410 if (CGNAPT_DEBUG > 2) {
2411 printf("MAC found for ip 0x%x, port %d - "
2412 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2413 dest_address, *outport_id,
2414 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
2415 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
2416 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
2418 printf("Dest MAC before - "
2419 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2420 eth_dest[0], eth_dest[1], eth_dest[2],
2421 eth_dest[3], eth_dest[4], eth_dest[5]);
2425 #ifdef CGNAPT_DBG_PRNT
2426 if (CGNAPT_DEBUG > 2) {
2427 printf("Dest MAC after - "
2428 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2429 eth_dest[0], eth_dest[1], eth_dest[2],
2430 eth_dest[3], eth_dest[4], eth_dest[5]);
2434 #ifdef CGNAPT_DBG_PRNT
2435 if (CGNAPT_DEBUG > 4)
2436 print_pkt(pkts[pkt_index]);
2440 if (ret == ARP_NOT_FOUND) {
2441 printf("%s: ARP Not Found, nhip: %x, "
2442 "outport_id: %d\n", __func__, nhip,
2445 //request_arp(*outport_id,
2446 // nhip, p_nat->p.p);
2447 p_nat->invalid_packets |= pkt_mask;
2448 p_nat->naptDroppedPktCount++;
2449 #ifdef CGNAPT_DEBUGGING
2450 p_nat->naptDroppedPktCount4++;
2455 if (*protocol == IP_PROTOCOL_ICMP) {
2456 // Query ID reverse translation done here
2458 rte_bswap16(entry->data.prv_port);
2460 #ifdef NAT_ONLY_CONFIG_REQ
2461 if (!nat_only_config_flag) {
2466 #ifdef NAT_ONLY_CONFIG_REQ
2472 p_nat->inaptedPktCount++;
2475 p_nat->naptedPktCount++;
2478 if (p_nat->hw_checksum_reqd)
2479 hw_checksum(pkts[pkt_index], pkt_type);
2481 sw_checksum(pkts[pkt_index], pkt_type);
2485 if (p_nat->invalid_packets) {
2486 /* get rid of invalid packets */
2487 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2489 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2491 #ifdef CGNAPT_DBG_PRNT
2492 if (CGNAPT_DEBUG > 1) {
2493 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
2494 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
2495 printf("invalid_packets:0x%jx\n",
2496 p_nat->invalid_packets);
2497 printf("rte_invalid_packets :0x%jx\n",
2498 rte_p->pkts_drop_mask);
2499 printf("Total pkts dropped :0x%jx\n",
2500 rte_p->n_pkts_ah_drop);
2505 return p_nat->valid_packets;
2509 * Input port handler for IPv4 private traffic
2510 * Starting from the packet burst it filters unwanted packets,
2511 * calculates keys, does lookup and then based on the lookup
2512 * updates NAPT table and does packet NAPT translation.
2515 * A pointer to struct rte_pipeline
2517 * A pointer to array of packets mbuf
2519 * Number of packets in the burst
2524 * int that is not checked by caller
2527 static int cgnapt_in_port_ah_ipv4_prv(struct rte_pipeline *rte_p,
2528 struct rte_mbuf **pkts,
2529 uint32_t n_pkts, void *arg)
2532 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
2533 struct pipeline_cgnapt *p_nat = ap->p;
2535 #ifdef CGNAPT_TIMING_INST
2536 uint64_t entry_timestamp = 0, exit_timestamp;
2538 if (p_nat->time_measurements_on) {
2539 entry_timestamp = rte_get_tsc_cycles();
2540 /* check since exit ts not valid first time through */
2541 if (likely(p_nat->in_port_exit_timestamp))
2542 p_nat->external_time_sum +=
2543 entry_timestamp - p_nat->in_port_exit_timestamp;
2547 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
2548 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
2549 p_nat->invalid_packets = 0;
2551 #ifdef CGNAPT_DBG_PRNT
2552 if (CGNAPT_DEBUG > 1)
2553 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
2556 /* prefetching for mbufs should be done here */
2557 for (j = 0; j < n_pkts; j++)
2558 rte_prefetch0(pkts[j]);
2560 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2561 pkt4_work_cgnapt_key_ipv4_prv(&pkts[i], i, arg, p_nat);
2563 for (; i < n_pkts; i++)
2564 pkt_work_cgnapt_key_ipv4_prv(pkts[i], i, arg, p_nat);
2566 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2568 if (unlikely(p_nat->valid_packets == 0)) {
2569 /* no suitable packet for lookup */
2570 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2571 return p_nat->valid_packets;
2574 /* lookup entries in the common napt table */
2576 int lookup_result = rte_hash_lookup_bulk(
2578 (const void **)&p_nat->key_ptrs,
2579 /* should be minus num invalid pkts */
2581 /*new pipeline data member */
2582 &p_nat->lkup_indx[0]);
2584 if (unlikely(lookup_result < 0)) {
2585 /* unknown error, just discard all packets */
2586 printf("Unexpected hash lookup error %d, discarding "
2587 "all packets", lookup_result);
2588 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
2592 /* Now call second stage of pipeline to one by one
2593 * check the result of our bulk lookup
2596 /* prefetching for table entries should be done here */
2597 for (j = 0; j < n_pkts; j++) {
2598 if (p_nat->lkup_indx[j] >= 0)
2599 rte_prefetch0(&napt_hash_tbl_entries
2600 [p_nat->lkup_indx[j]]);
2603 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2604 pkt4_work_cgnapt_ipv4_prv(pkts, i, arg, p_nat);
2606 for (; i < n_pkts; i++)
2607 pkt_work_cgnapt_ipv4_prv(pkts, i, arg, p_nat);
2609 if (p_nat->invalid_packets) {
2610 /* get rid of invalid packets */
2611 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2613 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2615 #ifdef CGNAPT_DBG_PRNT
2616 if (CGNAPT_DEBUG > 1) {
2617 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
2618 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
2619 printf("invalid_packets:0x%jx\n",
2620 p_nat->invalid_packets);
2621 printf("rte_invalid_packets :0x%jx\n",
2622 rte_p->pkts_drop_mask);
2623 printf("Total pkts dropped :0x%jx\n",
2624 rte_p->n_pkts_ah_drop);
2629 #ifdef CGNAPT_TIMING_INST
2630 if (p_nat->time_measurements_on) {
2631 exit_timestamp = rte_get_tsc_cycles();
2632 p_nat->in_port_exit_timestamp = exit_timestamp;
2633 p_nat->internal_time_sum += exit_timestamp - entry_timestamp;
2634 p_nat->time_measurements++;
2635 if (p_nat->time_measurements == p_nat->max_time_mesurements)
2636 p_nat->time_measurements_on = 0;
2640 return p_nat->valid_packets;
2644 * Input port handler for IPv4 public traffic
2645 * Starting from the packet burst it filters unwanted packets,
2646 * calculates keys, does lookup and then based on the lookup
2647 * updates NAPT table and does packet NAPT translation.
2650 * A pointer to struct rte_pipeline
2652 * A pointer to array of packets mbuf
2654 * Number of packets in the burst
2659 * int that is not checked by caller
2661 static int cgnapt_in_port_ah_ipv4_pub(struct rte_pipeline *rte_p,
2662 struct rte_mbuf **pkts,
2663 uint32_t n_pkts, void *arg)
2666 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
2667 struct pipeline_cgnapt *p_nat = ap->p;
2669 #ifdef CGNAPT_TIMING_INST
2670 uint64_t entry_timestamp = 0, exit_timestamp;
2672 if (p_nat->time_measurements_on) {
2673 entry_timestamp = rte_get_tsc_cycles();
2675 /* check since exit ts not valid first time through */
2676 if (likely(p_nat->in_port_exit_timestamp))
2677 p_nat->external_time_sum +=
2678 entry_timestamp - p_nat->in_port_exit_timestamp;
2682 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
2683 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
2684 p_nat->invalid_packets = 0;
2686 #ifdef CGNAPT_DBG_PRNT
2687 if (CGNAPT_DEBUG > 1)
2688 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
2691 /* prefetching for mbufs should be done here */
2692 for (j = 0; j < n_pkts; j++)
2693 rte_prefetch0(pkts[j]);
2695 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2696 pkt4_work_cgnapt_key_ipv4_pub(&pkts[i], i, arg, p_nat);
2698 for (; i < n_pkts; i++)
2699 pkt_work_cgnapt_key_ipv4_pub(pkts[i], i, arg, p_nat);
2701 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2703 if (unlikely(p_nat->valid_packets == 0)) {
2704 /* no suitable packet for lookup */
2705 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2706 return p_nat->valid_packets;
2709 /* lookup entries in the common napt table */
2711 int lookup_result = rte_hash_lookup_bulk(
2713 (const void **)&p_nat->key_ptrs,
2714 /* should be minus num invalid pkts */
2716 /*new pipeline data member */
2717 &p_nat->lkup_indx[0]);
2719 if (unlikely(lookup_result < 0)) {
2720 /* unknown error, just discard all packets */
2721 printf("Unexpected hash lookup error %d, discarding "
2722 "all packets", lookup_result);
2723 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
2727 /* Now call second stage of pipeline to one by one
2728 * check the result of our bulk lookup
2731 /* prefetching for table entries should be done here */
2732 for (j = 0; j < n_pkts; j++) {
2733 if (p_nat->lkup_indx[j] >= 0)
2734 rte_prefetch0(&napt_hash_tbl_entries
2735 [p_nat->lkup_indx[j]]);
2738 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2739 pkt4_work_cgnapt_ipv4_pub(pkts, i, arg, p_nat);
2741 for (; i < n_pkts; i++)
2742 pkt_work_cgnapt_ipv4_pub(pkts, i, arg, p_nat);
2744 if (p_nat->invalid_packets) {
2745 /* get rid of invalid packets */
2746 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2748 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2750 #ifdef CGNAPT_DBG_PRNT
2751 if (CGNAPT_DEBUG > 1) {
2752 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
2753 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
2754 printf("invalid_packets:0x%jx\n",
2755 p_nat->invalid_packets);
2756 printf("rte_invalid_packets :0x%jx\n",
2757 rte_p->pkts_drop_mask);
2758 printf("Total pkts dropped :0x%jx\n",
2759 rte_p->n_pkts_ah_drop);
2764 #ifdef CGNAPT_TIMING_INST
2765 if (p_nat->time_measurements_on) {
2766 exit_timestamp = rte_get_tsc_cycles();
2767 p_nat->in_port_exit_timestamp = exit_timestamp;
2769 p_nat->internal_time_sum += exit_timestamp - entry_timestamp;
2770 p_nat->time_measurements++;
2771 if (p_nat->time_measurements == p_nat->max_time_mesurements)
2772 p_nat->time_measurements_on = 0;
2776 return p_nat->valid_packets;
2780 * NAPT key calculation function for IPv4 private traffic
2781 * which handles 4 pkts
2784 * A pointer to array of packets mbuf
2786 * Starting pkt number of pkts
2790 * A pointer to main CGNAPT structure
2794 pkt4_work_cgnapt_key_ipv4_prv(
2795 struct rte_mbuf **pkt,
2797 __rte_unused void *arg,
2798 struct pipeline_cgnapt *p_nat)
2800 p_nat->receivedPktCount += 4;
2801 /* bitmask representing only this packet */
2802 uint64_t pkt_mask0 = 1LLU << pkt_num;
2803 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
2804 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
2805 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
2807 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
2809 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
2811 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
2813 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
2816 uint32_t src_addr0 = RTE_MBUF_METADATA_UINT32(pkt[0],
2818 uint32_t src_addr1 = RTE_MBUF_METADATA_UINT32(pkt[1],
2820 uint32_t src_addr2 = RTE_MBUF_METADATA_UINT32(pkt[2],
2822 uint32_t src_addr3 = RTE_MBUF_METADATA_UINT32(pkt[3],
2825 uint16_t src_port_offset0;
2826 uint16_t src_port_offset1;
2827 uint16_t src_port_offset2;
2828 uint16_t src_port_offset3;
2835 uint16_t phy_port0 = pkt[0]->port;
2836 uint16_t phy_port1 = pkt[1]->port;
2837 uint16_t phy_port2 = pkt[2]->port;
2838 uint16_t phy_port3 = pkt[3]->port;
2840 struct pipeline_cgnapt_entry_key key0;
2841 struct pipeline_cgnapt_entry_key key1;
2842 struct pipeline_cgnapt_entry_key key2;
2843 struct pipeline_cgnapt_entry_key key3;
2845 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
2846 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
2847 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
2848 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
2851 #ifdef CGNAPT_DBG_PRNT
2852 if (CGNAPT_DEBUG > 4)
2857 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
2861 switch (protocol0) {
2862 case IP_PROTOCOL_UDP:
2866 struct udp_hdr *udp;
2868 udp = (struct udp_hdr *)
2869 RTE_MBUF_METADATA_UINT8_PTR(pkt[0],
2872 if (rte_bswap16(udp->dst_port) ==
2874 handle_pcp_req(pkt[0], IPV4_SZ, p_nat);
2875 p_nat->invalid_packets |= pkt_mask0;
2881 case IP_PROTOCOL_TCP:
2883 src_port_offset0 = SRC_PRT_OFST_IP4_TCP;
2884 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
2889 case IP_PROTOCOL_ICMP:
2891 src_port_offset0 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
2893 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
2899 /* remember invalid packets to be dropped */
2900 p_nat->invalid_packets |= pkt_mask0;
2901 p_nat->naptDroppedPktCount++;
2903 #ifdef CGNAPT_DEBUGGING
2904 p_nat->naptDroppedPktCount2++;
2909 key0.pid = phy_port0;
2910 key0.ip = rte_bswap32(src_addr0);
2911 key0.port = rte_bswap16(src_port0);
2913 #ifdef NAT_ONLY_CONFIG_REQ
2914 if (nat_only_config_flag)
2918 memcpy(&p_nat->keys[pkt_num], &key0,
2919 sizeof(struct pipeline_cgnapt_entry_key));
2920 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
2925 #ifdef CGNAPT_DBG_PRNT
2926 if (CGNAPT_DEBUG > 4)
2931 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
2934 switch (protocol1) {
2935 case IP_PROTOCOL_UDP:
2939 struct udp_hdr *udp;
2941 udp = (struct udp_hdr *)
2942 RTE_MBUF_METADATA_UINT8_PTR(pkt[1],
2945 if (rte_bswap16(udp->dst_port) ==
2947 handle_pcp_req(pkt[1], IPV4_SZ, p_nat);
2948 p_nat->invalid_packets |= pkt_mask1;
2954 case IP_PROTOCOL_TCP:
2956 src_port_offset1 = SRC_PRT_OFST_IP4_TCP;
2957 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
2962 case IP_PROTOCOL_ICMP:
2964 src_port_offset1 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
2966 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
2972 /* remember invalid packets to be dropped */
2973 p_nat->invalid_packets |= pkt_mask1;
2974 p_nat->naptDroppedPktCount++;
2976 #ifdef CGNAPT_DEBUGGING
2977 p_nat->naptDroppedPktCount2++;
2982 key1.pid = phy_port1;
2983 key1.ip = rte_bswap32(src_addr1);
2984 key1.port = rte_bswap16(src_port1);
2986 #ifdef NAT_ONLY_CONFIG_REQ
2987 if (nat_only_config_flag)
2991 memcpy(&p_nat->keys[pkt_num + 1], &key1,
2992 sizeof(struct pipeline_cgnapt_entry_key));
2993 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
2997 #ifdef CGNAPT_DBG_PRNT
2998 if (CGNAPT_DEBUG > 4)
3003 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
3007 switch (protocol2) {
3008 case IP_PROTOCOL_UDP:
3012 struct udp_hdr *udp;
3014 udp = (struct udp_hdr *)
3015 RTE_MBUF_METADATA_UINT8_PTR(pkt[2],
3018 if (rte_bswap16(udp->dst_port) ==
3020 handle_pcp_req(pkt[2], IPV4_SZ, p_nat);
3021 p_nat->invalid_packets |= pkt_mask2;
3027 case IP_PROTOCOL_TCP:
3029 src_port_offset2 = SRC_PRT_OFST_IP4_TCP;
3030 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3035 case IP_PROTOCOL_ICMP:
3037 src_port_offset2 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3039 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3045 /* remember invalid packets to be dropped */
3046 p_nat->invalid_packets |= pkt_mask2;
3047 p_nat->naptDroppedPktCount++;
3049 #ifdef CGNAPT_DEBUGGING
3050 p_nat->naptDroppedPktCount2++;
3055 key2.pid = phy_port2;
3056 key2.ip = rte_bswap32(src_addr2);
3057 key2.port = rte_bswap16(src_port2);
3059 #ifdef NAT_ONLY_CONFIG_REQ
3060 if (nat_only_config_flag)
3064 memcpy(&p_nat->keys[pkt_num + 2], &key2,
3065 sizeof(struct pipeline_cgnapt_entry_key));
3066 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
3070 #ifdef CGNAPT_DBG_PRNT
3071 if (CGNAPT_DEBUG > 4)
3075 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
3079 switch (protocol3) {
3080 case IP_PROTOCOL_UDP:
3084 struct udp_hdr *udp;
3086 udp = (struct udp_hdr *)
3087 RTE_MBUF_METADATA_UINT8_PTR(pkt[3],
3090 if (rte_bswap16(udp->dst_port) ==
3092 handle_pcp_req(pkt[3], IPV4_SZ, p_nat);
3093 p_nat->invalid_packets |= pkt_mask3;
3099 case IP_PROTOCOL_TCP:
3101 src_port_offset3 = SRC_PRT_OFST_IP4_TCP;
3102 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3107 case IP_PROTOCOL_ICMP:
3109 src_port_offset3 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3111 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3117 /* remember invalid packets to be dropped */
3118 p_nat->invalid_packets |= pkt_mask3;
3119 p_nat->naptDroppedPktCount++;
3121 #ifdef CGNAPT_DEBUGGING
3122 p_nat->naptDroppedPktCount2++;
3127 key3.pid = phy_port3;
3128 key3.ip = rte_bswap32(src_addr3);
3129 key3.port = rte_bswap16(src_port3);
3131 #ifdef NAT_ONLY_CONFIG_REQ
3132 if (nat_only_config_flag)
3136 memcpy(&p_nat->keys[pkt_num + 3], &key3,
3137 sizeof(struct pipeline_cgnapt_entry_key));
3138 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
3142 * NAPT key calculation function for IPv4 public traffic
3143 * which handles 4 pkts
3146 * A pointer to array of packets mbuf
3148 * Starting pkt number of pkts
3152 * A pointer to main CGNAPT structure
3156 pkt4_work_cgnapt_key_ipv4_pub(
3157 struct rte_mbuf **pkt,
3159 __rte_unused void *arg,
3160 struct pipeline_cgnapt *p_nat)
3162 p_nat->receivedPktCount += 4;
3163 /* bitmask representing only this packet */
3164 uint64_t pkt_mask0 = 1LLU << pkt_num;
3165 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
3166 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
3167 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
3169 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
3171 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
3173 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
3175 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
3178 uint32_t dst_addr0 = RTE_MBUF_METADATA_UINT32(pkt[0],
3180 uint32_t dst_addr1 = RTE_MBUF_METADATA_UINT32(pkt[1],
3182 uint32_t dst_addr2 = RTE_MBUF_METADATA_UINT32(pkt[2],
3184 uint32_t dst_addr3 = RTE_MBUF_METADATA_UINT32(pkt[3],
3187 uint16_t src_port_offset0;
3188 uint16_t src_port_offset1;
3189 uint16_t src_port_offset2;
3190 uint16_t src_port_offset3;
3192 uint16_t dst_port_offset0;
3193 uint16_t dst_port_offset1;
3194 uint16_t dst_port_offset2;
3195 uint16_t dst_port_offset3;
3207 struct pipeline_cgnapt_entry_key key0;
3208 struct pipeline_cgnapt_entry_key key1;
3209 struct pipeline_cgnapt_entry_key key2;
3210 struct pipeline_cgnapt_entry_key key3;
3212 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
3213 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
3214 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
3215 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
3218 #ifdef CGNAPT_DBG_PRNT
3219 if (CGNAPT_DEBUG > 4)
3224 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
3228 switch (protocol0) {
3229 case IP_PROTOCOL_UDP:
3230 case IP_PROTOCOL_TCP:
3232 src_port_offset0 = SRC_PRT_OFST_IP4_TCP;
3233 dst_port_offset0 = DST_PRT_OFST_IP4_TCP;
3235 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3237 dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3240 key0.port = rte_bswap16(dst_port0);
3244 case IP_PROTOCOL_ICMP:
3246 src_port_offset0 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3248 /*Sequence number */
3249 dst_port_offset0 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3252 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3254 dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3257 key0.port = rte_bswap16(src_port0);
3262 /* remember invalid packets to be dropped */
3263 p_nat->invalid_packets |= pkt_mask0;
3264 p_nat->naptDroppedPktCount++;
3266 #ifdef CGNAPT_DEBUGGING
3267 p_nat->naptDroppedPktCount2++;
3273 key0.ip = rte_bswap32(dst_addr0);
3275 #ifdef NAT_ONLY_CONFIG_REQ
3276 if (nat_only_config_flag)
3280 memcpy(&p_nat->keys[pkt_num], &key0,
3281 sizeof(struct pipeline_cgnapt_entry_key));
3282 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3287 #ifdef CGNAPT_DBG_PRNT
3288 if (CGNAPT_DEBUG > 4)
3293 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
3297 switch (protocol1) {
3298 case IP_PROTOCOL_UDP:
3299 case IP_PROTOCOL_TCP:
3301 src_port_offset1 = SRC_PRT_OFST_IP4_TCP;
3302 dst_port_offset1 = DST_PRT_OFST_IP4_TCP;
3304 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3306 dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3309 key1.port = rte_bswap16(dst_port1);
3313 case IP_PROTOCOL_ICMP:
3315 src_port_offset1 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3317 /*Sequence number */
3318 dst_port_offset1 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3321 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3323 dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3326 key1.port = rte_bswap16(src_port1);
3330 /* remember invalid packets to be dropped */
3331 p_nat->invalid_packets |= pkt_mask1;
3332 p_nat->naptDroppedPktCount++;
3334 #ifdef CGNAPT_DEBUGGING
3335 p_nat->naptDroppedPktCount2++;
3341 key1.ip = rte_bswap32(dst_addr1);
3343 #ifdef NAT_ONLY_CONFIG_REQ
3344 if (nat_only_config_flag)
3348 memcpy(&p_nat->keys[pkt_num + 1], &key1,
3349 sizeof(struct pipeline_cgnapt_entry_key));
3350 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
3354 #ifdef CGNAPT_DBG_PRNT
3355 if (CGNAPT_DEBUG > 4)
3360 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
3364 switch (protocol2) {
3365 case IP_PROTOCOL_UDP:
3366 case IP_PROTOCOL_TCP:
3368 src_port_offset2 = SRC_PRT_OFST_IP4_TCP;
3369 dst_port_offset2 = DST_PRT_OFST_IP4_TCP;
3371 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3373 dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3376 key2.port = rte_bswap16(dst_port2);
3380 case IP_PROTOCOL_ICMP:
3382 src_port_offset2 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3384 /*Sequence number */
3385 dst_port_offset2 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3388 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3390 dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3393 key2.port = rte_bswap16(src_port2);
3398 /* remember invalid packets to be dropped */
3399 p_nat->invalid_packets |= pkt_mask2;
3400 p_nat->naptDroppedPktCount++;
3402 #ifdef CGNAPT_DEBUGGING
3403 p_nat->naptDroppedPktCount2++;
3409 key2.ip = rte_bswap32(dst_addr2);
3411 #ifdef NAT_ONLY_CONFIG_REQ
3412 if (nat_only_config_flag)
3416 memcpy(&p_nat->keys[pkt_num + 2], &key2,
3417 sizeof(struct pipeline_cgnapt_entry_key));
3418 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
3422 #ifdef CGNAPT_DBG_PRNT
3423 if (CGNAPT_DEBUG > 4)
3428 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
3432 switch (protocol3) {
3433 case IP_PROTOCOL_UDP:
3434 case IP_PROTOCOL_TCP:
3436 src_port_offset3 = SRC_PRT_OFST_IP4_TCP;
3437 dst_port_offset3 = DST_PRT_OFST_IP4_TCP;
3439 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3441 dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3444 key3.port = rte_bswap16(dst_port3);
3448 case IP_PROTOCOL_ICMP:
3450 src_port_offset3 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3452 /*Sequence number */
3453 dst_port_offset3 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3456 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3458 dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3461 key3.port = rte_bswap16(src_port3);
3466 /* remember invalid packets to be dropped */
3467 p_nat->invalid_packets |= pkt_mask3;
3468 p_nat->naptDroppedPktCount++;
3470 #ifdef CGNAPT_DEBUGGING
3471 p_nat->naptDroppedPktCount2++;
3477 key3.ip = rte_bswap32(dst_addr3);
3479 #ifdef NAT_ONLY_CONFIG_REQ
3480 if (nat_only_config_flag)
3484 memcpy(&p_nat->keys[pkt_num + 3], &key3,
3485 sizeof(struct pipeline_cgnapt_entry_key));
3486 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
3490 * NAPT key calculation function for IPv4 private traffic
3491 * which handles 1 pkt
3494 * A pointer to array of packets mbuf
3496 * Pkt number of pkts
3500 * A pointer to main CGNAPT structure
3504 pkt_work_cgnapt_key_ipv4_prv(
3505 struct rte_mbuf *pkt,
3507 __rte_unused void *arg,
3508 struct pipeline_cgnapt *p_nat)
3511 p_nat->receivedPktCount++;
3513 /* bitmask representing only this packet */
3514 uint64_t pkt_mask = 1LLU << pkt_num;
3515 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3517 uint32_t src_addr = RTE_MBUF_METADATA_UINT32(pkt, SRC_ADR_OFST_IP4);
3519 uint16_t src_port_offset;
3523 uint16_t phy_port = pkt->port;
3524 struct pipeline_cgnapt_entry_key key;
3526 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
3529 #ifdef CGNAPT_DBG_PRNT
3530 if (CGNAPT_DEBUG > 4)
3535 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
3540 case IP_PROTOCOL_UDP:
3544 struct udp_hdr *udp;
3546 udp = (struct udp_hdr *)
3547 RTE_MBUF_METADATA_UINT8_PTR(pkt,
3550 if (rte_bswap16(udp->dst_port) ==
3552 handle_pcp_req(pkt, IPV4_SZ, p_nat);
3553 p_nat->invalid_packets |= pkt_mask;
3559 case IP_PROTOCOL_TCP:
3561 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3562 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3564 key.port = rte_bswap16(src_port);
3567 case IP_PROTOCOL_ICMP:
3569 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3571 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3573 key.port = rte_bswap16(src_port);
3577 /* remember invalid packets to be dropped */
3578 p_nat->invalid_packets |= pkt_mask;
3579 p_nat->naptDroppedPktCount++;
3581 #ifdef CGNAPT_DEBUGGING
3582 p_nat->naptDroppedPktCount2++;
3588 key.ip = rte_bswap32(src_addr);
3590 #ifdef NAT_ONLY_CONFIG_REQ
3591 if (nat_only_config_flag)
3595 memcpy(&p_nat->keys[pkt_num], &key,
3596 sizeof(struct pipeline_cgnapt_entry_key));
3597 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3601 * NAPT key calculation function for IPv4 public traffic
3602 * which handles 1 pkt
3605 * A pointer to array of packets mbuf
3607 * Pkt number of pkts
3611 * A pointer to main CGNAPT structure
3615 pkt_work_cgnapt_key_ipv4_pub(
3616 struct rte_mbuf *pkt,
3618 __rte_unused void *arg,
3619 struct pipeline_cgnapt *p_nat)
3621 p_nat->receivedPktCount++;
3623 /* bitmask representing only this packet */
3624 uint64_t pkt_mask = 1LLU << pkt_num;
3625 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3626 uint32_t dst_addr = RTE_MBUF_METADATA_UINT32(pkt, DST_ADR_OFST_IP4);
3627 uint16_t src_port_offset;
3628 uint16_t dst_port_offset;
3631 struct pipeline_cgnapt_entry_key key;
3632 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
3634 #ifdef CGNAPT_DBG_PRNT
3635 if (CGNAPT_DEBUG > 4)
3640 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
3645 case IP_PROTOCOL_UDP:
3646 case IP_PROTOCOL_TCP:
3647 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3648 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3650 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3651 dst_port = RTE_MBUF_METADATA_UINT16(pkt, dst_port_offset);
3653 key.port = rte_bswap16(dst_port);
3655 case IP_PROTOCOL_ICMP:
3657 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3659 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3662 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3663 dst_port = RTE_MBUF_METADATA_UINT16(pkt, dst_port_offset);
3665 /* common table lookupkey preparation from incoming
3666 * ICMP Packet- Indentifier field
3668 key.port = rte_bswap16(src_port);
3671 /* remember invalid packets to be dropped */
3672 p_nat->invalid_packets |= pkt_mask;
3673 p_nat->naptDroppedPktCount++;
3675 #ifdef CGNAPT_DEBUGGING
3676 p_nat->naptDroppedPktCount2++;
3681 key.ip = rte_bswap32(dst_addr);
3683 #ifdef NAT_ONLY_CONFIG_REQ
3684 if (nat_only_config_flag)
3690 memcpy(&p_nat->keys[pkt_num], &key,
3691 sizeof(struct pipeline_cgnapt_entry_key));
3692 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3697 * NAPT function for IPv4 private traffic which handles 1 pkt
3700 * A pointer to array of packet mbuf
3706 * A pointer to main CGNAPT structure
3710 pkt_work_cgnapt_ipv4_prv(
3711 struct rte_mbuf **pkts,
3713 __rte_unused void *arg,
3714 struct pipeline_cgnapt *p_nat)
3717 struct rte_CT_helper ct_helper;
3718 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
3721 /* index into hash table entries */
3722 int hash_table_entry = p_nat->lkup_indx[pkt_num];
3723 /*bitmask representing only this packet */
3724 uint64_t pkt_mask = 1LLU << pkt_num;
3725 struct rte_mbuf *pkt = pkts[pkt_num];
3727 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3729 uint32_t dest_if = 0xff; /* Added for Multiport */
3730 uint16_t *outport_id =
3731 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
3733 struct cgnapt_table_entry *entry = NULL;
3735 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
3737 if (hash_table_entry < 0) {
3739 /* try to add new entry */
3740 struct rte_pipeline_table_entry *table_entry = NULL;
3742 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
3744 &p_nat->valid_packets, pkt_num,
3748 /* ICMP Error message generation for Destination
3751 if (protocol == IP_PROTOCOL_ICMP) {
3752 cgnapt_icmp_pkt = pkt;
3753 send_icmp_dest_unreachable_msg();
3756 /* Drop packet by adding to invalid pkt mask */
3758 p_nat->invalid_packets |= dropmask;
3759 #ifdef CGNAPT_DEBUGGING
3760 if (p_nat->kpc2++ < 5) {
3761 printf("in_ah Th: %d", p_nat->pipeline_num);
3762 print_key(p_nat->key_ptrs[pkt_num]);
3766 p_nat->naptDroppedPktCount++;
3768 #ifdef CGNAPT_DEBUGGING
3769 p_nat->naptDroppedPktCount3++;
3774 entry = (struct cgnapt_table_entry *)table_entry;
3776 /* entry found for this packet */
3777 entry = &napt_hash_tbl_entries[hash_table_entry];
3780 /* apply napt and mac changes */
3782 p_nat->entries[pkt_num] = &(entry->head);
3784 uint32_t *src_addr =
3785 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP4);
3786 uint32_t *dst_addr =
3787 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
3788 uint16_t src_port_offset = 0;
3789 uint16_t dst_port_offset = 0;
3794 case IP_PROTOCOL_TCP:
3795 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3796 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3797 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3798 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3801 if ((rte_be_to_cpu_16(*src_port) == 21) ||
3802 rte_be_to_cpu_16(*dst_port) == 21) {
3805 printf("cgnapt_ct_process: pkt_mask: % "PRIu64", "
3806 "pkt_num: %d\n", pkt_mask, pkt_num);
3809 pkt_mask = cgnapt_ct_process(cgnat_cnxn_tracker, pkts,
3810 pkt_mask, &ct_helper);
3814 case IP_PROTOCOL_UDP:
3815 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3816 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3817 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3818 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3820 case IP_PROTOCOL_ICMP:
3822 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3824 /*Sequence number */
3825 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3827 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3828 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3832 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
3833 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
3835 if (entry->data.ttl == NAPT_ENTRY_STALE)
3836 entry->data.ttl = NAPT_ENTRY_VALID;
3838 struct ether_addr hw_addr;
3839 uint32_t dest_address = 0;
3842 if (unlikely(protocol == IP_PROTOCOL_UDP
3843 && rte_be_to_cpu_16(*dst_port) == 53)) {
3844 p_nat->invalid_packets |= pkt_mask;
3845 p_nat->naptDroppedPktCount++;
3847 #ifdef CGNAPT_DEBUGGING
3848 p_nat->naptDroppedPktCount6++;
3853 dest_address = rte_bswap32(*dst_addr);
3854 /*Multiport Changes */
3857 ret = local_get_nh_ipv4(dest_address, &dest_if, &nhip, p_nat);
3859 dest_if = get_prv_to_pub_port(&dest_address, IP_VERSION_4);
3861 if (dest_if == INVALID_DESTIF) {
3862 p_nat->invalid_packets |= pkt_mask;
3863 p_nat->naptDroppedPktCount++;
3864 #ifdef CGNAPT_DEBUGGING
3865 p_nat->naptDroppedPktCount6++;
3870 do_local_nh_ipv4_cache(dest_if, p_nat);
3873 *outport_id = p_nat->outport_id[dest_if];
3875 #ifdef CGNAPT_DBG_PRNT
3876 if (CGNAPT_DEBUG > 2)
3877 printf("Egress: \tphy_port:%d\t get_prv_to_pub():%d "
3878 "\tout_port:%d\n", pkt->port, dest_if,
3882 if (local_dest_mac_present(dest_if)) {
3884 get_local_link_hw_addr(dest_if),
3885 sizeof(struct ether_addr));
3886 memcpy(eth_src, get_link_hw_addr(dest_if),
3887 sizeof(struct ether_addr));
3890 ret = get_dest_mac_addr_port(dest_address, &dest_if, &hw_addr);
3892 if (unlikely(ret != ARP_FOUND)) {
3894 if (unlikely(ret == ARP_NOT_FOUND)) {
3895 //request_arp(*outport_id, nhip, p_nat->p.p);
3896 printf("%s: ARP Not Found, nhip: %x, "
3897 "outport_id: %d\n", __func__, nhip,
3902 p_nat->invalid_packets |= pkt_mask;
3903 p_nat->naptDroppedPktCount++;
3905 #ifdef CGNAPT_DEBUGGING
3906 p_nat->naptDroppedPktCount4++;
3912 #ifdef CGNAPT_DBG_PRNT
3913 if (CGNAPT_DEBUG > 2) {
3914 printf("MAC found for ip 0x%x, port %d - %02x:%02x: "
3915 "%02x:%02x:%02x:%02x\n", dest_address,
3917 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
3918 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
3919 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
3921 printf("Dest MAC before - %02x:%02x:%02x: "
3922 "%02x:%02x:%02x\n", eth_dest[0], eth_dest[1],
3923 eth_dest[2], eth_dest[3], eth_dest[4], eth_dest[5]);
3928 memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
3930 link_hw_laddr_valid[dest_if] = 1;
3931 memcpy(&link_hw_laddr[dest_if], &hw_addr,
3932 sizeof(struct ether_addr));
3934 #ifdef CGNAPT_DBG_PRNT
3935 if (CGNAPT_DEBUG > 2) {
3936 printf("Dest MAC after - %02x:%02x:%02x:%02x:%02x"
3937 ":%02x\n", eth_dest[0], eth_dest[1], eth_dest[2],
3938 eth_dest[3], eth_dest[4], eth_dest[5]);
3942 memcpy(eth_src, get_link_hw_addr(dest_if),
3943 sizeof(struct ether_addr));
3948 *src_addr = rte_bswap32(entry->data.pub_ip);
3951 #ifdef NAT_ONLY_CONFIG_REQ
3952 if (!nat_only_config_flag) {
3954 *src_port = rte_bswap16(entry->data.pub_port);
3955 #ifdef NAT_ONLY_CONFIG_REQ
3960 uint16_t rtp_port = 0, rtcp_port = 0;
3961 struct cgnapt_table_entry *entry_ptr1 = NULL,
3962 *entry_ptr2 = NULL, *entry_ptr3 = NULL,
3965 if (unlikely(protocol == IP_PROTOCOL_UDP
3966 && (rte_be_to_cpu_16(*dst_port) == 5060
3967 || rte_be_to_cpu_16(*src_port) == 5060))) {
3969 int ret = natSipAlgGetAudioPorts(pkt, &rtp_port,
3971 /* Commented code may be required for debug
3972 * and future use, Please keep it*/
3975 printf("%s: Wrong SIP ALG packet1\n",
3977 p_nat->invalid_packets |= pkt_mask;
3979 p_nat->naptDroppedPktCount++;
3981 #ifdef CGNAPT_DEBUGGING
3982 p_nat->naptDroppedPktCount4++;
3988 if (ret >= 0 && rtp_port != 0) {
3989 struct pipeline_cgnapt_entry_key rtp_key;
3990 rtp_key.ip = entry->data.u.prv_ip;
3991 rtp_key.port = rtp_port;
3992 rtp_key.pid = entry->data.prv_phy_port;
3994 if (add_dynamic_cgnapt_entry_alg(
3995 (struct pipeline *)p_nat, &rtp_key,
3996 &entry_ptr1, &entry_ptr2) == 0) {
3997 printf("%s: Wrong SIP ALG packet2\n",
3999 p_nat->invalid_packets |= pkt_mask;
4001 p_nat->naptDroppedPktCount++;
4003 #ifdef CGNAPT_DEBUGGING
4004 p_nat->naptDroppedPktCount4++;
4010 if (ret >= 0 && rtcp_port != 0) {
4011 struct pipeline_cgnapt_entry_key rtcp_key;
4012 rtcp_key.ip = entry->data.u.prv_ip;
4013 rtcp_key.port = rtcp_port;
4014 rtcp_key.pid = entry->data.prv_phy_port;
4016 if (add_dynamic_cgnapt_entry_alg(
4017 (struct pipeline *)p_nat, &rtcp_key,
4018 &entry_ptr3, &entry_ptr4) == 0) {
4019 printf("%s: Wrong SIP ALG packet3\n",
4021 p_nat->invalid_packets |= pkt_mask;
4023 p_nat->naptDroppedPktCount++;
4025 #ifdef CGNAPT_DEBUGGING
4026 p_nat->naptDroppedPktCount4++;
4032 //if(entry_ptr1 != NULL && entry_ptr3 != NULL)
4033 if (sip_alg_dpi(pkt, PRIVATE, entry->data.pub_ip,
4034 entry->data.pub_port, entry->data.u.prv_ip,
4035 entry->data.prv_port, (rtp_port == 0) ? 0 :
4036 entry_ptr1->data.pub_port,
4037 (rtcp_port == 0) ? 0 :
4038 entry_ptr3->data.pub_port) == 0) {
4040 printf("%s: Wrong SIP ALG packet4\n",
4042 p_nat->invalid_packets |= pkt_mask;
4044 p_nat->naptDroppedPktCount++;
4046 #ifdef CGNAPT_DEBUGGING
4047 p_nat->naptDroppedPktCount4++;
4052 #endif /* SIP_ALG */
4057 printf("@CGNAT-pktwork ct_position :%d, pkt_num %d pkt_mask= "
4058 "%" PRIu64 "\n", ct_position, pkt_num, pkt_mask);
4061 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4062 rte_be_to_cpu_16(*dst_port) == 21) {
4064 int32_t ct_position = cgnat_cnxn_tracker->positions[pkt_num];
4065 if (ct_position < 0){
4066 p_nat->invalid_packets |= pkt_mask;
4067 p_nat->naptDroppedPktCount++;
4070 /* Commented code may be required for future usage,
4073 //if (cgnat_cnxn_tracker->hash_table_entries
4074 // [ct_position].alg_bypass_flag != BYPASS)
4076 struct pipeline_cgnapt_entry_key data_channel_entry_key;
4078 data_channel_entry_key.ip = entry->data.pub_ip;
4079 data_channel_entry_key.port = entry->data.pub_port;
4080 data_channel_entry_key.pid = pkt->port;
4081 ftp_alg_dpi(p_nat, &data_channel_entry_key, pkt,
4082 cgnat_cnxn_tracker, ct_position, PRIVATE);
4085 #endif /* FTP_ALG */
4087 p_nat->enaptedPktCount++;
4090 p_nat->naptedPktCount++;
4093 if (p_nat->hw_checksum_reqd)
4094 hw_checksum(pkt, pkt_type);
4096 sw_checksum(pkt, pkt_type);
4103 * NAPT function for IPv4 public traffic which handles 1 pkt
4106 * A pointer to array of packet mbuf
4112 * A pointer to main CGNAPT structure
4116 pkt_work_cgnapt_ipv4_pub(
4117 struct rte_mbuf **pkts,
4119 __rte_unused void *arg,
4120 struct pipeline_cgnapt *p_nat)
4124 struct rte_CT_helper ct_helper;
4125 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4128 /* index into hash table entries */
4129 int hash_table_entry = p_nat->lkup_indx[pkt_num];
4130 /*bitmask representing only this packet */
4131 uint64_t pkt_mask = 1LLU << pkt_num;
4132 struct rte_mbuf *pkt = pkts[pkt_num];
4134 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
4136 uint32_t dest_if = 0xff; /* Added for Multiport */
4137 uint16_t *outport_id =
4138 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
4140 struct cgnapt_table_entry *entry = NULL;
4142 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4144 if (hash_table_entry < 0) {
4146 /* try to add new entry */
4147 struct rte_pipeline_table_entry *table_entry = NULL;
4149 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
4151 &p_nat->valid_packets, pkt_num,
4155 /* ICMP Error message generation for
4156 * Destination Host unreachable
4158 if (protocol == IP_PROTOCOL_ICMP) {
4159 cgnapt_icmp_pkt = pkt;
4160 send_icmp_dest_unreachable_msg();
4163 /* Drop packet by adding to invalid pkt mask */
4165 p_nat->invalid_packets |= dropmask;
4166 #ifdef CGNAPT_DEBUGGING
4167 if (p_nat->kpc2++ < 5) {
4168 printf("in_ah Th: %d", p_nat->pipeline_num);
4169 print_key(p_nat->key_ptrs[pkt_num]);
4173 p_nat->naptDroppedPktCount++;
4175 #ifdef CGNAPT_DEBUGGING
4176 p_nat->naptDroppedPktCount3++;
4181 entry = (struct cgnapt_table_entry *)table_entry;
4183 /* entry found for this packet */
4184 entry = &napt_hash_tbl_entries[hash_table_entry];
4187 /* apply napt and mac changes */
4189 p_nat->entries[pkt_num] = &(entry->head);
4191 uint32_t *dst_addr =
4192 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4193 uint16_t src_port_offset = 0;
4194 uint16_t dst_port_offset = 0;
4196 if ((protocol == IP_PROTOCOL_TCP) || (protocol == IP_PROTOCOL_UDP)) {
4197 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4198 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4199 } else if (protocol == IP_PROTOCOL_ICMP) {
4201 src_port_offset = MBUF_HDR_ROOM +
4204 /*Sequence number */
4205 dst_port_offset = MBUF_HDR_ROOM +
4210 uint16_t *src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
4211 uint16_t *dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
4213 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4214 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4216 if (entry->data.ttl == NAPT_ENTRY_STALE)
4217 entry->data.ttl = NAPT_ENTRY_VALID;
4219 struct ether_addr hw_addr;
4220 uint32_t dest_address = 0;
4222 /* Multiport Changes */
4228 if (unlikely(protocol == IP_PROTOCOL_UDP
4229 && rte_be_to_cpu_16(*src_port) == 53)) {
4230 p_nat->invalid_packets |= pkt_mask;
4231 p_nat->naptDroppedPktCount++;
4232 #ifdef CGNAPT_DEBUGGING
4233 p_nat->naptDroppedPktCount6++;
4238 dest_address = entry->data.u.prv_ip;
4240 ret = local_get_nh_ipv4(dest_address, &dest_if, &nhip, p_nat);
4242 dest_if = get_prv_to_pub_port(&dest_address, IP_VERSION_4);
4244 if (dest_if == INVALID_DESTIF) {
4245 p_nat->invalid_packets |= pkt_mask;
4246 p_nat->naptDroppedPktCount++;
4247 #ifdef CGNAPT_DEBUGGING
4248 p_nat->naptDroppedPktCount6++;
4253 do_local_nh_ipv4_cache(dest_if, p_nat);
4256 *outport_id = p_nat->outport_id[dest_if];
4258 #ifdef CGNAPT_DBG_PRNT
4259 if (CGNAPT_DEBUG > 2)
4260 printf("Ingress: \tphy_port:%d\t get_pub_to_prv():%d "
4261 "\tout_port%d\n", pkt->port, dest_if, *outport_id);
4265 if (local_dest_mac_present(dest_if)) {
4267 get_local_link_hw_addr(dest_if),
4268 sizeof(struct ether_addr));
4269 memcpy(eth_src, get_link_hw_addr(dest_if),
4270 sizeof(struct ether_addr));
4273 ret = get_dest_mac_addr_port(dest_address, &dest_if, &hw_addr);
4275 if (unlikely(ret != ARP_FOUND)) {
4277 if (unlikely(ret == ARP_NOT_FOUND)) {
4278 /* Commented code may be required for debug
4279 * and future use, Please keep it */
4280 //request_arp(*outport_id, nhip, p_nat->p.p);
4281 printf("%s: ARP Not Found, nhip: %x, "
4282 "outport_id: %d\n", __func__, nhip,
4288 p_nat->invalid_packets |= pkt_mask;
4289 p_nat->naptDroppedPktCount++;
4291 #ifdef CGNAPT_DEBUGGING
4292 p_nat->naptDroppedPktCount4++;
4297 #ifdef CGNAPT_DBG_PRNT
4298 if (CGNAPT_DEBUG > 2) {
4300 ("MAC found for ip 0x%x, port %d - %02x:%02x: "
4301 "%02x:%02x:%02x:%02x\n", dest_address,
4303 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
4304 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
4305 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]
4309 ("Dest MAC before - %02x:%02x:%02x:%02x "
4310 ":%02x:%02x\n", eth_dest[0], eth_dest[1],
4311 eth_dest[2], eth_dest[3], eth_dest[4],
4316 memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
4318 link_hw_laddr_valid[dest_if] = 1;
4319 memcpy(&link_hw_laddr[dest_if], &hw_addr,
4320 sizeof(struct ether_addr));
4322 #ifdef CGNAPT_DBG_PRNT
4323 if (CGNAPT_DEBUG > 2) {
4324 printf("Dest MAC after - "
4325 "%02x:%02x:%02x:%02x:%02x:%02x\n",
4326 eth_dest[0], eth_dest[1], eth_dest[2], eth_dest[3],
4327 eth_dest[4], eth_dest[5]);
4331 memcpy(eth_src, get_link_hw_addr(dest_if),
4332 sizeof(struct ether_addr));
4338 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
4339 if (protocol == IP_PROTOCOL_ICMP) {
4340 /* Query ID reverse translation done here */
4341 /* dont care sequence num */
4342 *src_port = rte_bswap16(entry->data.prv_port);
4345 #ifdef NAT_ONLY_CONFIG_REQ
4346 if (!nat_only_config_flag) {
4348 *dst_port = rte_bswap16(entry->data.prv_port);
4350 #ifdef NAT_ONLY_CONFIG_REQ
4354 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4355 rte_be_to_cpu_16(*dst_port) == 21) {
4356 pkt_mask = cgnapt_ct_process(cgnat_cnxn_tracker, pkts,
4357 pkt_mask, &ct_helper);
4363 uint16_t rtp_port = 0, rtcp_port = 0;
4364 struct cgnapt_table_entry *entry_ptr1 = NULL,
4367 /* Commented code may be required for debug
4368 * and future use, Please keep it */
4370 struct cgnapt_table_entry *entry_ptr2 = NULL,
4374 if (unlikely(protocol == IP_PROTOCOL_UDP
4375 && (rte_be_to_cpu_16(*dst_port) == 5060
4376 || rte_be_to_cpu_16(*src_port) == 5060))) {
4377 /* Commented code may be required for future usage,
4381 int ret = natSipAlgGetAudioPorts(pkt, &rtp_port,
4384 printf("%s: Wrong SIP ALG packet1\n",
4386 p_nat->invalid_packets |= pkt_mask;
4388 p_nat->naptDroppedPktCount++;
4390 #ifdef CGNAPT_DEBUGGING
4391 p_nat->naptDroppedPktCount4++;
4395 if (rtp_port != 0) {
4396 struct pipeline_cgnapt_entry_key rtp_key;
4397 rtp_key.ip = entry->data.pub_ip;
4398 rtp_key.port = rtp_port;
4399 rtp_key.pid = 0xffff;
4401 if (retrieve_cgnapt_entry_alg(&rtp_key,
4402 &entry_ptr1, &entry_ptr2) == 0) {
4403 printf("%s: Wrong SIP ALG packet2\n",
4405 p_nat->invalid_packets |= pkt_mask;
4407 p_nat->naptDroppedPktCount++;
4409 #ifdef CGNAPT_DEBUGGING
4410 p_nat->naptDroppedPktCount4++;
4416 if (rtcp_port != 0) {
4417 struct pipeline_cgnapt_entry_key rtcp_key;
4418 rtcp_key.ip = entry->data.pub_ip;
4419 rtcp_key.port = rtcp_port;
4420 rtcp_key.pid = 0xffff;
4422 if (retrieve_cgnapt_entry_alg(&rtcp_key,
4423 &entry_ptr3, &entry_ptr4) == 0) {
4424 printf("%s: Wrong SIP ALG packet3\n",
4426 p_nat->invalid_packets |= pkt_mask;
4428 p_nat->naptDroppedPktCount++;
4430 #ifdef CGNAPT_DEBUGGING
4431 p_nat->naptDroppedPktCount4++;
4439 if (sip_alg_dpi(pkt, PUBLIC, entry->data.u.prv_ip,
4440 entry->data.prv_port, entry->data.pub_ip,
4441 entry->data.pub_port, (rtp_port == 0) ? 0 :
4442 entry_ptr1->data.prv_port,
4443 (rtcp_port == 0) ? 0 :
4444 entry_ptr3->data.prv_port) == 0) {
4446 printf("%s: Wrong SIP ALG packet4\n",
4448 p_nat->invalid_packets |= pkt_mask;
4450 p_nat->naptDroppedPktCount++;
4452 #ifdef CGNAPT_DEBUGGING
4453 p_nat->naptDroppedPktCount4++;
4459 #endif /* SIP_ALG */
4462 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4463 rte_be_to_cpu_16(*dst_port) == 21) {
4464 int32_t ct_position = cgnat_cnxn_tracker->
4466 if (ct_position < 0){
4467 p_nat->invalid_packets |= pkt_mask;
4469 p_nat->naptDroppedPktCount++;
4473 rte_hexdump(stdout, "CT Entry", &cgnat_cnxn_tracker->
4474 hash_table_entries[ct_position].key, 40);
4477 /* Commented code may be required for debug
4478 * and future use, Please keep it*/
4479 //if (cgnat_cnxn_tracker->hash_table_entries
4480 // [ct_position].alg_bypass_flag != BYPASS)
4483 struct pipeline_cgnapt_entry_key
4484 data_channel_entry_key;
4486 data_channel_entry_key.ip = entry->data.pub_ip;
4487 data_channel_entry_key.port = entry->data.pub_port;
4488 data_channel_entry_key.pid = 0xffff;
4489 //printf("pkt_work_pub ftp_alg_dpi\n");
4490 ftp_alg_dpi(p_nat, &data_channel_entry_key, pkt,
4491 cgnat_cnxn_tracker, ct_position, PUBLIC);
4497 p_nat->inaptedPktCount++;
4500 p_nat->naptedPktCount++;
4503 if (p_nat->hw_checksum_reqd)
4504 hw_checksum(pkt, pkt_type);
4506 sw_checksum(pkt, pkt_type);
4512 * NAPT function for IPv4 private traffic which handles 4 pkts
4515 * A pointer to array of packets mbuf
4517 * Starting pkt number of pkts
4521 * A pointer to main CGNAPT structure
4525 pkt4_work_cgnapt_ipv4_prv(
4526 struct rte_mbuf **pkts,
4527 uint32_t in_pkt_num,
4528 __rte_unused void *arg,
4529 struct pipeline_cgnapt *p_nat)
4531 uint32_t dest_if = 0xff; /* Added for Multiport */
4532 struct rte_mbuf *pkt;
4535 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4538 struct rte_CT_helper ct_helper;
4539 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4542 for (i = 0; i < 4; i++) {
4543 pkt_num = in_pkt_num + i;
4544 pkt = pkts[pkt_num];
4546 /* index into hash table entries */
4547 int hash_table_entry = p_nat->lkup_indx[pkt_num];
4548 /*bitmask representing only this packet */
4549 uint64_t pkt_mask = 1LLU << pkt_num;
4551 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
4553 uint16_t *outport_id =
4554 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
4556 struct cgnapt_table_entry *entry = NULL;
4558 if (hash_table_entry < 0) {
4560 /* try to add new entry */
4561 struct rte_pipeline_table_entry *table_entry = NULL;
4564 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
4566 &p_nat->valid_packets, pkt_num,
4570 /* ICMP Error message generation for
4571 * Destination Host unreachable
4573 if (protocol == IP_PROTOCOL_ICMP) {
4574 cgnapt_icmp_pkt = pkt;
4575 send_icmp_dest_unreachable_msg();
4578 /* Drop packet by adding to invalid pkt mask */
4580 p_nat->invalid_packets |= dropmask;
4582 #ifdef CGNAPT_DEBUGGING
4583 if (p_nat->kpc2++ < 5) {
4584 printf("in_ah Th: %d",
4585 p_nat->pipeline_num);
4586 print_key(p_nat->key_ptrs[pkt_num]);
4590 p_nat->naptDroppedPktCount++;
4592 #ifdef CGNAPT_DEBUGGING
4593 p_nat->naptDroppedPktCount3++;
4598 entry = (struct cgnapt_table_entry *)table_entry;
4600 /* entry found for this packet */
4601 entry = &napt_hash_tbl_entries[hash_table_entry];
4604 /* apply napt and mac changes */
4606 p_nat->entries[pkt_num] = &(entry->head);
4608 uint32_t *src_addr =
4609 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP4);
4610 uint32_t *dst_addr =
4611 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4612 uint16_t src_port_offset = 0;
4613 uint16_t dst_port_offset = 0;
4618 if ((protocol == IP_PROTOCOL_TCP)
4619 || (protocol == IP_PROTOCOL_UDP)) {
4620 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4621 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4622 } else if (protocol == IP_PROTOCOL_ICMP) {
4624 src_port_offset = MBUF_HDR_ROOM +
4627 /*Sequence number */
4628 dst_port_offset = MBUF_HDR_ROOM +
4635 case IP_PROTOCOL_TCP:
4636 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4637 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4638 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4640 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4644 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4645 rte_be_to_cpu_16(*dst_port) == 21) {
4647 //To process CT , pkt_mask does it need
4648 //to be complemented ??
4650 printf("cgnapt_ct_process: pkt_mask: "
4651 "% "PRIu64", pkt_num: %d\n",
4655 pkt_mask = cgnapt_ct_process(
4656 cgnat_cnxn_tracker, pkts,
4657 pkt_mask, &ct_helper);
4661 case IP_PROTOCOL_UDP:
4662 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4663 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4664 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4666 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4669 case IP_PROTOCOL_ICMP:
4671 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
4673 /*Sequence number */
4674 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
4676 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4678 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4685 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4687 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4689 if (entry->data.ttl == NAPT_ENTRY_STALE)
4690 entry->data.ttl = NAPT_ENTRY_VALID;
4692 struct ether_addr hw_addr;
4693 uint32_t dest_address = 0;
4694 /*Multiport Changes */
4701 if (unlikely(protocol == IP_PROTOCOL_UDP
4702 && rte_be_to_cpu_16(*dst_port) == 53)) {
4703 p_nat->invalid_packets |= pkt_mask;
4704 p_nat->naptDroppedPktCount++;
4706 #ifdef CGNAPT_DEBUGGING
4707 p_nat->naptDroppedPktCount6++;
4712 dest_address = rte_bswap32(*dst_addr);
4713 ret = local_get_nh_ipv4(dest_address, &dest_if, &nhip, p_nat);
4715 dest_if = get_prv_to_pub_port(&dest_address,
4717 if (dest_if == INVALID_DESTIF) {
4718 p_nat->invalid_packets |= pkt_mask;
4719 p_nat->naptDroppedPktCount++;
4720 #ifdef CGNAPT_DEBUGGING
4721 p_nat->naptDroppedPktCount6++;
4725 do_local_nh_ipv4_cache(dest_if, p_nat);
4727 *outport_id = p_nat->outport_id[dest_if];
4729 #ifdef CGNAPT_DBG_PRNT
4730 if (CGNAPT_DEBUG > 2)
4731 printf("Egress: \tphy_port:%d\t "
4732 "get_prv_to_pub():%d \tout_port:%d\n",
4733 pkt->port, dest_if, *outport_id);
4737 if (local_dest_mac_present(dest_if)) {
4739 get_local_link_hw_addr(dest_if),
4740 sizeof(struct ether_addr));
4742 get_link_hw_addr(dest_if),
4743 sizeof(struct ether_addr));
4746 ret = get_dest_mac_addr_port(dest_address, &dest_if, &hw_addr);
4748 if (unlikely(ret != ARP_FOUND)) {
4750 if (unlikely(ret == ARP_NOT_FOUND)) {
4751 printf("%s: ARP Not Found, nhip: %x, "
4752 "outport_id: %d\n", __func__, nhip,
4754 //request_arp(*outport_id, nhip, p_nat->p.p);
4758 p_nat->invalid_packets |= pkt_mask;
4759 p_nat->naptDroppedPktCount++;
4761 #ifdef CGNAPT_DEBUGGING
4762 p_nat->naptDroppedPktCount4++;
4767 #ifdef CGNAPT_DBG_PRNT
4768 if (CGNAPT_DEBUG > 2) {
4769 printf("MAC found for ip 0x%x, port %d - "
4770 "%02x:%02x:%02x:%02x:%02x:%02x\n",
4773 hw_addr.addr_bytes[0],
4774 hw_addr.addr_bytes[1],
4775 hw_addr.addr_bytes[2],
4776 hw_addr.addr_bytes[3],
4777 hw_addr.addr_bytes[4],
4778 hw_addr.addr_bytes[5]
4781 printf("Dest MAC before - "
4782 "%02x:%02x:%02x:%02x:%02x:%02x\n",
4783 eth_dest[0], eth_dest[1], eth_dest[2],
4784 eth_dest[3], eth_dest[4], eth_dest[5]);
4788 memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
4790 link_hw_laddr_valid[dest_if] = 1;
4791 memcpy(&link_hw_laddr[dest_if], &hw_addr,
4792 sizeof(struct ether_addr));
4794 #ifdef CGNAPT_DBG_PRNT
4795 if (CGNAPT_DEBUG > 2) {
4796 printf("Dest MAC after - "
4797 "%02x:%02x:%02x:%02x:%02x:%02x\n",
4798 eth_dest[0], eth_dest[1], eth_dest[2],
4799 eth_dest[3], eth_dest[4], eth_dest[5]);
4804 get_link_hw_addr(dest_if),
4805 sizeof(struct ether_addr));
4810 *src_addr = rte_bswap32(entry->data.pub_ip);
4812 #ifdef NAT_ONLY_CONFIG_REQ
4813 if (!nat_only_config_flag) {
4815 *src_port = rte_bswap16(entry->data.pub_port);
4816 #ifdef NAT_ONLY_CONFIG_REQ
4821 uint16_t rtp_port = 0, rtcp_port = 0;
4822 struct cgnapt_table_entry *entry_ptr1 = NULL,
4823 *entry_ptr2 = NULL, *entry_ptr3 = NULL,
4826 if (unlikely(protocol == IP_PROTOCOL_UDP
4827 && (rte_be_to_cpu_16(*dst_port) == 5060
4828 || rte_be_to_cpu_16(*src_port) == 5060))) {
4830 int ret = natSipAlgGetAudioPorts(pkt,
4831 &rtp_port, &rtcp_port);
4832 /* Commented code may be required for future usage,
4837 printf("%s: Wrong SIP ALG packet1\n",
4839 p_nat->invalid_packets |= pkt_mask;
4841 p_nat->naptDroppedPktCount++;
4843 #ifdef CGNAPT_DEBUGGING
4844 p_nat->naptDroppedPktCount4++;
4850 if (ret >= 0 && rtp_port != 0) {
4851 struct pipeline_cgnapt_entry_key rtp_key;
4852 rtp_key.ip = entry->data.u.prv_ip;
4853 rtp_key.port = rtp_port;
4854 rtp_key.pid = entry->data.prv_phy_port;
4856 if (add_dynamic_cgnapt_entry_alg(
4857 (struct pipeline *)p_nat, &rtp_key,
4858 &entry_ptr1, &entry_ptr2) == 0) {
4859 printf("%s: Wrong SIP ALG packet2\n",
4861 p_nat->invalid_packets |= pkt_mask;
4863 p_nat->naptDroppedPktCount++;
4865 #ifdef CGNAPT_DEBUGGING
4866 p_nat->naptDroppedPktCount4++;
4872 if (ret >= 0 && rtcp_port != 0) {
4873 struct pipeline_cgnapt_entry_key rtcp_key;
4874 rtcp_key.ip = entry->data.u.prv_ip;
4875 rtcp_key.port = rtcp_port;
4876 rtcp_key.pid = entry->data.prv_phy_port;
4878 if (add_dynamic_cgnapt_entry_alg(
4879 (struct pipeline *)p_nat, &rtcp_key,
4880 &entry_ptr3, &entry_ptr4) == 0) {
4882 printf("%s: Wrong SIP ALG packet3\n",
4884 p_nat->invalid_packets |= pkt_mask;
4886 p_nat->naptDroppedPktCount++;
4888 #ifdef CGNAPT_DEBUGGING
4889 p_nat->naptDroppedPktCount4++;
4895 //if(entry_ptr1 != NULL && entry_ptr3 != NULL)
4896 if (sip_alg_dpi(pkt, PRIVATE,
4898 entry->data.pub_port,
4899 entry->data.u.prv_ip,
4900 entry->data.prv_port,
4901 (rtp_port == 0) ? 0 :
4902 entry_ptr1->data.pub_port,
4903 (rtcp_port == 0) ? 0 :
4904 entry_ptr3->data.pub_port) == 0) {
4906 printf("%s: Wrong SIP ALG packet4\n",
4908 p_nat->invalid_packets |= pkt_mask;
4910 p_nat->naptDroppedPktCount++;
4912 #ifdef CGNAPT_DEBUGGING
4913 p_nat->naptDroppedPktCount4++;
4918 #endif /* SIP_ALG */
4921 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4922 rte_be_to_cpu_16(*dst_port) == 21) {
4924 int32_t ct_position =
4925 cgnat_cnxn_tracker->positions[pkt_num];
4927 printf("@CGNAT-pkt4work ct_position :%d, pkt_num %d "
4928 "pkt_mask = %" PRIu64 "\n", ct_position,
4932 if (ct_position < 0){
4933 p_nat->invalid_packets |= pkt_mask;
4934 p_nat->naptDroppedPktCount++;
4937 if (cgnat_cnxn_tracker->hash_table_entries[ct_position].
4938 alg_bypass_flag != BYPASS){
4940 struct pipeline_cgnapt_entry_key
4941 data_channel_entry_key;
4943 data_channel_entry_key.ip =
4945 data_channel_entry_key.port =
4946 entry->data.pub_port;
4947 data_channel_entry_key.pid = 0xffff;
4949 ftp_alg_dpi(p_nat, &data_channel_entry_key,
4950 pkt, cgnat_cnxn_tracker, ct_position,
4956 p_nat->enaptedPktCount++;
4959 p_nat->naptedPktCount++;
4962 if (p_nat->hw_checksum_reqd)
4963 hw_checksum(pkt, pkt_type);
4965 sw_checksum(pkt, pkt_type);
4971 * NAPT function for IPv4 public traffic which handles 4 pkts
4974 * A pointer to array of packets mbuf
4976 * Starting pkt number of pkts
4980 * A pointer to main CGNAPT structure
4984 pkt4_work_cgnapt_ipv4_pub(
4985 struct rte_mbuf **pkts,
4986 uint32_t in_pkt_num,
4987 __rte_unused void *arg,
4988 struct pipeline_cgnapt *p_nat)
4991 struct rte_CT_helper ct_helper;
4992 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4994 struct rte_mbuf *pkt;
4997 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4999 for (i = 0; i < 4; i++) {
5000 pkt_num = in_pkt_num + i;
5001 pkt = pkts[pkt_num];
5003 /* index into hash table entries */
5004 int hash_table_entry = p_nat->lkup_indx[pkt_num];
5005 /*bitmask representing only this packet */
5006 uint64_t pkt_mask = 1LLU << pkt_num;
5008 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
5010 uint32_t dest_if = 0xff; /* Added for Multiport */
5011 uint16_t *outport_id =
5012 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
5014 struct cgnapt_table_entry *entry = NULL;
5016 if (hash_table_entry < 0) {
5018 /* try to add new entry */
5019 struct rte_pipeline_table_entry *table_entry = NULL;
5022 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
5024 &p_nat->valid_packets, pkt_num,
5028 /* ICMP Error message generation for
5029 * Destination Host unreachable
5031 if (protocol == IP_PROTOCOL_ICMP) {
5032 cgnapt_icmp_pkt = pkt;
5033 send_icmp_dest_unreachable_msg();
5036 /* Drop packet by adding to invalid pkt mask */
5038 p_nat->invalid_packets |= dropmask;
5040 #ifdef CGNAPT_DEBUGGING
5041 if (p_nat->kpc2++ < 5) {
5042 printf("in_ah Th: %d",
5043 p_nat->pipeline_num);
5044 print_key(p_nat->key_ptrs[pkt_num]);
5048 p_nat->naptDroppedPktCount++;
5050 #ifdef CGNAPT_DEBUGGING
5051 p_nat->naptDroppedPktCount3++;
5057 entry = (struct cgnapt_table_entry *)table_entry;
5059 /* entry found for this packet */
5060 entry = &napt_hash_tbl_entries[hash_table_entry];
5063 /* apply napt and mac changes */
5065 p_nat->entries[pkt_num] = &(entry->head);
5067 uint32_t *dst_addr =
5068 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
5069 uint16_t src_port_offset = 0;
5070 uint16_t dst_port_offset = 0;
5072 if ((protocol == IP_PROTOCOL_TCP)
5073 || (protocol == IP_PROTOCOL_UDP)) {
5074 src_port_offset = SRC_PRT_OFST_IP4_TCP;
5075 dst_port_offset = DST_PRT_OFST_IP4_TCP;
5076 } else if (protocol == IP_PROTOCOL_ICMP) {
5078 src_port_offset = MBUF_HDR_ROOM +
5081 /*Sequence number */
5082 dst_port_offset = MBUF_HDR_ROOM +
5087 uint16_t *src_port =
5088 RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
5089 uint16_t *dst_port =
5090 RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
5093 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
5095 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
5097 if (entry->data.ttl == NAPT_ENTRY_STALE)
5098 entry->data.ttl = NAPT_ENTRY_VALID;
5100 struct ether_addr hw_addr;
5101 uint32_t dest_address = 0;
5102 /* Multiport Changes */
5108 if (unlikely(protocol == IP_PROTOCOL_UDP
5109 && rte_be_to_cpu_16(*src_port) == 53)) {
5110 p_nat->invalid_packets |= pkt_mask;
5111 p_nat->naptDroppedPktCount++;
5112 #ifdef CGNAPT_DEBUGGING
5113 p_nat->naptDroppedPktCount6++;
5118 dest_address = entry->data.u.prv_ip;
5119 ret = local_get_nh_ipv4(dest_address, &dest_if, &nhip, p_nat);
5121 dest_if = get_prv_to_pub_port(&dest_address, IP_VERSION_4);
5123 if (dest_if == INVALID_DESTIF) {
5124 p_nat->invalid_packets |= pkt_mask;
5125 p_nat->naptDroppedPktCount++;
5126 #ifdef CGNAPT_DEBUGGING
5127 p_nat->naptDroppedPktCount6++;
5132 do_local_nh_ipv4_cache(dest_if, p_nat);
5135 *outport_id = p_nat->outport_id[dest_if];
5137 #ifdef CGNAPT_DBG_PRNT
5138 if (CGNAPT_DEBUG > 2)
5139 printf("Ingress: \tphy_port:%d\t "
5140 "get_pub_to_prv():%d \tout_port%d\n",
5146 if (local_dest_mac_present(dest_if)) {
5148 get_local_link_hw_addr(dest_if),
5149 sizeof(struct ether_addr));
5151 get_link_hw_addr(dest_if),
5152 sizeof(struct ether_addr));
5155 ret = get_dest_mac_addr_port(dest_address, &dest_if, &hw_addr);
5157 if (unlikely(ret != ARP_FOUND)) {
5159 if (unlikely(ret == ARP_NOT_FOUND)) {
5160 printf("%s: ARP Not Found, nhip: %x, "
5161 "outport_id: %d\n", __func__, nhip,
5163 //request_arp(*outport_id, nhip, p_nat->p.p);
5167 p_nat->invalid_packets |= pkt_mask;
5168 p_nat->naptDroppedPktCount++;
5170 #ifdef CGNAPT_DEBUGGING
5171 p_nat->naptDroppedPktCount4++;
5176 #ifdef CGNAPT_DBG_PRNT
5177 if (CGNAPT_DEBUG > 2) {
5178 printf("MAC found for ip 0x%x, port %d - "
5179 "%02x:%02x:%02x:%02x:%02x:%02x\n",
5180 dest_address, *outport_id,
5181 hw_addr.addr_bytes[0],
5182 hw_addr.addr_bytes[1],
5183 hw_addr.addr_bytes[2],
5184 hw_addr.addr_bytes[3],
5185 hw_addr.addr_bytes[4],
5186 hw_addr.addr_bytes[5]
5189 printf("Dest MAC before - "
5190 "%02x:%02x:%02x:%02x:%02x:%02x\n",
5191 eth_dest[0], eth_dest[1], eth_dest[2],
5192 eth_dest[3], eth_dest[4], eth_dest[5]);
5196 memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
5198 link_hw_laddr_valid[dest_if] = 1;
5199 memcpy(&link_hw_laddr[dest_if],
5200 &hw_addr, sizeof(struct ether_addr));
5202 #ifdef CGNAPT_DBG_PRNT
5203 if (CGNAPT_DEBUG > 2) {
5204 printf("Dest MAC after - %02x:%02x:%02x: "
5206 eth_dest[0], eth_dest[1], eth_dest[2],
5207 eth_dest[3], eth_dest[4], eth_dest[5]);
5212 get_link_hw_addr(dest_if),
5213 sizeof(struct ether_addr));
5219 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
5220 if (protocol == IP_PROTOCOL_ICMP) {
5221 /* Query ID reverse translation done here */
5222 *src_port = rte_bswap16(entry->data.prv_port);
5223 /* dont care sequence num */
5225 #ifdef NAT_ONLY_CONFIG_REQ
5226 if (!nat_only_config_flag) {
5229 rte_bswap16(entry->data.prv_port);
5230 #ifdef NAT_ONLY_CONFIG_REQ
5235 if ((rte_be_to_cpu_16(*src_port) == 21) ||
5236 rte_be_to_cpu_16(*dst_port) == 21) {
5237 pkt_mask = cgnapt_ct_process(
5238 cgnat_cnxn_tracker, pkts,
5239 pkt_mask, &ct_helper);
5245 uint16_t rtp_port = 0, rtcp_port = 0;
5246 struct cgnapt_table_entry *entry_ptr1 = NULL,
5248 /* Commented code may be required for future usage,
5252 struct cgnapt_table_entry *entry_ptr2 = NULL,
5256 if (unlikely(protocol == IP_PROTOCOL_UDP
5257 && (rte_be_to_cpu_16(*dst_port) == 5060
5258 || rte_be_to_cpu_16(*src_port) == 5060))) {
5259 /* Commented code may be required for future usage,
5263 int ret = natSipAlgGetAudioPorts(pkt,
5264 &rtp_port, &rtcp_port);
5266 printf("%s: Wrong SIP ALG packet1\n",
5268 p_nat->invalid_packets |= pkt_mask;
5270 p_nat->naptDroppedPktCount++;
5272 #ifdef CGNAPT_DEBUGGING
5273 p_nat->naptDroppedPktCount4++;
5278 if (rtp_port != 0) {
5279 struct pipeline_cgnapt_entry_key rtp_key;
5280 rtp_key.ip = entry->data.pub_ip;
5281 rtp_key.port = rtp_port;
5282 rtp_key.pid = 0xffff;
5284 if (retrieve_cgnapt_entry_alg(&rtp_key,
5285 &entry_ptr1, &entry_ptr2) == 0) {
5286 printf("%s: Wrong SIP ALG packet2\n",
5288 p_nat->invalid_packets |= pkt_mask;
5290 p_nat->naptDroppedPktCount++;
5292 #ifdef CGNAPT_DEBUGGING
5293 p_nat->naptDroppedPktCount4++;
5299 if (rtcp_port != 0) {
5300 struct pipeline_cgnapt_entry_key rtcp_key;
5301 rtcp_key.ip = entry->data.pub_ip;
5302 rtcp_key.port = rtcp_port;
5303 rtcp_key.pid = 0xffff;
5305 if (retrieve_cgnapt_entry_alg(&rtcp_key,
5306 &entry_ptr3, &entry_ptr4) == 0) {
5307 printf("%s: Wrong SIP ALG packet3\n",
5309 p_nat->invalid_packets |= pkt_mask;
5310 p_nat->naptDroppedPktCount++;
5312 #ifdef CGNAPT_DEBUGGING
5313 p_nat->naptDroppedPktCount4++;
5320 if (sip_alg_dpi(pkt, PUBLIC,
5321 entry->data.u.prv_ip,
5322 entry->data.prv_port,
5324 entry->data.pub_port,
5325 (rtp_port == 0) ? 0 :
5326 entry_ptr1->data.prv_port,
5327 (rtcp_port == 0) ? 0 :
5328 entry_ptr3->data.prv_port) == 0) {
5330 printf("%s: Wrong SIP ALG packet4\n",
5332 p_nat->invalid_packets |= pkt_mask;
5334 p_nat->naptDroppedPktCount++;
5336 #ifdef CGNAPT_DEBUGGING
5337 p_nat->naptDroppedPktCount4++;
5342 #endif /* SIP_ALG */
5345 if ((rte_be_to_cpu_16(*src_port) == 21) ||
5346 rte_be_to_cpu_16(*dst_port) == 21) {
5348 int32_t ct_position =
5349 cgnat_cnxn_tracker->positions[pkt_num];
5350 if (ct_position < 0){
5351 p_nat->invalid_packets |= pkt_mask;
5353 p_nat->naptDroppedPktCount++;
5356 if (cgnat_cnxn_tracker->hash_table_entries
5357 [ct_position].alg_bypass_flag != BYPASS){
5359 struct pipeline_cgnapt_entry_key
5360 data_channel_entry_key;
5363 data_channel_entry_key.ip =
5365 data_channel_entry_key.port =
5366 entry->data.pub_port;
5367 data_channel_entry_key.pid = 0xffff;
5369 ftp_alg_dpi(p_nat, &data_channel_entry_key,
5370 pkt, cgnat_cnxn_tracker,
5371 ct_position, PUBLIC);
5376 p_nat->inaptedPktCount++;
5379 p_nat->naptedPktCount++;
5382 if (p_nat->hw_checksum_reqd)
5383 hw_checksum(pkt, pkt_type);
5385 sw_checksum(pkt, pkt_type);
5391 * NAPT key calculation function for IPv6 private traffic
5392 * which handles 1 pkt
5395 * A pointer to array of packets mbuf
5397 * Pkt number of pkts
5401 * A pointer to main CGNAPT structure
5405 pkt_work_cgnapt_key_ipv6_prv(
5406 struct rte_mbuf *pkt,
5408 __rte_unused void *arg,
5409 struct pipeline_cgnapt *p_nat)
5412 p_nat->receivedPktCount++;
5414 /* bitmask representing only this packet */
5415 uint64_t pkt_mask = 1LLU << pkt_num;
5417 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
5418 uint32_t *src_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
5420 uint16_t src_port = RTE_MBUF_METADATA_UINT16(pkt, SRC_PRT_OFST_IP6);
5422 uint16_t phy_port = pkt->port;
5423 struct pipeline_cgnapt_entry_key key;
5425 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
5427 #ifdef CGNAPT_DBG_PRNT
5428 if (CGNAPT_DEBUG > 4)
5433 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
5438 case IP_PROTOCOL_UDP:
5442 struct udp_hdr *udp;
5444 udp = (struct udp_hdr *)
5445 RTE_MBUF_METADATA_UINT8_PTR(pkt,
5448 if (rte_bswap16(udp->dst_port) ==
5450 handle_pcp_req(pkt, IPV6_SZ, p_nat);
5451 p_nat->invalid_packets |= pkt_mask;
5457 case IP_PROTOCOL_TCP:
5458 case IP_PROTOCOL_ICMP:
5459 /*we don't need icmp check in ipv6 */
5463 printf("wrong protocol: %d\n", protocol);
5464 /* remember invalid packets to be dropped */
5465 p_nat->invalid_packets |= pkt_mask;
5466 p_nat->naptDroppedPktCount++;
5468 #ifdef CGNAPT_DEBUGGING
5469 p_nat->naptDroppedPktCount2++;
5475 key.ip = rte_bswap32(src_addr[3]);
5476 key.port = rte_bswap16(src_port);
5478 #ifdef NAT_ONLY_CONFIG_REQ
5479 if (nat_only_config_flag)
5483 memcpy(&p_nat->keys[pkt_num], &key,
5484 sizeof(struct pipeline_cgnapt_entry_key));
5485 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5489 * NAPT key calculation function for IPv6 public traffic
5490 * which handles 1 pkt
5493 * A pointer to array of packets mbuf
5495 * Pkt number of pkts
5499 * A pointer to main CGNAPT structure
5503 pkt_work_cgnapt_key_ipv6_pub(
5504 struct rte_mbuf *pkt,
5506 __rte_unused void *arg,
5507 struct pipeline_cgnapt *p_nat)
5511 p_nat->receivedPktCount++;
5513 /* bitmask representing only this packet */
5514 uint64_t pkt_mask = 1LLU << pkt_num;
5516 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
5518 uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
5520 uint16_t dst_port = RTE_MBUF_METADATA_UINT16(pkt,
5521 DST_PRT_OFST_IP4_TCP);
5523 struct pipeline_cgnapt_entry_key key;
5525 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
5527 #ifdef CGNAPT_DBG_PRNT
5528 if (CGNAPT_DEBUG > 4)
5533 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
5539 case IP_PROTOCOL_UDP:
5540 case IP_PROTOCOL_TCP:
5541 case IP_PROTOCOL_ICMP:
5542 /*we don't need icmp check in ipv6 */
5546 /* remember invalid packets to be dropped */
5547 p_nat->invalid_packets |= pkt_mask;
5548 p_nat->naptDroppedPktCount++;
5550 #ifdef CGNAPT_DEBUGGING
5551 p_nat->naptDroppedPktCount2++;
5557 key.ip = rte_bswap32(dst_addr[0]);
5558 key.port = rte_bswap16(dst_port);
5560 #ifdef NAT_ONLY_CONFIG_REQ
5561 if (nat_only_config_flag)
5565 memcpy(&p_nat->keys[pkt_num], &key,
5566 sizeof(struct pipeline_cgnapt_entry_key));
5567 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5571 * NAPT key calculation function for IPv6 private traffic
5572 * which handles 4 pkts
5575 * A pointer to array of packets mbuf
5577 * Starting pkt number of pkts
5581 * A pointer to main CGNAPT structure
5585 pkt4_work_cgnapt_key_ipv6_prv(
5586 struct rte_mbuf **pkt,
5588 __rte_unused void *arg,
5589 struct pipeline_cgnapt *p_nat)
5591 p_nat->receivedPktCount += 4;
5593 /* bitmask representing only this packet */
5594 uint64_t pkt_mask0 = 1LLU << pkt_num;
5595 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
5596 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
5597 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
5599 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
5601 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
5603 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
5605 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
5608 uint32_t *src_addr0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0],
5610 uint32_t *src_addr1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1],
5612 uint32_t *src_addr2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2],
5614 uint32_t *src_addr3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3],
5617 uint16_t src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
5619 uint16_t src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
5621 uint16_t src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
5623 uint16_t src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
5626 uint16_t phy_port0 = pkt[0]->port;
5627 uint16_t phy_port1 = pkt[1]->port;
5628 uint16_t phy_port2 = pkt[2]->port;
5629 uint16_t phy_port3 = pkt[3]->port;
5631 struct pipeline_cgnapt_entry_key key0;
5632 struct pipeline_cgnapt_entry_key key1;
5633 struct pipeline_cgnapt_entry_key key2;
5634 struct pipeline_cgnapt_entry_key key3;
5636 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
5637 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
5638 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
5639 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
5643 #ifdef CGNAPT_DBG_PRNT
5644 if (CGNAPT_DEBUG > 4)
5649 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
5653 switch (protocol0) {
5655 case IP_PROTOCOL_UDP:
5659 struct udp_hdr *udp;
5661 udp = (struct udp_hdr *)
5662 RTE_MBUF_METADATA_UINT8_PTR(pkt[0],
5665 if (rte_bswap16(udp->dst_port) ==
5667 handle_pcp_req(pkt[0], IPV6_SZ, p_nat);
5668 p_nat->invalid_packets |= pkt_mask0;
5674 case IP_PROTOCOL_TCP:
5675 case IP_PROTOCOL_ICMP:
5676 /*we don't need icmp check in ipv6 */
5680 /* remember invalid packets to be dropped */
5681 p_nat->invalid_packets |= pkt_mask0;
5682 p_nat->naptDroppedPktCount++;
5684 #ifdef CGNAPT_DEBUGGING
5685 p_nat->naptDroppedPktCount2++;
5692 key0.pid = phy_port0;
5693 key0.ip = rte_bswap32(src_addr0[3]);
5694 key0.port = rte_bswap16(src_port0);
5696 #ifdef NAT_ONLY_CONFIG_REQ
5697 if (nat_only_config_flag)
5701 memcpy(&p_nat->keys[pkt_num], &key0,
5702 sizeof(struct pipeline_cgnapt_entry_key));
5703 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5706 #ifdef CGNAPT_DBG_PRNT
5707 if (CGNAPT_DEBUG > 4)
5712 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
5716 switch (protocol1) {
5717 case IP_PROTOCOL_UDP:
5721 struct udp_hdr *udp;
5723 udp = (struct udp_hdr *)
5724 RTE_MBUF_METADATA_UINT8_PTR(pkt[1],
5727 if (rte_bswap16(udp->dst_port) ==
5729 handle_pcp_req(pkt[1], IPV6_SZ, p_nat);
5730 p_nat->invalid_packets |= pkt_mask1;
5736 case IP_PROTOCOL_TCP:
5737 case IP_PROTOCOL_ICMP:
5738 /*we don't need icmp check in ipv6 */
5742 /* remember invalid packets to be dropped */
5743 p_nat->invalid_packets |= pkt_mask1;
5744 p_nat->naptDroppedPktCount++;
5746 #ifdef CGNAPT_DEBUGGING
5747 p_nat->naptDroppedPktCount2++;
5753 key1.pid = phy_port1;
5754 key1.ip = rte_bswap32(src_addr1[3]);
5755 key1.port = rte_bswap16(src_port1);
5757 #ifdef NAT_ONLY_CONFIG_REQ
5758 if (nat_only_config_flag)
5762 memcpy(&p_nat->keys[pkt_num + 1], &key1,
5763 sizeof(struct pipeline_cgnapt_entry_key));
5764 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
5767 #ifdef CGNAPT_DBG_PRNT
5768 if (CGNAPT_DEBUG > 4)
5773 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
5777 switch (protocol2) {
5778 case IP_PROTOCOL_UDP:
5782 struct udp_hdr *udp;
5784 udp = (struct udp_hdr *)
5785 RTE_MBUF_METADATA_UINT8_PTR(pkt[2],
5788 if (rte_bswap16(udp->dst_port) ==
5790 handle_pcp_req(pkt[2], IPV6_SZ, p_nat);
5791 p_nat->invalid_packets |= pkt_mask2;
5797 case IP_PROTOCOL_TCP:
5798 case IP_PROTOCOL_ICMP:
5799 /*we don't need icmp check in ipv6 */
5803 /* remember invalid packets to be dropped */
5804 p_nat->invalid_packets |= pkt_mask2;
5805 p_nat->naptDroppedPktCount++;
5807 #ifdef CGNAPT_DEBUGGING
5808 p_nat->naptDroppedPktCount2++;
5814 key2.pid = phy_port2;
5815 key2.ip = rte_bswap32(src_addr2[3]);
5816 key2.port = rte_bswap16(src_port2);
5818 #ifdef NAT_ONLY_CONFIG_REQ
5819 if (nat_only_config_flag)
5823 memcpy(&p_nat->keys[pkt_num + 2], &key2,
5824 sizeof(struct pipeline_cgnapt_entry_key));
5825 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
5828 #ifdef CGNAPT_DBG_PRNT
5829 if (CGNAPT_DEBUG > 4)
5834 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
5838 switch (protocol3) {
5839 case IP_PROTOCOL_UDP:
5843 struct udp_hdr *udp;
5845 udp = (struct udp_hdr *)
5846 RTE_MBUF_METADATA_UINT8_PTR(pkt[3],
5849 if (rte_bswap16(udp->dst_port) ==
5851 handle_pcp_req(pkt[3], IPV6_SZ, p_nat);
5852 p_nat->invalid_packets |= pkt_mask3;
5858 case IP_PROTOCOL_TCP:
5859 case IP_PROTOCOL_ICMP:
5860 /*we don't need icmp check in ipv6 */
5864 /* remember invalid packets to be dropped */
5865 p_nat->invalid_packets |= pkt_mask2;
5866 p_nat->naptDroppedPktCount++;
5868 #ifdef CGNAPT_DEBUGGING
5869 p_nat->naptDroppedPktCount2++;
5875 key3.pid = phy_port3;
5876 key3.ip = rte_bswap32(src_addr3[3]);
5877 key3.port = rte_bswap16(src_port3);
5879 #ifdef NAT_ONLY_CONFIG_REQ
5880 if (nat_only_config_flag)
5884 memcpy(&p_nat->keys[pkt_num + 3], &key3,
5885 sizeof(struct pipeline_cgnapt_entry_key));
5886 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
5892 * NAPT key calculation function for IPv4 public traffic
5893 * which handles 4 pkts
5896 * A pointer to array of packets mbuf
5898 * Starting pkt number of pkts
5902 * A pointer to main CGNAPT structure
5906 pkt4_work_cgnapt_key_ipv6_pub(
5907 struct rte_mbuf **pkt,
5909 __rte_unused void *arg,
5910 struct pipeline_cgnapt *p_nat)
5912 p_nat->receivedPktCount += 4;
5914 /* bitmask representing only this packet */
5915 uint64_t pkt_mask0 = 1LLU << pkt_num;
5916 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
5917 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
5918 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
5920 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
5922 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
5924 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
5926 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
5929 uint32_t *dst_addr0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0],
5931 uint32_t *dst_addr1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1],
5933 uint32_t *dst_addr2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2],
5935 uint32_t *dst_addr3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3],
5938 uint16_t dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
5939 DST_PRT_OFST_IP4_TCP);
5940 uint16_t dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
5941 DST_PRT_OFST_IP4_TCP);
5942 uint16_t dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
5943 DST_PRT_OFST_IP4_TCP);
5944 uint16_t dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
5945 DST_PRT_OFST_IP4_TCP);
5947 struct pipeline_cgnapt_entry_key key0;
5948 struct pipeline_cgnapt_entry_key key1;
5949 struct pipeline_cgnapt_entry_key key2;
5950 struct pipeline_cgnapt_entry_key key3;
5952 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
5953 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
5954 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
5955 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
5959 #ifdef CGNAPT_DBG_PRNT
5960 if (CGNAPT_DEBUG > 4)
5965 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
5969 switch (protocol0) {
5971 case IP_PROTOCOL_TCP:
5972 case IP_PROTOCOL_UDP:
5973 case IP_PROTOCOL_ICMP:
5974 /*we don't need icmp check in ipv6 */
5978 /* remember invalid packets to be dropped */
5979 p_nat->invalid_packets |= pkt_mask0;
5980 p_nat->naptDroppedPktCount++;
5982 #ifdef CGNAPT_DEBUGGING
5983 p_nat->naptDroppedPktCount2++;
5989 key0.ip = rte_bswap32(dst_addr0[0]);
5990 key0.port = rte_bswap16(dst_port0);
5992 #ifdef NAT_ONLY_CONFIG_REQ
5993 if (nat_only_config_flag)
5997 memcpy(&p_nat->keys[pkt_num], &key0,
5998 sizeof(struct pipeline_cgnapt_entry_key));
5999 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
6005 #ifdef CGNAPT_DBG_PRNT
6006 if (CGNAPT_DEBUG > 4)
6011 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
6015 switch (protocol1) {
6017 case IP_PROTOCOL_TCP:
6018 case IP_PROTOCOL_UDP:
6019 case IP_PROTOCOL_ICMP:
6020 /*we don't need icmp check in ipv6 */
6024 /* remember invalid packets to be dropped */
6025 p_nat->invalid_packets |= pkt_mask1;
6026 p_nat->naptDroppedPktCount++;
6028 #ifdef CGNAPT_DEBUGGING
6029 p_nat->naptDroppedPktCount2++;
6035 key1.ip = rte_bswap32(dst_addr1[0]);
6036 key1.port = rte_bswap16(dst_port1);
6038 #ifdef NAT_ONLY_CONFIG_REQ
6039 if (nat_only_config_flag)
6043 memcpy(&p_nat->keys[pkt_num + 1], &key1,
6044 sizeof(struct pipeline_cgnapt_entry_key));
6045 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
6051 #ifdef CGNAPT_DBG_PRNT
6052 if (CGNAPT_DEBUG > 4)
6057 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
6061 switch (protocol2) {
6063 case IP_PROTOCOL_TCP:
6064 case IP_PROTOCOL_UDP:
6065 case IP_PROTOCOL_ICMP:
6066 /*we don't need icmp check in ipv6 */
6070 /* remember invalid packets to be dropped */
6071 p_nat->invalid_packets |= pkt_mask2;
6072 p_nat->naptDroppedPktCount++;
6074 #ifdef CGNAPT_DEBUGGING
6075 p_nat->naptDroppedPktCount2++;
6081 key2.ip = rte_bswap32(dst_addr2[0]);
6082 key2.port = rte_bswap16(dst_port2);
6084 #ifdef NAT_ONLY_CONFIG_REQ
6085 if (nat_only_config_flag)
6089 memcpy(&p_nat->keys[pkt_num + 2], &key2,
6090 sizeof(struct pipeline_cgnapt_entry_key));
6092 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
6098 #ifdef CGNAPT_DBG_PRNT
6099 if (CGNAPT_DEBUG > 4)
6104 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
6108 switch (protocol3) {
6110 case IP_PROTOCOL_TCP:
6111 case IP_PROTOCOL_UDP:
6112 case IP_PROTOCOL_ICMP:
6113 /*we don't need icmp check in ipv6 */
6117 /* remember invalid packets to be dropped */
6118 p_nat->invalid_packets |= pkt_mask3;
6119 p_nat->naptDroppedPktCount++;
6121 #ifdef CGNAPT_DEBUGGING
6122 p_nat->naptDroppedPktCount2++;
6128 key3.ip = rte_bswap32(dst_addr3[0]);
6129 key3.port = rte_bswap16(dst_port3);
6131 #ifdef NAT_ONLY_CONFIG_REQ
6132 if (nat_only_config_flag)
6136 memcpy(&p_nat->keys[pkt_num + 3], &key3,
6137 sizeof(struct pipeline_cgnapt_entry_key));
6139 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
6143 * NAPT function for IPv6 private traffic which handles 1 pkt
6146 * A pointer to array of packet mbuf
6152 * A pointer to main CGNAPT structure
6156 pkt_work_cgnapt_ipv6_prv(
6157 struct rte_mbuf *pkt,
6159 __rte_unused void *arg,
6160 struct pipeline_cgnapt *p_nat)
6163 /* index into hash table entries */
6164 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6166 /*bitmask representing only this packet */
6167 uint64_t pkt_mask = 1LLU << pkt_num;
6169 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
6171 /* Added for Multiport */
6172 uint32_t dest_if = INVALID_DESTIF;
6173 uint16_t *outport_id = RTE_MBUF_METADATA_UINT16_PTR(pkt,
6174 cgnapt_meta_offset);
6176 struct cgnapt_table_entry *entry = NULL;
6177 enum PKT_TYPE pkt_type = PKT_TYPE_IPV6to4;
6179 if (hash_table_entry < 0) {
6181 /* try to add new entry */
6182 struct rte_pipeline_table_entry *table_entry = NULL;
6184 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
6186 &p_nat->valid_packets, pkt_num,
6190 /* ICMP Error message generation for
6191 * Destination Host unreachable
6193 /* Do we need this check for ipv6? */
6194 if (protocol == IP_PROTOCOL_ICMP) {
6195 cgnapt_icmp_pkt = pkt;
6196 send_icmp_dest_unreachable_msg();
6199 /* Drop packet by adding to invalid pkt mask */
6201 p_nat->invalid_packets |= dropmask;
6203 #ifdef CGNAPT_DEBUGGING
6204 if (p_nat->kpc2++ < 5) {
6205 printf("in_ah Th: %d", p_nat->pipeline_num);
6206 print_key(p_nat->key_ptrs[pkt_num]);
6210 p_nat->naptDroppedPktCount++;
6212 #ifdef CGNAPT_DEBUGGING
6213 p_nat->naptDroppedPktCount3++;
6219 entry = (struct cgnapt_table_entry *)table_entry;
6221 /* entry found for this packet */
6222 entry = &napt_hash_tbl_entries[hash_table_entry];
6225 /* apply napt and mac changes */
6227 p_nat->entries[pkt_num] = &(entry->head);
6229 struct ipv6_hdr ipv6_hdr;
6231 struct ether_addr hw_addr;
6232 uint32_t dest_address = 0;
6237 convert_ipv6_to_ipv4(pkt, &ipv6_hdr);
6239 #ifdef CGNAPT_DBG_PRNT
6240 if (CGNAPT_DEBUG == 1)
6241 printf("pkt_work_cganpt: convert_ipv6_to_ipv4\n");
6244 struct cgnapt_nsp_node *ll = nsp_ll;
6247 while (ll != NULL) {
6249 (&ipv6_hdr.dst_addr[0], &ll->nsp.prefix[0],
6250 ll->nsp.depth / 8)) {
6258 && !memcmp(&ipv6_hdr.dst_addr[0], &well_known_prefix[0],
6264 p_nat->invalid_packets |= pkt_mask;
6265 p_nat->naptDroppedPktCount++;
6267 #ifdef CGNAPT_DEBUGGING
6268 p_nat->naptDroppedPktCount5++;
6276 /* As packet is already converted into IPv4 we must not
6277 * operate IPv6 offsets on packet
6278 * Only perform IPv4 operations
6281 uint32_t *src_addr =
6282 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP6t4);
6283 uint32_t *dst_addr =
6284 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP6t4);
6285 uint16_t *src_port =
6286 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP6t4);
6287 uint16_t *dst_port =
6288 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP6t4);
6290 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt,
6292 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt,
6293 ETH_OFST_IP6t4 + 6);
6295 if (entry->data.ttl == NAPT_ENTRY_STALE)
6296 entry->data.ttl = NAPT_ENTRY_VALID;
6299 if (unlikely(protocol == IP_PROTOCOL_UDP
6300 && rte_be_to_cpu_16(*dst_port) == 53)) {
6301 p_nat->invalid_packets |= pkt_mask;
6302 p_nat->naptDroppedPktCount++;
6304 #ifdef CGNAPT_DEBUGGING
6305 p_nat->naptDroppedPktCount6++;
6311 dest_address = rte_bswap32(*dst_addr);
6312 /*Multiport Changes */
6315 ret = local_get_nh_ipv4(dest_address, &dest_if, &nhip, p_nat);
6317 dest_if = get_prv_to_pub_port(&dest_address, IP_VERSION_4);
6319 if (dest_if == INVALID_DESTIF) {
6320 p_nat->invalid_packets |= pkt_mask;
6321 p_nat->naptDroppedPktCount++;
6322 #ifdef CGNAPT_DEBUGGING
6323 p_nat->naptDroppedPktCount6++;
6328 do_local_nh_ipv4_cache(dest_if, p_nat);
6330 *outport_id = p_nat->outport_id[dest_if];
6332 #ifdef CGNAPT_DBG_PRNT
6333 if (CGNAPT_DEBUG > 2)
6334 printf("Egress: \tphy_port:%d\t get_prv_to_pub():%d "
6335 "\tout_port:%d\n", pkt->port,
6336 dest_if, *outport_id);
6340 #ifdef CGNAPT_DBG_PRNT
6341 static int static_count;
6343 if (static_count++ < 10) {
6345 my_print_entry(entry);
6346 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6347 printf("dest_add:%x\n", entry->data.u.prv_ip);
6348 printf("dest_add:%x\n", *dst_addr);
6349 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6353 if (local_dest_mac_present(dest_if)) {
6355 get_local_link_hw_addr(dest_if),
6356 sizeof(struct ether_addr));
6357 memcpy(eth_src, get_link_hw_addr(dest_if),
6358 sizeof(struct ether_addr));
6361 ret = get_dest_mac_addr_port(dest_address, &dest_if, &hw_addr);
6363 if (unlikely(ret != ARP_FOUND)) {
6365 if (unlikely(ret == ARP_NOT_FOUND)) {
6366 printf("%s: ARP Not Found, nhip: %x, "
6367 "outport_id: %d\n", __func__, nhip,
6369 //request_arp(*outport_id, nhip, p_nat->p.p);
6373 p_nat->invalid_packets |= pkt_mask;
6374 p_nat->naptDroppedPktCount++;
6376 #ifdef CGNAPT_DEBUGGING
6377 p_nat->naptDroppedPktCount4++;
6382 #ifdef CGNAPT_DBG_PRNT
6383 if (CGNAPT_DEBUG > 2) {
6384 printf("MAC found for ip 0x%x, port %d - %02x:%02x: "
6385 "%02x:%02x:%02x:%02x\n", dest_address,
6387 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
6388 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
6389 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
6391 printf("Dest MAC before - %02x:%02x:%02x:%02x: "
6392 "%02x:%02x\n", eth_dest[0], eth_dest[1],
6393 eth_dest[2], eth_dest[3],
6394 eth_dest[4], eth_dest[5]);
6398 memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
6400 #ifdef CGNAPT_DBG_PRNT
6401 if (CGNAPT_DEBUG > 2) {
6402 printf("Dest MAC after - "
6403 "%02x:%02x:%02x:%02x:%02x:%02x\n",
6404 eth_dest[0], eth_dest[1], eth_dest[2], eth_dest[3],
6405 eth_dest[4], eth_dest[5]);
6409 memcpy(eth_src, get_link_hw_addr(dest_if),
6410 sizeof(struct ether_addr));
6415 *src_addr = rte_bswap32(entry->data.pub_ip);
6417 #ifdef NAT_ONLY_CONFIG_REQ
6418 if (!nat_only_config_flag) {
6420 *src_port = rte_bswap16(entry->data.pub_port);
6422 #ifdef NAT_ONLY_CONFIG_REQ
6426 p_nat->enaptedPktCount++;
6429 p_nat->naptedPktCount++;
6432 if (p_nat->hw_checksum_reqd)
6433 hw_checksum(pkt, pkt_type);
6435 sw_checksum(pkt, pkt_type);
6441 * NAPT function for IPv6 public traffic which handles 1 pkt
6444 * A pointer to array of packet mbuf
6450 * A pointer to main CGNAPT structure
6454 pkt_work_cgnapt_ipv6_pub(
6455 struct rte_mbuf *pkt,
6457 __rte_unused void *arg,
6458 struct pipeline_cgnapt *p_nat)
6461 /* index into hash table entries */
6462 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6463 /*bitmask representing only this packet */
6464 uint64_t pkt_mask = 1LLU << pkt_num;
6466 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
6468 uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */
6469 uint16_t *outport_id =
6470 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6471 struct cgnapt_table_entry *entry = NULL;
6473 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4to6;
6475 if (hash_table_entry < 0) {
6477 /* Drop ingress initial traffic */
6479 p_nat->invalid_packets |= pkt_mask;
6480 p_nat->naptDroppedPktCount++;
6482 #ifdef CGNAPT_DEBUGGING
6483 p_nat->naptDroppedPktCount3++;
6484 if (p_nat->kpc2++ < 5) {
6485 printf("in_ah Th: %d", p_nat->pipeline_num);
6486 print_key(p_nat->key_ptrs[pkt_num]);
6493 /* entry found for this packet */
6494 entry = &napt_hash_tbl_entries[hash_table_entry];
6497 /* apply napt and mac changes */
6499 p_nat->entries[pkt_num] = &(entry->head);
6500 if (entry->data.type != CGNAPT_ENTRY_IPV6) {
6501 p_nat->invalid_packets |= pkt_mask;
6502 p_nat->naptDroppedPktCount++;
6506 struct ipv4_hdr ipv4_hdr;
6507 uint16_t *src_port =
6508 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP4_TCP);
6510 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
6511 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
6513 if (entry->data.ttl == NAPT_ENTRY_STALE)
6514 entry->data.ttl = NAPT_ENTRY_VALID;
6516 struct ether_addr hw_addr;
6517 uint8_t dest_addr_ipv6[16];
6518 uint8_t nh_ipv6[16];
6523 if (unlikely(protocol == IP_PROTOCOL_UDP
6524 && rte_be_to_cpu_16(*src_port) == 53)) {
6525 p_nat->invalid_packets |= pkt_mask;
6526 p_nat->naptDroppedPktCount++;
6527 #ifdef CGNAPT_DEBUGGING
6528 p_nat->naptDroppedPktCount6++;
6533 memcpy(&dest_addr_ipv6[0], &entry->data.u.prv_ipv6[0], 16);
6536 ret = local_get_nh_ipv6(&dest_addr_ipv6[0], &dest_if,
6539 dest_if = get_prv_to_pub_port((uint32_t *)
6543 if (dest_if == INVALID_DESTIF) {
6544 p_nat->invalid_packets |= pkt_mask;
6545 p_nat->naptDroppedPktCount++;
6546 #ifdef CGNAPT_DEBUGGING
6547 p_nat->naptDroppedPktCount6++;
6552 do_local_nh_ipv6_cache(dest_if, p_nat);
6554 *outport_id = p_nat->outport_id[dest_if];
6557 #ifdef CGNAPT_DEBUGGING
6558 static int static_count;
6560 if (static_count++ < 10) {
6562 my_print_entry(entry);
6563 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6564 printf("dest_add:%x\n", entry->data.u.prv_ip);
6565 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6569 memset(nh_ipv6, 0, 16);
6570 if (get_dest_mac_address_ipv6_port(
6576 #ifdef CGNAPT_DBG_PRNT
6577 if (CGNAPT_DEBUG > 2) {
6578 printf("MAC found for ip 0x%x, port %d - "
6579 "%02x:%02x:%02x:%02x:%02x:%02x\n",
6580 *((uint32_t *)dest_addr_ipv6 + 12),
6582 hw_addr.addr_bytes[0],
6583 hw_addr.addr_bytes[1], hw_addr.addr_bytes[2],
6584 hw_addr.addr_bytes[3], hw_addr.addr_bytes[4],
6585 hw_addr.addr_bytes[5]);
6587 printf("Dest MAC before - "
6588 "%02x:%02x:%02x:%02x:%02x:%02x\n",
6589 eth_dest[0], eth_dest[1], eth_dest[2],
6590 eth_dest[3], eth_dest[4], eth_dest[5]);
6594 memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
6596 #ifdef CGNAPT_DBG_PRNT
6597 if (CGNAPT_DEBUG > 2) {
6598 printf("Dest MAC after - "
6599 "%02x:%02x:%02x:%02x:%02x:%02x\n",
6600 eth_dest[0], eth_dest[1], eth_dest[2], eth_dest[3],
6601 eth_dest[4], eth_dest[5]);
6605 memcpy(eth_src, get_link_hw_addr(dest_if),
6606 sizeof(struct ether_addr));
6608 p_nat->invalid_packets |= pkt_mask;
6609 p_nat->naptDroppedPktCount++;
6611 #ifdef CGNAPT_DEBUGGING
6612 p_nat->naptDroppedPktCount4++;
6620 convert_ipv4_to_ipv6(pkt, &ipv4_hdr);
6622 /* Ethernet MTU check */
6623 if ((rte_pktmbuf_data_len(pkt) - 14) > 1500) {
6624 p_nat->invalid_packets |= pkt_mask;
6625 p_nat->naptDroppedPktCount++;
6628 uint32_t *dst_addr =
6629 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4t6);
6630 uint16_t *dst_port =
6631 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP4t6);
6633 memcpy((uint8_t *) &dst_addr[0], &entry->data.u.prv_ipv6[0],
6636 #ifdef NAT_ONLY_CONFIG_REQ
6637 if (!nat_only_config_flag) {
6639 *dst_port = rte_bswap16(entry->data.prv_port);
6641 #ifdef NAT_ONLY_CONFIG_REQ
6645 p_nat->inaptedPktCount++;
6648 p_nat->naptedPktCount++;
6651 if (p_nat->hw_checksum_reqd)
6652 hw_checksum(pkt, pkt_type);
6654 sw_checksum(pkt, pkt_type);
6660 * NAPT function for IPv6 private traffic which handles 4 pkts
6663 * A pointer to array of packets mbuf
6665 * Starting pkt number of pkts
6669 * A pointer to main CGNAPT structure
6673 pkt4_work_cgnapt_ipv6_prv(
6674 struct rte_mbuf **pkts,
6675 uint32_t in_pkt_num,
6676 __rte_unused void *arg,
6677 struct pipeline_cgnapt *p_nat)
6679 struct rte_mbuf *pkt;
6683 enum PKT_TYPE pkt_type = PKT_TYPE_IPV6to4;
6685 for (i = 0; i < 4; i++) {
6686 pkt_num = in_pkt_num + i;
6689 /* index into hash table entries */
6690 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6691 /*bitmask representing only this packet */
6692 uint64_t pkt_mask = 1LLU << pkt_num;
6694 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
6695 uint32_t dest_if = INVALID_DESTIF;
6696 uint16_t *outport_id =
6697 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6698 struct cgnapt_table_entry *entry = NULL;
6700 if (hash_table_entry < 0) {
6702 /* try to add new entry */
6703 struct rte_pipeline_table_entry *table_entry = NULL;
6706 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
6708 &p_nat->valid_packets, pkt_num,
6712 /* ICMP Error message generation for
6713 * Destination Host unreachable
6715 /* Do we need this check for ipv6? */
6716 if (protocol == IP_PROTOCOL_ICMP) {
6717 cgnapt_icmp_pkt = pkt;
6718 send_icmp_dest_unreachable_msg();
6721 /* Drop packet by adding to invalid pkt mask */
6723 p_nat->invalid_packets |= dropmask;
6725 #ifdef CGNAPT_DEBUGGING
6726 if (p_nat->kpc2++ < 5) {
6727 printf("in_ah Th: %d",
6728 p_nat->pipeline_num);
6729 print_key(p_nat->key_ptrs[pkt_num]);
6733 p_nat->naptDroppedPktCount++;
6735 #ifdef CGNAPT_DEBUGGING
6736 p_nat->naptDroppedPktCount3++;
6742 entry = (struct cgnapt_table_entry *)table_entry;
6744 /* entry found for this packet */
6745 entry = &napt_hash_tbl_entries[hash_table_entry];
6748 /* apply napt and mac changes */
6750 p_nat->entries[pkt_num] = &(entry->head);
6752 struct ipv6_hdr ipv6_hdr;
6753 struct ether_addr hw_addr;
6754 uint32_t dest_address = 0;
6755 uint8_t nh_ipv6[16];
6760 convert_ipv6_to_ipv4(pkt, &ipv6_hdr);
6762 #ifdef CGNAPT_DBG_PRNT
6763 if (CGNAPT_DEBUG >= 1)
6764 printf("pkt_work_cganpt: "
6765 "convert_ipv6_to_ipv4\n");
6768 struct cgnapt_nsp_node *ll = nsp_ll;
6771 while (ll != NULL) {
6772 if (!memcmp(&ipv6_hdr.dst_addr[0],
6774 ll->nsp.depth / 8)) {
6782 && !memcmp(&ipv6_hdr.dst_addr[0],
6783 &well_known_prefix[0], 12)) {
6788 p_nat->invalid_packets |= pkt_mask;
6789 p_nat->naptDroppedPktCount++;
6791 #ifdef CGNAPT_DEBUGGING
6792 p_nat->naptDroppedPktCount5++;
6799 /* As packet is already converted into IPv4 we must not
6800 * operate IPv6 offsets on packet only perform IPv4 operations
6803 uint32_t *src_addr =
6804 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP6t4);
6805 uint32_t *dst_addr =
6806 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP6t4);
6807 uint16_t *src_port =
6808 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP6t4);
6809 uint16_t *dst_port =
6810 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP6t4);
6813 RTE_MBUF_METADATA_UINT8_PTR(pkt, ETH_OFST_IP6t4);
6815 RTE_MBUF_METADATA_UINT8_PTR(pkt, ETH_OFST_IP6t4 + 6);
6817 if (entry->data.ttl == NAPT_ENTRY_STALE)
6818 entry->data.ttl = NAPT_ENTRY_VALID;
6823 if (unlikely(protocol == IP_PROTOCOL_UDP
6824 && rte_be_to_cpu_16(*dst_port) == 53)) {
6825 p_nat->invalid_packets |= pkt_mask;
6826 p_nat->naptDroppedPktCount++;
6828 #ifdef CGNAPT_DEBUGGING
6829 p_nat->naptDroppedPktCount6++;
6834 dest_address = rte_bswap32(*dst_addr);
6837 ret = local_get_nh_ipv4(dest_address, &dest_if, &nhip, p_nat);
6839 dest_if = get_prv_to_pub_port(&dest_address, IP_VERSION_4);
6841 if (dest_if == INVALID_DESTIF) {
6842 p_nat->invalid_packets |= pkt_mask;
6843 p_nat->naptDroppedPktCount++;
6844 #ifdef CGNAPT_DEBUGGING
6845 p_nat->naptDroppedPktCount6++;
6850 do_local_nh_ipv4_cache(dest_if, p_nat);
6852 *outport_id = p_nat->outport_id[dest_if];
6854 #ifdef CGNAPT_DBG_PRNT
6855 if (CGNAPT_DEBUG > 2)
6856 printf("Egress: \tphy_port:%d\t"
6857 "get_prv_to_pub():%d \tout_port:%d\n",
6858 pkt->port, dest_if, *outport_id);
6862 #ifdef CGNAPT_DEBUGGING
6863 static int static_count;
6865 if (static_count++ < 10) {
6867 my_print_entry(entry);
6868 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6869 printf("dest_add:%x\n", entry->data.u.prv_ip);
6870 printf("dest_add:%x\n", *dst_addr);
6871 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6875 memset(nh_ipv6, 0, 16);
6879 ret = get_dest_mac_addr_port(dest_address, &dest_if, &hw_addr);
6881 if (unlikely(ret != ARP_FOUND)) {
6883 if (unlikely(ret == ARP_NOT_FOUND)) {
6884 /* Commented code may be required for debug
6885 * and future use, Please keep it */
6886 //request_arp(*outport_id, nhip, p_nat->p.p);
6887 printf("%s: ARP Not Found, nhip: %x, "
6888 "outport_id: %d\n", __func__, nhip,
6893 p_nat->invalid_packets |= pkt_mask;
6894 p_nat->naptDroppedPktCount++;
6896 #ifdef CGNAPT_DEBUGGING
6897 p_nat->naptDroppedPktCount4++;
6903 #ifdef CGNAPT_DBG_PRNT
6904 if (CGNAPT_DEBUG > 2) {
6905 printf("MAC found for ip 0x%x, port %d - "
6906 "%02x:%02x:%02x:%02x:%02x:%02x\n",
6907 dest_address, *outport_id,
6908 hw_addr.addr_bytes[0],
6909 hw_addr.addr_bytes[1],
6910 hw_addr.addr_bytes[2],
6911 hw_addr.addr_bytes[3],
6912 hw_addr.addr_bytes[4],
6913 hw_addr.addr_bytes[5]
6916 printf("Dest MAC before - "
6917 "%02x:%02x:%02x:%02x:%02x:%02x\n",
6918 eth_dest[0], eth_dest[1], eth_dest[2],
6919 eth_dest[3], eth_dest[4], eth_dest[5]);
6923 memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
6925 #ifdef CGNAPT_DBG_PRNT
6926 if (CGNAPT_DEBUG > 2) {
6927 printf("Dest MAC after - "
6928 "%02x:%02x:%02x:%02x:%02x:%02x\n",
6929 eth_dest[0], eth_dest[1], eth_dest[2],
6930 eth_dest[3], eth_dest[4], eth_dest[5]);
6935 get_link_hw_addr(dest_if),
6936 sizeof(struct ether_addr));
6941 *src_addr = rte_bswap32(entry->data.pub_ip);
6943 #ifdef NAT_ONLY_CONFIG_REQ
6944 if (!nat_only_config_flag) {
6946 *src_port = rte_bswap16(entry->data.pub_port);
6948 #ifdef NAT_ONLY_CONFIG_REQ
6952 p_nat->enaptedPktCount++;
6955 p_nat->naptedPktCount++;
6958 if (p_nat->hw_checksum_reqd)
6959 hw_checksum(pkt, pkt_type);
6961 sw_checksum(pkt, pkt_type);
6967 * NAPT function for IPv6 public traffic which handles 4 pkts
6970 * A pointer to array of packets mbuf
6972 * Starting pkt number of pkts
6976 * A pointer to main CGNAPT structure
6980 pkt4_work_cgnapt_ipv6_pub(
6981 struct rte_mbuf **pkts,
6982 uint32_t in_pkt_num,
6983 __rte_unused void *arg,
6984 struct pipeline_cgnapt *p_nat)
6986 struct rte_mbuf *pkt;
6990 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4to6;
6992 for (i = 0; i < 4; i++) {
6993 pkt_num = in_pkt_num + i;
6996 /* index into hash table entries */
6997 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6998 /*bitmask representing only this packet */
6999 uint64_t pkt_mask = 1LLU << pkt_num;
7001 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
7002 uint16_t *outport_id =
7003 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
7004 struct cgnapt_table_entry *entry = NULL;
7006 if (hash_table_entry < 0) {
7008 /* Drop ingress initial traffic */
7010 p_nat->invalid_packets |= pkt_mask;
7011 p_nat->naptDroppedPktCount++;
7012 #ifdef CGNAPT_DEBUGGING
7013 p_nat->naptDroppedPktCount3++;
7014 if (p_nat->kpc2++ < 5) {
7015 printf("in_ah Th: %d", p_nat->pipeline_num);
7016 print_key(p_nat->key_ptrs[pkt_num]);
7023 /* entry found for this packet */
7024 entry = &napt_hash_tbl_entries[hash_table_entry];
7027 /* apply napt and mac changes */
7029 p_nat->entries[pkt_num] = &(entry->head);
7030 if (entry->data.type != CGNAPT_ENTRY_IPV6) {
7031 p_nat->invalid_packets |= pkt_mask;
7032 p_nat->naptDroppedPktCount++;
7036 struct ipv4_hdr ipv4_hdr;
7038 uint16_t *src_port =
7039 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP4_TCP);
7042 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
7044 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
7046 if (entry->data.ttl == NAPT_ENTRY_STALE)
7047 entry->data.ttl = NAPT_ENTRY_VALID;
7049 struct ether_addr hw_addr;
7050 uint8_t dest_addr_ipv6[16];
7051 uint8_t nh_ipv6[16];
7052 uint32_t dest_if = INVALID_DESTIF;
7056 if (unlikely(protocol == IP_PROTOCOL_UDP
7057 && rte_be_to_cpu_16(*src_port) == 53)) {
7058 p_nat->invalid_packets |= pkt_mask;
7059 p_nat->naptDroppedPktCount++;
7060 #ifdef CGNAPT_DEBUGGING
7061 p_nat->naptDroppedPktCount6++;
7066 memcpy(&dest_addr_ipv6[0], &entry->data.u.prv_ipv6[0],
7070 ret = local_get_nh_ipv6(&dest_addr_ipv6[0], &dest_if,
7073 dest_if = get_prv_to_pub_port((uint32_t *)
7074 &dest_addr_ipv6[0], IP_VERSION_6);
7076 if (dest_if == INVALID_DESTIF) {
7077 p_nat->invalid_packets |= pkt_mask;
7078 p_nat->naptDroppedPktCount++;
7079 #ifdef CGNAPT_DEBUGGING
7080 p_nat->naptDroppedPktCount6++;
7085 do_local_nh_ipv6_cache(dest_if, p_nat);
7088 *outport_id = p_nat->outport_id[dest_if];
7091 #ifdef CGNAPT_DEBUGGING
7092 static int static_count;
7094 if (static_count++ < 10) {
7096 my_print_entry(entry);
7097 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
7098 printf("dest_add:%x\n", entry->data.u.prv_ip);
7099 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
7103 memset(nh_ipv6, 0, 16);
7104 if (get_dest_mac_address_ipv6
7105 (&dest_addr_ipv6[0], &dest_if,
7106 &hw_addr, &nh_ipv6[0])) {
7107 #ifdef CGNAPT_DBG_PRNT
7108 if (CGNAPT_DEBUG > 2) {
7109 printf("MAC found for ip 0x%x, port %d - "
7110 "%02x:%02x:%02x:%02x:%02x:%02x\n",
7111 *((uint32_t *)dest_addr_ipv6 + 12),
7113 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
7114 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
7115 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
7117 printf("Dest MAC before - "
7118 "%02x:%02x:%02x:%02x:%02x:%02x\n",
7119 eth_dest[0], eth_dest[1], eth_dest[2],
7120 eth_dest[3], eth_dest[4], eth_dest[5]);
7124 memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
7126 #ifdef CGNAPT_DBG_PRNT
7127 if (CGNAPT_DEBUG > 2) {
7128 printf("Dest MAC after - "
7129 "%02x:%02x:%02x:%02x:%02x:%02x\n",
7130 eth_dest[0], eth_dest[1], eth_dest[2],
7131 eth_dest[3], eth_dest[4], eth_dest[5]);
7136 get_link_hw_addr(dest_if),
7137 sizeof(struct ether_addr));
7139 p_nat->invalid_packets |= pkt_mask;
7140 p_nat->naptDroppedPktCount++;
7142 #ifdef CGNAPT_DEBUGGING
7143 p_nat->naptDroppedPktCount4++;
7152 convert_ipv4_to_ipv6(pkt, &ipv4_hdr);
7154 /* Ethernet MTU check */
7155 if ((rte_pktmbuf_data_len(pkt) - 14) > 1500) {
7156 p_nat->invalid_packets |= pkt_mask;
7157 p_nat->naptDroppedPktCount++;
7160 uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
7161 DST_ADR_OFST_IP4t6);
7162 uint16_t *dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
7163 DST_PRT_OFST_IP4t6);
7165 memcpy((uint8_t *) &dst_addr[0],
7166 &entry->data.u.prv_ipv6[0], 16);
7168 #ifdef NAT_ONLY_CONFIG_REQ
7169 if (!nat_only_config_flag) {
7171 *dst_port = rte_bswap16(entry->data.prv_port);
7173 #ifdef NAT_ONLY_CONFIG_REQ
7177 p_nat->inaptedPktCount++;
7180 p_nat->naptedPktCount++;
7183 if (p_nat->hw_checksum_reqd)
7184 hw_checksum(pkt, pkt_type);
7186 sw_checksum(pkt, pkt_type);
7192 * Input port handler for IPv6 private traffic
7193 * Starting from the packet burst it filters unwanted packets,
7194 * calculates keys, does lookup and then based on the lookup
7195 * updates NAPT table and does packet NAPT translation.
7198 * A pointer to struct rte_pipeline
7200 * A pointer to array of packets mbuf
7202 * Number of packets in the burst
7207 * int that is not checked by caller
7209 static int cgnapt_in_port_ah_ipv6_prv(struct rte_pipeline *rte_p,
7210 struct rte_mbuf **pkts,
7211 uint32_t n_pkts, void *arg)
7214 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
7215 struct pipeline_cgnapt *p_nat = ap->p;
7217 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
7218 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
7219 p_nat->invalid_packets = 0;
7221 #ifdef CGNAPT_DBG_PRNT
7222 if (CGNAPT_DEBUG > 1)
7223 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
7226 /* prefetching for mbufs should be done here */
7227 for (j = 0; j < n_pkts; j++)
7228 rte_prefetch0(pkts[j]);
7230 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7231 pkt4_work_cgnapt_key_ipv6_prv(&pkts[i], i, arg, p_nat);
7233 for (; i < n_pkts; i++)
7234 pkt_work_cgnapt_key_ipv6_prv(pkts[i], i, arg, p_nat);
7236 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7238 if (unlikely(p_nat->valid_packets == 0)) {
7239 /* no suitable packet for lookup */
7240 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7241 return p_nat->valid_packets;
7244 /* lookup entries in the common napt table */
7246 int lookup_result = rte_hash_lookup_bulk(
7248 (const void **) &p_nat->key_ptrs,
7249 /* should be minus num invalid pkts */
7251 /*new pipeline data member */
7252 &p_nat->lkup_indx[0]);
7254 if (unlikely(lookup_result < 0)) {
7255 /* unknown error, just discard all packets */
7256 printf("Unexpected hash lookup error %d, "
7257 "discarding all packets",
7259 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
7263 /* Now call second stage of pipeline to one by one
7264 * check the result of our bulk lookup
7267 /* prefetching for table entries should be done here */
7268 for (j = 0; j < n_pkts; j++) {
7269 if (p_nat->lkup_indx[j] >= 0)
7270 rte_prefetch0(&napt_hash_tbl_entries
7271 [p_nat->lkup_indx[j]]);
7274 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7275 pkt4_work_cgnapt_ipv6_prv(&pkts[i], i, arg, p_nat);
7277 for (; i < n_pkts; i++)
7278 pkt_work_cgnapt_ipv6_prv(pkts[i], i, arg, p_nat);
7280 if (p_nat->invalid_packets) {
7281 /* get rid of invalid packets */
7282 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7284 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7286 #ifdef CGNAPT_DBG_PRNT
7287 if (CGNAPT_DEBUG > 1) {
7288 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
7289 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
7290 printf("invalid_packets:0x%jx\n",
7291 p_nat->invalid_packets);
7292 printf("rte_invalid_packets :0x%jx\n",
7293 rte_p->pkts_drop_mask);
7294 printf("Total pkts dropped :0x%jx\n",
7295 rte_p->n_pkts_ah_drop);
7300 return p_nat->valid_packets;
7305 * Input port handler for IPv6 public traffic
7306 * Starting from the packet burst it filters unwanted packets,
7307 * calculates keys, does lookup and then based on the lookup
7308 * updates NAPT table and does packet NAPT translation.
7311 * A pointer to struct rte_pipeline
7313 * A pointer to array of packets mbuf
7315 * Number of packets in the burst
7320 * int that is not checked by caller
7322 static int cgnapt_in_port_ah_ipv6_pub(struct rte_pipeline *rte_p,
7323 struct rte_mbuf **pkts,
7324 uint32_t n_pkts, void *arg)
7327 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
7328 struct pipeline_cgnapt *p_nat = ap->p;
7330 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
7331 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
7332 p_nat->invalid_packets = 0;
7334 #ifdef CGNAPT_DBG_PRNT
7335 if (CGNAPT_DEBUG > 1)
7336 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
7339 /* prefetching for mbufs should be done here */
7340 for (j = 0; j < n_pkts; j++)
7341 rte_prefetch0(pkts[j]);
7343 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7344 pkt4_work_cgnapt_key_ipv6_pub(&pkts[i], i, arg, p_nat);
7346 for (; i < n_pkts; i++)
7347 pkt_work_cgnapt_key_ipv6_pub(pkts[i], i, arg, p_nat);
7349 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7351 if (unlikely(p_nat->valid_packets == 0)) {
7352 /* no suitable packet for lookup */
7353 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7354 return p_nat->valid_packets;
7357 /* lookup entries in the common napt table */
7359 int lookup_result = rte_hash_lookup_bulk(
7361 (const void **) &p_nat->key_ptrs,
7362 /* should be minus num invalid pkts */
7364 /*new pipeline data member */
7365 &p_nat->lkup_indx[0]);
7367 if (unlikely(lookup_result < 0)) {
7368 /* unknown error, just discard all packets */
7369 printf("Unexpected hash lookup error %d, "
7370 "discarding all packets",
7372 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
7376 /* Now call second stage of pipeline to one by one
7377 * check the result of our bulk lookup
7380 /* prefetching for table entries should be done here */
7381 for (j = 0; j < n_pkts; j++) {
7382 if (p_nat->lkup_indx[j] >= 0)
7383 rte_prefetch0(&napt_hash_tbl_entries
7384 [p_nat->lkup_indx[j]]);
7387 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7388 pkt4_work_cgnapt_ipv6_pub(&pkts[i], i, arg, p_nat);
7390 for (; i < n_pkts; i++)
7391 pkt_work_cgnapt_ipv6_pub(pkts[i], i, arg, p_nat);
7393 if (p_nat->invalid_packets) {
7394 /* get rid of invalid packets */
7395 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7397 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7399 #ifdef CGNAPT_DBG_PRNT
7400 if (CGNAPT_DEBUG > 1) {
7401 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
7402 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
7403 printf("invalid_packets:0x%jx\n",
7404 p_nat->invalid_packets);
7405 printf("rte_invalid_packets :0x%jx\n",
7406 rte_p->pkts_drop_mask);
7407 printf("Total pkts dropped :0x%jx\n",
7408 rte_p->n_pkts_ah_drop);
7413 return p_nat->valid_packets;
7417 * Function to send ICMP dest unreachable msg
7420 void send_icmp_dest_unreachable_msg(void)
7423 struct ether_hdr *eth_h;
7424 struct ipv4_hdr *ip_h;
7425 struct icmp_hdr *icmp_h;
7426 struct rte_mbuf *icmp_pkt = cgnapt_icmp_pkt;
7428 if (icmp_pkt == NULL) {
7430 printf("Error allocating icmp_pkt rte_mbuf\n");
7434 port_id = icmp_pkt->port;
7436 struct app_link_params *link;
7437 link = &mylink[port_id];
7438 eth_h = rte_pktmbuf_mtod(icmp_pkt, struct ether_hdr *);
7439 ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
7440 icmp_h = (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
7442 struct ether_addr gw_addr;
7443 struct ether_addr dst_addr;
7444 ether_addr_copy(ð_h->s_addr, &dst_addr);
7445 rte_eth_macaddr_get(port_id, &gw_addr);
7446 ether_addr_copy(&gw_addr, ð_h->s_addr);
7447 ether_addr_copy(&dst_addr, ð_h->d_addr);
7449 eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
7450 ip_h->version_ihl = IP_VHL_DEF;
7451 ip_h->type_of_service = 0;
7452 ip_h->total_length = rte_cpu_to_be_16(sizeof(struct ipv4_hdr) +
7453 sizeof(struct icmp_hdr));
7454 ip_h->packet_id = 0xaabb;
7455 ip_h->fragment_offset = 0x0000;
7456 ip_h->time_to_live = 64;
7457 ip_h->next_proto_id = 1;
7460 uint32_t src_addr_offset =
7461 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_SRC_ADR_OFST;
7463 RTE_MBUF_METADATA_UINT32_PTR(cgnapt_icmp_pkt, src_addr_offset);
7465 ip_h->dst_addr = *src_addr;
7466 ip_h->src_addr = rte_bswap32(link->ip);
7468 ip_h->dst_addr = *src_addr;
7469 ip_h->src_addr = rte_bswap32(link->ip);
7471 ip_h->hdr_checksum = 0;
7472 ip_h->hdr_checksum = rte_ipv4_cksum(ip_h);
7473 icmp_h->icmp_type = 3; /* Destination Unreachable */
7474 icmp_h->icmp_code = 13; /* Communication administratively prohibited */
7476 icmp_h->icmp_cksum = ~rte_raw_cksum(icmp_h, sizeof(struct icmp_hdr));
7478 icmp_pkt->pkt_len = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
7479 sizeof(struct icmp_hdr);
7480 icmp_pkt->data_len = icmp_pkt->pkt_len;
7481 if (ARPICMP_DEBUG) {
7482 printf("Sending ICMP error message - "
7483 "Destination Unreachable\n");
7485 rte_pipeline_port_out_packet_insert(myP, port_id, icmp_pkt);
7489 * Function to add a dynamic NAPT entry pair
7492 * A pointer to struct pipeline
7494 * A pointer to struct pipeline_cgnapt_entry_key
7496 * expairy time of an dynamic or PCP req entry
7498 * uint8_t pointer of source address
7501 * A pointer to struct cgnapt_table_entry for added entry
7504 struct cgnapt_table_entry *add_dynamic_cgnapt_entry(
7506 struct pipeline_cgnapt_entry_key *key,
7513 void *entry_ptr, *ret_ptr;
7516 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
7518 #ifdef CGNAPT_DBG_PRNT
7519 if (CGNAPT_DEBUG >= 1) {
7520 printf("Th%d add_dynamic_cgnapt_entry key detail Entry:"
7521 "0x%x, %d, %d\n", p_nat->pipeline_num, key->ip, key->port,
7526 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX && i < p_nat->pkt_burst_cnt;
7528 if (p_nat->cgnapt_dyn_ent_table[i].ip == key->ip
7529 && p_nat->cgnapt_dyn_ent_table[i].port == key->port
7530 && p_nat->cgnapt_dyn_ent_table[i].pid == key->pid) {
7532 #ifdef CGNAPT_DBG_PRNT
7533 if (CGNAPT_DEBUG > 1)
7534 printf("add_dynamic_cgnapt_entry:pkt_burst "
7535 "array key matched!!!\n");
7538 return &napt_hash_tbl_entries
7539 [p_nat->cgnapt_dyn_ent_index[i]];
7543 #ifdef NAT_ONLY_CONFIG_REQ
7544 if (!nat_only_config_flag) {
7547 ret = increment_max_port_counter(key->ip, key->pid, p_nat);
7548 if (ret == MAX_PORT_INC_ERROR) {
7550 #ifdef CGNAPT_DEBUGGING
7551 p_nat->missedpktcount5++;
7554 #ifdef CGNAPT_DBG_PRNT
7555 if (CGNAPT_DEBUG > 1)
7556 printf("add_dynamic_cgnapt_entry:"
7557 "increment_max_port_counter-1 failed\n");
7564 if (ret == MAX_PORT_INC_REACHED) {
7566 #ifdef CGNAPT_DEBUGGING
7567 p_nat->missedpktcount6++;
7570 #ifdef CGNAPT_DBG_PRNT
7571 if (CGNAPT_DEBUG > 1)
7572 printf("add_dynamic_cgnapt_entry:"
7573 "increment_max_port_counter-2 failed\n");
7580 #ifdef NAT_ONLY_CONFIG_REQ
7585 port_num = get_free_iport(p_nat, &public_ip);
7587 if (port_num == -1) {
7589 #ifdef CGNAPT_DBG_PRNT
7590 if (CGNAPT_DEBUG > 2) {
7591 printf("add_dynamic_cgnapt_entry: %d\n", port_num);
7592 printf("add_dynamic_cgnapt_entry key detail:0x%x, "
7593 "%d, %d\n", key->ip, key->port, key->pid);
7597 #ifdef CGNAPT_DEBUGGING
7598 p_nat->missedpktcount7++;
7605 #ifdef NAT_ONLY_CONFIG_REQ
7606 if (!nat_only_config_flag) {
7609 if (ret == 2) { //MPPC_NEW_ENTRY
7611 /* check for max_clients_per_ip */
7612 if (rte_atomic16_read
7614 [rte_jhash(&public_ip, 4, 0) %
7615 CGNAPT_MAX_PUB_IP].count) ==
7616 p_nat->max_clients_per_ip) {
7618 /* For now just bail out
7619 * In future we can think about
7620 * retrying getting a new iport
7623 release_iport(port_num, public_ip, p_nat);
7625 #ifdef CGNAPT_DEBUGGING
7626 p_nat->missedpktcount10++;
7632 rte_atomic16_inc(&all_public_ip
7633 [rte_jhash(&public_ip, 4, 0) %
7634 CGNAPT_MAX_PUB_IP].count);
7636 #ifdef CGNAPT_DBG_PRNT
7637 if ((rte_jhash(&public_ip, 4, 0) %
7638 CGNAPT_MAX_PUB_IP) == 8)
7639 printf("pub ip:%x coutn:%d\n", public_ip,
7640 rte_atomic16_read(&all_public_ip
7641 [rte_jhash(&public_ip, 4, 0) %
7642 CGNAPT_MAX_PUB_IP].count));
7646 #ifdef NAT_ONLY_CONFIG_REQ
7650 #ifdef CGNAPT_DBG_PRNT
7651 if (CGNAPT_DEBUG > 0) {
7652 printf("add_dynamic_cgnapt_entry: %d\n",
7654 printf("add_dynamic_cgnapt_entry key detail: "
7655 "0x%x, %d, %d\n", key->ip, key->port, key->pid);
7659 struct cgnapt_table_entry entry = {
7661 .action = RTE_PIPELINE_ACTION_PORT,
7662 /* made it configurable below */
7663 {.port_id = p->port_out_id[0]},
7667 .prv_port = key->port,
7668 .pub_ip = public_ip,
7669 .pub_port = port_num,
7670 .prv_phy_port = key->pid,
7671 .pub_phy_port = get_pub_to_prv_port(
7675 /* if(timeout == -1) : static entry
7676 * if(timeout == 0 ) : dynamic entry
7677 * if(timeout > 0 ) : PCP requested entry
7679 .timeout = timeout > 0 ? timeout : 0,
7686 #ifdef NAT_ONLY_CONFIG_REQ
7687 if (nat_only_config_flag) {
7688 entry.data.prv_port = 0xffff;
7689 entry.data.pub_port = 0xffff;
7693 if (pkt_type == CGNAPT_ENTRY_IPV6) {
7694 entry.data.type = CGNAPT_ENTRY_IPV6;
7695 memcpy(&entry.data.u.prv_ipv6[0], src_addr, 16);
7697 entry.data.u.prv_ip = key->ip;
7698 entry.data.type = CGNAPT_ENTRY_IPV4;
7701 //entry.head.port_id = CGNAPT_PUB_PORT_ID; /* outgoing port info */
7702 entry.head.port_id = entry.data.pub_phy_port; /* outgoing port info */
7704 struct pipeline_cgnapt_entry_key second_key;
7705 /* Need to add a second ingress entry */
7706 second_key.ip = public_ip;
7707 second_key.port = port_num;
7708 second_key.pid = 0xffff;
7710 #ifdef NAT_ONLY_CONFIG_REQ
7711 if (nat_only_config_flag)
7712 second_key.port = 0xffff;
7715 #ifdef CGNAPT_DBG_PRNT
7716 if (CGNAPT_DEBUG > 2)
7717 printf("add_dynamic_cgnapt_entry second key detail:"
7718 "0x%x, %d, %d\n", second_key.ip, second_key.port,
7722 int32_t position = rte_hash_add_key(napt_common_table, (void *)key);
7725 #ifdef CGNAPT_DEBUGGING
7726 p_nat->missedpktcount8++;
7729 printf("CG-NAPT entry add failed ...returning "
7730 "without adding ... %d\n", position);
7735 #ifdef CGNAPT_DBG_PRNT
7737 printf("add_dynamic_cgnapt_entry\n");
7739 print_cgnapt_entry(&entry);
7743 memcpy(&napt_hash_tbl_entries[position], &entry,
7744 sizeof(struct cgnapt_table_entry));
7746 /* this pointer is returned to pkt miss function */
7747 ret_ptr = &napt_hash_tbl_entries[position];
7749 p_nat->n_cgnapt_entry_added++;
7750 p_nat->dynCgnaptCount++;
7752 /* Now modify the forward port for reverse entry */
7754 /* outgoing port info */
7755 //entry.head.port_id = CGNAPT_PRV_PORT_ID;
7756 /* outgoing port info */
7757 entry.head.port_id = entry.data.prv_phy_port;
7759 int32_t position2 = rte_hash_add_key(napt_common_table, &second_key);
7761 if (position2 < 0) {
7762 #ifdef CGNAPT_DEBUGGING
7763 p_nat->missedpktcount9++;
7765 printf("CG-NAPT entry reverse bulk add failed ..."
7766 "returning with fwd add ...%d\n",
7772 memcpy(&napt_hash_tbl_entries[position2], &entry,
7773 sizeof(struct cgnapt_table_entry));
7775 entry_ptr = &napt_hash_tbl_entries[position2];
7777 timer_thread_enqueue(key, &second_key, ret_ptr,
7778 entry_ptr, (struct pipeline *)p_nat);
7780 p_nat->n_cgnapt_entry_added++;
7781 p_nat->dynCgnaptCount++;
7783 if (p_nat->pkt_burst_cnt < RTE_PORT_IN_BURST_SIZE_MAX) {
7784 memcpy(&p_nat->cgnapt_dyn_ent_table[p_nat->pkt_burst_cnt], key,
7785 sizeof(struct pipeline_cgnapt_entry_key));
7786 p_nat->cgnapt_dyn_ent_index[p_nat->pkt_burst_cnt] = position;
7787 p_nat->pkt_burst_cnt++;
7792 int pkt_miss_cgnapt_count;
7794 * Function handle a missed NAPT entry lookup
7795 * Will attempt to add a dynamic entry pair.
7798 * A pointer to struct pipeline
7800 * A pointer to struct pipeline_cgnapt_entry_key
7802 * A pointer to pkt struct rte_mbuf
7804 * uint64_t pointer to pkt mask
7805 * @param table_entry
7806 * A pointer to struct rte_pipeline_table_entry to be created and returned
7808 * number of this pkt in current burst
7811 * A uint64_t mask for drop packets
7814 pkt_miss_cgnapt(struct pipeline_cgnapt_entry_key *key,
7815 struct rte_mbuf *pkt,
7816 struct rte_pipeline_table_entry **table_entry,
7817 __rte_unused uint64_t *pkts_mask,
7818 uint32_t pkt_num, void *arg)
7821 #ifdef CGNAPT_DBG_PRNT
7822 if (CGNAPT_DEBUG > 0)
7823 printf("\n pkt_miss_cgnapt\n");
7827 * see if get_port passes for this src address
7828 * if passed add a new egress entry and a
7829 * corresponding new ingress entry
7830 * return the fwd entry to calling function using input pointer
7831 * else if get_port fails drop packet
7834 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)arg;
7836 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
7837 uint32_t src_addr_offset_ipv6 =
7838 MBUF_HDR_ROOM + ETH_HDR_SIZE + IPV6_HDR_SRC_ADR_OFST;
7839 uint16_t phy_port = pkt->port;
7841 uint16_t *eth_proto =
7842 RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
7844 uint8_t *src_addr = NULL;
7845 uint8_t src_addr_ipv6[16];
7846 uint8_t pkt_type = CGNAPT_ENTRY_IPV4;
7847 /* To drop the packet */
7848 uint64_t drop_mask = 0;
7850 if (p_nat->is_static_cgnapt) {
7851 drop_mask |= 1LLU << pkt_num;
7852 p_nat->missedPktCount++;
7854 #ifdef CGNAPT_DEBUGGING
7855 p_nat->missedpktcount1++;
7860 if (rte_be_to_cpu_16(*eth_proto) == ETHER_TYPE_IPv6) {
7862 RTE_MBUF_METADATA_UINT8_PTR(pkt, src_addr_offset_ipv6);
7863 pkt_type = CGNAPT_ENTRY_IPV6;
7864 memcpy(src_addr_ipv6, src_addr, 16);
7869 /* some validation first */
7870 if (is_phy_port_privte(phy_port)) {
7871 /* dynamic NAPT entry creation */
7872 *table_entry = (struct rte_pipeline_table_entry *)
7873 add_dynamic_cgnapt_entry(
7874 (struct pipeline *)&p_nat->p,
7876 DYNAMIC_CGNAPT_TIMEOUT,
7878 src_addr_ipv6, &err);
7880 if (!(*table_entry)) {
7882 drop_mask |= 1LLU << pkt_num;
7883 p_nat->missedPktCount++;
7885 #ifdef CGNAPT_DEBUGGING
7886 p_nat->missedpktcount2++;
7889 #ifdef CGNAPT_DBG_PRNT
7890 if (CGNAPT_DEBUG > 1)
7891 printf("Add Dynamic NAT entry failed "
7895 #ifdef CGNAPT_DEBUGGING
7896 p_nat->missedpktcount11++;
7902 } else if (!is_phy_port_privte(phy_port)) {
7904 #ifdef CGNAPT_DBG_PRNT
7905 if (CGNAPT_DEBUG >= 2) {
7906 printf("Initial Ingress entry creation NOT ALLOWED "
7911 drop_mask |= 1LLU << pkt_num;
7912 p_nat->missedPktCount++;
7914 #ifdef CGNAPT_DEBUGGING
7915 p_nat->missedpktcount3++;
7919 #ifdef CGNAPT_DBG_PRNT
7920 if (CGNAPT_DEBUG > 1)
7921 printf("NOT a PRIVATE or PUBLIC port!!!!!\n");
7924 drop_mask |= 1LLU << pkt_num;
7925 p_nat->missedPktCount++;
7927 #ifdef CGNAPT_DEBUGGING
7928 p_nat->missedpktcount4++;
7932 #ifdef CGNAPT_DBG_PRNT
7933 if (CGNAPT_DEBUG > 5)
7943 * Function to print the contents of a packet
7946 * A pointer to pkt struct rte_mbuf
7948 void print_pkt(struct rte_mbuf *pkt)
7952 printf("\nPacket Contents:\n");
7954 uint8_t *rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
7956 for (i = 0; i < 20; i++) {
7957 for (j = 0; j < 20; j++)
7958 printf("%02x ", rd[(20 * i) + j]);
7964 rte_table_hash_op_hash cgnapt_hash_func[] = {
7976 * Function to parse incoming pipeline arguments
7977 * Called during pipeline initialization
7980 * A pointer to struct pipeline_cgnapt
7982 * A pointer to struct pipeline_params
7985 * 0 if success, negative if failure
7988 pipeline_cgnapt_parse_args(struct pipeline_cgnapt *p,
7989 struct pipeline_params *params)
7991 uint32_t n_flows_present = 0;
7992 uint32_t key_offset_present = 0;
7993 uint32_t key_size_present = 0;
7994 uint32_t hash_offset_present = 0;
7995 uint32_t n_entries_present = 0;
7996 uint32_t max_port_present = 0;
7997 uint32_t max_client_present = 0;
7998 uint32_t public_ip_range_present = 0;
7999 uint32_t public_ip_port_range_present = 0;
8001 uint8_t public_ip_count = 0;
8002 uint8_t public_ip_range_count = 0;
8003 uint8_t dest_if_offset_present = 0;
8004 uint8_t cgnapt_meta_offset_present = 0;
8005 uint8_t prv_que_handler_present = 0;
8006 uint8_t n_prv_in_port = 0;
8008 if (CGNAPT_DEBUG > 2) {
8009 printf("CGNAPT pipeline_cgnapt_parse_args params->n_args: %d\n",
8012 for (i = 0; i < params->n_args; i++) {
8013 char *arg_name = params->args_name[i];
8014 char *arg_value = params->args_value[i];
8016 if (CGNAPT_DEBUG > 2) {
8017 printf("CGNAPT args[%d]: %s %d, %s\n", i, arg_name,
8018 atoi(arg_value), arg_value);
8020 if (strcmp(arg_name, "prv_que_handler") == 0) {
8022 if (prv_que_handler_present) {
8023 printf("Duplicate pktq_in_prv ..\n\n");
8026 prv_que_handler_present = 1;
8031 /* get the first token */
8032 token = strtok(arg_value, "(");
8033 token = strtok(token, ")");
8034 token = strtok(token, ",");
8035 printf("***** prv_que_handler *****\n");
8037 if (token == NULL) {
8038 printf("string is null\n");
8039 printf("invalid prv_que_handler value/n");
8042 printf("string is :%s\n", token);
8044 /* walk through other tokens */
8045 while (token != NULL) {
8046 printf(" %s\n", token);
8047 rxport = atoi(token);
8048 cgnapt_prv_que_port_index[n_prv_in_port++] =
8050 if (rxport < PIPELINE_MAX_PORT_IN)
8051 cgnapt_in_port_egress_prv[rxport] = 1;
8052 token = strtok(NULL, ",");
8055 if (n_prv_in_port == 0) {
8056 printf("VNF common parse err - "
8057 "no prv RX phy port\n");
8063 if (strcmp(arg_name, "cgnapt_meta_offset") == 0) {
8064 if (cgnapt_meta_offset_present) {
8065 printf("CG-NAPT parse error:");
8066 printf("cgnapt_meta_offset initizlized "
8067 "mulitple times\n");
8070 cgnapt_meta_offset_present = 1;
8072 temp = atoi(arg_value);
8075 printf("cgnapt_meta_offset is invalid :");
8076 printf("Not be more than metadata size\n");
8079 cgnapt_meta_offset = (uint16_t) temp;
8081 if (strcmp(arg_name, "vnf_set") == 0)
8084 if (strcmp(arg_name, "public_ip_range") == 0) {
8085 public_ip_range_present = 1;
8086 if (public_ip_port_range_present) {
8087 printf("CG-NAPT parse error:");
8088 printf("public_ip_range with "
8089 "public_ip_port_range_present\n");
8093 p->pub_ip_range = rte_realloc(p->pub_ip_range,
8096 RTE_CACHE_LINE_SIZE);
8098 if (!p->pub_ip_range) {
8099 printf("Memory allocation failed for "
8104 uint32_t sip = 0, eip = 0;
8106 if (sscanf(arg_value, "(%x,%x)", &sip, &eip) != 2) {
8107 printf("public_ip_range is invalid\n");
8111 if (sip <= 0 || eip <= 0 || sip >= eip) {
8112 printf("public_ip_range is invalid %x-%x\n",
8117 printf("public_ip_range: %d-%d\n",
8118 p->pub_ip_range[public_ip_range_count].
8120 p->pub_ip_range[public_ip_range_count].
8123 p->pub_ip_range_count = ++public_ip_range_count;
8127 if (strcmp(arg_name, "public_ip_port_range") == 0) {
8128 public_ip_port_range_present = 1;
8129 if (nat_only_config_flag || public_ip_range_present) {
8131 printf("CG-NAPT parse error:");
8132 printf("nat_only_config_flag OR ");
8133 printf("public_ip_range_present with "
8134 "public_ip_port_range_present\n");
8138 p->pub_ip_port_set = rte_realloc(
8140 sizeof(struct pub_ip_port_set),
8141 RTE_CACHE_LINE_SIZE);
8143 if (!p->pub_ip_port_set) {
8144 printf("Memory allocation failed for "
8152 if (sscanf(arg_value, "%x:(%d,%d)",
8153 &ip, &sp, &ep) != 3) {
8154 printf("Public IP or Port-range is invalid\n");
8158 if (ip <= 0 || sp <= 0 || ep <= 0 || sp > ep) {
8159 printf("Public IP or Port-range is invalid "
8160 "%x:%d-%d\n", ip, sp, ep);
8164 printf("public_ip: 0x%x Range:%d-%d\n",
8165 p->pub_ip_port_set[public_ip_count].ip = ip,
8166 p->pub_ip_port_set[public_ip_count].start_port = sp,
8167 p->pub_ip_port_set[public_ip_count].end_port = ep);
8169 napt_port_alloc_elem_count += (ep - sp + 1);
8170 printf("parse - napt_port_alloc_elem_count :%d\n",
8171 napt_port_alloc_elem_count);
8173 /* Store all public IPs of all CGNAPT threads
8174 * in the global variable
8176 /* to revisit indexing */
8177 all_public_ip[rte_jhash(&ip, 4, 0) %
8178 CGNAPT_MAX_PUB_IP].ip = ip;
8179 p->pub_ip_count = ++public_ip_count;
8180 printf("public_ip_count:%d hash:%d\n", public_ip_count,
8181 rte_jhash(&ip, 4, 0) % CGNAPT_MAX_PUB_IP);
8185 /* hw_checksum_reqd */
8186 if (strcmp(arg_name, "hw_checksum_reqd") == 0) {
8188 temp = atoi(arg_value);
8189 if ((temp != 0) && (temp != 1)) {
8190 printf("hw_checksum_reqd is invalid\n");
8193 p->hw_checksum_reqd = temp;
8197 /* nat_only_config_flag */
8198 if (strcmp(arg_name, "nat_only_config_flag") == 0) {
8199 nat_only_config_flag = 1;
8200 if (public_ip_port_range_present) {
8202 printf("CG-NAPT parse error:");
8203 printf("nat_only_config_flag with "
8204 "public_ip_port_range_present\n");
8210 /* max_port_per_client */
8211 if (strcmp(arg_name, "max_port_per_client") == 0) {
8212 if (max_port_present) {
8213 printf("CG-NAPT Parse Error: "
8214 "duplicate max_port_per_client\n");
8217 max_port_present = 1;
8220 max = atoi(arg_value);
8222 printf("max_port_per_client is invalid !!!\n");
8226 p->max_port_per_client = (uint16_t) max;
8228 if (p->max_port_per_client <= 0) {
8229 printf("max port per client is invalid\n");
8233 printf("max_port_per_client comp: %d\n",
8234 p->max_port_per_client);
8238 /* max_clients_per_ip */
8239 if (strcmp(arg_name, "max_clients_per_ip") == 0) {
8240 if (max_client_present) {
8241 printf("CG-NAPT parse Error: duplicate "
8242 "max_clients_per_ip\n");
8245 max_client_present = 1;
8247 if (nat_only_config_flag) {
8248 printf("CG-NAPT parse error:");
8249 printf("nat_only_config_flag with "
8250 "max_clients_per_ip\n");
8255 max = atoi(arg_value);
8257 printf("max_clients_per_ip is invalid !!!\n");
8261 p->max_clients_per_ip = (uint16_t) max;
8263 if (p->max_clients_per_ip <= 0) {
8264 printf("max_clients_per_ip is invalid\n");
8268 printf("max_clients_per_ip: %d\n",
8269 p->max_clients_per_ip);
8274 if (strcmp(arg_name, "n_entries") == 0) {
8275 if (n_entries_present)
8277 n_entries_present = 1;
8279 p->n_entries = atoi(arg_value);
8280 if (p->n_entries == 0)
8287 if (strcmp(arg_name, "n_flows") == 0) {
8288 if (n_flows_present)
8290 n_flows_present = 1;
8292 p->n_flows = atoi(arg_value);
8293 if (p->n_flows == 0)
8296 napt_common_table_hash_params.entries = p->n_flows;
8299 /* dest_if_offset Multiport Changes */
8300 if (strcmp(arg_name, "dest_if_offset") == 0) {
8301 if (dest_if_offset_present)
8303 //dest_if_offset_present = 1;
8305 dest_if_offset = atoi(arg_value);
8311 if (strcmp(arg_name, "key_offset") == 0) {
8312 if (key_offset_present)
8314 key_offset_present = 1;
8316 p->key_offset = atoi(arg_value);
8322 if (strcmp(arg_name, "key_size") == 0) {
8323 if (key_size_present)
8325 key_size_present = 1;
8327 p->key_size = atoi(arg_value);
8328 if ((p->key_size == 0) ||
8329 (p->key_size > PIPELINE_CGNAPT_KEY_MAX_SIZE) ||
8337 if (strcmp(arg_name, "hash_offset") == 0) {
8338 if (hash_offset_present)
8340 hash_offset_present = 1;
8342 p->hash_offset = atoi(arg_value);
8348 if (strcmp(arg_name, "pkt_type") == 0) {
8349 if (strcmp(arg_value, "ipv4") == 0) {
8350 p->traffic_type = TRAFFIC_TYPE_IPV4;
8351 printf("Traffic is set to IPv4\n");
8352 } else if (strcmp(arg_value, "ipv6") == 0) {
8353 p->traffic_type = TRAFFIC_TYPE_IPV6;
8354 printf("Traffic is set to IPv6\n");
8360 if (strcmp(arg_name, "cgnapt_debug") == 0) {
8361 CGNAPT_DEBUG = atoi(arg_value);
8366 /* any other Unknown argument return -1 */
8369 #ifdef NAT_ONLY_CONFIG_REQ
8370 if (nat_only_config_flag) {
8371 if (!public_ip_range_count) {
8372 printf("No public_ip_range %d for NAT only config.\n",
8373 public_ip_range_count);
8374 printf("Running static NAT only configuration\n");
8375 p->is_static_cgnapt = 1;
8380 if (!p->max_port_per_client)
8381 p->is_static_cgnapt = 1;
8384 /* Check that mandatory arguments are present */
8385 if ((n_flows_present == 0) ||
8386 (cgnapt_meta_offset_present == 0))
8394 * Function to initialize the pipeline
8397 * A pointer to struct pipeline_params
8399 * Void pointer - points to app params
8402 * void pointer to the pipeline, NULL 0 if failure
8404 static void *pipeline_cgnapt_init(struct pipeline_params *params, void *arg)
8405 /* (struct app_params *app) save it for use in port in handler */
8408 struct pipeline_cgnapt *p_nat;
8409 uint32_t size, i, in_ports_arg_size;
8411 /* Check input arguments */
8412 if ((params == NULL) ||
8413 (params->n_ports_in == 0) || (params->n_ports_out == 0))
8416 /* Memory allocation */
8417 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_cgnapt));
8418 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8419 p_nat = (struct pipeline_cgnapt *)p;
8423 all_pipeline_cgnapt[n_cgnapt_pipeline++] = p_nat;
8425 strcpy(p->name, params->name);
8426 p->log_level = params->log_level;
8428 PLOG(p, HIGH, "CG-NAPT");
8429 /* Initialize all counters and arrays */
8431 p_nat->n_cgnapt_entry_deleted = 0;
8432 p_nat->n_cgnapt_entry_added = 0;
8433 p_nat->naptedPktCount = 0;
8434 p_nat->naptDroppedPktCount = 0;
8435 p_nat->inaptedPktCount = 0;
8436 p_nat->enaptedPktCount = 0;
8437 p_nat->receivedPktCount = 0;
8438 p_nat->missedPktCount = 0;
8439 p_nat->dynCgnaptCount = 0;
8440 p_nat->arpicmpPktCount = 0;
8442 p_nat->app_params_addr = (uint64_t) arg;
8443 for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
8444 p_nat->links_map[i] = 0xff;
8445 p_nat->outport_id[i] = 0xff;
8446 cgnapt_in_port_egress_prv[i] = 0;
8447 cgnapt_prv_que_port_index[i] = 0;
8449 p_nat->pipeline_num = 0xff;
8450 p_nat->hw_checksum_reqd = 0;
8451 p_nat->pub_ip_port_set = NULL;
8452 p_nat->pub_ip_count = 0;
8453 p_nat->traffic_type = TRAFFIC_TYPE_MIX;
8454 p_nat->vnf_set = 0xff;
8456 /* For every init it should be reset */
8457 napt_port_alloc_elem_count = 0;
8459 #ifdef CGNAPT_TIMING_INST
8460 p_nat->in_port_exit_timestamp = 0;
8461 p_nat->external_time_sum = 0;
8462 p_nat->internal_time_sum = 0;
8463 p_nat->time_measurements = 0;
8464 p_nat->max_time_mesurements = 10000;
8465 p_nat->time_measurements_on = 0;
8468 #ifdef CGNAPT_DEBUGGING
8470 p_nat->naptDebugCount = 0;
8472 p_nat->naptDroppedPktCount1 = 0;
8473 p_nat->naptDroppedPktCount2 = 0;
8474 p_nat->naptDroppedPktCount3 = 0;
8475 p_nat->naptDroppedPktCount4 = 0;
8476 p_nat->naptDroppedPktCount5 = 0;
8477 p_nat->naptDroppedPktCount6 = 0;
8479 p_nat->missedpktcount1 = 0;
8480 p_nat->missedpktcount2 = 0;
8481 p_nat->missedpktcount3 = 0;
8482 p_nat->missedpktcount4 = 0;
8483 p_nat->missedpktcount5 = 0;
8484 p_nat->missedpktcount6 = 0;
8485 p_nat->missedpktcount7 = 0;
8486 p_nat->missedpktcount8 = 0;
8487 p_nat->missedpktcount9 = 0;
8488 p_nat->missedpktcount10 = 0;
8489 p_nat->missedpktcount11 = 0;
8490 p_nat->missedpktcount12 = 0;
8492 p_nat->max_port_dec_err1 = 0;
8493 p_nat->max_port_dec_err2 = 0;
8494 p_nat->max_port_dec_err3 = 0;
8495 p_nat->max_port_dec_success = 0;
8511 static int sip_enabled;
8515 #endif /* SIP_ALG */
8517 /*struct rte_pipeline_table_entry *entries[RTE_HASH_LOOKUP_BULK_MAX];*/
8518 /* bitmap of valid packets */
8519 p_nat->valid_packets = 0;
8520 /* bitmap of invalid packets to be dropped */
8521 p_nat->invalid_packets = 0;
8523 for (i = 0; i < RTE_HASH_LOOKUP_BULK_MAX; i++)
8524 p_nat->key_ptrs[i] = &(p_nat->keys[i]);
8526 p_nat->port_alloc_ring = NULL;
8528 /* Parse arguments */
8529 if (pipeline_cgnapt_parse_args(p_nat, params))
8532 p_nat->vnf_set = vnf_set_count;
8536 struct rte_pipeline_params pipeline_params = {
8537 .name = params->name,
8538 .socket_id = params->socket_id,
8539 .offset_port_id = cgnapt_meta_offset,
8542 p->p = rte_pipeline_create(&pipeline_params);
8550 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8552 uint32_t instr_size =
8553 RTE_CACHE_LINE_ROUNDUP((sizeof(uint64_t)) *
8556 (uint64_t *) rte_zmalloc(NULL, instr_size,
8557 RTE_CACHE_LINE_SIZE);
8559 (uint64_t *) rte_zmalloc(NULL, instr_size,
8560 RTE_CACHE_LINE_SIZE);
8562 (uint32_t *) rte_zmalloc(NULL, instr_size / 2,
8563 RTE_CACHE_LINE_SIZE);
8564 if ((inst_start_time == NULL) || (inst_end_time == NULL)
8565 || (inst_diff_time == NULL)) {
8566 printf("Inst array alloc failed .... ");
8571 /* Memory allocation for in_port_h_arg */
8572 in_ports_arg_size = RTE_CACHE_LINE_ROUNDUP(
8573 (sizeof(struct pipeline_cgnapt_in_port_h_arg)) *
8574 (params->n_ports_in));
8575 struct pipeline_cgnapt_in_port_h_arg *ap =
8576 (struct pipeline_cgnapt_in_port_h_arg *)
8579 RTE_CACHE_LINE_SIZE);
8583 myApp = (struct app_params *) arg;
8586 p->n_ports_in = params->n_ports_in;
8587 for (i = 0; i < p->n_ports_in; i++) {
8588 /* passing our cgnapt pipeline in call back arg */
8590 (ap[i]).in_port_id = i;
8592 struct rte_pipeline_port_in_params port_params = {
8594 pipeline_port_in_params_get_ops(¶ms->port_in
8597 pipeline_port_in_params_convert(¶ms->port_in
8599 .f_action = cgnapt_in_port_ah_mix,
8601 .burst_size = params->port_in[i].burst_size,
8604 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8606 instrumentation_port_in_arg = &(ap[i]);
8609 if (p_nat->traffic_type == TRAFFIC_TYPE_IPV4) {
8610 /* Private in-port handler */
8611 /* Multiport changes */
8612 if (cgnapt_in_port_egress_prv[i]) {
8613 port_params.f_action =
8614 cgnapt_in_port_ah_ipv4_prv;
8615 printf("CGNAPT port %d is IPv4 Prv\n", i);
8617 port_params.f_action =
8618 cgnapt_in_port_ah_ipv4_pub;
8619 printf("CGNAPT port %d is IPv4 Pub\n", i);
8623 if (p_nat->traffic_type == TRAFFIC_TYPE_IPV6) {
8624 if (cgnapt_in_port_egress_prv[i]) {
8625 port_params.f_action =
8626 cgnapt_in_port_ah_ipv6_prv;
8627 printf("CGNAPT port %d is IPv6 Prv\n", i);
8629 port_params.f_action =
8630 cgnapt_in_port_ah_ipv6_pub;
8631 printf("CGNAPT port %d is IPv6 Pub\n", i);
8635 int status = rte_pipeline_port_in_create(p->p,
8640 rte_pipeline_free(p->p);
8648 p->n_ports_out = params->n_ports_out;
8649 for (i = 0; i < p->n_ports_out; i++) {
8650 struct rte_pipeline_port_out_params port_params = {
8651 .ops = pipeline_port_out_params_get_ops(
8652 ¶ms->port_out[i]),
8653 .arg_create = pipeline_port_out_params_convert(
8654 ¶ms->port_out[i]),
8655 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8656 .f_action = port_out_ah_cgnapt,
8663 int status = rte_pipeline_port_out_create(p->p,
8665 &p->port_out_id[i]);
8668 rte_pipeline_free(p->p);
8674 int pipeline_num = 0;
8676 ignore = sscanf(params->name, "PIPELINE%d", &pipeline_num);
8678 printf("Not able to read pipeline number\n");
8681 p_nat->pipeline_num = (uint8_t) pipeline_num;
8682 register_pipeline_Qs(p_nat->pipeline_num, p);
8683 set_link_map(p_nat->pipeline_num, p, p_nat->links_map);
8684 set_outport_id(p_nat->pipeline_num, p, p_nat->outport_id);
8690 if (napt_common_table == NULL) {
8691 if (create_napt_common_table(p_nat->n_flows)) {
8693 "CG-NAPT create_napt_common_table failed.");
8698 struct rte_pipeline_table_params table_params = {
8699 .ops = &rte_table_stub_ops,
8701 .f_action_hit = NULL,
8702 .f_action_miss = NULL,
8704 .action_data_size = 0,
8707 int status = rte_pipeline_table_create(p->p,
8712 rte_pipeline_free(p->p);
8716 struct rte_pipeline_table_entry default_entry = {
8717 .action = RTE_PIPELINE_ACTION_PORT_META
8719 struct rte_pipeline_table_entry *default_entry_ptr;
8720 status = rte_pipeline_table_default_entry_add(
8724 &default_entry_ptr);
8726 rte_pipeline_free(p->p);
8732 /* Connecting input ports to tables */
8733 for (i = 0; i < p->n_ports_in; i++) {
8734 int status = rte_pipeline_port_in_connect_to_table(p->p,
8741 rte_pipeline_free(p->p);
8747 /* Enable input ports */
8748 for (i = 0; i < p->n_ports_in; i++) {
8749 int status = rte_pipeline_port_in_enable(p->p,
8753 rte_pipeline_free(p->p);
8759 /* Check pipeline consistency */
8760 if (rte_pipeline_check(p->p) < 0) {
8761 rte_pipeline_free(p->p);
8766 /* Message queues */
8767 p->n_msgq = params->n_msgq;
8768 for (i = 0; i < p->n_msgq; i++)
8769 p->msgq_in[i] = params->msgq_in[i];
8770 for (i = 0; i < p->n_msgq; i++)
8771 p->msgq_out[i] = params->msgq_out[i];
8773 /* Message handlers */
8774 memcpy(p->handlers, handlers, sizeof(p->handlers));
8775 memcpy(p_nat->custom_handlers,
8776 custom_handlers, sizeof(p_nat->custom_handlers));
8778 if (!p_nat->is_static_cgnapt) {
8779 printf("Initializing dyn napt components ... %d\n",
8780 p_nat->pipeline_num);
8781 if (napt_port_alloc_init(p_nat) == -1) {
8782 printf("Error - napt_port_alloc_init failed - %d\n",
8783 p_nat->pipeline_num);
8788 if (max_port_per_client_hash == NULL) {
8789 rc = init_max_port_per_client(p_nat);
8791 printf("CGNAPT Error - "
8792 "init_max_port_per_client failed %d", rc);
8799 if (!icmp_pool_init) {
8801 /* create the arp_icmp mbuf rx pool */
8802 cgnapt_icmp_pktmbuf_tx_pool =
8803 rte_pktmbuf_pool_create("icmp_mbuf_tx_pool", 63, 32, 0,
8804 RTE_MBUF_DEFAULT_BUF_SIZE,
8806 if (cgnapt_icmp_pktmbuf_tx_pool == NULL) {
8807 PLOG(p, HIGH, "ICMP mbuf pool create failed.");
8812 rte_pktmbuf_alloc(cgnapt_icmp_pktmbuf_tx_pool);
8814 if (cgnapt_icmp_pkt == NULL) {
8815 printf("Failed to allocate cgnapt_icmp_pkt\n");
8822 cgnat_cnxn_tracker = rte_zmalloc(NULL, rte_ct_get_cnxn_tracker_size(),
8823 RTE_CACHE_LINE_SIZE);
8825 if (cgnat_cnxn_tracker == NULL) {
8826 printf("CGNAPT CT memory not allocated\n");
8829 rte_ct_initialize_default_timeouts(cgnat_cnxn_tracker);
8831 printf("CGNAPT CT Flows %d\n", p_nat->n_flows);
8833 ret = rte_ct_initialize_cnxn_tracker(cgnat_cnxn_tracker,
8835 "CGNAT_CT_COMMON_TABLE");
8845 if (pcp_init() == PCP_INIT_SUCCESS)
8846 printf("PCP contents are initialized successfully\n");
8848 printf("Error in initializing PCP contents\n");
8855 * Function for pipeline cleanup
8858 * A void pointer to pipeline
8863 static int pipeline_cgnapt_free(void *pipeline)
8865 struct pipeline *p = (struct pipeline *)pipeline;
8867 /* Check input arguments */
8871 /* Free resources */
8872 rte_pipeline_free(p->p);
8878 pipeline_cgnapt_track(void *pipeline, __rte_unused uint32_t port_in,
8881 struct pipeline *p = (struct pipeline *)pipeline;
8883 /* Check input arguments */
8884 if ((p == NULL) || (port_in >= p->n_ports_in) || (port_out == NULL))
8887 if (p->n_ports_in == 1) {
8896 * Function for pipeline timers
8899 * A void pointer to pipeline
8904 static int pipeline_cgnapt_timer(void *pipeline)
8906 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)pipeline;
8908 pipeline_msg_req_handle(&p_nat->p);
8910 rte_pipeline_flush(((struct pipeline *)p_nat)->p);
8916 * Function for pipeline custom handlers
8919 * A void pointer to pipeline
8921 * void pointer for incoming data
8924 * void pointer of response
8926 void *pipeline_cgnapt_msg_req_custom_handler(struct pipeline *p, void *msg)
8928 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
8929 struct pipeline_custom_msg_req *req = msg;
8930 pipeline_msg_req_handler f_handle;
8932 f_handle = (req->subtype < PIPELINE_CGNAPT_MSG_REQS) ?
8933 p_nat->custom_handlers[req->subtype] :
8934 pipeline_msg_req_invalid_handler;
8936 if (f_handle == NULL)
8937 f_handle = pipeline_msg_req_invalid_handler;
8939 return f_handle(p, req);
8943 * Function for adding NSP data
8946 * A void pointer to pipeline
8948 * void pointer for incoming data
8951 * void pointer of response
8953 void *pipeline_cgnapt_msg_req_nsp_add_handler(
8954 __rte_unused struct pipeline *p,
8957 struct pipeline_cgnapt_nsp_add_msg_req *req = msg;
8958 struct pipeline_cgnapt_nsp_add_msg_rsp *rsp = msg;
8960 struct cgnapt_nsp_node *node = NULL, *ll = nsp_ll;
8963 (req->nsp.depth == 32 || req->nsp.depth == 40
8964 || req->nsp.depth == 48 || req->nsp.depth == 56
8965 || req->nsp.depth == 64 || req->nsp.depth == 96)) {
8971 printf("be initial cond\n");
8972 if (nsp_ll == NULL) {
8973 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_nsp_node));
8974 node = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8976 printf("be 1st cond\n");
8982 memcpy(&node->nsp, &req->nsp,
8983 sizeof(struct pipeline_cgnapt_nsp_t));
8987 while (ll != NULL) {
8988 if (!memcmp(ll->nsp.prefix, req->nsp.prefix, 16)
8989 && ll->nsp.depth == req->nsp.depth) {
8990 printf("be 2st cond\n");
8998 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_nsp_node));
8999 node = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
9001 printf("be 3st cond\n");
9007 memcpy(&node->nsp, &req->nsp,
9008 sizeof(struct pipeline_cgnapt_nsp_t));
9009 node->next = nsp_ll;
9016 printf("be 4st cond\n");
9021 * Function for deleting NSP data
9024 * A void pointer to pipeline
9026 * void pointer for incoming data
9029 * void pointer of response
9031 void *pipeline_cgnapt_msg_req_nsp_del_handler(
9032 __rte_unused struct pipeline *p,
9035 struct pipeline_cgnapt_nsp_del_msg_req *req = msg;
9036 struct pipeline_cgnapt_nsp_del_msg_rsp *rsp = msg;
9037 struct cgnapt_nsp_node *prev = NULL, *ll = nsp_ll;
9039 while (ll != NULL) {
9040 if (!memcmp(ll->nsp.prefix, req->nsp.prefix, 16)
9041 && ll->nsp.depth == req->nsp.depth) {
9043 prev->next = ll->next;
9066 * Function for adding NAPT entry
9069 * A void pointer to pipeline
9071 * void pointer for incoming data
9074 * void pointer of response
9076 void *pipeline_cgnapt_msg_req_entry_add_handler(struct pipeline *p, void *msg)
9078 struct pipeline_cgnapt_entry_add_msg_req *req = msg;
9079 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9080 uint8_t type = req->data.type;
9081 uint32_t src_ip = (type == CGNAPT_ENTRY_IPV4) ?
9082 req->data.u.prv_ip :
9083 rte_bswap32(req->data.u.u32_prv_ipv6[3]);
9085 uint8_t src_ipv6[16];
9087 uint32_t dest_ip = req->data.pub_ip;
9088 uint16_t src_port = req->data.prv_port;
9089 uint16_t dest_port = req->data.pub_port;
9090 uint16_t rx_port = req->data.prv_phy_port;
9091 uint32_t ttl = req->data.ttl;
9093 if (type == CGNAPT_ENTRY_IPV6)
9094 memcpy(src_ipv6, req->data.u.prv_ipv6, 16);
9096 printf("CG-NAPT addm - PrvIP %x, PrvPort %d,", src_ip, src_port);
9097 printf("PubIP %x, PubPort %d,", dest_ip, dest_port);
9099 printf("PhyPort %d, ttl %u,", rx_port, ttl);
9100 printf("entry_type %d\n", type);
9102 #ifdef NAT_ONLY_CONFIG_REQ
9103 if (nat_only_config_flag) {
9104 if (!p_nat->is_static_cgnapt) {
9107 for (i = 0; i < p_nat->pub_ip_range_count; i++) {
9108 if (((dest_ip >= p_nat->pub_ip_range[i].start_ip)
9109 && (dest_ip <= p_nat->pub_ip_range[i].end_ip))) {
9110 printf("Error - static port cannot be in Dynamic "
9112 printf("%x-%x\n", p_nat->pub_ip_range[i].start_ip,
9113 p_nat->pub_ip_range[i].end_ip);
9119 if (pipeline_cgnapt_msg_req_entry_addm_pair(p, msg,
9125 printf("pipeline_cgnapt_msg_req_entry_addm_handler\n");
9129 printf("Success - pipeline_cgnapt_msg_req_entry_addm_handler");
9130 printf("added %d rule pairs.\n", count);
9136 if (!p_nat->is_static_cgnapt) {
9139 for (i = 0; i < p_nat->pub_ip_count; i++) {
9140 /* Check port range if same Public-IP */
9141 if (dest_ip != p_nat->pub_ip_port_set[i].ip)
9143 if (((dest_port >= p_nat->pub_ip_port_set[i].start_port) &&
9144 (dest_port <= p_nat->pub_ip_port_set[i].end_port))) {
9145 printf("Error - port cannot be in Dynamic "
9146 "port range %d-%d\n",
9147 p_nat->pub_ip_port_set[i].start_port,
9148 p_nat->pub_ip_port_set[i].end_port);
9154 if (pipeline_cgnapt_msg_req_entry_addm_pair
9155 (p, msg, src_ip, src_port, dest_ip, dest_port, rx_port,
9156 ttl, type, src_ipv6)) {
9157 printf("Error - pipeline_cgnapt_msg_req_entry_add_handler\n");
9162 printf("\nSuccess - pipeline_cgnapt_msg_req_entry_add_handler "
9169 * Function for adding a NAPT entry pair
9172 * A void pointer to pipeline
9174 * void pointer for incoming data
9180 * destination ip address
9184 * Physical receive port
9186 * time to live value
9188 * type of entry IPv4 vs IPv6
9190 * uint8_t array of IPv6 address
9193 * 0 if success, negative if fails
9196 pipeline_cgnapt_msg_req_entry_addm_pair(
9197 struct pipeline *p, __rte_unused void *msg,
9198 uint32_t src_ip, uint16_t src_port,
9199 uint32_t dest_ip, uint16_t dest_port,
9200 uint16_t rx_port, uint32_t ttl,
9201 uint8_t type, uint8_t src_ipv6[16])
9204 struct pipeline_cgnapt_entry_key key;
9205 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9208 key.port = src_port;
9211 struct cgnapt_table_entry entry = {
9213 .action = RTE_PIPELINE_ACTION_PORT,
9214 .port_id = CGNAPT_PUB_PORT_ID,
9218 /*.prv_ip = src_ip, */
9219 .prv_port = src_port,
9221 .pub_port = dest_port,
9222 .prv_phy_port = rx_port,
9223 .pub_phy_port = get_prv_to_pub_port(&dest_ip,
9226 .timeout = STATIC_CGNAPT_TIMEOUT,
9233 if (type == CGNAPT_ENTRY_IPV4) {
9234 entry.data.type = CGNAPT_ENTRY_IPV4;
9235 entry.data.u.prv_ip = src_ip;
9237 entry.data.type = CGNAPT_ENTRY_IPV6;
9238 memcpy(entry.data.u.prv_ipv6, src_ipv6, 16);
9241 /* Also need to add a paired entry on our own */
9243 * Need to change key
9244 * Need to change entry header
9245 * Will keep the same entry and take care
9246 * of translation in table hit handler
9248 struct pipeline_cgnapt_entry_key second_key;
9250 /* Need to add a second ingress entry */
9251 second_key.ip = dest_ip;
9252 second_key.port = dest_port;
9253 second_key.pid = 0xffff;
9255 #ifdef NAT_ONLY_CONFIG_REQ
9256 if (nat_only_config_flag) {
9258 entry.data.pub_port = 0xffff;
9259 second_key.port = 0xffff;
9263 if (CGNAPT_DEBUG > 2)
9264 printf("key.ip %x, key.port %d", key.ip, key.port);
9265 printf("key.pid %d, in_type %d,", key.pid, type);
9266 printf("entry_type %d\n", entry.data.type);
9268 int32_t position = rte_hash_add_key(napt_common_table, &key);
9271 printf("CG-NAPT entry bulk add failed");
9272 printf(" ... returning without adding ...\n");
9276 memcpy(&napt_hash_tbl_entries[position], &entry,
9277 sizeof(struct cgnapt_table_entry));
9279 #ifdef CGNAPT_DEBUGGING
9280 if (p_nat->kpc1++ < 5)
9284 p_nat->n_cgnapt_entry_added++;
9286 /* Now modify the forward port for reverse entry */
9287 entry.head.port_id = CGNAPT_PRV_PORT_ID;
9289 position = rte_hash_add_key(napt_common_table, &second_key);
9292 printf("CG-NAPT entry reverse bulk add failed");
9293 printf(" ... returning with fwd add ...%d\n", position);
9297 memcpy(&napt_hash_tbl_entries[position], &entry,
9298 sizeof(struct cgnapt_table_entry));
9300 #ifdef CGNAPT_DEBUGGING
9301 if (p_nat->kpc1 < 5)
9302 print_key(&second_key);
9305 p_nat->n_cgnapt_entry_added++;
9310 * Function for adding multiple NAPT entries
9313 * A void pointer to pipeline
9315 * void pointer for incoming data
9318 * void pointer of response
9320 void *pipeline_cgnapt_msg_req_entry_addm_handler(struct pipeline *p, void *msg)
9322 struct pipeline_cgnapt_entry_addm_msg_req *req = msg;
9323 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9325 uint32_t max_ue = req->data.num_ue;
9326 uint8_t type = req->data.type;
9327 uint32_t src_ip = (type == CGNAPT_ENTRY_IPV4) ?
9328 req->data.u.prv_ip :
9329 rte_bswap32(req->data.u.u32_prv_ipv6[3]);
9331 uint8_t src_ipv6[16];
9333 uint32_t dest_ip = req->data.pub_ip;
9334 uint16_t src_port = req->data.prv_port;
9335 uint16_t dest_port = req->data.pub_port;
9336 uint16_t rx_port = req->data.prv_phy_port;
9337 uint32_t ttl = req->data.ttl;
9338 uint16_t max_src_port = req->data.prv_port_max;
9339 uint16_t max_dest_port = req->data.pub_port_max;
9341 uint16_t src_port_start = src_port;
9342 uint16_t dest_port_start = dest_port;
9343 uint32_t src_ip_temp;
9345 if (type == CGNAPT_ENTRY_IPV6)
9346 memcpy(src_ipv6, req->data.u.prv_ipv6, 16);
9348 printf("CG-NAPT addm - PrvIP %x, PrvPort %d,", src_ip, src_port);
9349 printf("PubIP %x, PubPort %d,", dest_ip, dest_port);
9350 printf("PhyPort %d, ttl %u, NumUe %d,", rx_port, ttl, max_ue);
9351 printf("mPrvPort %d, mPubPort %d,", max_src_port, max_dest_port);
9352 printf("entry_type %d\n", type);
9354 #ifdef NAT_ONLY_CONFIG_REQ
9355 if (nat_only_config_flag) {
9356 if (!p_nat->is_static_cgnapt) {
9359 for (i = 0; i < p_nat->pub_ip_range_count; i++) {
9360 if (((dest_ip >= p_nat->pub_ip_range[i].start_ip)
9361 && (dest_ip <= p_nat->pub_ip_range[i].end_ip)) ||
9362 (((dest_ip + max_ue) >=
9363 p_nat->pub_ip_range[i].start_ip) &&
9364 ((dest_ip + max_ue) <=
9365 p_nat->pub_ip_range[i].end_ip))) {
9366 printf("Error - static port cannot be in Dynamic "
9368 printf("%x-%x\n", p_nat->pub_ip_range[i].start_ip,
9369 p_nat->pub_ip_range[i].end_ip);
9376 for (uenum = 0; uenum < max_ue; uenum++) {
9378 if (pipeline_cgnapt_msg_req_entry_addm_pair(p, msg,
9384 printf("pipeline_cgnapt_msg_req_entry_addm_handler\n");
9394 printf("Success - pipeline_cgnapt_msg_req_entry_addm_handler");
9395 printf("added %d rule pairs.\n", count);
9401 if (!p_nat->is_static_cgnapt) {
9404 for (i = 0; i < p_nat->pub_ip_count; i++) {
9405 /* Check port range if same Public-IP */
9406 if (dest_ip != p_nat->pub_ip_port_set[i].ip)
9408 if (((dest_port >= p_nat->pub_ip_port_set[i].start_port) &&
9409 (dest_port <= p_nat->pub_ip_port_set[i].end_port)) ||
9410 ((max_dest_port >= p_nat->pub_ip_port_set[i].start_port)
9411 && max_dest_port <= p_nat->pub_ip_port_set[i].end_port)) {
9412 printf("Error - port cannot be in Dynamic port range %d-%d\n",
9413 p_nat->pub_ip_port_set[i].start_port,
9414 p_nat->pub_ip_port_set[i].end_port);
9420 for (uenum = 0; uenum < max_ue; uenum++) {
9421 if (pipeline_cgnapt_msg_req_entry_addm_pair
9422 (p, msg, src_ip, src_port, dest_ip, dest_port, rx_port,
9423 ttl, type, src_ipv6)) {
9424 printf("Error - pipeline_cgnapt_msg_req_entry_addm_handler\n");
9431 if (src_port > max_src_port) {
9432 src_port = src_port_start;
9434 if (req->data.type == CGNAPT_ENTRY_IPV6) {
9435 src_ip_temp = rte_bswap32(src_ip);
9436 memcpy(&src_ipv6[12], &src_ip_temp, 4);
9440 if (dest_port > max_dest_port) {
9441 dest_port = dest_port_start;
9446 printf("\nSuccess - pipeline_cgnapt_msg_req_entry_addm_handler added");
9447 printf("%d rule pairs.\n", count);
9453 * Function for deleting NAPT entry
9456 * A void pointer to pipeline
9458 * void pointer for incoming data
9461 * void pointer of response
9463 void *pipeline_cgnapt_msg_req_entry_del_handler(struct pipeline *p, void *msg)
9465 struct pipeline_cgnapt_entry_delete_msg_req *req = msg;
9466 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9467 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9470 uint8_t *KeyP = (void *)(&req->key);
9473 printf("pipeline_cgnapt_msg_req_entry_del_handler - Key: ");
9474 for (i = 0; i < (int)sizeof(struct pipeline_cgnapt_entry_key);
9476 printf(" %02x", KeyP[i]);
9477 printf(" ,KeySize %u\n",
9478 (int)sizeof(struct pipeline_cgnapt_entry_key));
9481 struct cgnapt_table_entry entry;
9483 /* If ingress key */
9484 if (!is_phy_port_privte(req->key.pid))
9485 req->key.pid = 0xffff;
9487 #ifdef NAT_ONLY_CONFIG_REQ
9488 if (nat_only_config_flag)
9489 req->key.port = 0xffff;
9493 position = rte_hash_lookup(napt_common_table, &req->key);
9494 if (position == -ENOENT) {
9495 printf("Entry not found\n");
9498 memcpy(&entry, &napt_hash_tbl_entries[position],
9499 sizeof(struct cgnapt_table_entry));
9500 position = rte_hash_del_key(napt_common_table, &req->key);
9501 p_nat->n_cgnapt_entry_deleted++;
9503 struct pipeline_cgnapt_entry_key second_key;
9505 if (is_phy_port_privte(req->key.pid)) {
9506 /* key is for egress - make second key for ingress */
9507 second_key.ip = entry.data.pub_ip;
9508 second_key.port = entry.data.pub_port;
9509 second_key.pid = 0xffff;
9512 /* key is for ingress - make second key for egress */
9513 second_key.ip = entry.data.u.prv_ip;
9514 second_key.port = entry.data.prv_port;
9515 second_key.pid = entry.data.prv_phy_port;
9518 #ifdef NAT_ONLY_CONFIG_REQ
9519 if (nat_only_config_flag)
9520 second_key.port = 0xffff;
9523 position = rte_hash_del_key(napt_common_table, &second_key);
9524 p_nat->n_cgnapt_entry_deleted++;
9529 void *pipeline_cgnapt_msg_req_entry_sync_handler(struct pipeline *p, void *msg)
9531 struct pipeline_cgnapt_entry_delete_msg_req *req = msg;
9532 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9534 rsp->status = rte_pipeline_table_entry_delete(
9538 &rsp->key_found, NULL);
9544 * Function to print the NAPT key
9547 * A pointer to struct pipeline_cgnapt_entry_key
9549 void print_key(struct pipeline_cgnapt_entry_key *key)
9551 uint8_t *KeyP = (void *)(key);
9555 for (i = 0; i < (int)sizeof(struct pipeline_cgnapt_entry_key); i++)
9556 printf(" %02x", KeyP[i]);
9560 * Function to print the table entry
9563 * A pointer to struct rte_pipeline_table_entry
9565 void print_entry1(struct rte_pipeline_table_entry *entry)
9567 uint8_t *entryP = (void *)(entry);
9571 for (i = 0; i < (int)sizeof(struct rte_pipeline_table_entry); i++)
9572 printf(" %02x", entryP[i]);
9576 * Function to print the NAPT table entry
9579 * A pointer to struct cgnapt_table_entry
9581 void print_cgnapt_entry(struct cgnapt_table_entry *entry)
9583 uint8_t *entryP = (void *)(entry);
9586 printf("CGNAPT Entry: ");
9587 for (i = 0; i < (int)sizeof(struct cgnapt_table_entry); i++)
9588 printf(" %02x", entryP[i]);
9589 printf(" size:%d\n", (int)sizeof(struct cgnapt_table_entry));
9593 * Function to get a free port
9596 * A pointer to struct pipeline_cgnapt
9598 * A uint32_t pointer to return corresponding ip address
9601 * free port number, 0 if error
9603 int get_free_iport(struct pipeline_cgnapt *p_nat, uint32_t *public_ip)
9606 /* If we don't have a valid napt_port_alloc_elem get one from
9609 if (p_nat->allocated_ports == NULL) {
9613 ret = rte_ring_dequeue(p_nat->port_alloc_ring, &ports);
9615 p_nat->allocated_ports =
9616 (struct napt_port_alloc_elem *)ports;
9618 #ifdef CGNAPT_DEBUGGING
9622 #ifdef CGNAPT_DBG_PRNT
9623 if (CGNAPT_DEBUG > 3)
9624 printf("p_nat->allocated_ports %p\n",
9625 p_nat->allocated_ports);
9628 printf("CGNAPT Err - get_free_iport rte_ring_dequeue "
9630 printf("%d, %d, %d\n", rte_ring_count(
9631 p_nat->port_alloc_ring), rte_ring_free_count(
9632 p_nat->port_alloc_ring), ret);
9634 #ifdef CGNAPT_DEBUGGING
9635 #ifdef CGNAPT_DBG_PRNT
9636 printf("Th%d GFP:: %" PRIu64 ", %" PRIu64 ", "
9637 "%" PRIu64", %" PRIu64 ",\n", p_nat->pipeline_num,
9638 p_nat->gfp_get, p_nat->gfp_ret, p_nat->gfp_suc,
9648 /* get the port from index count-1 and decrease count */
9649 port = p_nat->allocated_ports->ports
9650 [p_nat->allocated_ports->count - 1];
9651 *public_ip = p_nat->allocated_ports->ip_addr
9652 [p_nat->allocated_ports->count - 1];
9654 p_nat->allocated_ports->count -= 1;
9656 /* if count is zero, return buffer to mem pool */
9657 if (p_nat->allocated_ports->count == 0) {
9658 rte_mempool_put(napt_port_pool, p_nat->allocated_ports);
9660 #ifdef CGNAPT_DEBUGGING
9662 #ifdef CGNAPT_DBG_PRNT
9663 printf("Th%d Returned to pool p_nat->allocated_ports %p,",
9664 p_nat->pipeline_num, p_nat->allocated_ports);
9665 printf("%" PRIu64 ", %" PRIu64 ",",
9666 p_nat->gfp_get, p_nat->gfp_ret);
9667 printf("%" PRIu64 ", %" PRIu64 ",\n",
9668 p_nat->gfp_suc, p_nat->gfp_err);
9672 p_nat->allocated_ports = NULL;
9675 #ifdef CGNAPT_DEBUGGING
9683 * Function to free a port
9686 * Port number to free
9688 * Corresponding ip address
9690 * A pointer to struct pipeline_cgnapt
9693 void release_iport(uint16_t port_num, uint32_t public_ip,
9694 struct pipeline_cgnapt *p_nat)
9696 /* If we don't have a valid napt_port_alloc_elem get one
9699 if (p_nat->free_ports == NULL) {
9702 #ifdef CGNAPT_DEBUGGING
9706 if (rte_mempool_get(napt_port_pool, &ports) < 0) {
9707 #ifdef CGNAPT_DEBUGGING
9710 printf("CGNAPT release_iport error in getting "
9711 "port alloc buffer\n");
9715 p_nat->free_ports = (struct napt_port_alloc_elem *)ports;
9716 p_nat->free_ports->count = 0;
9719 /* put the port at index count and increase count */
9720 p_nat->free_ports->ip_addr[p_nat->free_ports->count] = public_ip;
9721 p_nat->free_ports->ports[p_nat->free_ports->count] = port_num;
9722 p_nat->free_ports->count += 1;
9724 /* if napt_port_alloc_elem is full add it to ring */
9727 #ifdef CGNAPT_DEBUGGING
9731 #ifdef CGNAPT_DBG_PRNT
9732 if (CGNAPT_DEBUG >= 2) {
9733 printf("CGNAPT port_alloc_ring before EnQ Cnt %d, Free %d\n",
9734 rte_ring_count(p_nat->port_alloc_ring),
9735 rte_ring_free_count(p_nat->port_alloc_ring));
9739 if (rte_ring_enqueue(p_nat->port_alloc_ring,
9740 (void *)p_nat->free_ports) != 0) {
9741 printf("CGNAPT release_iport Enqueue error %p\n",
9744 #ifdef CGNAPT_DEBUGGING
9749 #ifdef CGNAPT_DBG_PRNT
9750 if (CGNAPT_DEBUG >= 2) {
9751 printf("CGNAPT port_alloc_ring after EnQ Cnt %d",
9752 rte_ring_count(p_nat->port_alloc_ring));
9754 rte_ring_free_count(p_nat->port_alloc_ring));
9758 p_nat->free_ports = NULL;
9761 #ifdef CGNAPT_DEBUGGING
9767 * Function to initialize max ports per client data structures
9768 * Called during dynamic NAPT initialization.
9771 * A pointer to struct pipeline_cgnapt
9774 * 0 if success, negative if error
9776 int init_max_port_per_client(
9777 __rte_unused struct pipeline_cgnapt *p_nat)
9779 if (max_port_per_client_hash)
9782 /*MPPC_ALREADY_EXISTS */
9786 max_port_per_client_hash =
9787 rte_hash_create(&max_port_per_client_hash_params);
9788 if (!max_port_per_client_hash)
9791 /*MPPC_HASH_CREATE_ERROR */
9793 max_port_per_client_array =
9795 sizeof(struct max_port_per_client) * MAX_DYN_ENTRY,
9796 RTE_CACHE_LINE_SIZE);
9797 if (!max_port_per_client_array)
9800 /*MPPC_ARRAY_CREATE_ERROR */
9802 for (i = 0; i < MAX_DYN_ENTRY; i++) {
9803 max_port_per_client_array[i].prv_ip = 0;
9804 max_port_per_client_array[i].prv_phy_port = 0;
9805 max_port_per_client_array[i].max_port_cnt = 0;
9813 * Function to check if max ports for a client is reached
9815 * @param prv_ip_param
9816 * A uint32_t ip address of client
9817 * @param prv_phy_port_param
9818 * A uint32_t physical port id of the client
9820 * A pointer to struct pipeline_cgnapt
9823 * 0 if max port not reached, 1 if reached, -1 if error
9825 int is_max_port_per_client_reached(uint32_t prv_ip_param,
9826 uint32_t prv_phy_port_param,
9827 struct pipeline_cgnapt *p_nat)
9829 int index = MAX_PORT_INVALID_KEY;
9831 struct max_port_per_client_key key = {
9832 .prv_ip = prv_ip_param,
9833 .prv_phy_port = prv_phy_port_param,
9836 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9839 return MAX_PORT_INVALID_KEY;
9841 if (max_port_per_client_array[index].max_port_cnt >=
9842 p_nat->max_port_per_client)
9843 return MAX_PORT_REACHED;
9845 return MAX_PORT_NOT_REACHED;
9849 * Function to increase max ports for a client
9851 * @param prv_ip_param
9852 * A uint32_t ip address of client
9853 * @param prv_phy_port_param
9854 * A uint32_t physical port id of the client
9856 * A pointer to struct pipeline_cgnapt
9859 * 0 if max port reached, 1 if success, 2 if new entry, -1 if error
9861 int increment_max_port_counter(uint32_t prv_ip_param,
9862 uint32_t prv_phy_port_param,
9863 struct pipeline_cgnapt *p_nat)
9865 int index = MAX_PORT_INC_ERROR;
9867 struct max_port_per_client_key key = {
9868 .prv_ip = prv_ip_param,
9869 .prv_phy_port = prv_phy_port_param,
9872 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9874 if (index == -EINVAL)
9875 return MAX_PORT_INC_ERROR;
9877 if (index == -ENOENT) {
9878 if (max_port_per_client_add_entry(prv_ip_param,
9881 return MAX_PORT_INC_ERROR;
9883 return 2; /*return MAX_PORT_NEW_ENTRY; */
9886 if (CGNAPT_DEBUG > 2)
9887 printf("%s: max_port_cnt(%d), p_nat_max(%d)\n", __func__,
9888 max_port_per_client_array[index].max_port_cnt,
9889 p_nat->max_port_per_client);
9891 if (max_port_per_client_array[index].max_port_cnt <
9892 p_nat->max_port_per_client) {
9893 max_port_per_client_array[index].max_port_cnt++;
9894 return MAX_PORT_INC_SUCCESS;
9897 return MAX_PORT_INC_REACHED;
9901 * Function to decrease max ports for a client
9903 * @param prv_ip_param
9904 * A uint32_t ip address of client
9905 * @param prv_phy_port_param
9906 * A uint32_t physical port id of the client
9908 * A pointer to struct pipeline_cgnapt
9911 * 0 if count already 0, 1 if success, -1 if error
9913 int decrement_max_port_counter(uint32_t prv_ip_param,
9914 uint32_t prv_phy_port_param,
9915 struct pipeline_cgnapt *p_nat)
9917 int index = MAX_PORT_DEC_ERROR;
9919 struct max_port_per_client_key key = {
9920 .prv_ip = prv_ip_param,
9921 .prv_phy_port = prv_phy_port_param,
9924 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9927 #ifdef CGNAPT_DEBUGGING
9928 p_nat->max_port_dec_err1++;
9930 return MAX_PORT_DEC_ERROR;
9934 if (max_port_per_client_array[index].max_port_cnt > 0) {
9935 /* If it is the last port,ret this info which is used for
9936 * max_cli_per_pub_ip
9939 max_port_per_client_array[index].max_port_cnt--;
9940 /* Count should be atomic but we are good as we have only
9941 * one task handling this counter at a time (core affinity)
9945 if (max_port_per_client_array[index].max_port_cnt <= 0) {
9946 if (max_port_per_client_del_entry
9947 (prv_ip_param, prv_phy_port_param, p_nat) <= 0) {
9949 #ifdef CGNAPT_DEBUGGING
9950 p_nat->max_port_dec_err2++;
9952 return MAX_PORT_DEC_ERROR;
9955 #ifdef CGNAPT_DEBUGGING
9956 p_nat->max_port_dec_err3++;
9959 return MAX_PORT_DEC_REACHED;
9962 #ifdef CGNAPT_DEBUGGING
9963 p_nat->max_port_dec_success++;
9966 return MAX_PORT_DEC_SUCCESS;
9970 * Function to add a max ports per client entry
9972 * @param prv_ip_param
9973 * A uint32_t ip address of client
9974 * @param prv_phy_port_param
9975 * A uint32_t physical port id of the client
9977 * A pointer to struct pipeline_cgnapt
9980 * 0 no success, 1 if success, -1 if error
9982 int max_port_per_client_add_entry(
9983 uint32_t prv_ip_param,
9984 uint32_t prv_phy_port_param,
9985 __rte_unused struct pipeline_cgnapt *p_nat)
9987 int index = MAX_PORT_ADD_ERROR;
9989 struct max_port_per_client_key key = {
9990 .prv_ip = prv_ip_param,
9991 .prv_phy_port = prv_phy_port_param,
9994 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9995 if (index == -EINVAL)
9996 return MAX_PORT_ADD_ERROR;
9999 return MAX_PORT_ADD_UNSUCCESS;
10001 if (index == -ENOENT) {
10003 #ifdef CGNAPT_DBG_PRNT
10004 if (CGNAPT_DEBUG > 2)
10005 printf("max_port_per_client_add_entry fn: "
10006 "Entry does not exist\n");
10010 rte_hash_add_key(max_port_per_client_hash,
10011 (const void *)&key);
10012 if (index == -ENOSPC)
10013 return MAX_PORT_ADD_UNSUCCESS;
10015 #ifdef CGNAPT_DBG_PRNT
10016 if (CGNAPT_DEBUG > 2)
10017 printf("max_port_per_client_add_entry fn:"
10018 "Add entry index(%d)\n", index);
10021 max_port_per_client_array[index].prv_ip = prv_ip_param;
10022 max_port_per_client_array[index].prv_phy_port =
10023 prv_phy_port_param;
10026 max_port_per_client_array[index].max_port_cnt++;
10027 return MAX_PORT_ADD_SUCCESS;
10031 * Function to delete a max ports per client entry
10033 * @param prv_ip_param
10034 * A uint32_t ip address of client
10035 * @param prv_phy_port_param
10036 * A uint32_t physical port id of the client
10038 * A pointer to struct pipeline_cgnapt
10041 * 0 no success, 1 if success, -1 if error
10043 int max_port_per_client_del_entry(
10044 uint32_t prv_ip_param,
10045 uint32_t prv_phy_port_param,
10046 __rte_unused struct pipeline_cgnapt *p_nat)
10048 int index = MAX_PORT_DEL_ERROR;
10050 struct max_port_per_client_key key = {
10051 .prv_ip = prv_ip_param,
10052 .prv_phy_port = prv_phy_port_param,
10055 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
10057 if (index == -EINVAL)
10058 return MAX_PORT_DEL_ERROR;
10060 if (index == -ENOENT)
10061 return MAX_PORT_DEL_UNSUCCESS;
10063 index = rte_hash_del_key(max_port_per_client_hash, (const void *)&key);
10064 max_port_per_client_array[index].prv_ip = 0;
10065 max_port_per_client_array[index].prv_phy_port = 0;
10066 max_port_per_client_array[index].max_port_cnt = 0;
10068 return MAX_PORT_DEL_SUCCESS;
10072 * Function to execute debug commands
10075 * A pointer to struct pipeline
10077 * void pointer to incoming arguments
10079 void *pipeline_cgnapt_msg_req_entry_dbg_handler(struct pipeline *p, void *msg)
10081 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
10082 uint8_t *Msg = msg;
10083 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
10087 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_STATS_SHOW) {
10088 printf("\nCG-NAPT Packet Stats:\n");
10089 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10090 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10091 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10092 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10093 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10094 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10095 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10097 #ifdef CGNAPT_DEBUGGING
10098 printf("\n Drop detail 1:%" PRIu64 ",",
10099 p_nat->naptDroppedPktCount1);
10100 printf("\n Drop detail 2:%" PRIu64 ",",
10101 p_nat->naptDroppedPktCount2);
10102 printf("\n Drop detail 3:%" PRIu64 ",",
10103 p_nat->naptDroppedPktCount3);
10104 printf("\n Drop detail 4:%" PRIu64 ",",
10105 p_nat->naptDroppedPktCount4);
10106 printf("\n Drop detail 5:%" PRIu64 ",",
10107 p_nat->naptDroppedPktCount5);
10108 printf("\n Drop detail 6:%" PRIu64 "",
10109 p_nat->naptDroppedPktCount6);
10111 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10112 p_nat->missedpktcount1,
10113 p_nat->missedpktcount2);
10114 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10115 p_nat->missedpktcount3,
10116 p_nat->missedpktcount4);
10117 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10118 p_nat->missedpktcount5,
10119 p_nat->missedpktcount6);
10120 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10121 p_nat->missedpktcount7,
10122 p_nat->missedpktcount8);
10123 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10124 p_nat->missedpktcount9,
10125 p_nat->missedpktcount10);
10132 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_STATS_CLEAR) {
10133 printf("\nCG-NAPT Packet Stats:\n");
10134 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10135 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10136 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10137 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10138 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10139 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10140 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10142 p_nat->naptedPktCount = 0;
10143 p_nat->naptDroppedPktCount = 0;
10144 p_nat->inaptedPktCount = 0;
10145 p_nat->enaptedPktCount = 0;
10146 p_nat->receivedPktCount = 0;
10147 p_nat->missedPktCount = 0;
10148 p_nat->arpicmpPktCount = 0;
10149 printf("CG-NAPT Packet Stats cleared\n");
10153 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DBG_LEVEL) {
10154 CGNAPT_DEBUG = Msg[CGNAPT_DBG_CMD_OFST + 1];
10155 printf("CG-NAPT debug level set to %d\n", CGNAPT_DEBUG);
10159 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DBG_SHOW) {
10161 printf("\nNAPT entries - added %" PRIu64 ",",
10162 p_nat->n_cgnapt_entry_added);
10163 printf("deleted %" PRIu64 ",", p_nat->n_cgnapt_entry_deleted);
10164 printf("current %" PRIu64 "", p_nat->n_cgnapt_entry_added -
10165 p_nat->n_cgnapt_entry_deleted);
10167 printf("\nCG-NAPT Packet Stats:\n");
10168 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10169 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10170 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10171 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10172 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10173 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10174 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10178 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
10179 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_INSTRUMENTATION) {
10180 if (Msg[CGNAPT_DBG_CMD_OFST1] ==
10181 CGNAPT_CMD_INSTRUMENTATION_SUB0) {
10184 uint32_t diff_sum = 0;
10186 printf("CG-NAPT Instrumentation ...\n");
10187 printf("Instrumentation data collected for fn# %d\n",
10188 cgnapt_num_func_to_inst);
10189 printf("Current collection index %d\n",
10190 cgnapt_inst_index);
10192 if (Msg[CGNAPT_DBG_CMD_OFST + 2] == 2) {
10193 printf("Timer Start:\n");
10195 for (index = 0; index < INST_ARRAY_SIZE; index++) {
10196 if ((index % 5) == 0)
10198 printf(" 0x%jx", inst_start_time[index]);
10200 printf("\n\nTimer End:\n");
10202 for (index = 0; index < INST_ARRAY_SIZE; index++) {
10203 if ((index % 5) == 0)
10205 printf(" 0x%jx", inst_end_time[index]);
10209 for (index = 0; index < INST_ARRAY_SIZE; index++) {
10210 inst_diff_time[index] = (uint32_t) (inst_end_time[index] -
10211 inst_start_time[index]);
10214 if (Msg[CGNAPT_DBG_CMD_OFST + 2] ==
10215 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
10216 printf("\n\nTimer Diff:\n");
10218 for (index = 0; index < INST_ARRAY_SIZE; index++) {
10219 if (Msg[CGNAPT_DBG_CMD_OFST + 2] ==
10220 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
10221 if ((index % 5) == 0)
10223 printf(" 0x%08x", inst_diff_time[index]);
10226 diff_sum += inst_diff_time[index];
10229 printf("\ndiff_sum %u, INST_ARRAY_SIZE %d, Ave Time %u\n",
10230 diff_sum, INST_ARRAY_SIZE, (diff_sum / INST_ARRAY_SIZE));
10231 } else if (Msg[CGNAPT_DBG_CMD_OFST + 1] ==
10232 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
10233 /* p plid entry dbg 7 1 0
10234 * p plid entry dbg 7 1 1 <--- pkt_work_cgnapt
10235 * p plid entry dbg 7 1 2 <--- pkt4_work_cgnapt
10236 * p plid entry dbg 7 1 3 <--- pkt_work_cgnapt_key
10237 * p plid entry dbg 7 1 4 <--- pkt4_work_cgnapt_key
10238 * p plid entry dbg 7 1 5 <--- in port ah to out port ah
10239 * - pkt life in the system
10240 * p plid entry dbg 7 1 6 <--- how long this instrumentation
10243 cgnapt_inst_index = 0;
10244 cgnapt_num_func_to_inst = Msg[CGNAPT_DBG_CMD_OFST + 2];
10245 printf("Instrumentation data collection started for fn# %d\n",
10246 cgnapt_num_func_to_inst);
10247 } else if (Msg[CGNAPT_DBG_CMD_OFST + 1] ==
10248 CGNAPT_CMD_INSTRUMENTATION_SUB2) {
10249 /* p plid entry dbg 7 2 0
10250 * Test all major functions by calling them multiple times
10251 * pkt_work_cgnapt, pkt4_work_cgnapt, pkt_work_cgnapt_key,
10252 * pkt4_work_cgnapt_key
10254 if (cgnapt_test_pktmbuf_pool == NULL) {
10255 cgnapt_test_pktmbuf_pool = rte_pktmbuf_pool_create(
10256 "cgnapt_test_pktmbuf_pool", 63, 32, 0,
10257 RTE_MBUF_DEFAULT_BUF_SIZE,
10261 if (cgnapt_test_pktmbuf_pool == NULL)
10262 printf("CGNAPT test mbuf pool create failed.\n");
10264 struct rte_mbuf *cgnapt_test_pkt0 =
10265 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
10266 if (cgnapt_test_pkt0 == NULL)
10267 printf("CGNAPT test pkt 0 alloc failed.");
10268 struct rte_mbuf *cgnapt_test_pkt1 =
10269 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
10270 if (cgnapt_test_pkt1 == NULL)
10271 printf("CGNAPT test pkt 1 alloc failed.");
10272 struct rte_mbuf *cgnapt_test_pkt2 =
10273 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
10274 if (cgnapt_test_pkt2 == NULL)
10275 printf("CGNAPT test pkt 2 alloc failed.");
10276 struct rte_mbuf *cgnapt_test_pkt3 =
10277 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
10278 if (cgnapt_test_pkt3 == NULL)
10279 printf("CGNAPT test pkt 3 alloc failed.");
10281 struct rte_mbuf *cgnapt_test_pkts[4];
10283 cgnapt_test_pkts[0] = cgnapt_test_pkt0;
10284 cgnapt_test_pkts[1] = cgnapt_test_pkt1;
10285 cgnapt_test_pkts[2] = cgnapt_test_pkt2;
10286 cgnapt_test_pkts[3] = cgnapt_test_pkt3;
10288 uint32_t src_addr_offset =
10289 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_SRC_ADR_OFST;
10290 /* header room + eth hdr size +
10291 * src_aadr offset in ip header
10293 uint32_t dst_addr_offset =
10294 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
10295 /* header room + eth hdr size +
10296 * dst_aadr offset in ip header
10298 uint32_t prot_offset =
10299 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_PROTOCOL_OFST;
10300 /* header room + eth hdr size +
10301 * srprotocol char offset in ip header
10303 int pktCnt = 0, entCnt = 0, exCnt = 0;
10305 for (pktCnt = 0; pktCnt < 4; pktCnt++) {
10306 uint32_t *src_addr =
10307 RTE_MBUF_METADATA_UINT32_PTR
10308 (cgnapt_test_pkts[pktCnt], src_addr_offset);
10309 uint32_t *dst_addr =
10310 RTE_MBUF_METADATA_UINT32_PTR
10311 (cgnapt_test_pkts[pktCnt], dst_addr_offset);
10312 uint8_t *protocol =
10313 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10316 uint8_t *phy_port =
10317 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10319 uint8_t *eth_dest =
10320 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10324 RTE_MBUF_METADATA_UINT8_PTR(
10325 cgnapt_test_pkts[pktCnt],
10328 uint16_t *src_port =
10329 RTE_MBUF_METADATA_UINT16_PTR
10330 (cgnapt_test_pkts[pktCnt],
10331 MBUF_HDR_ROOM + ETH_HDR_SIZE +
10333 uint16_t *dst_port =
10334 RTE_MBUF_METADATA_UINT16_PTR
10335 (cgnapt_test_pkts[pktCnt],
10336 MBUF_HDR_ROOM + ETH_HDR_SIZE +
10338 *src_addr = 0xc0a80001;
10339 *dst_addr = 0x90418634;
10350 eth_dest[0] = 0x90;
10351 eth_dest[1] = 0xE2;
10352 eth_dest[2] = 0xba;
10353 eth_dest[3] = 0x54;
10354 eth_dest[4] = 0x67;
10355 eth_dest[5] = 0xc8;
10357 struct rte_pipeline_table_entry *table_entries[4];
10358 struct cgnapt_table_entry ctable_entries[4];
10359 table_entries[0] = (struct rte_pipeline_table_entry *)
10360 &ctable_entries[0];
10361 table_entries[1] = (struct rte_pipeline_table_entry *)
10362 &ctable_entries[1];
10363 table_entries[2] = (struct rte_pipeline_table_entry *)
10364 &ctable_entries[2];
10365 table_entries[3] = (struct rte_pipeline_table_entry *)
10366 &ctable_entries[3];
10367 for (entCnt = 0; entCnt < 4; entCnt++) {
10368 ctable_entries[entCnt].head.action =
10369 RTE_PIPELINE_ACTION_PORT;
10370 ctable_entries[entCnt].head.port_id = 0;
10372 ctable_entries[entCnt].data.prv_ip = 0x01020304;
10373 ctable_entries[entCnt].data.prv_port = 1234;
10374 ctable_entries[entCnt].data.pub_ip = 0x0a0b0c0d;
10375 ctable_entries[entCnt].data.pub_port = 4000;
10376 ctable_entries[entCnt].data.prv_phy_port = 0;
10377 ctable_entries[entCnt].data.pub_phy_port = 1;
10378 ctable_entries[entCnt].data.ttl = 500;
10381 uint64_t time1 = rte_get_tsc_cycles();
10383 for (exCnt = 0; exCnt < 1000; exCnt++) {
10384 pkt_work_cgnapt_key(cgnapt_test_pkts[0],
10385 instrumentation_port_in_arg);
10387 uint64_t time2 = rte_get_tsc_cycles();
10389 printf("times for %d times execution of "
10390 "pkt_work_cgnapt_key 0x%jx",
10392 printf(", 0x%jx, diff %" PRIu64 "\n", time2,
10395 time1 = rte_get_tsc_cycles();
10396 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10397 pkt_work_cgnapt_key(cgnapt_test_pkts[0],
10398 instrumentation_port_in_arg);
10400 time2 = rte_get_tsc_cycles();
10401 printf("times for %d times execution of "
10402 "pkt_work_cgnapt_key 0x%jx", exCnt, time1);
10403 printf("0x%jx, diff %" PRIu64 "\n", time2,
10406 time1 = rte_get_tsc_cycles();
10407 for (exCnt = 0; exCnt < 1000; exCnt++) {
10408 pkt4_work_cgnapt_key(cgnapt_test_pkts,
10409 instrumentation_port_in_arg);
10411 time2 = rte_get_tsc_cycles();
10412 printf("times for %d times execution of "
10413 "pkt4_work_cgnapt_key 0x%jx",
10415 printf(" 0x%jx, diff %" PRIu64 "\n", time2,
10418 time1 = rte_get_tsc_cycles();
10419 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10420 pkt4_work_cgnapt_key(cgnapt_test_pkts,
10421 instrumentation_port_in_arg);
10423 time2 = rte_get_tsc_cycles();
10424 printf("times for %d times execution of "
10425 "pkt4_work_cgnapt_key 0x%jx",
10427 printf("0x%jx, diff %" PRIu64 "\n", time2,
10430 uint64_t mask = 0xff;
10432 time1 = rte_get_tsc_cycles();
10433 for (exCnt = 0; exCnt < 1000; exCnt++) {
10434 pkt_work_cgnapt(cgnapt_test_pkts[0],
10435 table_entries[0], 3, &mask,
10438 time2 = rte_get_tsc_cycles();
10439 printf("times for %d times execution of "
10440 "pkt_work_cgnapt 0x%jx",
10442 printf("0x%jx, diff %" PRIu64 "\n", time2,
10445 time1 = rte_get_tsc_cycles();
10446 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10447 pkt_work_cgnapt(cgnapt_test_pkts[0],
10448 table_entries[0], 3, &mask,
10451 time2 = rte_get_tsc_cycles();
10452 printf("times for %d times execution of "
10453 "pkt_work_cgnapt 0x%jx",
10455 printf("0x%jx, diff %" PRIu64 "\n", time2,
10458 time1 = rte_get_tsc_cycles();
10459 for (exCnt = 0; exCnt < 1000; exCnt++) {
10460 pkt4_work_cgnapt(cgnapt_test_pkts,
10461 table_entries, 0, &mask, NULL);
10463 time2 = rte_get_tsc_cycles();
10464 printf("times for %d times execution of "
10465 "pkt4_work_cgnapt 0x%jx",
10467 printf("0x%jx, diff % " PRIu64 "\n", time2,
10470 int idummy = ctable_entries[0].data.prv_port;
10480 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_LS_ENTRY) {
10481 printf("CG-NAPT be entries are:\n");
10482 printf("Pipeline pointer %p\n", p);
10486 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DYN) {
10487 printf("Total Number of dynamic napt entries: %" PRIu64 "\n",
10488 p_nat->dynCgnaptCount);
10490 #ifdef CGNAPT_DEBUGGING
10491 printf("MAX PORT PER CLIENT:");
10492 printf("%" PRIu64 ",%" PRIu64 ",%" PRIu64 "\n",
10493 p_nat->max_port_dec_err1, p_nat->max_port_dec_err2,
10494 p_nat->max_port_dec_err3);
10495 printf("MPPC success : %" PRIu64 "\n",
10496 p_nat->max_port_dec_success);
10498 printf("Release port:err:%" PRIu64 ",ret::%" PRIu64 ",get::%"
10499 PRIu64 ",suc::%" PRIu64 "\n", p_nat->pfb_err,
10500 p_nat->pfb_ret, p_nat->pfb_get, p_nat->pfb_suc);
10501 printf("Get port::err:%" PRIu64 ",ret::%" PRIu64 ",get::%"
10502 PRIu64 ",suc::%" PRIu64 "\n", p_nat->gfp_err,
10503 p_nat->gfp_ret, p_nat->gfp_get, p_nat->gfp_suc);
10504 printf("Ring Info:\n");
10505 rte_ring_dump(stdout, p_nat->port_alloc_ring);
10509 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_IPV6) {
10510 dual_stack_enable = Msg[CGNAPT_DBG_CMD_OFST + 1];
10511 printf("Dual Stack option set: %x\n", dual_stack_enable);
10515 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_MAPS_INFO) {
10516 pipelines_port_info();
10517 pipelines_map_info();
10521 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_ITER_COM_TBL) {
10522 uint32_t count = 0;
10530 rte_hash_iterate(napt_common_table, &key, &data,
10533 if ((index != -EINVAL) && (index != -ENOENT)) {
10534 printf("\n%04d ", count);
10535 rte_hexdump(stdout, "KEY", key,
10537 pipeline_cgnapt_entry_key));
10539 //print_key((struct pipeline_cgnapt_entry_key *)
10542 rte_hash_lookup(napt_common_table,
10544 print_cgnapt_entry(&napt_hash_tbl_entries
10549 } while (index != -ENOENT);
10553 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_IF_STATS) {
10555 struct app_params *app =
10556 (struct app_params *)p_nat->app_params_addr;
10559 cmd[0] = Msg[CGNAPT_DBG_CMD_OFST + 1];
10560 cmd[1] = Msg[CGNAPT_DBG_CMD_OFST + 2];
10562 case CGNAPT_IF_STATS_HWQ:
10563 printf("n_pktq_hwq_int :%d\n", app->n_pktq_hwq_in);
10564 printf("n_pktq_hwq_out :%d\n", app->n_pktq_hwq_out);
10568 for (i = 0; i < app->n_pktq_hwq_in; i++) {
10569 struct rte_eth_stats stats;
10571 rte_eth_stats_get(p_nat->links_map[i], &stats);
10573 if (is_phy_port_privte(i))
10574 printf("Private Port Stats %d\n", i);
10576 printf("Public Port Stats %d\n", i);
10578 printf("\n\tipackets : %" PRIu64 "",
10580 printf("\n\topackets : %" PRIu64 "",
10582 printf("\n\tierrors : %" PRIu64 "",
10584 printf("\n\toerrors : %" PRIu64 "",
10586 printf("\n\trx_nombuf: %" PRIu64 "",
10589 if (is_phy_port_privte(i))
10590 printf("Private Q:");
10592 printf("Public Q:");
10593 for (j = 0; j < RTE_ETHDEV_QUEUE_STAT_CNTRS;
10595 printf(" %" PRIu64 ", %" PRIu64 "|",
10596 stats.q_ipackets[j],
10597 stats.q_opackets[j]);
10605 case CGNAPT_IF_STATS_SWQ:
10607 printf("n_pktq_swq :%d\n", app->n_pktq_swq);
10609 if (cmd[1] < app->n_pktq_swq) {
10610 rte_ring_dump(stdout, app->swq[cmd[1]]);
10613 printf("SWQ number is invalid\n");
10616 case CGNAPT_IF_STATS_OTH:
10618 printf("config_file:%s\n", app->config_file);
10619 printf("script_file:%s\n", app->script_file);
10620 printf("parser_file:%s\n", app->parser_file);
10621 printf("output_file:%s\n", app->output_file);
10622 printf("n_msgq :%d\n", app->n_msgq);
10623 printf("n_pktq_tm :%d\n", app->n_pktq_tm);
10624 printf("n_pktq_source :%d\n", app->n_pktq_source);
10625 printf("n_pktq_sink :%d\n", app->n_pktq_sink);
10626 printf("n_pipelines :%d\n", app->n_pipelines);
10630 printf("Command does not match\n\n");
10638 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_MAX_CLI_PER_PUB_IP) {
10639 if (nat_only_config_flag) {
10640 printf("Command not supported for NAT only config.\n");
10645 printf("\tPublic IP: Num Clients\n");
10646 for (ii = 0; ii < CGNAPT_MAX_PUB_IP; ii++)
10647 printf("\t%x : %7d\n", all_public_ip[ii].ip,
10648 rte_atomic16_read(&all_public_ip[ii].count));
10652 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_PUB_IP_LIST) {
10655 for (i = 0; i < p_nat->pub_ip_count; i++)
10656 printf("%x : (%d,%d)\n", p_nat->pub_ip_port_set[i].ip,
10657 p_nat->pub_ip_port_set[i].start_port,
10658 p_nat->pub_ip_port_set[i].end_port);
10662 #ifdef CGNAPT_TIMING_INST
10663 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_TIMING_INST) {
10664 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 0) {
10665 p_nat->time_measurements_on = 1;
10666 p_nat->time_measurements = 0;
10667 printf("CGNAPT timing instrumentation turned on.\n");
10668 printf("Max samples %d\n", p_nat->max_time_mesurements);
10670 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 1) {
10671 p_nat->time_measurements_on = 0;
10672 printf("CGNAPT timing instrumentation turned off.\n");
10673 printf("Cur Samples %d\n", p_nat->time_measurements);
10675 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 2) {
10676 uint64_t sum = p_nat->external_time_sum +
10677 p_nat->internal_time_sum;
10678 uint64_t isump = (p_nat->internal_time_sum * 100) / sum;
10679 uint64_t esump = (p_nat->external_time_sum * 100) / sum;
10680 printf("CGNAPT timing instrumentation status ...\n");
10681 printf("Max Count %d, Cur Count %d, Status %d (1=ON)\n",
10682 p_nat->max_time_mesurements,
10683 p_nat->time_measurements,
10684 p_nat->time_measurements_on);
10685 printf("Internal Time Sum %" PRIu64 " , Ave %" PRIu64
10686 ", percent %" PRIu64 "\n",
10687 p_nat->internal_time_sum,
10688 (p_nat->internal_time_sum /
10689 p_nat->time_measurements), isump);
10690 printf("External Time Sum %" PRIu64 " , Ave %" PRIu64
10691 ", percent %" PRIu64 "\n",
10692 p_nat->external_time_sum,
10693 (p_nat->external_time_sum /
10694 p_nat->time_measurements), esump);
10701 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_PRINT_NSP) {
10702 struct cgnapt_nsp_node *ll = nsp_ll;
10704 while (ll != NULL) {
10705 fprintf(stderr, "NSP Prefix/Depth=>%x%x:%x%x:%x%x: "
10706 "%x%x:%x%x:%x%x:%x%x:%x%x/%d",
10707 ll->nsp.prefix[0], ll->nsp.prefix[1],
10708 ll->nsp.prefix[2], ll->nsp.prefix[3],
10709 ll->nsp.prefix[4], ll->nsp.prefix[5],
10710 ll->nsp.prefix[6], ll->nsp.prefix[7],
10711 ll->nsp.prefix[8], ll->nsp.prefix[9],
10712 ll->nsp.prefix[10], ll->nsp.prefix[11],
10713 ll->nsp.prefix[12], ll->nsp.prefix[13],
10714 ll->nsp.prefix[14], ll->nsp.prefix[15],
10723 printf("CG-NAPT debug handler called with wrong args %x %x\n", Msg[0],
10727 for (i = 0; i < 20; i++)
10728 printf("%02x ", Msg[i]);
10734 * Function to print num of clients per IP address
10737 void print_num_ip_clients(void)
10739 if (nat_only_config_flag) {
10740 printf("Command not supported for NAT only config.\n");
10745 printf("\tPublic IP: Num Clients\n");
10746 for (ii = 0; ii < CGNAPT_MAX_PUB_IP; ii++)
10747 printf("\t%08x : %7d\n", all_public_ip[ii].ip,
10748 rte_atomic16_read(&all_public_ip[ii].count));
10752 * Function to print CGNAPT version info
10755 * An unused pointer to struct pipeline
10757 * void pointer to incoming arguments
10759 void *pipeline_cgnapt_msg_req_ver_handler(__rte_unused struct pipeline *p,
10762 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
10763 uint8_t *Msg = msg;
10767 printf("CG-NAPT debug handler called with args %x %x, offset %d\n",
10768 Msg[CGNAPT_VER_CMD_OFST], Msg[CGNAPT_VER_CMD_OFST + 1],
10769 CGNAPT_VER_CMD_OFST);
10771 if (Msg[CGNAPT_VER_CMD_OFST] == CGNAPT_VER_CMD_VER) {
10772 printf("CGNAPT Version %s\n", CGNAPT_VERSION);
10775 printf("CG-NAPT Version handler called with wrong args %x %x\n",
10779 for (i = 0; i < 20; i++)
10780 printf("%02x ", Msg[i]);
10786 * Function to show CGNAPT stats
10789 void all_cgnapt_stats(void)
10792 struct pipeline_cgnapt *p_nat;
10793 uint64_t receivedPktCount = 0;
10794 uint64_t missedPktCount = 0;
10795 uint64_t naptDroppedPktCount = 0;
10796 uint64_t naptedPktCount = 0;
10797 uint64_t inaptedPktCount = 0;
10798 uint64_t enaptedPktCount = 0;
10799 uint64_t arpicmpPktCount = 0;
10801 printf("\nCG-NAPT Packet Stats:\n");
10802 for (i = 0; i < n_cgnapt_pipeline; i++) {
10803 p_nat = all_pipeline_cgnapt[i];
10805 receivedPktCount += p_nat->receivedPktCount;
10806 missedPktCount += p_nat->missedPktCount;
10807 naptDroppedPktCount += p_nat->naptDroppedPktCount;
10808 naptedPktCount += p_nat->naptedPktCount;
10809 inaptedPktCount += p_nat->inaptedPktCount;
10810 enaptedPktCount += p_nat->enaptedPktCount;
10811 arpicmpPktCount += p_nat->arpicmpPktCount;
10813 printf("pipeline %d stats:\n", p_nat->pipeline_num);
10814 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10815 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10816 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10817 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10818 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10819 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10820 printf("arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10823 #ifdef CGNAPT_DEBUGGING
10824 printf("\n Drop detail 1:%" PRIu64 ",",
10825 p_nat->naptDroppedPktCount1);
10826 printf("\n Drop detail 2:%" PRIu64 ",",
10827 p_nat->naptDroppedPktCount2);
10828 printf("\n Drop detail 3:%" PRIu64 ",",
10829 p_nat->naptDroppedPktCount3);
10830 printf("\n Drop detail 4:%" PRIu64 ",",
10831 p_nat->naptDroppedPktCount4);
10832 printf("\n Drop detail 5:%" PRIu64 ",",
10833 p_nat->naptDroppedPktCount5);
10834 printf("\n Drop detail 6:%" PRIu64 "",
10835 p_nat->naptDroppedPktCount6);
10837 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10838 p_nat->missedpktcount1,
10839 p_nat->missedpktcount2);
10840 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10841 p_nat->missedpktcount3,
10842 p_nat->missedpktcount4);
10843 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10844 p_nat->missedpktcount5,
10845 p_nat->missedpktcount6);
10846 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10847 p_nat->missedpktcount7,
10848 p_nat->missedpktcount8);
10849 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10850 p_nat->missedpktcount9,
10851 p_nat->missedpktcount10);
10857 printf("\nTotal pipeline stats:\n");
10858 printf("Received %" PRIu64 ",", receivedPktCount);
10859 printf("Missed %" PRIu64 ",", missedPktCount);
10860 printf("Dropped %" PRIu64 ",", naptDroppedPktCount);
10861 printf("Translated %" PRIu64 ",", naptedPktCount);
10862 printf("ingress %" PRIu64 ",", inaptedPktCount);
10863 printf("egress %" PRIu64 "\n", enaptedPktCount);
10864 printf("arpicmp pkts %" PRIu64 "\n", arpicmpPktCount);
10867 void all_cgnapt_clear_stats(void)
10870 struct pipeline_cgnapt *p_nat;
10871 printf("\nCG-NAPT Packet Stats:\n");
10872 for (i = 0; i < n_cgnapt_pipeline; i++) {
10873 p_nat = all_pipeline_cgnapt[i];
10875 printf("pipeline %d stats:\n", p_nat->pipeline_num);
10876 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10877 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10878 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10879 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10880 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10881 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10882 printf("arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10884 p_nat->receivedPktCount = 0;
10885 p_nat->missedPktCount = 0;
10886 p_nat->naptDroppedPktCount = 0;
10887 p_nat->naptedPktCount = 0;
10888 p_nat->inaptedPktCount = 0;
10889 p_nat->enaptedPktCount = 0;
10890 p_nat->arpicmpPktCount = 0;
10892 #ifdef CGNAPT_DEBUGGING
10893 printf("\n Drop detail 1:%" PRIu64 ",",
10894 p_nat->naptDroppedPktCount1);
10895 printf("\n Drop detail 2:%" PRIu64 ",",
10896 p_nat->naptDroppedPktCount2);
10897 printf("\n Drop detail 3:%" PRIu64 ",",
10898 p_nat->naptDroppedPktCount3);
10899 printf("\n Drop detail 4:%" PRIu64 ",",
10900 p_nat->naptDroppedPktCount4);
10901 printf("\n Drop detail 5:%" PRIu64 ",",
10902 p_nat->naptDroppedPktCount5);
10903 printf("\n Drop detail 6:%" PRIu64 "",
10904 p_nat->naptDroppedPktCount6);
10906 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10907 p_nat->missedpktcount1,
10908 p_nat->missedpktcount2);
10909 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10910 p_nat->missedpktcount3,
10911 p_nat->missedpktcount4);
10912 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10913 p_nat->missedpktcount5,
10914 p_nat->missedpktcount6);
10915 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10916 p_nat->missedpktcount7,
10917 p_nat->missedpktcount8);
10918 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10919 p_nat->missedpktcount9,
10920 p_nat->missedpktcount10);
10928 * Function to print common CGNAPT table entries
10931 void print_static_cgnapt_entries(void)
10933 uint32_t count = 0;
10938 struct cgnapt_table_entry *entry;
10940 index = rte_hash_iterate(napt_common_table,
10941 &key, &data, &next);
10943 if ((index != -EINVAL) && (index != -ENOENT)) {
10944 printf("\n%04d ", count);
10945 rte_hexdump(stdout, "KEY", key,
10946 sizeof(struct pipeline_cgnapt_entry_key));
10947 int32_t position = rte_hash_lookup(
10948 napt_common_table, key);
10949 entry = &napt_hash_tbl_entries[position];
10951 if (entry->data.timeout == STATIC_CGNAPT_TIMEOUT)
10952 rte_hexdump(stdout, "Entry",
10953 (const void *)entry,
10954 sizeof(struct cgnapt_table_entry));
10958 } while (index != -ENOENT);
10962 * Function to show CGNAPT stats
10966 struct pipeline_be_ops pipeline_cgnapt_be_ops = {
10967 .f_init = pipeline_cgnapt_init,
10968 .f_free = pipeline_cgnapt_free,
10970 .f_timer = pipeline_cgnapt_timer,
10971 .f_track = pipeline_cgnapt_track,