2 // Copyright (c) 2017 Intel Corporation
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
19 * Pipeline CG-NAPT BE Implementation.
21 * Implementation of Pipeline CG-NAPT Back End (BE).
22 * Provides NAPT service on dataplane packets.
23 * Runs on a core as defined in the config file.
33 #include <rte_common.h>
34 #include <rte_malloc.h>
40 #include <rte_byteorder.h>
41 #include <rte_table_lpm.h>
42 #include <rte_table_hash.h>
43 #include <rte_table_stub.h>
45 #include <rte_mempool.h>
47 #include <rte_jhash.h>
48 #include <rte_cycles.h>
49 #include <rte_ethdev.h>
50 #include <rte_pipeline.h>
51 #include <rte_timer.h>
52 #include <rte_config.h>
53 #include <rte_prefetch.h>
54 #include <rte_hexdump.h>
56 #include "pipeline_cgnapt_be.h"
57 #include "pipeline_cgnapt_common.h"
58 #include "pipeline_actions_common.h"
59 #include "hash_func.h"
60 #include "pipeline_arpicmp_be.h"
61 #include "vnf_common.h"
63 #include "pipeline_common_be.h"
64 #include "vnf_common.h"
65 #include "lib_sip_alg.h"
66 #include "lib_icmpv6.h"
68 #include "pipeline_common_fe.h"
70 #include "rte_ct_tcp.h"
71 #include "rte_cnxn_tracking.h"
74 #include "lib_ftp_alg.h"
77 #include "cgnapt_pcp_be.h"
80 /* To maintain all cgnapt pipeline pointers used for all stats */
81 struct pipeline_cgnapt *all_pipeline_cgnapt[128];
82 uint8_t n_cgnapt_pipeline;
83 struct pipeline_cgnapt *global_pnat;
85 uint64_t arp_pkts_mask;
87 /* To know egress or ingress port */
88 static uint8_t cgnapt_in_port_egress_prv[PIPELINE_MAX_PORT_IN];
89 static uint8_t cgnapt_prv_que_port_index[PIPELINE_MAX_PORT_IN];
91 /* Max port per client declarations */
93 struct rte_hash_parameters max_port_per_client_hash_params = {
94 .name = "MAX_PORT_PER_CLIENT",
95 .entries = MAX_DYN_ENTRY,
96 .key_len = sizeof(struct max_port_per_client_key),
97 .hash_func = rte_jhash,
98 .hash_func_init_val = 0,
101 struct rte_ct_cnxn_tracker *cgnat_cnxn_tracker;
104 /***** Common Port Allocation declarations *****/
106 struct rte_ring *port_alloc_ring[MAX_CGNAPT_SETS] = { NULL, NULL, NULL, NULL,
107 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
108 NULL, NULL, NULL, NULL};
109 const char *napt_port_alloc_ring_name[MAX_CGNAPT_SETS] = {
110 "NAPT_PORT_ALLOC_0 ",
111 "NAPT_PORT_ALLOC_1 ",
112 "NAPT_PORT_ALLOC_2 ",
113 "NAPT_PORT_ALLOC_3 ",
114 "NAPT_PORT_ALLOC_4 ",
115 "NAPT_PORT_ALLOC_5 ",
116 "NAPT_PORT_ALLOC_6 ",
117 "NAPT_PORT_ALLOC_7 ",
118 "NAPT_PORT_ALLOC_8 ",
119 "NAPT_PORT_ALLOC_9 ",
120 "NAPT_PORT_ALLOC_10 ",
121 "NAPT_PORT_ALLOC_11 ",
122 "NAPT_PORT_ALLOC_12 ",
123 "NAPT_PORT_ALLOC_13 ",
124 "NAPT_PORT_ALLOC_14 ",
125 "NAPT_PORT_ALLOC_16 "
128 int vnf_set_count = -1;
130 struct app_params *myApp;
132 /***** Common Port Allocation declarations *****/
133 int napt_port_alloc_elem_count;
135 /***** Common Table declarations *****/
136 struct rte_hash_parameters napt_common_table_hash_params = {
137 .name = "NAPT_COM_TBL",
138 .entries = MAX_NAPT_ENTRIES,
139 .key_len = sizeof(struct pipeline_cgnapt_entry_key),
140 .hash_func = rte_jhash,
141 .hash_func_init_val = 0,
145 /***** ARP local cache *****/
147 uint8_t link_hw_laddr_valid[MAX_NUM_LOCAL_MAC_ADDRESS] = {
148 0, 0, 0, 0, 0, 0, 0, 0,
149 0, 0, 0, 0, 0, 0, 0, 0
152 struct ether_addr link_hw_laddr[MAX_NUM_LOCAL_MAC_ADDRESS] = {
153 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
154 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
155 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
156 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
157 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
158 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
159 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
160 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
161 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
162 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
163 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
164 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
165 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
166 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
167 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
168 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }
171 /****** NAT64 declarations *****/
173 uint8_t well_known_prefix[16] = {
174 0x00, 0x64, 0xff, 0x9b,
175 0x00, 0x00, 0x00, 0x00,
176 0x00, 0x00, 0x00, 0x00,
177 0x00, 0x00, 0x00, 0x00
180 static uint32_t local_get_nh_ipv4(
184 struct pipeline_cgnapt *p_nat);
185 static void do_local_nh_ipv4_cache(
187 struct pipeline_cgnapt *p_nat);
189 static uint32_t local_get_nh_ipv6(
193 struct pipeline_cgnapt *p_nat);
195 static uint8_t check_arp_icmp(
196 struct rte_mbuf *pkt,
198 struct pipeline_cgnapt *p_nat);
200 /* Finds next power of two for n. If n itself
201 * is a power of two then returns n
204 * Value usually 32-bit value
207 * Value after roundup to power of 2
209 uint64_t nextPowerOf2(uint64_t n)
222 void remove_local_cache(uint8_t port)
224 link_hw_laddr_valid[port] = 0;
228 * Function to get IPv4-IP NH from thread local array
237 * CGNAPT pipeline ptr
240 * 1 on success, 0 for failure
243 static uint32_t local_get_nh_ipv4(
247 struct pipeline_cgnapt *p_nat)
250 for (i = 0; i < p_nat->local_lib_arp_route_ent_cnt; i++) {
251 if (((p_nat->local_lib_arp_route_table[i].ip &
252 p_nat->local_lib_arp_route_table[i].mask) ==
253 (ip & p_nat->local_lib_arp_route_table[i].mask))) {
254 *port = p_nat->local_lib_arp_route_table[i].port;
256 *nhip = p_nat->local_lib_arp_route_table[i].nh;
264 * Function to make local copy for NH of type IPv4
267 * Physical port number
269 * CGNAPT pipeline ptr
273 static void do_local_nh_ipv4_cache(
275 struct pipeline_cgnapt *p_nat)
282 * Function to get IPv6-IP NH from thread local array
285 * Pointer to starting addr of IPv6
291 * CGNAPT pipeline ptr
294 * 1 on success, 0 for failure
297 static uint32_t local_get_nh_ipv6(
301 struct pipeline_cgnapt *p_nat)
304 uint8_t netmask_ipv6[16];
305 uint8_t k = 0, l = 0, depthflags = 0, depthflags1 = 0;
307 for (i = 0; i < p_nat->local_lib_nd_route_ent_cnt; i++) {
309 convert_prefixlen_to_netmask_ipv6(
310 p_nat->local_lib_nd_route_table[i].depth,
313 for (k = 0; k < 16; k++)
314 if (p_nat->local_lib_nd_route_table[i].ipv6[k] &
318 for (l = 0; l < 16; l++)
319 if (ip[l] & netmask_ipv6[l])
323 if (depthflags == depthflags1) {
324 *port = p_nat->local_lib_nd_route_table[i].port;
326 for (j = 0; j < 16; j++)
327 nhip[j] = p_nat->local_lib_nd_route_table[i].
340 /* Commented code may be required for future usage, Please keep it*/
342 static int retrieve_cgnapt_entry_alg(
343 struct pipeline_cgnapt_entry_key *key,
344 struct cgnapt_table_entry **entry_ptr1,
345 struct cgnapt_table_entry **entry_ptr2)
347 #ifdef CGNAPT_DBG_PRNT
348 printf("retrieve_cgnapt_entry key detail Entry:"
349 "0x%x, %d, %d\n", key->ip, key->port,
353 int position = rte_hash_lookup(napt_common_table, key);
355 printf("Invalid cgnapt entry position(first_key): %d\n",
360 *entry_ptr1 = &napt_hash_tbl_entries[position];
362 uint32_t prv_ip = (*entry_ptr1)->data.prv_ip;
363 uint32_t prv_port = (*entry_ptr1)->data.prv_port;
364 uint32_t prv_phy_port = (*entry_ptr1)->data.prv_phy_port;
366 struct pipeline_cgnapt_entry_key second_key;
367 second_key.ip = prv_ip;
368 second_key.port = prv_port;
369 second_key.pid = prv_phy_port;
371 position = rte_hash_lookup(napt_common_table, &second_key);
373 printf("Invalid cgnapt entry position(second_key): %d\n",
378 *entry_ptr2 = &napt_hash_tbl_entries[position];
384 int add_dynamic_cgnapt_entry_alg(
386 struct pipeline_cgnapt_entry_key *key,
387 struct cgnapt_table_entry **entry_ptr1,
388 struct cgnapt_table_entry **entry_ptr2)
390 int port_num = 0, ret;
392 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
394 #ifdef CGNAPT_DBG_PRNT
395 if (CGNAPT_DEBUG >= 1) {
396 printf("Th%d add_dynamic_cgnapt_entry key detail Entry:"
397 "0x%x, %d, %d\n", p_nat->pipeline_num, key->ip, key->port,
402 int32_t position = rte_hash_lookup(napt_common_table, key);
404 #ifdef CGNAPT_DBG_PRNT
405 if (CGNAPT_DEBUG >= 1) {
406 printf("%s: cgnapt entry exists in "
407 "position(first_key): %d\n", __func__, position);
410 *entry_ptr1 = &napt_hash_tbl_entries[position];
411 /* not required, as it is not used in the caller */
417 ret = increment_max_port_counter(key->ip, key->pid, p_nat);
418 if (ret == MAX_PORT_INC_ERROR) {
420 #ifdef CGNAPT_DBG_PRNT
421 if (CGNAPT_DEBUG > 1)
422 printf("add_dynamic_cgnapt_entry:"
423 "increment_max_port_counter-1 failed\n");
429 if (ret == MAX_PORT_INC_REACHED) {
431 #ifdef CGNAPT_DBG_PRNT
432 if (CGNAPT_DEBUG > 1)
433 printf("add_dynamic_cgnapt_entry:"
434 "increment_max_port_counter-2 failed\n");
441 port_num = get_free_iport(p_nat, &public_ip);
443 if (port_num == -1) {
445 #ifdef CGNAPT_DBG_PRNT
446 if (CGNAPT_DEBUG > 2) {
447 printf("add_dynamic_cgnapt_entry: %d\n", port_num);
448 printf("add_dynamic_cgnapt_entry key detail:0x%x, "
449 "%d, %d\n", key->ip, key->port, key->pid);
456 /* check for max_clients_per_ip */
457 if (rte_atomic16_read
459 [rte_jhash(&public_ip, 4, 0) % 16].count) ==
460 p_nat->max_clients_per_ip) {
461 /* For now just bail out
462 * In future we can think about
463 * retrying getting a new iport
465 release_iport(port_num, public_ip, p_nat);
470 rte_atomic16_inc(&all_public_ip
471 [rte_jhash(&public_ip, 4, 0) %
474 #ifdef CGNAPT_DBG_PRNT
475 if ((rte_jhash(&public_ip, 4, 0) % 16) == 8)
476 printf("pub ip:%x coutn:%d\n", public_ip,
477 rte_atomic16_read(&all_public_ip
478 [rte_jhash(&public_ip, 4, 0) % 16].count));
481 #ifdef CGNAPT_DBG_PRNT
482 if (CGNAPT_DEBUG > 0) {
483 printf("add_dynamic_cgnapt_entry: %d\n",
485 printf("add_dynamic_cgnapt_entry key detail: "
486 "0x%x, %d, %d\n", key->ip, key->port, key->pid);
490 struct cgnapt_table_entry entry = {
492 .action = RTE_PIPELINE_ACTION_PORT,
493 /* made it configurable below */
494 {.port_id = p->port_out_id[0]},
498 .prv_port = key->port,
500 .pub_port = port_num,
501 .prv_phy_port = key->pid,
502 .pub_phy_port = get_pub_to_prv_port(
506 /* if(timeout == -1) : static entry
507 * if(timeout == 0 ) : dynamic entry
508 * if(timeout > 0 ) : PCP requested entry
517 entry.data.u.prv_ip = key->ip;
518 entry.data.type = CGNAPT_ENTRY_IPV4;
520 entry.head.port_id = entry.data.pub_phy_port; /* outgoing port info */
522 struct pipeline_cgnapt_entry_key second_key;
523 /* Need to add a second ingress entry */
524 second_key.ip = public_ip;
525 second_key.port = port_num;
526 second_key.pid = 0xffff;
528 #ifdef CGNAPT_DBG_PRNT
529 if (CGNAPT_DEBUG > 2)
530 printf("add_dynamic_cgnapt_entry second key detail:"
531 "0x%x, %d, %d\n", second_key.ip, second_key.port,
535 int32_t position1 = rte_hash_add_key(napt_common_table, (void *)key);
538 printf("CG-NAPT entry add failed ...returning "
539 "without adding ... %d\n", position1);
544 #ifdef CGNAPT_DBG_PRNT
546 printf("add_dynamic_cgnapt_entry:");
548 print_cgnapt_entry(&entry);
552 memcpy(&napt_hash_tbl_entries[position1], &entry,
553 sizeof(struct cgnapt_table_entry));
555 /* this pointer is returned to pkt miss function */
556 *entry_ptr1 = &napt_hash_tbl_entries[position1];
558 p_nat->n_cgnapt_entry_added++;
559 p_nat->dynCgnaptCount++;
561 /* Now modify the forward port for reverse entry */
563 /* outgoing port info */
564 entry.head.port_id = entry.data.prv_phy_port;
566 int32_t position2 = rte_hash_add_key(napt_common_table, &second_key);
569 printf("CG-NAPT entry reverse bulk add failed ..."
570 "returning with fwd add ...%d\n",
575 memcpy(&napt_hash_tbl_entries[position2], &entry,
576 sizeof(struct cgnapt_table_entry));
578 *entry_ptr2 = &napt_hash_tbl_entries[position2];
580 #ifdef CGNAPT_DBG_PRNT
581 if (CGNAPT_DEBUG >= 1) {
582 printf("add_dynamic_cgnapt_entry position: %d, %d\n",
583 position1, position2);
584 printf("add_dynamic_cgnapt_entry: entry_ptr1: %p, "
585 "entry_ptr2: %p\n", *entry_ptr1, *entry_ptr2);
589 timer_thread_enqueue(key, &second_key, *entry_ptr1,
590 *entry_ptr2, (struct pipeline *)p_nat);
592 p_nat->n_cgnapt_entry_added++;
593 p_nat->dynCgnaptCount++;
600 void hw_checksum(struct rte_mbuf *pkt, enum PKT_TYPE ver)
602 struct tcp_hdr *tcp = NULL;
603 struct udp_hdr *udp = NULL;
604 struct icmp_hdr *icmp = NULL;
606 void *ip_header = NULL;
607 uint16_t prot_offset = 0;
608 uint32_t pkt_type_is_ipv4 = 1;
610 pkt->ol_flags |= PKT_TX_IP_CKSUM;
611 pkt->l2_len = ETH_HDR_SIZE;
616 case PKT_TYPE_IPV4to6:
620 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
621 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
623 pkt_type_is_ipv4 = 0;
624 pkt->ol_flags |= PKT_TX_IPV6;
626 sizeof(struct ipv6_hdr);
627 tcp = (struct tcp_hdr *)
628 ((unsigned char *)ip_header +
629 sizeof(struct ipv6_hdr));
630 udp = (struct udp_hdr *)
631 ((unsigned char *)ip_header +
632 sizeof(struct ipv6_hdr));
633 icmp = (struct icmp_hdr *)
634 ((unsigned char *)ip_header +
635 sizeof(struct ipv6_hdr));
637 prot_offset = PROT_OFST_IP6 + temp;
639 case PKT_TYPE_IPV6to4:
643 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
644 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
646 pkt->ol_flags |= PKT_TX_IPV4;
648 sizeof(struct ipv4_hdr);
649 tcp = (struct tcp_hdr *)
650 ((unsigned char *)ip_header +
651 sizeof(struct ipv4_hdr));
652 udp = (struct udp_hdr *)
653 ((unsigned char *)ip_header +
654 sizeof(struct ipv4_hdr));
655 icmp = (struct icmp_hdr *)
656 ((unsigned char *)ip_header +
657 sizeof(struct ipv4_hdr));
658 struct ipv4_hdr *ip_hdr =
659 (struct ipv4_hdr *)ip_header;
660 ip_hdr->hdr_checksum = 0;
662 prot_offset = PROT_OFST_IP4 + temp;
665 printf("hw_checksum: pkt version is invalid\n");
667 protocol = (uint8_t *) RTE_MBUF_METADATA_UINT8_PTR(pkt,
671 case IP_PROTOCOL_TCP: /* 6 */
673 pkt->ol_flags |= PKT_TX_TCP_CKSUM;
674 if (pkt_type_is_ipv4) {
675 tcp->cksum = rte_ipv4_phdr_cksum(
676 (struct ipv4_hdr *)ip_header,
679 tcp->cksum = rte_ipv6_phdr_cksum(
680 (struct ipv6_hdr *)ip_header,
684 case IP_PROTOCOL_UDP: /* 17 */
685 udp->dgram_cksum = 0;
686 pkt->ol_flags |= PKT_TX_UDP_CKSUM;
687 if (pkt_type_is_ipv4) {
690 (struct ipv4_hdr *)ip_header,
695 (struct ipv6_hdr *)ip_header,
699 case IP_PROTOCOL_ICMP: /* 1 */
700 if (pkt_type_is_ipv4) {
701 /* ICMP checksum code */
702 struct ipv4_hdr *ip_hdr =
703 (struct ipv4_hdr *)ip_header;
704 int size = rte_bswap16(ip_hdr->total_length) - 20;
705 icmp->icmp_cksum = 0;
713 #ifdef CGNAPT_DEBUGGING
714 printf("hw_checksum() : Neither TCP or UDP pkt\n");
721 void sw_checksum(struct rte_mbuf *pkt, enum PKT_TYPE ver)
723 struct tcp_hdr *tcp = NULL;
724 struct udp_hdr *udp = NULL;
725 struct icmp_hdr *icmp = NULL;
727 void *ip_header = NULL;
728 uint16_t prot_offset = 0;
729 uint32_t pkt_type_is_ipv4 = 1;
733 case PKT_TYPE_IPV4to6:
737 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
738 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
740 pkt_type_is_ipv4 = 0;
741 tcp = (struct tcp_hdr *)
742 ((unsigned char *)ip_header +
743 sizeof(struct ipv6_hdr));
744 udp = (struct udp_hdr *)
745 ((unsigned char *)ip_header +
746 sizeof(struct ipv6_hdr));
747 icmp = (struct icmp_hdr *)
748 ((unsigned char *)ip_header +
749 sizeof(struct ipv6_hdr));
751 prot_offset = PROT_OFST_IP6 + temp;
753 case PKT_TYPE_IPV6to4:
757 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
758 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
760 tcp = (struct tcp_hdr *)
761 ((unsigned char *)ip_header +
762 sizeof(struct ipv4_hdr));
763 udp = (struct udp_hdr *)
764 ((unsigned char *)ip_header +
765 sizeof(struct ipv4_hdr));
766 icmp = (struct icmp_hdr *)
767 ((unsigned char *)ip_header +
768 sizeof(struct ipv4_hdr));
770 prot_offset = PROT_OFST_IP4 + temp;
773 printf("sw_checksum: pkt version is invalid\n");
775 protocol = (uint8_t *) RTE_MBUF_METADATA_UINT8_PTR(pkt,
779 case IP_PROTOCOL_TCP: /* 6 */
781 if (pkt_type_is_ipv4) {
782 struct ipv4_hdr *ip_hdr =
783 (struct ipv4_hdr *)ip_header;
784 tcp->cksum = rte_ipv4_udptcp_cksum(ip_hdr,
786 ip_hdr->hdr_checksum = 0;
787 ip_hdr->hdr_checksum = rte_ipv4_cksum(
788 (struct ipv4_hdr *)ip_hdr);
790 tcp->cksum = rte_ipv6_udptcp_cksum(
792 ip_header, (void *)tcp);
795 case IP_PROTOCOL_UDP: /* 17 */
796 udp->dgram_cksum = 0;
797 if (pkt_type_is_ipv4) {
798 struct ipv4_hdr *ip_hdr =
799 (struct ipv4_hdr *)ip_header;
800 udp->dgram_cksum = rte_ipv4_udptcp_cksum(
801 ip_hdr, (void *)udp);
802 ip_hdr->hdr_checksum = 0;
803 ip_hdr->hdr_checksum = rte_ipv4_cksum(ip_hdr);
805 udp->dgram_cksum = rte_ipv6_udptcp_cksum(
807 ip_header, (void *)udp);
810 case IP_PROTOCOL_ICMP: /* 1 */
811 if (pkt_type_is_ipv4) {
812 /* ICMP checksum code */
813 struct ipv4_hdr *ip_hdr =
814 (struct ipv4_hdr *)ip_header;
815 int size = rte_bswap16(ip_hdr->total_length) - 20;
816 icmp->icmp_cksum = 0;
820 ip_hdr->hdr_checksum = 0;
821 ip_hdr->hdr_checksum = rte_ipv4_cksum(ip_hdr);
826 #ifdef CGNAPT_DEBUGGING
827 printf("sw_checksum() : Neither TCP or UDP pkt\n");
833 void print_pkt_info(uint8_t *eth_dest, struct ether_addr *hw_addr,
834 uint32_t dest_address, uint32_t port_id, struct rte_mbuf *pkt)
837 if (CGNAPT_DEBUG > 2) {
838 printf("MAC Found ip 0x%x, port %d - %02x:%02x:%02x:%02x:%02x:%02x \n",
839 dest_address, port_id, hw_addr->addr_bytes[0], hw_addr->addr_bytes[1],
840 hw_addr->addr_bytes[2], hw_addr->addr_bytes[3], hw_addr->addr_bytes[4],
841 hw_addr->addr_bytes[5]);
843 printf("Dest MAC before - %02x:%02x:%02x:%02x:%02x:%02x \n",
844 eth_dest[0], eth_dest[1], eth_dest[2], eth_dest[3], eth_dest[4],
848 if (CGNAPT_DEBUG > 2) {
849 printf("Dest MAC after - "
850 "%02x:%02x:%02x:%02x:%02x:%02x \n",
851 eth_dest[0], eth_dest[1],
852 eth_dest[2], eth_dest[3],
853 eth_dest[4], eth_dest[5]);
856 if (CGNAPT_DEBUG > 4)
860 static uint8_t check_arp_icmp(
861 struct rte_mbuf *pkt,
863 struct pipeline_cgnapt *p_nat)
865 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
866 uint16_t *eth_proto = RTE_MBUF_METADATA_UINT16_PTR(
867 pkt, eth_proto_offset);
868 struct app_link_params *link;
869 uint8_t solicited_node_multicast_addr[16] = {
870 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
871 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00};
873 /* ARP outport number */
874 uint16_t out_port = p_nat->p.n_ports_out - 1;
876 uint32_t prot_offset;
878 link = &myApp->link_params[pkt->port];
881 switch (rte_be_to_cpu_16(*eth_proto)) {
885 rte_pipeline_port_out_packet_insert(
891 * Pkt mask should be changed, and not changing the
894 p_nat->invalid_packets |= pkt_mask;
895 p_nat->arpicmpPktCount++;
899 case ETH_TYPE_IPV4: {
900 /* header room + eth hdr size +
901 * src_aadr offset in ip header
903 uint32_t dst_addr_offset = MBUF_HDR_ROOM +
904 ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
906 RTE_MBUF_METADATA_UINT32_PTR(pkt,
908 prot_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
909 IP_HDR_PROTOCOL_OFST;
910 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt,
912 if ((*protocol == IP_PROTOCOL_ICMP) &&
913 link->ip == rte_be_to_cpu_32(*dst_addr)) {
915 if (is_phy_port_privte(pkt->port)) {
917 rte_pipeline_port_out_packet_insert(
918 p_nat->p.p, out_port, pkt);
921 * Pkt mask should be changed,
922 * and not changing the drop mask
925 p_nat->invalid_packets |= pkt_mask;
926 p_nat->arpicmpPktCount++;
937 if (dual_stack_enable) {
939 /* Commented code may be required for future usage,
942 //uint32_t dst_addr_offset = MBUF_HDR_ROOM +
943 // ETH_HDR_SIZE + IPV6_HDR_DST_ADR_OFST;
944 //uint32_t *dst_addr =
945 // RTE_MBUF_METADATA_UINT32_PTR(pkt,
947 uint32_t prot_offset_ipv6 = MBUF_HDR_ROOM +
948 ETH_HDR_SIZE + IPV6_HDR_PROTOCOL_OFST;
949 struct ipv6_hdr *ipv6_h;
951 ipv6_h = (struct ipv6_hdr *) MBUF_HDR_ROOM +
953 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt,
956 if (ipv6_h->proto == ICMPV6_PROTOCOL_ID) {
957 if (!memcmp(ipv6_h->dst_addr, link->ipv6, 16)
958 || !memcmp(ipv6_h->dst_addr,
959 solicited_node_multicast_addr, 13)) {
960 rte_pipeline_port_out_packet_insert(
961 p_nat->p.p, out_port, pkt);
963 * Pkt mask should be changed,
964 * and not changing the drop mask
966 p_nat->invalid_packets |= pkt_mask;
967 p_nat->arpicmpPktCount++;
969 p_nat->invalid_packets |= pkt_mask;
970 p_nat->naptDroppedPktCount++;
972 #ifdef CGNAPT_DEBUGGING
973 p_nat->naptDroppedPktCount1++;
988 * Function to create common NAPT table
989 * Called during pipeline initialization
990 * Creates the common NAPT table
991 * If it is not already created and stores its pointer
992 * in global napt_common_table pointer.
995 * Max number of NAPT flows. This parameter is configurable via config file.
998 * 0 on success, negative on error.
1000 int create_napt_common_table(uint32_t nFlows)
1002 if (napt_common_table != NULL) {
1003 printf("napt_common_table already exists.\n");
1007 napt_common_table = rte_hash_create(&napt_common_table_hash_params);
1009 if (napt_common_table == NULL) {
1010 printf("napt_common_table creation failed.\n");
1014 uint32_t number_of_entries = nFlows;
1017 RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_table_entry) *
1019 napt_hash_tbl_entries = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1021 if (napt_hash_tbl_entries == NULL) {
1022 printf("napt_hash_tbl_entries creation failed. %d, %d\n",
1023 nFlows, (int)sizeof(struct cgnapt_table_entry));
1031 * Function to initialize bulk port allocation data structures
1032 * Called during pipeline initialization.
1034 * Creates the port alloc ring for the VNF_set this pipeline belongs
1036 * Creates global port allocation buffer pool
1038 * Initializes the port alloc ring according to config data
1041 * A pointer to struct pipeline_cgnapt
1044 * 0 on success, negative on error.
1046 int napt_port_alloc_init(struct pipeline_cgnapt *p_nat)
1048 p_nat->allocated_ports = NULL;
1049 p_nat->free_ports = NULL;
1051 uint32_t vnf_set_num = p_nat->vnf_set;
1052 /*uint32_t vnf_set_num = get_vnf_set_num(p_nat->pipeline_num); */
1054 #ifdef CGNAPT_DBG_PRNT
1055 printf("VNF set number for CGNAPT %d is %d.\n", p_nat->pipeline_num,
1058 if (vnf_set_num == 0xFF) {
1059 printf("VNF set number for CGNAPT %d is invalid %d.\n",
1060 p_nat->pipeline_num, vnf_set_num);
1064 p_nat->port_alloc_ring = port_alloc_ring[vnf_set_num];
1065 if (p_nat->port_alloc_ring != NULL) {
1066 printf("CGNAPT%d port_alloc_ring already exists.\n",
1067 p_nat->pipeline_num);
1071 printf("napt_port_alloc_elem_count :%d\n",
1072 napt_port_alloc_elem_count);
1073 napt_port_alloc_elem_count += 1;
1074 napt_port_alloc_elem_count =
1075 nextPowerOf2(napt_port_alloc_elem_count);
1076 printf("Next power of napt_port_alloc_elem_count: %d\n",
1077 napt_port_alloc_elem_count);
1079 port_alloc_ring[vnf_set_num] =
1080 rte_ring_create(napt_port_alloc_ring_name[vnf_set_num],
1081 napt_port_alloc_elem_count, rte_socket_id(), 0);
1082 p_nat->port_alloc_ring = port_alloc_ring[vnf_set_num];
1083 if (p_nat->port_alloc_ring == NULL) {
1084 printf("CGNAPT%d - Failed to create port_alloc_ring\n",
1085 p_nat->pipeline_num);
1089 /* Create port alloc buffer */
1090 /* Only one pool is enough for all vnf sets */
1091 if (napt_port_pool == NULL) {
1093 napt_port_pool = rte_mempool_create(
1095 napt_port_alloc_elem_count,
1096 sizeof(struct napt_port_alloc_elem),
1097 0, 0, NULL, NULL, NULL,
1098 NULL, rte_socket_id(), 0);
1101 if (napt_port_pool == NULL) {
1102 printf("CGNAPT - Create port pool failed\n");
1106 /* Add all available public IP addresses and ports to the ring */
1109 #ifdef NAT_ONLY_CONFIG_REQ
1110 if (nat_only_config_flag) {
1111 printf("******* pub_ip_range_count:%d ***********\n",
1112 p_nat->pub_ip_range_count);
1113 /* Initialize all public IP's addresses */
1115 uint32_t max_ips_remain;
1117 for (if_addrs = 0; if_addrs < p_nat->pub_ip_range_count;
1119 /* Add all available addresses to the ring */
1121 for (i = p_nat->pub_ip_range[if_addrs].start_ip;
1122 i <= p_nat->pub_ip_range[if_addrs].end_ip;) {
1123 /* 1. Get a port alloc buffer from napt_port_pool */
1127 /* get new napt_port_alloc_elem from pool */
1128 if (rte_mempool_get(napt_port_pool,
1130 printf("CGNAPT - Error in getting port "
1136 /* 2. Populate it with available ports and ip addr */
1137 struct napt_port_alloc_elem *pb =
1138 (struct napt_port_alloc_elem *)portsBuf;
1141 temp = p_nat->pub_ip_range[if_addrs].end_ip -
1144 /* Check if remaining port count is greater
1145 * than or equals to bulk count, if not give
1146 * remaining count ports than giving bulk count
1148 if (temp < NUM_NAPT_PORT_BULK_ALLOC)
1149 max_ips_remain = temp;
1152 NUM_NAPT_PORT_BULK_ALLOC;
1154 for (j = 0; j < max_ips_remain; j++) {
1156 pb->ip_addr[j] = i + j;
1159 p_nat->pub_ip_range[if_addrs].
1164 /* 3. add the port alloc buffer to ring */
1165 if (rte_ring_enqueue(p_nat->port_alloc_ring,
1167 printf("CGNAPT%d - Enqueue error - i %d,",
1168 p_nat->pipeline_num, i);
1169 printf("j %d, if_addrs %d, pb %p\n",
1171 rte_ring_dump(stdout,
1172 p_nat->port_alloc_ring);
1173 rte_mempool_put(napt_port_pool,
1178 /* reset j and advance i */
1180 i += max_ips_remain;
1188 printf("******* p_nat->pub_ip_count:%d ***********\n",
1189 p_nat->pub_ip_count);
1190 /* Initialize all public IP's ports */
1192 uint32_t max_ports_remain;
1194 for (if_ports = 0; if_ports < p_nat->pub_ip_count; if_ports++) {
1195 /* Add all available ports to the ring */
1197 for (i = p_nat->pub_ip_port_set[if_ports].start_port;
1198 i <= p_nat->pub_ip_port_set[if_ports].end_port;) {
1199 /* 1. Get a port alloc buffer from napt_port_pool */
1203 /* get new napt_port_alloc_elem from pool */
1204 if (rte_mempool_get(napt_port_pool, &portsBuf) <
1206 printf("CGNAPT - Error in getting "
1207 "port alloc buffer\n");
1212 /* 2. Populate it with available ports and ip addr */
1213 struct napt_port_alloc_elem *pb =
1214 (struct napt_port_alloc_elem *)portsBuf;
1217 temp = p_nat->pub_ip_port_set[if_ports].end_port -
1219 /* Check if remaining port count is greater
1220 * than or equals to bulk count, if not give
1221 * remaining count ports than giving bulk count
1223 if (temp < NUM_NAPT_PORT_BULK_ALLOC)
1224 max_ports_remain = temp;
1227 NUM_NAPT_PORT_BULK_ALLOC;
1229 for (j = 0; j < max_ports_remain; j++) {
1232 p_nat->pub_ip_port_set[if_ports].ip;
1233 pb->ports[j] = i + j;
1234 if ((i + j) == p_nat->pub_ip_port_set
1235 [if_ports].end_port)
1239 /* 3. add the port alloc buffer to ring */
1240 if (rte_ring_enqueue(p_nat->port_alloc_ring,
1242 printf("CGNAPT%d - Enqueue error - i %d, j %d, "
1243 " if_ports %d, pb %p\n", p_nat->pipeline_num,
1244 i, j, if_ports, pb);
1246 rte_ring_dump(stdout, p_nat->port_alloc_ring);
1247 rte_mempool_put(napt_port_pool, portsBuf);
1251 /* reset j and advance i */
1253 i += max_ports_remain;
1260 static pipeline_msg_req_handler handlers[] = {
1261 [PIPELINE_MSG_REQ_PING] =
1262 pipeline_msg_req_ping_handler,
1263 [PIPELINE_MSG_REQ_STATS_PORT_IN] =
1264 pipeline_msg_req_stats_port_in_handler,
1265 [PIPELINE_MSG_REQ_STATS_PORT_OUT] =
1266 pipeline_msg_req_stats_port_out_handler,
1267 [PIPELINE_MSG_REQ_STATS_TABLE] = pipeline_msg_req_stats_table_handler,
1268 [PIPELINE_MSG_REQ_PORT_IN_ENABLE] =
1269 pipeline_msg_req_port_in_enable_handler,
1270 [PIPELINE_MSG_REQ_PORT_IN_DISABLE] =
1271 pipeline_msg_req_port_in_disable_handler,
1272 [PIPELINE_MSG_REQ_CUSTOM] =
1273 pipeline_cgnapt_msg_req_custom_handler,
1276 static pipeline_msg_req_handler custom_handlers[] = {
1277 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_ADD] =
1278 pipeline_cgnapt_msg_req_entry_add_handler,
1279 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_DEL] =
1280 pipeline_cgnapt_msg_req_entry_del_handler,
1281 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_SYNC] =
1282 pipeline_cgnapt_msg_req_entry_sync_handler,
1283 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_DBG] =
1284 pipeline_cgnapt_msg_req_entry_dbg_handler,
1285 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_ADDM] =
1286 pipeline_cgnapt_msg_req_entry_addm_handler,
1287 [PIPELINE_CGNAPT_MSG_REQ_VER] =
1288 pipeline_cgnapt_msg_req_ver_handler,
1289 [PIPELINE_CGNAPT_MSG_REQ_NSP_ADD] =
1290 pipeline_cgnapt_msg_req_nsp_add_handler,
1291 [PIPELINE_CGNAPT_MSG_REQ_NSP_DEL] =
1292 pipeline_cgnapt_msg_req_nsp_del_handler,
1295 [PIPELINE_CGNAPT_MSG_REQ_PCP] =
1296 pipeline_cgnapt_msg_req_pcp_handler,
1301 * Function to convert an IPv6 packet to IPv4 packet
1304 * A pointer to packet mbuf
1305 * @param in_ipv6_hdr
1306 * A pointer to IPv6 header in the given pkt
1310 convert_ipv6_to_ipv4(struct rte_mbuf *pkt, struct ipv6_hdr *in_ipv6_hdr)
1312 uint32_t ip_hdr_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE;
1314 uint8_t *eth_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1315 uint8_t *ipv6_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, ip_hdr_offset);
1317 struct ether_hdr eth_hdr;
1318 struct ipv4_hdr *ipv4_hdr_p;
1319 uint16_t frag_off = 0x4000;
1320 struct cgnapt_nsp_node *ll = nsp_ll;
1321 uint8_t ipv4_dest[4];
1324 memcpy(ð_hdr, eth_hdr_p, sizeof(struct ether_hdr));
1325 memcpy(in_ipv6_hdr, ipv6_hdr_p, sizeof(struct ipv6_hdr));
1327 eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
1329 char *data_area_p = rte_pktmbuf_adj(pkt, 20);
1330 if (data_area_p == NULL) {
1331 printf("convert_ipv6_to_ipv4:data_area_p is NULL\n");
1334 ipv4_hdr_p = (struct ipv4_hdr *)(data_area_p + ETH_HDR_SIZE);
1335 memset(ipv4_hdr_p, 0, sizeof(struct ipv4_hdr));
1337 memcpy(data_area_p, ð_hdr, sizeof(struct ether_hdr));
1339 #ifdef CGNAPT_DBG_PRNT
1340 if (CGNAPT_DEBUG == 1)
1341 printf("convert_ipv6_to_ipv4: eth_hdr_p(%p), data_area_p(%p), "
1342 "ipv4_hdr_p(%p)\n", eth_hdr_p, data_area_p, ipv4_hdr_p);
1345 ipv4_hdr_p->version_ihl = 0x4 << 4 | 0x5;
1346 ipv4_hdr_p->type_of_service =
1347 rte_be_to_cpu_32(in_ipv6_hdr->vtc_flow) & 0x0ff00000 >> 20;
1348 ipv4_hdr_p->total_length =
1349 rte_cpu_to_be_16(rte_be_to_cpu_16(
1350 in_ipv6_hdr->payload_len) + 20);
1351 ipv4_hdr_p->packet_id = 0;
1352 ipv4_hdr_p->fragment_offset = rte_cpu_to_be_16(frag_off);
1353 ipv4_hdr_p->time_to_live = in_ipv6_hdr->hop_limits;
1354 ipv4_hdr_p->next_proto_id = in_ipv6_hdr->proto;
1355 ipv4_hdr_p->hdr_checksum = 0;
1356 ipv4_hdr_p->src_addr = 0;
1358 while (ll != NULL) {
1360 (&in_ipv6_hdr->dst_addr[0], &ll->nsp.prefix[0],
1361 ll->nsp.depth / 8)) {
1362 if (ll->nsp.depth == 32)
1363 memcpy(&ipv4_dest[0], &in_ipv6_hdr->dst_addr[4],
1365 else if (ll->nsp.depth == 40) {
1366 ipv4_dest[0] = in_ipv6_hdr->dst_addr[5];
1367 ipv4_dest[1] = in_ipv6_hdr->dst_addr[6];
1368 ipv4_dest[2] = in_ipv6_hdr->dst_addr[7];
1369 ipv4_dest[3] = in_ipv6_hdr->dst_addr[9];
1370 } else if (ll->nsp.depth == 48) {
1371 ipv4_dest[0] = in_ipv6_hdr->dst_addr[6];
1372 ipv4_dest[1] = in_ipv6_hdr->dst_addr[7];
1373 ipv4_dest[2] = in_ipv6_hdr->dst_addr[9];
1374 ipv4_dest[3] = in_ipv6_hdr->dst_addr[10];
1375 } else if (ll->nsp.depth == 56) {
1376 ipv4_dest[0] = in_ipv6_hdr->dst_addr[7];
1377 ipv4_dest[1] = in_ipv6_hdr->dst_addr[9];
1378 ipv4_dest[2] = in_ipv6_hdr->dst_addr[10];
1379 ipv4_dest[3] = in_ipv6_hdr->dst_addr[11];
1380 } else if (ll->nsp.depth == 64) {
1381 ipv4_dest[0] = in_ipv6_hdr->dst_addr[9];
1382 ipv4_dest[1] = in_ipv6_hdr->dst_addr[10];
1383 ipv4_dest[2] = in_ipv6_hdr->dst_addr[11];
1384 ipv4_dest[3] = in_ipv6_hdr->dst_addr[12];
1385 } else if (ll->nsp.depth == 96) {
1386 ipv4_dest[0] = in_ipv6_hdr->dst_addr[12];
1387 ipv4_dest[1] = in_ipv6_hdr->dst_addr[13];
1388 ipv4_dest[2] = in_ipv6_hdr->dst_addr[14];
1389 ipv4_dest[3] = in_ipv6_hdr->dst_addr[15];
1400 memcpy(&ipv4_hdr_p->dst_addr, &ipv4_dest[0], 4);
1402 memcpy(&ipv4_hdr_p->dst_addr, &in_ipv6_hdr->dst_addr[12], 4);
1407 * Function to convert an IPv4 packet to IPv6 packet
1410 * A pointer to packet mbuf
1411 * @param in_ipv4_hdr
1412 * A pointer to IPv4 header in the given pkt
1416 convert_ipv4_to_ipv6(struct rte_mbuf *pkt, struct ipv4_hdr *in_ipv4_hdr)
1418 uint32_t ip_hdr_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE;
1420 uint8_t *eth_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1421 uint8_t *ipv4_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, ip_hdr_offset);
1423 struct ether_hdr eth_hdr;
1424 struct ipv6_hdr *ipv6_hdr_p;
1426 memcpy(ð_hdr, eth_hdr_p, sizeof(struct ether_hdr));
1427 memcpy(in_ipv4_hdr, ipv4_hdr_p, sizeof(struct ipv4_hdr));
1429 eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
1431 char *data_area_p = rte_pktmbuf_prepend(pkt, 20);
1432 if (data_area_p == NULL) {
1433 printf("convert_ipv4_to_ipv6:data_area_p is NULL\n");
1436 ipv6_hdr_p = (struct ipv6_hdr *)(data_area_p + ETH_HDR_SIZE);
1437 memset(ipv6_hdr_p, 0, sizeof(struct ipv6_hdr));
1439 memcpy(data_area_p, ð_hdr, sizeof(struct ether_hdr));
1441 ipv6_hdr_p->vtc_flow =
1442 rte_cpu_to_be_32((0x6 << 28) |
1443 (in_ipv4_hdr->type_of_service << 20));
1444 ipv6_hdr_p->payload_len =
1445 rte_cpu_to_be_16(rte_be_to_cpu_16(
1446 in_ipv4_hdr->total_length) - 20);
1447 ipv6_hdr_p->proto = in_ipv4_hdr->next_proto_id;
1448 ipv6_hdr_p->hop_limits = in_ipv4_hdr->time_to_live;
1450 ipv6_hdr_p->src_addr[0] = 0x00;
1451 ipv6_hdr_p->src_addr[1] = 0x64;
1452 ipv6_hdr_p->src_addr[2] = 0xff;
1453 ipv6_hdr_p->src_addr[3] = 0x9b;
1454 ipv6_hdr_p->src_addr[4] = 0x00;
1455 ipv6_hdr_p->src_addr[5] = 0x00;
1456 ipv6_hdr_p->src_addr[6] = 0x00;
1457 ipv6_hdr_p->src_addr[7] = 0x00;
1458 ipv6_hdr_p->src_addr[8] = 0x00;
1459 ipv6_hdr_p->src_addr[9] = 0x00;
1460 ipv6_hdr_p->src_addr[10] = 0x00;
1461 ipv6_hdr_p->src_addr[11] = 0x00;
1462 memcpy(&ipv6_hdr_p->src_addr[12], &in_ipv4_hdr->src_addr, 4);
1464 memset(&ipv6_hdr_p->dst_addr, 0, 16);
1471 * Output port handler
1474 * A pointer to packet mbuf
1476 * Unused void pointer
1479 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1481 pkt_work_cgnapt_out(__rte_unused struct rte_mbuf *pkt, __rte_unused void *arg)
1483 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1484 if ((cgnapt_num_func_to_inst == 5)
1485 && (cgnapt_inst_index < INST_ARRAY_SIZE)) {
1486 if (cgnapt_inst5_flag == 0) {
1487 uint8_t *inst5_sig =
1488 RTE_MBUF_METADATA_UINT8_PTR(pkt,
1490 if (*inst5_sig == CGNAPT_INST5_SIG) {
1491 cgnapt_inst5_flag = 1;
1492 inst_end_time[cgnapt_inst_index] =
1493 rte_get_tsc_cycles();
1494 cgnapt_inst_index++;
1500 /* cgnapt_pkt_out_count++; */
1501 #ifdef CGNAPT_DBG_PRNT
1509 * Output port handler to handle 4 pkts
1512 * A pointer to packet mbuf
1514 * Inport handler argument pointer
1517 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1518 static void pkt4_work_cgnapt_out(struct rte_mbuf **pkt, void *arg)
1522 /* TO BE IMPLEMENTED IF REQUIRED */
1526 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1527 PIPELINE_CGNAPT_PORT_OUT_AH(port_out_ah_cgnapt,
1528 pkt_work_cgnapt_out, pkt4_work_cgnapt_out);
1530 PIPELINE_CGNAPT_PORT_OUT_BAH(port_out_ah_cgnapt_bulk,
1531 pkt_work_cgnapt_out, pkt4_work_cgnapt_out);
1535 * Function to validate the packet and return version
1538 * A pointer to packet mbuf
1541 * IP version of the valid pkt, -1 if invalid pkt
1543 int rte_get_pkt_ver(struct rte_mbuf *pkt)
1545 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
1546 uint16_t *eth_proto =
1547 RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
1549 if (*eth_proto == rte_be_to_cpu_16(ETHER_TYPE_IPv4))
1550 return IP_VERSION_4;
1552 if (dual_stack_enable
1553 && (*eth_proto == rte_be_to_cpu_16(ETHER_TYPE_IPv6)))
1554 return IP_VERSION_6;
1556 /* Check the protocol first, if not UDP or TCP return */
1562 * A method to print the NAPT entry
1565 * A pointer to struct cgnapt_table_entry
1567 void my_print_entry(struct cgnapt_table_entry *ent)
1569 printf("CGNAPT key:\n");
1570 printf("entry_type :%d\n", ent->data.type);
1571 printf("prv_ip: %x %x %x %x\n", ent->data.u.u32_prv_ipv6[0],
1572 ent->data.u.u32_prv_ipv6[1], ent->data.u.u32_prv_ipv6[2],
1573 ent->data.u.u32_prv_ipv6[3]);
1574 printf("prv_port:%d\n", ent->data.prv_port);
1576 printf("pub_ip:%x\n", ent->data.pub_ip);
1577 printf("prv_phy_port:%d\n", ent->data.prv_phy_port);
1578 printf("pub_phy_port:%d\n", ent->data.pub_phy_port);
1582 * Function to print common CGNAPT table entries
1585 void print_common_table(void)
1593 index = rte_hash_iterate(napt_common_table,
1594 &key, &data, &next);
1596 if ((index != -EINVAL) && (index != -ENOENT)) {
1597 printf("\n%04d ", count);
1598 //print_key((struct pipeline_cgnapt_entry_key *)key);
1599 rte_hexdump(stdout, "KEY", key,
1600 sizeof(struct pipeline_cgnapt_entry_key));
1601 int32_t position = rte_hash_lookup(
1602 napt_common_table, key);
1603 print_cgnapt_entry(&napt_hash_tbl_entries[position]);
1607 } while (index != -ENOENT);
1611 * Input port handler for mixed traffic
1612 * This is the main method in this file when running in mixed traffic mode.
1613 * Starting from the packet burst it filters unwanted packets,
1614 * calculates keys, does lookup and then based on the lookup
1615 * updates NAPT table and does packet NAPT translation.
1618 * A pointer to struct rte_pipeline
1620 * A pointer to array of packets mbuf
1622 * Number of packets in the burst
1627 * int that is not checked by caller
1629 static int cgnapt_in_port_ah_mix(struct rte_pipeline *rte_p,
1630 struct rte_mbuf **pkts,
1631 uint32_t n_pkts, void *arg)
1636 * 1. Read packet version, if invalid drop the packet
1637 * 2. Check protocol, if not UDP or TCP drop the packet
1638 * 3. Bring all valid packets together - useful for bulk lookup
1639 * and calculate key for all packets
1640 * a. If IPv4 : calculate key with full IP
1641 * b. If IPv6 : calculate key with last 32-bit of IP
1642 * 4. Do bulk lookup with rte_hash_lookup_bulk(), if something went wrong
1644 * 5. For lookup hit packets, read entry from table
1645 * 6. For lookup miss packets, add dynamic entry to table
1647 * a. If egress pkt, convert to IPv4 and NAPT it
1648 * b. If ingress, drop the pkt
1650 * a. If egress pkt, NAPT it. Get MAC
1651 * b. If first ingress pkt (with no egress entry), drop the pkt
1652 * If not first ingress pkt
1653 * I. If IPv6 converted packet, convert back to IPv6,
1655 * II. If IPv4 packet, NAPT it & get MAC
1656 * 9. Send all packets out to corresponding ports
1658 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
1659 struct pipeline_cgnapt *p_nat = ap->p;
1660 uint8_t compacting_map[RTE_HASH_LOOKUP_BULK_MAX];
1661 uint32_t packets_for_lookup = 0;
1664 p_nat->valid_packets = 0;
1665 p_nat->invalid_packets = 0;
1667 #ifdef CGNAPT_DBG_PRNT
1668 if (CGNAPT_DEBUG > 1)
1669 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
1672 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
1674 uint16_t phy_port = 0;
1675 uint16_t *src_port = NULL;
1676 uint16_t *dst_port = NULL;
1677 uint32_t *src_addr = NULL;
1678 uint32_t *dst_addr = NULL;
1679 uint8_t *protocol = NULL;
1680 uint8_t *eth_dest = NULL;
1681 uint8_t *eth_src = NULL;
1682 uint16_t src_port_offset = 0;
1683 uint16_t dst_port_offset = 0;
1684 uint16_t src_addr_offset = 0;
1685 uint16_t dst_addr_offset = 0;
1686 uint16_t prot_offset = 0;
1687 uint16_t eth_offset = 0;
1690 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
1692 src_port_offset = SRC_PRT_OFST_IP4_TCP;
1693 dst_port_offset = DST_PRT_OFST_IP4_TCP;
1695 for (i = 0; i < n_pkts; i++) {
1696 p_nat->receivedPktCount++;
1698 /* bitmask representing only this packet */
1699 uint64_t pkt_mask = 1LLU << i;
1701 /* remember this pkt as valid pkt */
1702 p_nat->valid_packets |= pkt_mask;
1704 struct rte_mbuf *pkt = pkts[i];
1707 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
1710 int ver = rte_get_pkt_ver(pkt);
1712 #ifdef CGNAPT_DBG_PRNT
1713 printf("ver no. of the pkt:%d\n", ver);
1716 if (unlikely(ver < 0)) {
1717 /* Not a valid pkt , ignore. */
1718 /* remember invalid packets to be dropped */
1719 p_nat->invalid_packets |= pkt_mask;
1720 p_nat->naptDroppedPktCount++;
1722 #ifdef CGNAPT_DEBUGGING
1723 p_nat->naptDroppedPktCount1++;
1728 prot_offset = PROT_OFST_IP4;
1730 prot_offset = PROT_OFST_IP6;
1732 (uint8_t *) RTE_MBUF_METADATA_UINT32_PTR(pkt,
1735 (*protocol == IP_PROTOCOL_TCP
1736 || *protocol == IP_PROTOCOL_UDP
1737 || *protocol == IP_PROTOCOL_ICMP)) {
1738 /* remember invalid packets to be dropped */
1739 p_nat->invalid_packets |= pkt_mask;
1740 p_nat->naptDroppedPktCount++;
1742 #ifdef CGNAPT_DEBUGGING
1743 p_nat->naptDroppedPktCount2++;
1748 #ifdef CGNAPT_DBG_PRNT
1749 if (CGNAPT_DEBUG > 4)
1755 * 1. Handel PCP for egress traffic
1756 * 2. If PCP, then give response (send pkt) from the same port
1757 * 3. Drop the PCP packet, should not be added in the NAPT table
1760 if (*protocol == IP_PROTOCOL_UDP) {
1761 struct udp_hdr *udp;
1763 udp = (struct udp_hdr *)
1764 RTE_MBUF_METADATA_UINT8_PTR(pkt,
1767 udp = (struct udp_hdr *)
1768 RTE_MBUF_METADATA_UINT8_PTR(pkt,
1771 if (rte_bswap16(udp->dst_port) ==
1773 handle_pcp_req(pkt, ver, p_nat);
1774 p_nat->invalid_packets |= pkt_mask;
1784 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1787 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1790 if ((*protocol == IP_PROTOCOL_TCP)
1791 || (*protocol == IP_PROTOCOL_UDP)) {
1793 src_port_offset = SRC_PRT_OFST_IP4_TCP;
1794 dst_port_offset = DST_PRT_OFST_IP4_TCP;
1796 } else if (*protocol == IP_PROTOCOL_ICMP) {
1798 src_port_offset = IDEN_OFST_IP4_ICMP;
1799 /* Sequence number */
1800 dst_port_offset = SEQN_OFST_IP4_ICMP;
1804 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1807 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1812 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1815 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1818 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1821 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1824 /* need to create compacted table of pointers to
1825 * pass to bulk lookup
1828 compacting_map[packets_for_lookup] = i;
1830 //phy_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, phyport_offset);
1831 phy_port = pkt->port;
1833 struct pipeline_cgnapt_entry_key key;
1835 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
1838 if (get_in_port_dir(phy_port)) {
1841 key.ip = rte_bswap32(*src_addr);
1843 key.ip = rte_bswap32(src_addr[3]);
1844 key.port = rte_bswap16(*src_port);
1846 #ifdef NAT_ONLY_CONFIG_REQ
1847 if (nat_only_config_flag)
1852 key.ip = rte_bswap32(*dst_addr);
1854 if (*protocol == IP_PROTOCOL_ICMP) {
1855 /* common table lookupkey preparation from
1856 * incoming ICMP Packet- Indentifier field
1858 key.port = rte_bswap16(*src_port);
1860 key.port = rte_bswap16(*dst_port);
1863 #ifdef NAT_ONLY_CONFIG_REQ
1864 if (nat_only_config_flag)
1871 memcpy(&(p_nat->keys[packets_for_lookup]), &key,
1872 sizeof(struct pipeline_cgnapt_entry_key));
1873 p_nat->key_ptrs[packets_for_lookup] =
1874 &(p_nat->keys[packets_for_lookup]);
1875 packets_for_lookup++;
1878 if (unlikely(packets_for_lookup == 0)) {
1879 /* no suitable packet for lookup */
1880 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
1881 return p_nat->valid_packets;
1884 /* lookup entries in the common napt table */
1886 int lookup_result = rte_hash_lookup_bulk(napt_common_table,
1890 &p_nat->lkup_indx[0]);
1892 if (unlikely(lookup_result < 0)) {
1893 /* unknown error, just discard all packets */
1894 printf("Unexpected hash lookup error %d, discarding all "
1895 "packets", lookup_result);
1896 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
1899 //struct rte_pipeline_table_entry *entries[64];
1900 /* Now one by one check the result of our bulk lookup */
1902 for (i = 0; i < packets_for_lookup; i++) {
1903 /* index into hash table entries */
1904 int hash_table_entry = p_nat->lkup_indx[i];
1905 /* index into packet table of this packet */
1906 uint8_t pkt_index = compacting_map[i];
1907 /*bitmask representing only this packet */
1908 uint64_t pkt_mask = 1LLU << pkt_index;
1910 struct cgnapt_table_entry *entry = NULL;
1911 if (hash_table_entry < 0) {
1913 /* try to add new entry */
1914 struct rte_pipeline_table_entry *table_entry = NULL;
1917 pkt_miss_cgnapt(p_nat->key_ptrs[i],
1920 &p_nat->valid_packets,
1925 /* ICMP Error message generation for
1926 * Destination Host unreachable
1928 if (*protocol == IP_PROTOCOL_ICMP) {
1929 cgnapt_icmp_pkt = pkts[pkt_index];
1930 send_icmp_dest_unreachable_msg();
1933 /* Drop packet by adding to invalid pkt mask */
1935 p_nat->invalid_packets |= dropmask;
1936 #ifdef CGNAPT_DEBUGGING
1937 if (p_nat->kpc2++ < 5) {
1938 printf("in_ah Th: %d",
1939 p_nat->pipeline_num);
1940 print_key(p_nat->key_ptrs[i]);
1944 p_nat->naptDroppedPktCount++;
1946 #ifdef CGNAPT_DEBUGGING
1947 p_nat->naptDroppedPktCount3++;
1952 entry = (struct cgnapt_table_entry *)table_entry;
1954 /* entry found for this packet */
1955 entry = &napt_hash_tbl_entries[hash_table_entry];
1958 /* apply napt and mac changes */
1960 p_nat->entries[pkt_index] = &(entry->head);
1962 phy_port = pkts[pkt_index]->port;
1964 struct ipv6_hdr ipv6_hdr;
1965 struct ipv4_hdr ipv4_hdr;
1967 ver = rte_get_pkt_ver(pkts[pkt_index]);
1968 #ifdef CGNAPT_DEBUGGING
1969 if (CGNAPT_DEBUG >= 1) {
1970 printf("ver:%d\n", ver);
1971 printf("entry->data.type:%d\n", entry->data.type);
1974 if ((ver == 6) && (entry->data.type == CGNAPT_ENTRY_IPV6)
1975 && is_phy_port_privte(phy_port)) {
1976 convert_ipv6_to_ipv4(pkts[pkt_index], &ipv6_hdr);
1978 pkt_type = PKT_TYPE_IPV6to4;
1980 #ifdef CGNAPT_DBG_PRNT
1981 if (CGNAPT_DEBUG >= 1)
1982 printf("pkt_work_cganpt: "
1983 "convert_ipv6_to_ipv4\n");
1986 struct cgnapt_nsp_node *ll = nsp_ll;
1988 while (ll != NULL) {
1989 if (!memcmp(&ipv6_hdr.dst_addr[0],
1991 ll->nsp.depth / 8)) {
1999 && !memcmp(&ipv6_hdr.dst_addr[0],
2000 &well_known_prefix[0], 12)) {
2005 p_nat->invalid_packets |= 1LLU << pkt_index;
2006 p_nat->naptDroppedPktCount++;
2008 #ifdef CGNAPT_DEBUGGING
2009 p_nat->naptDroppedPktCount5++;
2016 /* As packet is already converted into IPv4 we must not operate
2017 * IPv6 offsets on packet
2018 * Only perform IPv4 operations
2023 src_port_offset = SRC_PRT_OFST_IP6t4;
2024 dst_port_offset = DST_PRT_OFST_IP6t4;
2025 src_addr_offset = SRC_ADR_OFST_IP6t4;
2026 dst_addr_offset = DST_ADR_OFST_IP6t4;
2027 prot_offset = PROT_OFST_IP6t4;
2028 eth_offset = ETH_OFST_IP6t4;
2032 if ((*protocol == IP_PROTOCOL_TCP)
2033 || (*protocol == IP_PROTOCOL_UDP)) {
2034 src_port_offset = SRC_PRT_OFST_IP4_TCP;
2035 dst_port_offset = DST_PRT_OFST_IP4_TCP;
2036 } else if (*protocol == IP_PROTOCOL_ICMP) {
2038 src_port_offset = IDEN_OFST_IP4_ICMP;
2039 /* Sequence number */
2040 dst_port_offset = SEQN_OFST_IP4_ICMP;
2043 src_addr_offset = SRC_ADR_OFST_IP4;
2044 dst_addr_offset = DST_ADR_OFST_IP4;
2045 prot_offset = PROT_OFST_IP4;
2046 eth_offset = MBUF_HDR_ROOM;
2051 RTE_MBUF_METADATA_UINT32_PTR(pkts[pkt_index],
2054 RTE_MBUF_METADATA_UINT32_PTR(pkts[pkt_index],
2057 RTE_MBUF_METADATA_UINT16_PTR(pkts[pkt_index],
2060 RTE_MBUF_METADATA_UINT16_PTR(pkts[pkt_index],
2063 RTE_MBUF_METADATA_UINT8_PTR(pkts[pkt_index],
2067 RTE_MBUF_METADATA_UINT8_PTR(pkts[pkt_index],
2070 RTE_MBUF_METADATA_UINT8_PTR(pkts[pkt_index],
2073 if (entry->data.ttl == NAPT_ENTRY_STALE)
2074 entry->data.ttl = NAPT_ENTRY_VALID;
2076 struct ether_addr hw_addr;
2077 uint32_t dest_address = 0;
2078 uint8_t nh_ipv6[16];
2081 uint32_t dest_if = 0xff;
2084 uint16_t *outport_id =
2085 RTE_MBUF_METADATA_UINT16_PTR(pkts[pkt_index],
2086 cgnapt_meta_offset);
2088 if (is_phy_port_privte(phy_port)) {
2090 if (*protocol == IP_PROTOCOL_UDP
2091 && rte_be_to_cpu_16(*dst_port) == 53) {
2092 p_nat->invalid_packets |= 1LLU << pkt_index;
2093 p_nat->naptDroppedPktCount++;
2094 #ifdef CGNAPT_DEBUGGING
2095 p_nat->naptDroppedPktCount6++;
2100 dest_address = rte_bswap32(*dst_addr);
2101 ret = local_get_nh_ipv4(dest_address, &dest_if,
2104 dest_if = get_prv_to_pub_port(&dest_address,
2106 if (dest_if == INVALID_DESTIF) {
2107 p_nat->invalid_packets |=
2109 p_nat->naptDroppedPktCount++;
2110 #ifdef CGNAPT_DEBUGGING
2111 p_nat->naptDroppedPktCount6++;
2115 do_local_nh_ipv4_cache(dest_if, p_nat);
2118 *outport_id = p_nat->outport_id[dest_if];
2119 struct arp_entry_data *ret_arp_data;
2120 ret_arp_data = get_dest_mac_addr_port(dest_address,
2121 &dest_if, (struct ether_addr *)eth_dest);
2123 if (unlikely(ret_arp_data == NULL)) {
2125 #ifdef CGNAPT_DEBUGGING
2126 printf("%s: NHIP Not Found, nhip: %x, "
2127 "outport_id: %d\n", __func__, nhip,
2131 p_nat->invalid_packets |= pkt_mask;
2132 p_nat->naptDroppedPktCount++;
2134 #ifdef CGNAPT_DEBUGGING
2135 p_nat->naptDroppedPktCount4++;
2140 if (ret_arp_data->status == COMPLETE) {
2142 if (ret_arp_data->num_pkts) {
2143 p_nat->naptedPktCount += ret_arp_data->num_pkts;
2144 arp_send_buffered_pkts(ret_arp_data,
2145 &hw_addr, *outport_id);
2148 memcpy(eth_dest, &hw_addr,
2149 sizeof(struct ether_addr));
2150 memcpy(eth_src, get_link_hw_addr(dest_if),
2151 sizeof(struct ether_addr));
2152 #ifdef CGNAPT_DBG_PRNT
2153 if (CGNAPT_DEBUG > 2) {
2154 printf("MAC found for ip 0x%x, port %d - "
2155 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2156 dest_address, *outport_id,
2157 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
2158 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
2159 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
2161 printf("Dest MAC before - "
2162 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2163 eth_dest[0], eth_dest[1], eth_dest[2],
2164 eth_dest[3], eth_dest[4], eth_dest[5]);
2168 #ifdef CGNAPT_DBG_PRNT
2169 if (CGNAPT_DEBUG > 2) {
2170 printf("Dest MAC after - "
2171 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2172 eth_dest[0], eth_dest[1], eth_dest[2],
2173 eth_dest[3], eth_dest[4], eth_dest[5]);
2177 #ifdef CGNAPT_DBG_PRNT
2178 if (CGNAPT_DEBUG > 4)
2179 print_pkt(pkts[pkt_index]);
2182 } else if (ret_arp_data->status == INCOMPLETE ||
2183 ret_arp_data->status == PROBE) {
2184 if (ret_arp_data->num_pkts >= NUM_DESC) {
2186 p_nat->invalid_packets |= pkt_mask;
2187 p_nat->naptDroppedPktCount++;
2189 #ifdef CGNAPT_DEBUGGING
2190 p_nat->naptDroppedPktCount4++;
2194 arp_queue_unresolved_packet(ret_arp_data,
2200 #ifdef CGNAPT_DBG_PRNT
2201 if (CGNAPT_DEBUG > 2)
2202 printf("Egress: \tphy_port:%d\t "
2203 "get_prv_to_pub():%d \tout_port:%d\n",
2209 *src_addr = rte_bswap32(entry->data.pub_ip);
2211 #ifdef NAT_ONLY_CONFIG_REQ
2212 if (!nat_only_config_flag) {
2214 *src_port = rte_bswap16(entry->data.pub_port);
2215 #ifdef NAT_ONLY_CONFIG_REQ
2219 p_nat->enaptedPktCount++;
2222 if (*protocol == IP_PROTOCOL_UDP
2223 && rte_be_to_cpu_16(*src_port) == 53) {
2224 p_nat->invalid_packets |= 1LLU << pkt_index;
2225 p_nat->naptDroppedPktCount++;
2226 #ifdef CGNAPT_DEBUGGING
2227 p_nat->naptDroppedPktCount6++;
2232 #ifdef CGNAPT_DBG_PRNT
2233 if (CGNAPT_DEBUG > 2)
2234 printf("Ingress: \tphy_port:%d\t "
2235 "get_pub_to_prv():%d \tout_port%d\n",
2240 if (entry->data.type == CGNAPT_ENTRY_IPV6) {
2241 convert_ipv4_to_ipv6(pkts[pkt_index],
2243 pkt_type = PKT_TYPE_IPV4to6;
2244 /* Ethernet MTU check */
2245 if ((rte_pktmbuf_data_len(pkts[pkt_index]) -
2247 p_nat->invalid_packets |= pkt_mask;
2248 p_nat->naptDroppedPktCount++;
2252 eth_dest = eth_dest - 20;
2253 eth_src = eth_src - 20;
2255 dst_port_offset = DST_PRT_OFST_IP4t6;
2256 dst_addr_offset = DST_ADR_OFST_IP4t6;
2258 RTE_MBUF_METADATA_UINT32_PTR(
2262 RTE_MBUF_METADATA_UINT16_PTR(
2266 memcpy((uint8_t *) &dst_addr[0],
2267 &entry->data.u.prv_ipv6[0], 16);
2268 memset(nh_ipv6, 0, 16);
2269 struct nd_entry_data *ret_nd_data = NULL;
2270 ret_nd_data = get_dest_mac_address_ipv6_port((uint8_t *)
2271 &dst_addr[0], &dest_if,
2272 &hw_addr, &nh_ipv6[0]);
2273 *outport_id = p_nat->outport_id[dest_if];
2275 if (nd_cache_dest_mac_present(dest_if)) {
2276 ether_addr_copy(get_link_hw_addr(dest_if),
2277 (struct ether_addr *)eth_src);
2278 update_nhip_access(dest_if);
2280 if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) {
2281 p_nat->naptedPktCount += ret_nd_data->num_pkts;
2282 nd_send_buffered_pkts(ret_nd_data,
2283 (struct ether_addr *)eth_dest,
2287 if (unlikely(ret_nd_data == NULL)) {
2289 #ifdef CGNAPT_DEBUGGING
2290 printf("%s: NHIP Not Found, "
2291 "outport_id: %d\n", __func__,
2296 p_nat->invalid_packets |= pkt_mask;
2297 p_nat->naptDroppedPktCount++;
2299 #ifdef CGNAPT_DEBUGGING
2300 p_nat->naptDroppedPktCount4++;
2305 if (ret_nd_data->status == INCOMPLETE ||
2306 ret_nd_data->status == PROBE) {
2307 if (ret_nd_data->num_pkts >= NUM_DESC) {
2309 p_nat->invalid_packets |= pkt_mask;
2310 p_nat->naptDroppedPktCount++;
2312 #ifdef CGNAPT_DEBUGGING
2313 p_nat->naptDroppedPktCount4++;
2317 arp_pkts_mask |= pkt_mask;
2318 nd_queue_unresolved_packet(ret_nd_data,
2326 #ifdef NAT_ONLY_CONFIG_REQ
2327 if (!nat_only_config_flag) {
2330 rte_bswap16(entry->data.prv_port);
2331 #ifdef NAT_ONLY_CONFIG_REQ
2336 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
2337 dest_address = entry->data.u.prv_ip;
2338 ret = local_get_nh_ipv4(dest_address, &dest_if,
2341 dest_if = get_pub_to_prv_port(
2342 &dest_address, IP_VERSION_4);
2343 if (dest_if == INVALID_DESTIF) {
2344 p_nat->invalid_packets |=
2346 p_nat->naptDroppedPktCount++;
2347 #ifdef CGNAPT_DEBUGGING
2348 p_nat->naptDroppedPktCount6++;
2352 do_local_nh_ipv4_cache(dest_if, p_nat);
2355 *outport_id = p_nat->outport_id[dest_if];
2356 struct arp_entry_data *ret_arp_data;
2357 ret_arp_data = get_dest_mac_addr_port(dest_address,
2358 &dest_if, (struct ether_addr *)eth_dest);
2360 if (unlikely(ret_arp_data == NULL)) {
2362 #ifdef CGNAPT_DEBUGGING
2363 printf("%s: NHIP Not Found, nhip: %x, "
2364 "outport_id: %d\n", __func__, nhip,
2369 p_nat->invalid_packets |= pkt_mask;
2370 p_nat->naptDroppedPktCount++;
2372 #ifdef CGNAPT_DEBUGGING
2373 p_nat->naptDroppedPktCount4++;
2378 if (ret_arp_data->status == COMPLETE) {
2380 if (ret_arp_data->num_pkts) {
2381 p_nat->naptedPktCount +=
2382 ret_arp_data->num_pkts;
2383 arp_send_buffered_pkts(ret_arp_data,
2384 &hw_addr, *outport_id);
2387 memcpy(eth_dest, &hw_addr,
2388 sizeof(struct ether_addr));
2389 memcpy(eth_src, get_link_hw_addr(
2391 sizeof(struct ether_addr));
2392 #ifdef CGNAPT_DBG_PRNT
2393 if (CGNAPT_DEBUG > 2) {
2394 printf("MAC found for ip 0x%x, port %d - "
2395 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2396 dest_address, *outport_id,
2397 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
2398 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
2399 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
2401 printf("Dest MAC before - "
2402 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2403 eth_dest[0], eth_dest[1], eth_dest[2],
2404 eth_dest[3], eth_dest[4], eth_dest[5]);
2408 #ifdef CGNAPT_DBG_PRNT
2409 if (CGNAPT_DEBUG > 2) {
2410 printf("Dest MAC after - "
2411 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2412 eth_dest[0], eth_dest[1], eth_dest[2],
2413 eth_dest[3], eth_dest[4], eth_dest[5]);
2417 #ifdef CGNAPT_DBG_PRNT
2418 if (CGNAPT_DEBUG > 4)
2419 print_pkt(pkts[pkt_index]);
2422 } else if (ret_arp_data->status == INCOMPLETE ||
2423 ret_arp_data->status == PROBE) {
2424 arp_queue_unresolved_packet(ret_arp_data,
2429 if (*protocol == IP_PROTOCOL_ICMP) {
2430 // Query ID reverse translation done here
2432 rte_bswap16(entry->data.prv_port);
2434 #ifdef NAT_ONLY_CONFIG_REQ
2435 if (!nat_only_config_flag) {
2440 #ifdef NAT_ONLY_CONFIG_REQ
2446 p_nat->inaptedPktCount++;
2449 p_nat->naptedPktCount++;
2452 if (p_nat->hw_checksum_reqd)
2453 hw_checksum(pkts[pkt_index], pkt_type);
2455 sw_checksum(pkts[pkt_index], pkt_type);
2459 if (p_nat->invalid_packets) {
2460 /* get rid of invalid packets */
2461 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2463 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2465 #ifdef CGNAPT_DBG_PRNT
2466 if (CGNAPT_DEBUG > 1) {
2467 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
2468 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
2469 printf("invalid_packets:0x%jx\n",
2470 p_nat->invalid_packets);
2471 printf("rte_invalid_packets :0x%jx\n",
2472 rte_p->pkts_drop_mask);
2473 printf("Total pkts dropped :0x%jx\n",
2474 rte_p->n_pkts_ah_drop);
2479 return p_nat->valid_packets;
2483 * Input port handler for IPv4 private traffic
2484 * Starting from the packet burst it filters unwanted packets,
2485 * calculates keys, does lookup and then based on the lookup
2486 * updates NAPT table and does packet NAPT translation.
2489 * A pointer to struct rte_pipeline
2491 * A pointer to array of packets mbuf
2493 * Number of packets in the burst
2498 * int that is not checked by caller
2501 static int cgnapt_in_port_ah_ipv4_prv(struct rte_pipeline *rte_p,
2502 struct rte_mbuf **pkts,
2503 uint32_t n_pkts, void *arg)
2506 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
2507 struct pipeline_cgnapt *p_nat = ap->p;
2509 #ifdef CGNAPT_TIMING_INST
2510 uint64_t entry_timestamp = 0, exit_timestamp;
2512 if (p_nat->time_measurements_on) {
2513 entry_timestamp = rte_get_tsc_cycles();
2514 /* check since exit ts not valid first time through */
2515 if (likely(p_nat->in_port_exit_timestamp))
2516 p_nat->external_time_sum +=
2517 entry_timestamp - p_nat->in_port_exit_timestamp;
2521 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
2522 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
2523 p_nat->invalid_packets = 0;
2525 #ifdef CGNAPT_DBG_PRNT
2526 if (CGNAPT_DEBUG > 1)
2527 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
2530 /* prefetching for mbufs should be done here */
2531 for (j = 0; j < n_pkts; j++)
2532 rte_prefetch0(pkts[j]);
2534 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2535 pkt4_work_cgnapt_key_ipv4_prv(&pkts[i], i, arg, p_nat);
2537 for (; i < n_pkts; i++)
2538 pkt_work_cgnapt_key_ipv4_prv(pkts[i], i, arg, p_nat);
2540 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2542 if (unlikely(p_nat->valid_packets == 0)) {
2543 /* no suitable packet for lookup */
2544 printf("no suitable valid packets\n");
2545 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2546 return p_nat->valid_packets;
2549 /* lookup entries in the common napt table */
2551 int lookup_result = rte_hash_lookup_bulk(
2553 (const void **)&p_nat->key_ptrs,
2554 /* should be minus num invalid pkts */
2556 /*new pipeline data member */
2557 &p_nat->lkup_indx[0]);
2559 if (unlikely(lookup_result < 0)) {
2560 /* unknown error, just discard all packets */
2561 printf("Unexpected hash lookup error %d, discarding "
2562 "all packets", lookup_result);
2563 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
2567 /* Now call second stage of pipeline to one by one
2568 * check the result of our bulk lookup
2571 /* prefetching for table entries should be done here */
2572 for (j = 0; j < n_pkts; j++) {
2573 if (p_nat->lkup_indx[j] >= 0)
2574 rte_prefetch0(&napt_hash_tbl_entries
2575 [p_nat->lkup_indx[j]]);
2578 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2579 pkt4_work_cgnapt_ipv4_prv(pkts, i, arg, p_nat);
2581 for (; i < n_pkts; i++)
2582 pkt_work_cgnapt_ipv4_prv(pkts, i, arg, p_nat);
2584 if (arp_pkts_mask) {
2585 p_nat->valid_packets &= ~(arp_pkts_mask);
2586 rte_pipeline_ah_packet_hijack(rte_p, arp_pkts_mask);
2589 if (p_nat->invalid_packets) {
2590 /* get rid of invalid packets */
2591 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2593 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2595 #ifdef CGNAPT_DBG_PRNT
2596 if (CGNAPT_DEBUG > 1) {
2597 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
2598 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
2599 printf("invalid_packets:0x%jx\n",
2600 p_nat->invalid_packets);
2601 printf("rte_invalid_packets :0x%jx\n",
2602 rte_p->pkts_drop_mask);
2603 printf("Total pkts dropped :0x%jx\n",
2604 rte_p->n_pkts_ah_drop);
2609 #ifdef CGNAPT_TIMING_INST
2610 if (p_nat->time_measurements_on) {
2611 exit_timestamp = rte_get_tsc_cycles();
2612 p_nat->in_port_exit_timestamp = exit_timestamp;
2613 p_nat->internal_time_sum += exit_timestamp - entry_timestamp;
2614 p_nat->time_measurements++;
2615 if (p_nat->time_measurements == p_nat->max_time_mesurements)
2616 p_nat->time_measurements_on = 0;
2620 return p_nat->valid_packets;
2624 * Input port handler for IPv4 public traffic
2625 * Starting from the packet burst it filters unwanted packets,
2626 * calculates keys, does lookup and then based on the lookup
2627 * updates NAPT table and does packet NAPT translation.
2630 * A pointer to struct rte_pipeline
2632 * A pointer to array of packets mbuf
2634 * Number of packets in the burst
2639 * int that is not checked by caller
2641 static int cgnapt_in_port_ah_ipv4_pub(struct rte_pipeline *rte_p,
2642 struct rte_mbuf **pkts,
2643 uint32_t n_pkts, void *arg)
2646 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
2647 struct pipeline_cgnapt *p_nat = ap->p;
2649 #ifdef CGNAPT_TIMING_INST
2650 uint64_t entry_timestamp = 0, exit_timestamp;
2652 if (p_nat->time_measurements_on) {
2653 entry_timestamp = rte_get_tsc_cycles();
2655 /* check since exit ts not valid first time through */
2656 if (likely(p_nat->in_port_exit_timestamp))
2657 p_nat->external_time_sum +=
2658 entry_timestamp - p_nat->in_port_exit_timestamp;
2662 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
2663 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
2664 p_nat->invalid_packets = 0;
2666 #ifdef CGNAPT_DBG_PRNT
2667 if (CGNAPT_DEBUG > 1)
2668 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
2671 /* prefetching for mbufs should be done here */
2672 for (j = 0; j < n_pkts; j++)
2673 rte_prefetch0(pkts[j]);
2675 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2676 pkt4_work_cgnapt_key_ipv4_pub(&pkts[i], i, arg, p_nat);
2678 for (; i < n_pkts; i++)
2679 pkt_work_cgnapt_key_ipv4_pub(pkts[i], i, arg, p_nat);
2681 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2683 if (unlikely(p_nat->valid_packets == 0)) {
2684 printf("no valid packets in pub\n");
2685 /* no suitable packet for lookup */
2686 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2687 return p_nat->valid_packets;
2690 /* lookup entries in the common napt table */
2692 int lookup_result = rte_hash_lookup_bulk(
2694 (const void **)&p_nat->key_ptrs,
2695 /* should be minus num invalid pkts */
2697 /*new pipeline data member */
2698 &p_nat->lkup_indx[0]);
2700 if (unlikely(lookup_result < 0)) {
2701 /* unknown error, just discard all packets */
2702 printf("Unexpected hash lookup error %d, discarding "
2703 "all packets", lookup_result);
2704 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
2708 /* Now call second stage of pipeline to one by one
2709 * check the result of our bulk lookup
2712 /* prefetching for table entries should be done here */
2713 for (j = 0; j < n_pkts; j++) {
2714 if (p_nat->lkup_indx[j] >= 0)
2715 rte_prefetch0(&napt_hash_tbl_entries
2716 [p_nat->lkup_indx[j]]);
2719 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2720 pkt4_work_cgnapt_ipv4_pub(pkts, i, arg, p_nat);
2722 for (; i < n_pkts; i++)
2723 pkt_work_cgnapt_ipv4_pub(pkts, i, arg, p_nat);
2725 if (arp_pkts_mask) {
2726 rte_pipeline_ah_packet_hijack(rte_p, arp_pkts_mask);
2727 p_nat->valid_packets &= ~(arp_pkts_mask);
2730 if (p_nat->invalid_packets) {
2731 /* get rid of invalid packets */
2732 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2734 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2736 #ifdef CGNAPT_DBG_PRNT
2737 if (CGNAPT_DEBUG > 1) {
2738 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
2739 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
2740 printf("invalid_packets:0x%jx\n",
2741 p_nat->invalid_packets);
2742 printf("rte_invalid_packets :0x%jx\n",
2743 rte_p->pkts_drop_mask);
2744 printf("Total pkts dropped :0x%jx\n",
2745 rte_p->n_pkts_ah_drop);
2750 #ifdef CGNAPT_TIMING_INST
2751 if (p_nat->time_measurements_on) {
2752 exit_timestamp = rte_get_tsc_cycles();
2753 p_nat->in_port_exit_timestamp = exit_timestamp;
2755 p_nat->internal_time_sum += exit_timestamp - entry_timestamp;
2756 p_nat->time_measurements++;
2757 if (p_nat->time_measurements == p_nat->max_time_mesurements)
2758 p_nat->time_measurements_on = 0;
2762 return p_nat->valid_packets;
2766 * NAPT key calculation function for IPv4 private traffic
2767 * which handles 4 pkts
2770 * A pointer to array of packets mbuf
2772 * Starting pkt number of pkts
2776 * A pointer to main CGNAPT structure
2780 pkt4_work_cgnapt_key_ipv4_prv(
2781 struct rte_mbuf **pkt,
2783 __rte_unused void *arg,
2784 struct pipeline_cgnapt *p_nat)
2786 p_nat->receivedPktCount += 4;
2787 /* bitmask representing only this packet */
2788 uint64_t pkt_mask0 = 1LLU << pkt_num;
2789 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
2790 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
2791 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
2793 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
2795 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
2797 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
2799 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
2802 uint32_t src_addr0 = RTE_MBUF_METADATA_UINT32(pkt[0],
2804 uint32_t src_addr1 = RTE_MBUF_METADATA_UINT32(pkt[1],
2806 uint32_t src_addr2 = RTE_MBUF_METADATA_UINT32(pkt[2],
2808 uint32_t src_addr3 = RTE_MBUF_METADATA_UINT32(pkt[3],
2811 uint16_t src_port_offset0;
2812 uint16_t src_port_offset1;
2813 uint16_t src_port_offset2;
2814 uint16_t src_port_offset3;
2821 uint16_t phy_port0 = pkt[0]->port;
2822 uint16_t phy_port1 = pkt[1]->port;
2823 uint16_t phy_port2 = pkt[2]->port;
2824 uint16_t phy_port3 = pkt[3]->port;
2826 struct pipeline_cgnapt_entry_key key0;
2827 struct pipeline_cgnapt_entry_key key1;
2828 struct pipeline_cgnapt_entry_key key2;
2829 struct pipeline_cgnapt_entry_key key3;
2831 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
2832 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
2833 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
2834 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
2837 #ifdef CGNAPT_DBG_PRNT
2838 if (CGNAPT_DEBUG > 4)
2843 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
2847 switch (protocol0) {
2848 case IP_PROTOCOL_UDP:
2852 struct udp_hdr *udp;
2854 udp = (struct udp_hdr *)
2855 RTE_MBUF_METADATA_UINT8_PTR(pkt[0],
2858 if (rte_bswap16(udp->dst_port) ==
2860 handle_pcp_req(pkt[0], IPV4_SZ, p_nat);
2861 p_nat->invalid_packets |= pkt_mask0;
2867 case IP_PROTOCOL_TCP:
2869 src_port_offset0 = SRC_PRT_OFST_IP4_TCP;
2870 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
2875 case IP_PROTOCOL_ICMP:
2877 src_port_offset0 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
2879 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
2885 /* remember invalid packets to be dropped */
2886 p_nat->invalid_packets |= pkt_mask0;
2887 p_nat->naptDroppedPktCount++;
2889 #ifdef CGNAPT_DEBUGGING
2890 p_nat->naptDroppedPktCount2++;
2895 key0.pid = phy_port0;
2896 key0.ip = rte_bswap32(src_addr0);
2897 key0.port = rte_bswap16(src_port0);
2899 #ifdef NAT_ONLY_CONFIG_REQ
2900 if (nat_only_config_flag)
2904 memcpy(&p_nat->keys[pkt_num], &key0,
2905 sizeof(struct pipeline_cgnapt_entry_key));
2906 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
2911 #ifdef CGNAPT_DBG_PRNT
2912 if (CGNAPT_DEBUG > 4)
2917 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
2920 switch (protocol1) {
2921 case IP_PROTOCOL_UDP:
2925 struct udp_hdr *udp;
2927 udp = (struct udp_hdr *)
2928 RTE_MBUF_METADATA_UINT8_PTR(pkt[1],
2931 if (rte_bswap16(udp->dst_port) ==
2933 handle_pcp_req(pkt[1], IPV4_SZ, p_nat);
2934 p_nat->invalid_packets |= pkt_mask1;
2940 case IP_PROTOCOL_TCP:
2942 src_port_offset1 = SRC_PRT_OFST_IP4_TCP;
2943 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
2948 case IP_PROTOCOL_ICMP:
2950 src_port_offset1 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
2952 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
2958 /* remember invalid packets to be dropped */
2959 p_nat->invalid_packets |= pkt_mask1;
2960 p_nat->naptDroppedPktCount++;
2962 #ifdef CGNAPT_DEBUGGING
2963 p_nat->naptDroppedPktCount2++;
2968 key1.pid = phy_port1;
2969 key1.ip = rte_bswap32(src_addr1);
2970 key1.port = rte_bswap16(src_port1);
2972 #ifdef NAT_ONLY_CONFIG_REQ
2973 if (nat_only_config_flag)
2977 memcpy(&p_nat->keys[pkt_num + 1], &key1,
2978 sizeof(struct pipeline_cgnapt_entry_key));
2979 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
2983 #ifdef CGNAPT_DBG_PRNT
2984 if (CGNAPT_DEBUG > 4)
2989 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
2993 switch (protocol2) {
2994 case IP_PROTOCOL_UDP:
2998 struct udp_hdr *udp;
3000 udp = (struct udp_hdr *)
3001 RTE_MBUF_METADATA_UINT8_PTR(pkt[2],
3004 if (rte_bswap16(udp->dst_port) ==
3006 handle_pcp_req(pkt[2], IPV4_SZ, p_nat);
3007 p_nat->invalid_packets |= pkt_mask2;
3013 case IP_PROTOCOL_TCP:
3015 src_port_offset2 = SRC_PRT_OFST_IP4_TCP;
3016 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3021 case IP_PROTOCOL_ICMP:
3023 src_port_offset2 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3025 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3031 /* remember invalid packets to be dropped */
3032 p_nat->invalid_packets |= pkt_mask2;
3033 p_nat->naptDroppedPktCount++;
3035 #ifdef CGNAPT_DEBUGGING
3036 p_nat->naptDroppedPktCount2++;
3041 key2.pid = phy_port2;
3042 key2.ip = rte_bswap32(src_addr2);
3043 key2.port = rte_bswap16(src_port2);
3045 #ifdef NAT_ONLY_CONFIG_REQ
3046 if (nat_only_config_flag)
3050 memcpy(&p_nat->keys[pkt_num + 2], &key2,
3051 sizeof(struct pipeline_cgnapt_entry_key));
3052 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
3056 #ifdef CGNAPT_DBG_PRNT
3057 if (CGNAPT_DEBUG > 4)
3061 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
3065 switch (protocol3) {
3066 case IP_PROTOCOL_UDP:
3070 struct udp_hdr *udp;
3072 udp = (struct udp_hdr *)
3073 RTE_MBUF_METADATA_UINT8_PTR(pkt[3],
3076 if (rte_bswap16(udp->dst_port) ==
3078 handle_pcp_req(pkt[3], IPV4_SZ, p_nat);
3079 p_nat->invalid_packets |= pkt_mask3;
3085 case IP_PROTOCOL_TCP:
3087 src_port_offset3 = SRC_PRT_OFST_IP4_TCP;
3088 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3093 case IP_PROTOCOL_ICMP:
3095 src_port_offset3 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3097 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3103 /* remember invalid packets to be dropped */
3104 p_nat->invalid_packets |= pkt_mask3;
3105 p_nat->naptDroppedPktCount++;
3107 #ifdef CGNAPT_DEBUGGING
3108 p_nat->naptDroppedPktCount2++;
3113 key3.pid = phy_port3;
3114 key3.ip = rte_bswap32(src_addr3);
3115 key3.port = rte_bswap16(src_port3);
3117 #ifdef NAT_ONLY_CONFIG_REQ
3118 if (nat_only_config_flag)
3122 memcpy(&p_nat->keys[pkt_num + 3], &key3,
3123 sizeof(struct pipeline_cgnapt_entry_key));
3124 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
3128 * NAPT key calculation function for IPv4 public traffic
3129 * which handles 4 pkts
3132 * A pointer to array of packets mbuf
3134 * Starting pkt number of pkts
3138 * A pointer to main CGNAPT structure
3142 pkt4_work_cgnapt_key_ipv4_pub(
3143 struct rte_mbuf **pkt,
3145 __rte_unused void *arg,
3146 struct pipeline_cgnapt *p_nat)
3148 p_nat->receivedPktCount += 4;
3149 /* bitmask representing only this packet */
3150 uint64_t pkt_mask0 = 1LLU << pkt_num;
3151 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
3152 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
3153 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
3155 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
3157 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
3159 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
3161 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
3164 uint32_t dst_addr0 = RTE_MBUF_METADATA_UINT32(pkt[0],
3166 uint32_t dst_addr1 = RTE_MBUF_METADATA_UINT32(pkt[1],
3168 uint32_t dst_addr2 = RTE_MBUF_METADATA_UINT32(pkt[2],
3170 uint32_t dst_addr3 = RTE_MBUF_METADATA_UINT32(pkt[3],
3173 uint16_t src_port_offset0;
3174 uint16_t src_port_offset1;
3175 uint16_t src_port_offset2;
3176 uint16_t src_port_offset3;
3178 uint16_t dst_port_offset0;
3179 uint16_t dst_port_offset1;
3180 uint16_t dst_port_offset2;
3181 uint16_t dst_port_offset3;
3193 struct pipeline_cgnapt_entry_key key0;
3194 struct pipeline_cgnapt_entry_key key1;
3195 struct pipeline_cgnapt_entry_key key2;
3196 struct pipeline_cgnapt_entry_key key3;
3198 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
3199 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
3200 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
3201 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
3204 #ifdef CGNAPT_DBG_PRNT
3205 if (CGNAPT_DEBUG > 4)
3210 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
3214 switch (protocol0) {
3215 case IP_PROTOCOL_UDP:
3216 case IP_PROTOCOL_TCP:
3218 src_port_offset0 = SRC_PRT_OFST_IP4_TCP;
3219 dst_port_offset0 = DST_PRT_OFST_IP4_TCP;
3221 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3223 dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3226 key0.port = rte_bswap16(dst_port0);
3230 case IP_PROTOCOL_ICMP:
3232 src_port_offset0 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3234 /*Sequence number */
3235 dst_port_offset0 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3238 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3240 dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3243 key0.port = rte_bswap16(src_port0);
3248 /* remember invalid packets to be dropped */
3249 p_nat->invalid_packets |= pkt_mask0;
3250 p_nat->naptDroppedPktCount++;
3252 #ifdef CGNAPT_DEBUGGING
3253 p_nat->naptDroppedPktCount2++;
3259 key0.ip = rte_bswap32(dst_addr0);
3261 #ifdef NAT_ONLY_CONFIG_REQ
3262 if (nat_only_config_flag)
3266 memcpy(&p_nat->keys[pkt_num], &key0,
3267 sizeof(struct pipeline_cgnapt_entry_key));
3268 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3273 #ifdef CGNAPT_DBG_PRNT
3274 if (CGNAPT_DEBUG > 4)
3279 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
3283 switch (protocol1) {
3284 case IP_PROTOCOL_UDP:
3285 case IP_PROTOCOL_TCP:
3287 src_port_offset1 = SRC_PRT_OFST_IP4_TCP;
3288 dst_port_offset1 = DST_PRT_OFST_IP4_TCP;
3290 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3292 dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3295 key1.port = rte_bswap16(dst_port1);
3299 case IP_PROTOCOL_ICMP:
3301 src_port_offset1 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3303 /*Sequence number */
3304 dst_port_offset1 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3307 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3309 dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3312 key1.port = rte_bswap16(src_port1);
3316 /* remember invalid packets to be dropped */
3317 p_nat->invalid_packets |= pkt_mask1;
3318 p_nat->naptDroppedPktCount++;
3320 #ifdef CGNAPT_DEBUGGING
3321 p_nat->naptDroppedPktCount2++;
3327 key1.ip = rte_bswap32(dst_addr1);
3329 #ifdef NAT_ONLY_CONFIG_REQ
3330 if (nat_only_config_flag)
3334 memcpy(&p_nat->keys[pkt_num + 1], &key1,
3335 sizeof(struct pipeline_cgnapt_entry_key));
3336 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
3340 #ifdef CGNAPT_DBG_PRNT
3341 if (CGNAPT_DEBUG > 4)
3346 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
3350 switch (protocol2) {
3351 case IP_PROTOCOL_UDP:
3352 case IP_PROTOCOL_TCP:
3354 src_port_offset2 = SRC_PRT_OFST_IP4_TCP;
3355 dst_port_offset2 = DST_PRT_OFST_IP4_TCP;
3357 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3359 dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3362 key2.port = rte_bswap16(dst_port2);
3366 case IP_PROTOCOL_ICMP:
3368 src_port_offset2 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3370 /*Sequence number */
3371 dst_port_offset2 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3374 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3376 dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3379 key2.port = rte_bswap16(src_port2);
3384 /* remember invalid packets to be dropped */
3385 p_nat->invalid_packets |= pkt_mask2;
3386 p_nat->naptDroppedPktCount++;
3388 #ifdef CGNAPT_DEBUGGING
3389 p_nat->naptDroppedPktCount2++;
3395 key2.ip = rte_bswap32(dst_addr2);
3397 #ifdef NAT_ONLY_CONFIG_REQ
3398 if (nat_only_config_flag)
3402 memcpy(&p_nat->keys[pkt_num + 2], &key2,
3403 sizeof(struct pipeline_cgnapt_entry_key));
3404 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
3408 #ifdef CGNAPT_DBG_PRNT
3409 if (CGNAPT_DEBUG > 4)
3414 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
3418 switch (protocol3) {
3419 case IP_PROTOCOL_UDP:
3420 case IP_PROTOCOL_TCP:
3422 src_port_offset3 = SRC_PRT_OFST_IP4_TCP;
3423 dst_port_offset3 = DST_PRT_OFST_IP4_TCP;
3425 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3427 dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3430 key3.port = rte_bswap16(dst_port3);
3434 case IP_PROTOCOL_ICMP:
3436 src_port_offset3 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3438 /*Sequence number */
3439 dst_port_offset3 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3442 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3444 dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3447 key3.port = rte_bswap16(src_port3);
3452 /* remember invalid packets to be dropped */
3453 p_nat->invalid_packets |= pkt_mask3;
3454 p_nat->naptDroppedPktCount++;
3456 #ifdef CGNAPT_DEBUGGING
3457 p_nat->naptDroppedPktCount2++;
3463 key3.ip = rte_bswap32(dst_addr3);
3465 #ifdef NAT_ONLY_CONFIG_REQ
3466 if (nat_only_config_flag)
3470 memcpy(&p_nat->keys[pkt_num + 3], &key3,
3471 sizeof(struct pipeline_cgnapt_entry_key));
3472 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
3476 * NAPT key calculation function for IPv4 private traffic
3477 * which handles 1 pkt
3480 * A pointer to array of packets mbuf
3482 * Pkt number of pkts
3486 * A pointer to main CGNAPT structure
3490 pkt_work_cgnapt_key_ipv4_prv(
3491 struct rte_mbuf *pkt,
3493 __rte_unused void *arg,
3494 struct pipeline_cgnapt *p_nat)
3497 p_nat->receivedPktCount++;
3499 /* bitmask representing only this packet */
3500 uint64_t pkt_mask = 1LLU << pkt_num;
3501 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3503 uint32_t src_addr = RTE_MBUF_METADATA_UINT32(pkt, SRC_ADR_OFST_IP4);
3505 uint16_t src_port_offset;
3509 uint16_t phy_port = pkt->port;
3510 struct pipeline_cgnapt_entry_key key;
3512 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
3515 #ifdef CGNAPT_DBG_PRNT
3516 if (CGNAPT_DEBUG > 4)
3521 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
3526 case IP_PROTOCOL_UDP:
3530 struct udp_hdr *udp;
3532 udp = (struct udp_hdr *)
3533 RTE_MBUF_METADATA_UINT8_PTR(pkt,
3536 if (rte_bswap16(udp->dst_port) ==
3538 handle_pcp_req(pkt, IPV4_SZ, p_nat);
3539 p_nat->invalid_packets |= pkt_mask;
3545 case IP_PROTOCOL_TCP:
3547 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3548 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3550 key.port = rte_bswap16(src_port);
3553 case IP_PROTOCOL_ICMP:
3555 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3557 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3559 key.port = rte_bswap16(src_port);
3563 /* remember invalid packets to be dropped */
3564 p_nat->invalid_packets |= pkt_mask;
3565 p_nat->naptDroppedPktCount++;
3567 #ifdef CGNAPT_DEBUGGING
3568 p_nat->naptDroppedPktCount2++;
3574 key.ip = rte_bswap32(src_addr);
3576 #ifdef NAT_ONLY_CONFIG_REQ
3577 if (nat_only_config_flag)
3581 memcpy(&p_nat->keys[pkt_num], &key,
3582 sizeof(struct pipeline_cgnapt_entry_key));
3583 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3587 * NAPT key calculation function for IPv4 public traffic
3588 * which handles 1 pkt
3591 * A pointer to array of packets mbuf
3593 * Pkt number of pkts
3597 * A pointer to main CGNAPT structure
3601 pkt_work_cgnapt_key_ipv4_pub(
3602 struct rte_mbuf *pkt,
3604 __rte_unused void *arg,
3605 struct pipeline_cgnapt *p_nat)
3607 p_nat->receivedPktCount++;
3609 /* bitmask representing only this packet */
3610 uint64_t pkt_mask = 1LLU << pkt_num;
3611 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3612 uint32_t dst_addr = RTE_MBUF_METADATA_UINT32(pkt, DST_ADR_OFST_IP4);
3613 uint16_t src_port_offset;
3614 uint16_t dst_port_offset;
3617 struct pipeline_cgnapt_entry_key key;
3618 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
3620 #ifdef CGNAPT_DBG_PRNT
3621 if (CGNAPT_DEBUG > 4)
3626 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
3631 case IP_PROTOCOL_UDP:
3632 case IP_PROTOCOL_TCP:
3633 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3634 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3636 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3637 dst_port = RTE_MBUF_METADATA_UINT16(pkt, dst_port_offset);
3639 key.port = rte_bswap16(dst_port);
3641 case IP_PROTOCOL_ICMP:
3643 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3645 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3648 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3649 dst_port = RTE_MBUF_METADATA_UINT16(pkt, dst_port_offset);
3651 /* common table lookupkey preparation from incoming
3652 * ICMP Packet- Indentifier field
3654 key.port = rte_bswap16(src_port);
3657 /* remember invalid packets to be dropped */
3658 p_nat->invalid_packets |= pkt_mask;
3659 p_nat->naptDroppedPktCount++;
3661 #ifdef CGNAPT_DEBUGGING
3662 p_nat->naptDroppedPktCount2++;
3667 key.ip = rte_bswap32(dst_addr);
3669 #ifdef NAT_ONLY_CONFIG_REQ
3670 if (nat_only_config_flag)
3676 memcpy(&p_nat->keys[pkt_num], &key,
3677 sizeof(struct pipeline_cgnapt_entry_key));
3678 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3683 * NAPT function for IPv4 private traffic which handles 1 pkt
3686 * A pointer to array of packet mbuf
3692 * A pointer to main CGNAPT structure
3695 uint64_t last_update;
3697 pkt_work_cgnapt_ipv4_prv(
3698 struct rte_mbuf **pkts,
3700 __rte_unused void *arg,
3701 struct pipeline_cgnapt *p_nat)
3704 struct rte_CT_helper ct_helper;
3705 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
3708 /* index into hash table entries */
3709 int hash_table_entry = p_nat->lkup_indx[pkt_num];
3710 /*bitmask representing only this packet */
3711 uint64_t pkt_mask = 1LLU << pkt_num;
3712 struct rte_mbuf *pkt = pkts[pkt_num];
3714 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3716 uint32_t dest_if = 0xff; /* Added for Multiport */
3717 uint16_t *outport_id =
3718 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
3720 struct cgnapt_table_entry *entry = NULL;
3722 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
3724 if (hash_table_entry < 0) {
3726 /* try to add new entry */
3727 struct rte_pipeline_table_entry *table_entry = NULL;
3729 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
3731 &p_nat->valid_packets, pkt_num,
3735 /* ICMP Error message generation for Destination
3738 if (protocol == IP_PROTOCOL_ICMP) {
3739 cgnapt_icmp_pkt = pkt;
3740 send_icmp_dest_unreachable_msg();
3743 /* Drop packet by adding to invalid pkt mask */
3745 p_nat->invalid_packets |= dropmask;
3746 #ifdef CGNAPT_DEBUGGING
3747 if (p_nat->kpc2++ < 5) {
3748 printf("in_ah Th: %d", p_nat->pipeline_num);
3749 print_key(p_nat->key_ptrs[pkt_num]);
3753 p_nat->naptDroppedPktCount++;
3755 #ifdef CGNAPT_DEBUGGING
3756 p_nat->naptDroppedPktCount3++;
3761 entry = (struct cgnapt_table_entry *)table_entry;
3763 /* entry found for this packet */
3764 entry = &napt_hash_tbl_entries[hash_table_entry];
3767 /* apply napt and mac changes */
3769 p_nat->entries[pkt_num] = &(entry->head);
3771 uint32_t *src_addr =
3772 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP4);
3773 uint32_t *dst_addr =
3774 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
3775 uint16_t src_port_offset = 0;
3776 uint16_t dst_port_offset = 0;
3781 case IP_PROTOCOL_TCP:
3782 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3783 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3784 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3785 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3788 if ((rte_be_to_cpu_16(*src_port) == 21) ||
3789 rte_be_to_cpu_16(*dst_port) == 21) {
3792 printf("cgnapt_ct_process: pkt_mask: % "PRIu64", "
3793 "pkt_num: %d\n", pkt_mask, pkt_num);
3796 pkt_mask = cgnapt_ct_process(cgnat_cnxn_tracker, pkts,
3797 pkt_mask, &ct_helper);
3801 case IP_PROTOCOL_UDP:
3802 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3803 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3804 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3805 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3807 case IP_PROTOCOL_ICMP:
3809 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3811 /*Sequence number */
3812 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3814 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3815 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3819 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
3820 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
3822 if (entry->data.ttl == NAPT_ENTRY_STALE)
3823 entry->data.ttl = NAPT_ENTRY_VALID;
3825 struct ether_addr hw_addr;
3826 uint32_t dest_address = 0;
3829 if (unlikely(protocol == IP_PROTOCOL_UDP
3830 && rte_be_to_cpu_16(*dst_port) == 53)) {
3831 p_nat->invalid_packets |= pkt_mask;
3832 p_nat->naptDroppedPktCount++;
3834 #ifdef CGNAPT_DEBUGGING
3835 p_nat->naptDroppedPktCount6++;
3839 last_update = rte_rdtsc();
3840 dest_address = rte_bswap32(*dst_addr);
3842 struct arp_entry_data *ret_arp_data = NULL;
3843 ret_arp_data = get_dest_mac_addr_port(dest_address,
3844 &dest_if, (struct ether_addr *)eth_dest);
3845 *outport_id = p_nat->outport_id[dest_if];
3847 if (arp_cache_dest_mac_present(dest_if)) {
3848 ether_addr_copy(get_link_hw_addr(dest_if),(struct ether_addr *)eth_src);
3849 update_nhip_access(dest_if);
3850 if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) {
3851 p_nat->naptedPktCount += ret_arp_data->num_pkts;
3852 arp_send_buffered_pkts(ret_arp_data,
3853 (struct ether_addr *)eth_dest, *outport_id);
3858 if (unlikely(ret_arp_data == NULL)) {
3860 #ifdef CGNAPT_DEBUGGING
3861 printf("%s: NHIP Not Found, nhip:%x , "
3862 "outport_id: %d\n", __func__, nhip,
3867 p_nat->invalid_packets |= pkt_mask;
3868 p_nat->naptDroppedPktCount++;
3870 #ifdef CGNAPT_DEBUGGING
3871 p_nat->naptDroppedPktCount4++;
3876 if (ret_arp_data->status == INCOMPLETE ||
3877 ret_arp_data->status == PROBE) {
3878 if (ret_arp_data->num_pkts >= NUM_DESC) {
3880 p_nat->invalid_packets |= pkt_mask;
3881 p_nat->naptDroppedPktCount++;
3883 #ifdef CGNAPT_DEBUGGING
3884 p_nat->naptDroppedPktCount4++;
3888 arp_pkts_mask |= pkt_mask;
3889 arp_queue_unresolved_packet(ret_arp_data, pkt);
3898 *src_addr = rte_bswap32(entry->data.pub_ip);
3901 #ifdef NAT_ONLY_CONFIG_REQ
3902 if (!nat_only_config_flag) {
3904 *src_port = rte_bswap16(entry->data.pub_port);
3905 #ifdef NAT_ONLY_CONFIG_REQ
3910 uint16_t rtp_port = 0, rtcp_port = 0;
3911 struct cgnapt_table_entry *entry_ptr1 = NULL,
3912 *entry_ptr2 = NULL, *entry_ptr3 = NULL,
3915 if (unlikely(protocol == IP_PROTOCOL_UDP
3916 && (rte_be_to_cpu_16(*dst_port) == 5060
3917 || rte_be_to_cpu_16(*src_port) == 5060))) {
3919 int ret = natSipAlgGetAudioPorts(pkt, &rtp_port,
3921 /* Commented code may be required for debug
3922 * and future use, Please keep it*/
3925 printf("%s: Wrong SIP ALG packet1\n",
3927 p_nat->invalid_packets |= pkt_mask;
3929 p_nat->naptDroppedPktCount++;
3931 #ifdef CGNAPT_DEBUGGING
3932 p_nat->naptDroppedPktCount4++;
3938 if (ret >= 0 && rtp_port != 0) {
3939 struct pipeline_cgnapt_entry_key rtp_key;
3940 rtp_key.ip = entry->data.u.prv_ip;
3941 rtp_key.port = rtp_port;
3942 rtp_key.pid = entry->data.prv_phy_port;
3944 if (add_dynamic_cgnapt_entry_alg(
3945 (struct pipeline *)p_nat, &rtp_key,
3946 &entry_ptr1, &entry_ptr2) == 0) {
3947 printf("%s: Wrong SIP ALG packet2\n",
3949 p_nat->invalid_packets |= pkt_mask;
3951 p_nat->naptDroppedPktCount++;
3953 #ifdef CGNAPT_DEBUGGING
3954 p_nat->naptDroppedPktCount4++;
3960 if (ret >= 0 && rtcp_port != 0) {
3961 struct pipeline_cgnapt_entry_key rtcp_key;
3962 rtcp_key.ip = entry->data.u.prv_ip;
3963 rtcp_key.port = rtcp_port;
3964 rtcp_key.pid = entry->data.prv_phy_port;
3966 if (add_dynamic_cgnapt_entry_alg(
3967 (struct pipeline *)p_nat, &rtcp_key,
3968 &entry_ptr3, &entry_ptr4) == 0) {
3969 printf("%s: Wrong SIP ALG packet3\n",
3971 p_nat->invalid_packets |= pkt_mask;
3973 p_nat->naptDroppedPktCount++;
3975 #ifdef CGNAPT_DEBUGGING
3976 p_nat->naptDroppedPktCount4++;
3982 //if(entry_ptr1 != NULL && entry_ptr3 != NULL)
3983 if (sip_alg_dpi(pkt, PRIVATE, entry->data.pub_ip,
3984 entry->data.pub_port, entry->data.u.prv_ip,
3985 entry->data.prv_port, (rtp_port == 0) ? 0 :
3986 entry_ptr1->data.pub_port,
3987 (rtcp_port == 0) ? 0 :
3988 entry_ptr3->data.pub_port) == 0) {
3990 printf("%s: Wrong SIP ALG packet4\n",
3992 p_nat->invalid_packets |= pkt_mask;
3994 p_nat->naptDroppedPktCount++;
3996 #ifdef CGNAPT_DEBUGGING
3997 p_nat->naptDroppedPktCount4++;
4002 #endif /* SIP_ALG */
4007 printf("@CGNAT-pktwork ct_position :%d, pkt_num %d pkt_mask= "
4008 "%" PRIu64 "\n", ct_position, pkt_num, pkt_mask);
4011 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4012 rte_be_to_cpu_16(*dst_port) == 21) {
4014 int32_t ct_position = cgnat_cnxn_tracker->positions[pkt_num];
4015 if (ct_position < 0){
4016 p_nat->invalid_packets |= pkt_mask;
4017 p_nat->naptDroppedPktCount++;
4020 /* Commented code may be required for future usage,
4023 //if (cgnat_cnxn_tracker->hash_table_entries
4024 // [ct_position].alg_bypass_flag != BYPASS)
4026 struct pipeline_cgnapt_entry_key data_channel_entry_key;
4028 data_channel_entry_key.ip = entry->data.pub_ip;
4029 data_channel_entry_key.port = entry->data.pub_port;
4030 data_channel_entry_key.pid = pkt->port;
4031 ftp_alg_dpi(p_nat, &data_channel_entry_key, pkt,
4032 cgnat_cnxn_tracker, ct_position, PRIVATE);
4035 #endif /* FTP_ALG */
4037 p_nat->enaptedPktCount++;
4040 p_nat->naptedPktCount++;
4043 if (p_nat->hw_checksum_reqd)
4044 hw_checksum(pkt, pkt_type);
4046 sw_checksum(pkt, pkt_type);
4053 * NAPT function for IPv4 public traffic which handles 1 pkt
4056 * A pointer to array of packet mbuf
4062 * A pointer to main CGNAPT structure
4066 pkt_work_cgnapt_ipv4_pub(
4067 struct rte_mbuf **pkts,
4069 __rte_unused void *arg,
4070 struct pipeline_cgnapt *p_nat)
4074 struct rte_CT_helper ct_helper;
4075 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4078 /* index into hash table entries */
4079 int hash_table_entry = p_nat->lkup_indx[pkt_num];
4080 /*bitmask representing only this packet */
4081 uint64_t pkt_mask = 1LLU << pkt_num;
4082 struct rte_mbuf *pkt = pkts[pkt_num];
4084 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
4086 uint32_t dest_if = 0xff; /* Added for Multiport */
4087 uint16_t *outport_id =
4088 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
4090 struct cgnapt_table_entry *entry = NULL;
4092 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4094 if (hash_table_entry < 0) {
4096 /* try to add new entry */
4097 struct rte_pipeline_table_entry *table_entry = NULL;
4099 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
4101 &p_nat->valid_packets, pkt_num,
4105 /* ICMP Error message generation for
4106 * Destination Host unreachable
4108 if (protocol == IP_PROTOCOL_ICMP) {
4109 cgnapt_icmp_pkt = pkt;
4110 send_icmp_dest_unreachable_msg();
4113 /* Drop packet by adding to invalid pkt mask */
4115 p_nat->invalid_packets |= dropmask;
4116 #ifdef CGNAPT_DEBUGGING
4117 if (p_nat->kpc2++ < 5) {
4118 printf("in_ah Th: %d", p_nat->pipeline_num);
4119 print_key(p_nat->key_ptrs[pkt_num]);
4123 p_nat->naptDroppedPktCount++;
4125 #ifdef CGNAPT_DEBUGGING
4126 p_nat->naptDroppedPktCount3++;
4131 entry = (struct cgnapt_table_entry *)table_entry;
4133 /* entry found for this packet */
4134 entry = &napt_hash_tbl_entries[hash_table_entry];
4137 /* apply napt and mac changes */
4139 p_nat->entries[pkt_num] = &(entry->head);
4141 uint32_t *dst_addr =
4142 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4143 uint16_t src_port_offset = 0;
4144 uint16_t dst_port_offset = 0;
4146 if ((protocol == IP_PROTOCOL_TCP) || (protocol == IP_PROTOCOL_UDP)) {
4147 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4148 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4149 } else if (protocol == IP_PROTOCOL_ICMP) {
4151 src_port_offset = MBUF_HDR_ROOM +
4154 /*Sequence number */
4155 dst_port_offset = MBUF_HDR_ROOM +
4160 uint16_t *src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
4161 uint16_t *dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
4163 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4164 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4166 if (entry->data.ttl == NAPT_ENTRY_STALE)
4167 entry->data.ttl = NAPT_ENTRY_VALID;
4169 struct ether_addr hw_addr;
4170 uint32_t dest_address = 0;
4172 /* Multiport Changes */
4178 if (unlikely(protocol == IP_PROTOCOL_UDP
4179 && rte_be_to_cpu_16(*src_port) == 53)) {
4180 p_nat->invalid_packets |= pkt_mask;
4181 p_nat->naptDroppedPktCount++;
4182 #ifdef CGNAPT_DEBUGGING
4183 p_nat->naptDroppedPktCount6++;
4189 dest_address = entry->data.u.prv_ip;
4190 struct arp_entry_data *ret_arp_data = NULL;
4191 ret_arp_data = get_dest_mac_addr_port(dest_address,
4192 &dest_if, (struct ether_addr *)eth_dest);
4193 *outport_id = p_nat->outport_id[dest_if];
4195 if (arp_cache_dest_mac_present(dest_if)) {
4196 ether_addr_copy(get_link_hw_addr(dest_if), (struct ether_addr *)eth_src);
4197 update_nhip_access(dest_if);
4199 if (ret_arp_data && ret_arp_data->num_pkts) {
4200 p_nat->naptedPktCount += ret_arp_data->num_pkts;
4201 arp_send_buffered_pkts(ret_arp_data,
4202 (struct ether_addr *)eth_dest, *outport_id);
4207 if (unlikely(ret_arp_data == NULL)) {
4209 /* Commented code may be required for debug
4210 * and future use, Please keep it */
4212 #ifdef CGNAPT_DEBUGGING
4213 printf("%s: NHIP Not Found, nhip: %x, "
4214 "outport_id: %d\n", __func__, nhip,
4219 p_nat->invalid_packets |= pkt_mask;
4220 p_nat->naptDroppedPktCount++;
4222 #ifdef CGNAPT_DEBUGGING
4223 p_nat->naptDroppedPktCount4++;
4229 if (ret_arp_data->status == INCOMPLETE ||
4230 ret_arp_data->status == PROBE) {
4231 if (ret_arp_data->num_pkts >= NUM_DESC) {
4233 p_nat->invalid_packets |= pkt_mask;
4234 p_nat->naptDroppedPktCount++;
4236 #ifdef CGNAPT_DEBUGGING
4237 p_nat->naptDroppedPktCount4++;
4241 arp_pkts_mask |= pkt_mask;
4242 arp_queue_unresolved_packet(ret_arp_data, pkt);
4251 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
4252 if (protocol == IP_PROTOCOL_ICMP) {
4253 /* Query ID reverse translation done here */
4254 /* dont care sequence num */
4255 *src_port = rte_bswap16(entry->data.prv_port);
4258 #ifdef NAT_ONLY_CONFIG_REQ
4259 if (!nat_only_config_flag) {
4261 *dst_port = rte_bswap16(entry->data.prv_port);
4263 #ifdef NAT_ONLY_CONFIG_REQ
4267 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4268 rte_be_to_cpu_16(*dst_port) == 21) {
4269 pkt_mask = cgnapt_ct_process(cgnat_cnxn_tracker, pkts,
4270 pkt_mask, &ct_helper);
4276 uint16_t rtp_port = 0, rtcp_port = 0;
4277 struct cgnapt_table_entry *entry_ptr1 = NULL,
4280 /* Commented code may be required for debug
4281 * and future use, Please keep it */
4283 struct cgnapt_table_entry *entry_ptr2 = NULL,
4287 if (unlikely(protocol == IP_PROTOCOL_UDP
4288 && (rte_be_to_cpu_16(*dst_port) == 5060
4289 || rte_be_to_cpu_16(*src_port) == 5060))) {
4290 /* Commented code may be required for future usage,
4294 int ret = natSipAlgGetAudioPorts(pkt, &rtp_port,
4297 printf("%s: Wrong SIP ALG packet1\n",
4299 p_nat->invalid_packets |= pkt_mask;
4301 p_nat->naptDroppedPktCount++;
4303 #ifdef CGNAPT_DEBUGGING
4304 p_nat->naptDroppedPktCount4++;
4308 if (rtp_port != 0) {
4309 struct pipeline_cgnapt_entry_key rtp_key;
4310 rtp_key.ip = entry->data.pub_ip;
4311 rtp_key.port = rtp_port;
4312 rtp_key.pid = 0xffff;
4314 if (retrieve_cgnapt_entry_alg(&rtp_key,
4315 &entry_ptr1, &entry_ptr2) == 0) {
4316 printf("%s: Wrong SIP ALG packet2\n",
4318 p_nat->invalid_packets |= pkt_mask;
4320 p_nat->naptDroppedPktCount++;
4322 #ifdef CGNAPT_DEBUGGING
4323 p_nat->naptDroppedPktCount4++;
4329 if (rtcp_port != 0) {
4330 struct pipeline_cgnapt_entry_key rtcp_key;
4331 rtcp_key.ip = entry->data.pub_ip;
4332 rtcp_key.port = rtcp_port;
4333 rtcp_key.pid = 0xffff;
4335 if (retrieve_cgnapt_entry_alg(&rtcp_key,
4336 &entry_ptr3, &entry_ptr4) == 0) {
4337 printf("%s: Wrong SIP ALG packet3\n",
4339 p_nat->invalid_packets |= pkt_mask;
4341 p_nat->naptDroppedPktCount++;
4343 #ifdef CGNAPT_DEBUGGING
4344 p_nat->naptDroppedPktCount4++;
4352 if (sip_alg_dpi(pkt, PUBLIC, entry->data.u.prv_ip,
4353 entry->data.prv_port, entry->data.pub_ip,
4354 entry->data.pub_port, (rtp_port == 0) ? 0 :
4355 entry_ptr1->data.prv_port,
4356 (rtcp_port == 0) ? 0 :
4357 entry_ptr3->data.prv_port) == 0) {
4359 printf("%s: Wrong SIP ALG packet4\n",
4361 p_nat->invalid_packets |= pkt_mask;
4363 p_nat->naptDroppedPktCount++;
4365 #ifdef CGNAPT_DEBUGGING
4366 p_nat->naptDroppedPktCount4++;
4372 #endif /* SIP_ALG */
4375 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4376 rte_be_to_cpu_16(*dst_port) == 21) {
4377 int32_t ct_position = cgnat_cnxn_tracker->
4379 if (ct_position < 0){
4380 p_nat->invalid_packets |= pkt_mask;
4382 p_nat->naptDroppedPktCount++;
4386 rte_hexdump(stdout, "CT Entry", &cgnat_cnxn_tracker->
4387 hash_table_entries[ct_position].key, 40);
4390 /* Commented code may be required for debug
4391 * and future use, Please keep it*/
4392 //if (cgnat_cnxn_tracker->hash_table_entries
4393 // [ct_position].alg_bypass_flag != BYPASS)
4396 struct pipeline_cgnapt_entry_key
4397 data_channel_entry_key;
4399 data_channel_entry_key.ip = entry->data.pub_ip;
4400 data_channel_entry_key.port = entry->data.pub_port;
4401 data_channel_entry_key.pid = 0xffff;
4402 //printf("pkt_work_pub ftp_alg_dpi\n");
4403 ftp_alg_dpi(p_nat, &data_channel_entry_key, pkt,
4404 cgnat_cnxn_tracker, ct_position, PUBLIC);
4410 p_nat->inaptedPktCount++;
4413 p_nat->naptedPktCount++;
4416 if (p_nat->hw_checksum_reqd)
4417 hw_checksum(pkt, pkt_type);
4419 sw_checksum(pkt, pkt_type);
4425 * NAPT function for IPv4 private traffic which handles 4 pkts
4428 * A pointer to array of packets mbuf
4430 * Starting pkt number of pkts
4434 * A pointer to main CGNAPT structure
4438 pkt4_work_cgnapt_ipv4_prv(
4439 struct rte_mbuf **pkts,
4440 uint32_t in_pkt_num,
4441 __rte_unused void *arg,
4442 struct pipeline_cgnapt *p_nat)
4444 uint32_t dest_if = 0xff; /* Added for Multiport */
4445 struct rte_mbuf *pkt;
4448 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4451 struct rte_CT_helper ct_helper;
4452 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4455 for (i = 0; i < 4; i++) {
4456 pkt_num = in_pkt_num + i;
4457 pkt = pkts[pkt_num];
4459 /* index into hash table entries */
4460 int hash_table_entry = p_nat->lkup_indx[pkt_num];
4461 /*bitmask representing only this packet */
4462 uint64_t pkt_mask = 1LLU << pkt_num;
4464 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
4466 uint16_t *outport_id =
4467 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
4469 struct cgnapt_table_entry *entry = NULL;
4471 if (hash_table_entry < 0) {
4473 /* try to add new entry */
4474 struct rte_pipeline_table_entry *table_entry = NULL;
4477 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
4479 &p_nat->valid_packets, pkt_num,
4483 /* ICMP Error message generation for
4484 * Destination Host unreachable
4486 if (protocol == IP_PROTOCOL_ICMP) {
4487 cgnapt_icmp_pkt = pkt;
4488 send_icmp_dest_unreachable_msg();
4491 /* Drop packet by adding to invalid pkt mask */
4493 p_nat->invalid_packets |= dropmask;
4495 #ifdef CGNAPT_DEBUGGING
4496 if (p_nat->kpc2++ < 5) {
4497 printf("in_ah Th: %d",
4498 p_nat->pipeline_num);
4499 print_key(p_nat->key_ptrs[pkt_num]);
4503 p_nat->naptDroppedPktCount++;
4505 #ifdef CGNAPT_DEBUGGING
4506 p_nat->naptDroppedPktCount3++;
4511 entry = (struct cgnapt_table_entry *)table_entry;
4513 /* entry found for this packet */
4514 entry = &napt_hash_tbl_entries[hash_table_entry];
4517 /* apply napt and mac changes */
4519 p_nat->entries[pkt_num] = &(entry->head);
4521 uint32_t *src_addr =
4522 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP4);
4523 uint32_t *dst_addr =
4524 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4525 uint16_t src_port_offset = 0;
4526 uint16_t dst_port_offset = 0;
4531 if ((protocol == IP_PROTOCOL_TCP)
4532 || (protocol == IP_PROTOCOL_UDP)) {
4533 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4534 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4535 } else if (protocol == IP_PROTOCOL_ICMP) {
4537 src_port_offset = MBUF_HDR_ROOM +
4540 /*Sequence number */
4541 dst_port_offset = MBUF_HDR_ROOM +
4548 case IP_PROTOCOL_TCP:
4549 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4550 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4551 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4553 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4557 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4558 rte_be_to_cpu_16(*dst_port) == 21) {
4560 //To process CT , pkt_mask does it need
4561 //to be complemented ??
4563 printf("cgnapt_ct_process: pkt_mask: "
4564 "% "PRIu64", pkt_num: %d\n",
4568 pkt_mask = cgnapt_ct_process(
4569 cgnat_cnxn_tracker, pkts,
4570 pkt_mask, &ct_helper);
4574 case IP_PROTOCOL_UDP:
4575 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4576 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4577 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4579 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4582 case IP_PROTOCOL_ICMP:
4584 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
4586 /*Sequence number */
4587 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
4589 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4591 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4598 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4600 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4602 if (entry->data.ttl == NAPT_ENTRY_STALE)
4603 entry->data.ttl = NAPT_ENTRY_VALID;
4605 struct ether_addr hw_addr;
4606 uint32_t dest_address = 0;
4607 /*Multiport Changes */
4614 if (unlikely(protocol == IP_PROTOCOL_UDP
4615 && rte_be_to_cpu_16(*dst_port) == 53)) {
4616 p_nat->invalid_packets |= pkt_mask;
4617 p_nat->naptDroppedPktCount++;
4619 #ifdef CGNAPT_DEBUGGING
4620 p_nat->naptDroppedPktCount6++;
4626 dest_address = rte_bswap32(*dst_addr);
4627 struct arp_entry_data *ret_arp_data = NULL;
4628 uint64_t start, end;
4629 ret_arp_data = get_dest_mac_addr_port(dest_address,
4630 &dest_if, (struct ether_addr *)eth_dest);
4631 *outport_id = p_nat->outport_id[dest_if];
4632 if (arp_cache_dest_mac_present(dest_if)) {
4633 ether_addr_copy(get_link_hw_addr(dest_if),
4634 (struct ether_addr *)eth_src);
4635 update_nhip_access(dest_if);
4637 if (ret_arp_data && ret_arp_data->num_pkts) {
4638 p_nat->naptedPktCount += ret_arp_data->num_pkts;
4639 arp_send_buffered_pkts(ret_arp_data,
4640 (struct ether_addr *)eth_dest, *outport_id);
4645 if (unlikely(ret_arp_data == NULL)) {
4647 #ifdef CGNAPT_DEBUGGING
4648 printf("%s: ARP Not Found, nhip: %x, "
4649 "outport_id: %d\n", __func__, nhip,
4654 p_nat->invalid_packets |= pkt_mask;
4655 p_nat->naptDroppedPktCount++;
4657 #ifdef CGNAPT_DEBUGGING
4658 p_nat->naptDroppedPktCount4++;
4664 if (ret_arp_data->status == INCOMPLETE ||
4665 ret_arp_data->status == PROBE) {
4666 if (ret_arp_data->num_pkts >= NUM_DESC) {
4668 p_nat->invalid_packets |= pkt_mask;
4669 p_nat->naptDroppedPktCount++;
4671 #ifdef CGNAPT_DEBUGGING
4672 p_nat->naptDroppedPktCount4++;
4676 arp_pkts_mask |= pkt_mask;
4677 arp_queue_unresolved_packet(ret_arp_data, pkt);
4685 *src_addr = rte_bswap32(entry->data.pub_ip);
4687 #ifdef NAT_ONLY_CONFIG_REQ
4688 if (!nat_only_config_flag) {
4690 *src_port = rte_bswap16(entry->data.pub_port);
4691 #ifdef NAT_ONLY_CONFIG_REQ
4696 uint16_t rtp_port = 0, rtcp_port = 0;
4697 struct cgnapt_table_entry *entry_ptr1 = NULL,
4698 *entry_ptr2 = NULL, *entry_ptr3 = NULL,
4701 if (unlikely(protocol == IP_PROTOCOL_UDP
4702 && (rte_be_to_cpu_16(*dst_port) == 5060
4703 || rte_be_to_cpu_16(*src_port) == 5060))) {
4705 int ret = natSipAlgGetAudioPorts(pkt,
4706 &rtp_port, &rtcp_port);
4707 /* Commented code may be required for future usage,
4712 printf("%s: Wrong SIP ALG packet1\n",
4714 p_nat->invalid_packets |= pkt_mask;
4716 p_nat->naptDroppedPktCount++;
4718 #ifdef CGNAPT_DEBUGGING
4719 p_nat->naptDroppedPktCount4++;
4725 if (ret >= 0 && rtp_port != 0) {
4726 struct pipeline_cgnapt_entry_key rtp_key;
4727 rtp_key.ip = entry->data.u.prv_ip;
4728 rtp_key.port = rtp_port;
4729 rtp_key.pid = entry->data.prv_phy_port;
4731 if (add_dynamic_cgnapt_entry_alg(
4732 (struct pipeline *)p_nat, &rtp_key,
4733 &entry_ptr1, &entry_ptr2) == 0) {
4734 printf("%s: Wrong SIP ALG packet2\n",
4736 p_nat->invalid_packets |= pkt_mask;
4738 p_nat->naptDroppedPktCount++;
4740 #ifdef CGNAPT_DEBUGGING
4741 p_nat->naptDroppedPktCount4++;
4747 if (ret >= 0 && rtcp_port != 0) {
4748 struct pipeline_cgnapt_entry_key rtcp_key;
4749 rtcp_key.ip = entry->data.u.prv_ip;
4750 rtcp_key.port = rtcp_port;
4751 rtcp_key.pid = entry->data.prv_phy_port;
4753 if (add_dynamic_cgnapt_entry_alg(
4754 (struct pipeline *)p_nat, &rtcp_key,
4755 &entry_ptr3, &entry_ptr4) == 0) {
4757 printf("%s: Wrong SIP ALG packet3\n",
4759 p_nat->invalid_packets |= pkt_mask;
4761 p_nat->naptDroppedPktCount++;
4763 #ifdef CGNAPT_DEBUGGING
4764 p_nat->naptDroppedPktCount4++;
4770 //if(entry_ptr1 != NULL && entry_ptr3 != NULL)
4771 if (sip_alg_dpi(pkt, PRIVATE,
4773 entry->data.pub_port,
4774 entry->data.u.prv_ip,
4775 entry->data.prv_port,
4776 (rtp_port == 0) ? 0 :
4777 entry_ptr1->data.pub_port,
4778 (rtcp_port == 0) ? 0 :
4779 entry_ptr3->data.pub_port) == 0) {
4781 printf("%s: Wrong SIP ALG packet4\n",
4783 p_nat->invalid_packets |= pkt_mask;
4785 p_nat->naptDroppedPktCount++;
4787 #ifdef CGNAPT_DEBUGGING
4788 p_nat->naptDroppedPktCount4++;
4793 #endif /* SIP_ALG */
4796 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4797 rte_be_to_cpu_16(*dst_port) == 21) {
4799 int32_t ct_position =
4800 cgnat_cnxn_tracker->positions[pkt_num];
4802 printf("@CGNAT-pkt4work ct_position :%d, pkt_num %d "
4803 "pkt_mask = %" PRIu64 "\n", ct_position,
4807 if (ct_position < 0){
4808 p_nat->invalid_packets |= pkt_mask;
4809 p_nat->naptDroppedPktCount++;
4812 if (cgnat_cnxn_tracker->hash_table_entries[ct_position].
4813 alg_bypass_flag != BYPASS){
4815 struct pipeline_cgnapt_entry_key
4816 data_channel_entry_key;
4818 data_channel_entry_key.ip =
4820 data_channel_entry_key.port =
4821 entry->data.pub_port;
4822 data_channel_entry_key.pid = 0xffff;
4824 ftp_alg_dpi(p_nat, &data_channel_entry_key,
4825 pkt, cgnat_cnxn_tracker, ct_position,
4831 p_nat->enaptedPktCount++;
4834 p_nat->naptedPktCount++;
4837 if (p_nat->hw_checksum_reqd)
4838 hw_checksum(pkt, pkt_type);
4840 sw_checksum(pkt, pkt_type);
4846 * NAPT function for IPv4 public traffic which handles 4 pkts
4849 * A pointer to array of packets mbuf
4851 * Starting pkt number of pkts
4855 * A pointer to main CGNAPT structure
4859 pkt4_work_cgnapt_ipv4_pub(
4860 struct rte_mbuf **pkts,
4861 uint32_t in_pkt_num,
4862 __rte_unused void *arg,
4863 struct pipeline_cgnapt *p_nat)
4866 struct rte_CT_helper ct_helper;
4867 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4869 struct rte_mbuf *pkt;
4872 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4874 for (i = 0; i < 4; i++) {
4875 pkt_num = in_pkt_num + i;
4876 pkt = pkts[pkt_num];
4878 /* index into hash table entries */
4879 int hash_table_entry = p_nat->lkup_indx[pkt_num];
4880 /*bitmask representing only this packet */
4881 uint64_t pkt_mask = 1LLU << pkt_num;
4883 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
4885 uint32_t dest_if = 0xff; /* Added for Multiport */
4886 uint16_t *outport_id =
4887 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
4889 struct cgnapt_table_entry *entry = NULL;
4891 if (hash_table_entry < 0) {
4893 /* try to add new entry */
4894 struct rte_pipeline_table_entry *table_entry = NULL;
4897 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
4899 &p_nat->valid_packets, pkt_num,
4903 /* ICMP Error message generation for
4904 * Destination Host unreachable
4906 if (protocol == IP_PROTOCOL_ICMP) {
4907 cgnapt_icmp_pkt = pkt;
4908 send_icmp_dest_unreachable_msg();
4911 /* Drop packet by adding to invalid pkt mask */
4913 p_nat->invalid_packets |= dropmask;
4915 #ifdef CGNAPT_DEBUGGING
4916 if (p_nat->kpc2++ < 5) {
4917 printf("in_ah Th: %d",
4918 p_nat->pipeline_num);
4919 print_key(p_nat->key_ptrs[pkt_num]);
4923 p_nat->naptDroppedPktCount++;
4925 #ifdef CGNAPT_DEBUGGING
4926 p_nat->naptDroppedPktCount3++;
4931 entry = (struct cgnapt_table_entry *)table_entry;
4933 /* entry found for this packet */
4934 entry = &napt_hash_tbl_entries[hash_table_entry];
4937 /* apply napt and mac changes */
4939 p_nat->entries[pkt_num] = &(entry->head);
4941 uint32_t *dst_addr =
4942 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4943 uint16_t src_port_offset = 0;
4944 uint16_t dst_port_offset = 0;
4946 if ((protocol == IP_PROTOCOL_TCP)
4947 || (protocol == IP_PROTOCOL_UDP)) {
4948 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4949 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4950 } else if (protocol == IP_PROTOCOL_ICMP) {
4952 src_port_offset = MBUF_HDR_ROOM +
4955 /*Sequence number */
4956 dst_port_offset = MBUF_HDR_ROOM +
4961 uint16_t *src_port =
4962 RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
4963 uint16_t *dst_port =
4964 RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
4967 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4969 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4971 if (entry->data.ttl == NAPT_ENTRY_STALE)
4972 entry->data.ttl = NAPT_ENTRY_VALID;
4974 struct ether_addr hw_addr;
4975 uint32_t dest_address = 0;
4976 /* Multiport Changes */
4982 if (unlikely(protocol == IP_PROTOCOL_UDP
4983 && rte_be_to_cpu_16(*src_port) == 53)) {
4984 p_nat->invalid_packets |= pkt_mask;
4985 p_nat->naptDroppedPktCount++;
4986 #ifdef CGNAPT_DEBUGGING
4987 p_nat->naptDroppedPktCount6++;
4992 dest_address = entry->data.u.prv_ip;
4993 struct arp_entry_data *ret_arp_data = NULL;
4994 ret_arp_data = get_dest_mac_addr_port(dest_address,
4995 &dest_if, (struct ether_addr *)eth_dest);
4996 *outport_id = p_nat->outport_id[dest_if];
4998 if (arp_cache_dest_mac_present(dest_if)) {
4999 ether_addr_copy(get_link_hw_addr(dest_if), (struct ether_addr *)eth_src);
5000 update_nhip_access(dest_if);
5002 if (ret_arp_data && ret_arp_data->num_pkts) {
5003 p_nat->naptedPktCount += ret_arp_data->num_pkts;
5004 arp_send_buffered_pkts(ret_arp_data,
5005 (struct ether_addr *)eth_dest, *outport_id);
5010 if (unlikely(ret_arp_data == NULL)) {
5012 #ifdef CGNAPT_DEBUGGING
5013 printf("%s: NHIP Not Found, nhip: %x, "
5014 "outport_id: %d\n", __func__, nhip,
5019 p_nat->invalid_packets |= pkt_mask;
5020 p_nat->naptDroppedPktCount++;
5022 #ifdef CGNAPT_DEBUGGING
5023 p_nat->naptDroppedPktCount4++;
5028 if (ret_arp_data->status == INCOMPLETE ||
5029 ret_arp_data->status == PROBE) {
5030 if (ret_arp_data->num_pkts >= NUM_DESC) {
5032 p_nat->invalid_packets |= pkt_mask;
5033 p_nat->naptDroppedPktCount++;
5035 #ifdef CGNAPT_DEBUGGING
5036 p_nat->naptDroppedPktCount4++;
5040 arp_pkts_mask |= pkt_mask;
5041 arp_queue_unresolved_packet(ret_arp_data, pkt);
5050 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
5051 if (protocol == IP_PROTOCOL_ICMP) {
5052 /* Query ID reverse translation done here */
5053 *src_port = rte_bswap16(entry->data.prv_port);
5054 /* dont care sequence num */
5056 #ifdef NAT_ONLY_CONFIG_REQ
5057 if (!nat_only_config_flag) {
5060 rte_bswap16(entry->data.prv_port);
5061 #ifdef NAT_ONLY_CONFIG_REQ
5066 if ((rte_be_to_cpu_16(*src_port) == 21) ||
5067 rte_be_to_cpu_16(*dst_port) == 21) {
5068 pkt_mask = cgnapt_ct_process(
5069 cgnat_cnxn_tracker, pkts,
5070 pkt_mask, &ct_helper);
5076 uint16_t rtp_port = 0, rtcp_port = 0;
5077 struct cgnapt_table_entry *entry_ptr1 = NULL,
5079 /* Commented code may be required for future usage,
5083 struct cgnapt_table_entry *entry_ptr2 = NULL,
5087 if (unlikely(protocol == IP_PROTOCOL_UDP
5088 && (rte_be_to_cpu_16(*dst_port) == 5060
5089 || rte_be_to_cpu_16(*src_port) == 5060))) {
5090 /* Commented code may be required for future usage,
5094 int ret = natSipAlgGetAudioPorts(pkt,
5095 &rtp_port, &rtcp_port);
5097 printf("%s: Wrong SIP ALG packet1\n",
5099 p_nat->invalid_packets |= pkt_mask;
5101 p_nat->naptDroppedPktCount++;
5103 #ifdef CGNAPT_DEBUGGING
5104 p_nat->naptDroppedPktCount4++;
5109 if (rtp_port != 0) {
5110 struct pipeline_cgnapt_entry_key rtp_key;
5111 rtp_key.ip = entry->data.pub_ip;
5112 rtp_key.port = rtp_port;
5113 rtp_key.pid = 0xffff;
5115 if (retrieve_cgnapt_entry_alg(&rtp_key,
5116 &entry_ptr1, &entry_ptr2) == 0) {
5117 printf("%s: Wrong SIP ALG packet2\n",
5119 p_nat->invalid_packets |= pkt_mask;
5121 p_nat->naptDroppedPktCount++;
5123 #ifdef CGNAPT_DEBUGGING
5124 p_nat->naptDroppedPktCount4++;
5130 if (rtcp_port != 0) {
5131 struct pipeline_cgnapt_entry_key rtcp_key;
5132 rtcp_key.ip = entry->data.pub_ip;
5133 rtcp_key.port = rtcp_port;
5134 rtcp_key.pid = 0xffff;
5136 if (retrieve_cgnapt_entry_alg(&rtcp_key,
5137 &entry_ptr3, &entry_ptr4) == 0) {
5138 printf("%s: Wrong SIP ALG packet3\n",
5140 p_nat->invalid_packets |= pkt_mask;
5141 p_nat->naptDroppedPktCount++;
5143 #ifdef CGNAPT_DEBUGGING
5144 p_nat->naptDroppedPktCount4++;
5151 if (sip_alg_dpi(pkt, PUBLIC,
5152 entry->data.u.prv_ip,
5153 entry->data.prv_port,
5155 entry->data.pub_port,
5156 (rtp_port == 0) ? 0 :
5157 entry_ptr1->data.prv_port,
5158 (rtcp_port == 0) ? 0 :
5159 entry_ptr3->data.prv_port) == 0) {
5161 printf("%s: Wrong SIP ALG packet4\n",
5163 p_nat->invalid_packets |= pkt_mask;
5165 p_nat->naptDroppedPktCount++;
5167 #ifdef CGNAPT_DEBUGGING
5168 p_nat->naptDroppedPktCount4++;
5173 #endif /* SIP_ALG */
5176 if ((rte_be_to_cpu_16(*src_port) == 21) ||
5177 rte_be_to_cpu_16(*dst_port) == 21) {
5179 int32_t ct_position =
5180 cgnat_cnxn_tracker->positions[pkt_num];
5181 if (ct_position < 0){
5182 p_nat->invalid_packets |= pkt_mask;
5184 p_nat->naptDroppedPktCount++;
5187 if (cgnat_cnxn_tracker->hash_table_entries
5188 [ct_position].alg_bypass_flag != BYPASS){
5190 struct pipeline_cgnapt_entry_key
5191 data_channel_entry_key;
5194 data_channel_entry_key.ip =
5196 data_channel_entry_key.port =
5197 entry->data.pub_port;
5198 data_channel_entry_key.pid = 0xffff;
5200 ftp_alg_dpi(p_nat, &data_channel_entry_key,
5201 pkt, cgnat_cnxn_tracker,
5202 ct_position, PUBLIC);
5207 p_nat->inaptedPktCount++;
5210 p_nat->naptedPktCount++;
5213 if (p_nat->hw_checksum_reqd)
5214 hw_checksum(pkt, pkt_type);
5216 sw_checksum(pkt, pkt_type);
5222 * NAPT key calculation function for IPv6 private traffic
5223 * which handles 1 pkt
5226 * A pointer to array of packets mbuf
5228 * Pkt number of pkts
5232 * A pointer to main CGNAPT structure
5236 pkt_work_cgnapt_key_ipv6_prv(
5237 struct rte_mbuf *pkt,
5239 __rte_unused void *arg,
5240 struct pipeline_cgnapt *p_nat)
5243 p_nat->receivedPktCount++;
5245 /* bitmask representing only this packet */
5246 uint64_t pkt_mask = 1LLU << pkt_num;
5248 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
5249 uint32_t *src_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
5251 uint16_t src_port = RTE_MBUF_METADATA_UINT16(pkt, SRC_PRT_OFST_IP6);
5253 uint16_t phy_port = pkt->port;
5254 struct pipeline_cgnapt_entry_key key;
5256 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
5258 #ifdef CGNAPT_DBG_PRNT
5259 if (CGNAPT_DEBUG > 4)
5264 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
5269 case IP_PROTOCOL_UDP:
5273 struct udp_hdr *udp;
5275 udp = (struct udp_hdr *)
5276 RTE_MBUF_METADATA_UINT8_PTR(pkt,
5279 if (rte_bswap16(udp->dst_port) ==
5281 handle_pcp_req(pkt, IPV6_SZ, p_nat);
5282 p_nat->invalid_packets |= pkt_mask;
5288 case IP_PROTOCOL_TCP:
5289 case IP_PROTOCOL_ICMP:
5290 /*we don't need icmp check in ipv6 */
5294 printf("wrong protocol: %d\n", protocol);
5295 /* remember invalid packets to be dropped */
5296 p_nat->invalid_packets |= pkt_mask;
5297 p_nat->naptDroppedPktCount++;
5299 #ifdef CGNAPT_DEBUGGING
5300 p_nat->naptDroppedPktCount2++;
5306 key.ip = rte_bswap32(src_addr[3]);
5307 key.port = rte_bswap16(src_port);
5309 #ifdef NAT_ONLY_CONFIG_REQ
5310 if (nat_only_config_flag)
5314 memcpy(&p_nat->keys[pkt_num], &key,
5315 sizeof(struct pipeline_cgnapt_entry_key));
5316 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5320 * NAPT key calculation function for IPv6 public traffic
5321 * which handles 1 pkt
5324 * A pointer to array of packets mbuf
5326 * Pkt number of pkts
5330 * A pointer to main CGNAPT structure
5334 pkt_work_cgnapt_key_ipv6_pub(
5335 struct rte_mbuf *pkt,
5337 __rte_unused void *arg,
5338 struct pipeline_cgnapt *p_nat)
5342 p_nat->receivedPktCount++;
5344 /* bitmask representing only this packet */
5345 uint64_t pkt_mask = 1LLU << pkt_num;
5347 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
5349 uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
5351 uint16_t dst_port = RTE_MBUF_METADATA_UINT16(pkt,
5352 DST_PRT_OFST_IP4_TCP);
5354 struct pipeline_cgnapt_entry_key key;
5356 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
5358 #ifdef CGNAPT_DBG_PRNT
5359 if (CGNAPT_DEBUG > 4)
5364 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
5370 case IP_PROTOCOL_UDP:
5371 case IP_PROTOCOL_TCP:
5372 case IP_PROTOCOL_ICMP:
5373 /*we don't need icmp check in ipv6 */
5377 /* remember invalid packets to be dropped */
5378 p_nat->invalid_packets |= pkt_mask;
5379 p_nat->naptDroppedPktCount++;
5381 #ifdef CGNAPT_DEBUGGING
5382 p_nat->naptDroppedPktCount2++;
5388 key.ip = rte_bswap32(dst_addr[0]);
5389 key.port = rte_bswap16(dst_port);
5391 #ifdef NAT_ONLY_CONFIG_REQ
5392 if (nat_only_config_flag)
5396 memcpy(&p_nat->keys[pkt_num], &key,
5397 sizeof(struct pipeline_cgnapt_entry_key));
5398 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5402 * NAPT key calculation function for IPv6 private traffic
5403 * which handles 4 pkts
5406 * A pointer to array of packets mbuf
5408 * Starting pkt number of pkts
5412 * A pointer to main CGNAPT structure
5416 pkt4_work_cgnapt_key_ipv6_prv(
5417 struct rte_mbuf **pkt,
5419 __rte_unused void *arg,
5420 struct pipeline_cgnapt *p_nat)
5422 p_nat->receivedPktCount += 4;
5424 /* bitmask representing only this packet */
5425 uint64_t pkt_mask0 = 1LLU << pkt_num;
5426 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
5427 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
5428 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
5430 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
5432 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
5434 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
5436 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
5439 uint32_t *src_addr0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0],
5441 uint32_t *src_addr1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1],
5443 uint32_t *src_addr2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2],
5445 uint32_t *src_addr3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3],
5448 uint16_t src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
5450 uint16_t src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
5452 uint16_t src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
5454 uint16_t src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
5457 uint16_t phy_port0 = pkt[0]->port;
5458 uint16_t phy_port1 = pkt[1]->port;
5459 uint16_t phy_port2 = pkt[2]->port;
5460 uint16_t phy_port3 = pkt[3]->port;
5462 struct pipeline_cgnapt_entry_key key0;
5463 struct pipeline_cgnapt_entry_key key1;
5464 struct pipeline_cgnapt_entry_key key2;
5465 struct pipeline_cgnapt_entry_key key3;
5467 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
5468 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
5469 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
5470 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
5474 #ifdef CGNAPT_DBG_PRNT
5475 if (CGNAPT_DEBUG > 4)
5480 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
5484 switch (protocol0) {
5486 case IP_PROTOCOL_UDP:
5490 struct udp_hdr *udp;
5492 udp = (struct udp_hdr *)
5493 RTE_MBUF_METADATA_UINT8_PTR(pkt[0],
5496 if (rte_bswap16(udp->dst_port) ==
5498 handle_pcp_req(pkt[0], IPV6_SZ, p_nat);
5499 p_nat->invalid_packets |= pkt_mask0;
5505 case IP_PROTOCOL_TCP:
5506 case IP_PROTOCOL_ICMP:
5507 /*we don't need icmp check in ipv6 */
5511 /* remember invalid packets to be dropped */
5512 p_nat->invalid_packets |= pkt_mask0;
5513 p_nat->naptDroppedPktCount++;
5515 #ifdef CGNAPT_DEBUGGING
5516 p_nat->naptDroppedPktCount2++;
5523 key0.pid = phy_port0;
5524 key0.ip = rte_bswap32(src_addr0[3]);
5525 key0.port = rte_bswap16(src_port0);
5527 #ifdef NAT_ONLY_CONFIG_REQ
5528 if (nat_only_config_flag)
5532 memcpy(&p_nat->keys[pkt_num], &key0,
5533 sizeof(struct pipeline_cgnapt_entry_key));
5534 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5537 #ifdef CGNAPT_DBG_PRNT
5538 if (CGNAPT_DEBUG > 4)
5543 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
5547 switch (protocol1) {
5548 case IP_PROTOCOL_UDP:
5552 struct udp_hdr *udp;
5554 udp = (struct udp_hdr *)
5555 RTE_MBUF_METADATA_UINT8_PTR(pkt[1],
5558 if (rte_bswap16(udp->dst_port) ==
5560 handle_pcp_req(pkt[1], IPV6_SZ, p_nat);
5561 p_nat->invalid_packets |= pkt_mask1;
5567 case IP_PROTOCOL_TCP:
5568 case IP_PROTOCOL_ICMP:
5569 /*we don't need icmp check in ipv6 */
5573 /* remember invalid packets to be dropped */
5574 p_nat->invalid_packets |= pkt_mask1;
5575 p_nat->naptDroppedPktCount++;
5577 #ifdef CGNAPT_DEBUGGING
5578 p_nat->naptDroppedPktCount2++;
5584 key1.pid = phy_port1;
5585 key1.ip = rte_bswap32(src_addr1[3]);
5586 key1.port = rte_bswap16(src_port1);
5588 #ifdef NAT_ONLY_CONFIG_REQ
5589 if (nat_only_config_flag)
5593 memcpy(&p_nat->keys[pkt_num + 1], &key1,
5594 sizeof(struct pipeline_cgnapt_entry_key));
5595 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
5598 #ifdef CGNAPT_DBG_PRNT
5599 if (CGNAPT_DEBUG > 4)
5604 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
5608 switch (protocol2) {
5609 case IP_PROTOCOL_UDP:
5613 struct udp_hdr *udp;
5615 udp = (struct udp_hdr *)
5616 RTE_MBUF_METADATA_UINT8_PTR(pkt[2],
5619 if (rte_bswap16(udp->dst_port) ==
5621 handle_pcp_req(pkt[2], IPV6_SZ, p_nat);
5622 p_nat->invalid_packets |= pkt_mask2;
5628 case IP_PROTOCOL_TCP:
5629 case IP_PROTOCOL_ICMP:
5630 /*we don't need icmp check in ipv6 */
5634 /* remember invalid packets to be dropped */
5635 p_nat->invalid_packets |= pkt_mask2;
5636 p_nat->naptDroppedPktCount++;
5638 #ifdef CGNAPT_DEBUGGING
5639 p_nat->naptDroppedPktCount2++;
5645 key2.pid = phy_port2;
5646 key2.ip = rte_bswap32(src_addr2[3]);
5647 key2.port = rte_bswap16(src_port2);
5649 #ifdef NAT_ONLY_CONFIG_REQ
5650 if (nat_only_config_flag)
5654 memcpy(&p_nat->keys[pkt_num + 2], &key2,
5655 sizeof(struct pipeline_cgnapt_entry_key));
5656 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
5659 #ifdef CGNAPT_DBG_PRNT
5660 if (CGNAPT_DEBUG > 4)
5665 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
5669 switch (protocol3) {
5670 case IP_PROTOCOL_UDP:
5674 struct udp_hdr *udp;
5676 udp = (struct udp_hdr *)
5677 RTE_MBUF_METADATA_UINT8_PTR(pkt[3],
5680 if (rte_bswap16(udp->dst_port) ==
5682 handle_pcp_req(pkt[3], IPV6_SZ, p_nat);
5683 p_nat->invalid_packets |= pkt_mask3;
5689 case IP_PROTOCOL_TCP:
5690 case IP_PROTOCOL_ICMP:
5691 /*we don't need icmp check in ipv6 */
5695 /* remember invalid packets to be dropped */
5696 p_nat->invalid_packets |= pkt_mask2;
5697 p_nat->naptDroppedPktCount++;
5699 #ifdef CGNAPT_DEBUGGING
5700 p_nat->naptDroppedPktCount2++;
5706 key3.pid = phy_port3;
5707 key3.ip = rte_bswap32(src_addr3[3]);
5708 key3.port = rte_bswap16(src_port3);
5710 #ifdef NAT_ONLY_CONFIG_REQ
5711 if (nat_only_config_flag)
5715 memcpy(&p_nat->keys[pkt_num + 3], &key3,
5716 sizeof(struct pipeline_cgnapt_entry_key));
5717 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
5723 * NAPT key calculation function for IPv4 public traffic
5724 * which handles 4 pkts
5727 * A pointer to array of packets mbuf
5729 * Starting pkt number of pkts
5733 * A pointer to main CGNAPT structure
5737 pkt4_work_cgnapt_key_ipv6_pub(
5738 struct rte_mbuf **pkt,
5740 __rte_unused void *arg,
5741 struct pipeline_cgnapt *p_nat)
5743 p_nat->receivedPktCount += 4;
5745 /* bitmask representing only this packet */
5746 uint64_t pkt_mask0 = 1LLU << pkt_num;
5747 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
5748 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
5749 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
5751 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
5753 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
5755 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
5757 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
5760 uint32_t *dst_addr0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0],
5762 uint32_t *dst_addr1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1],
5764 uint32_t *dst_addr2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2],
5766 uint32_t *dst_addr3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3],
5769 uint16_t dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
5770 DST_PRT_OFST_IP4_TCP);
5771 uint16_t dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
5772 DST_PRT_OFST_IP4_TCP);
5773 uint16_t dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
5774 DST_PRT_OFST_IP4_TCP);
5775 uint16_t dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
5776 DST_PRT_OFST_IP4_TCP);
5778 struct pipeline_cgnapt_entry_key key0;
5779 struct pipeline_cgnapt_entry_key key1;
5780 struct pipeline_cgnapt_entry_key key2;
5781 struct pipeline_cgnapt_entry_key key3;
5783 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
5784 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
5785 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
5786 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
5790 #ifdef CGNAPT_DBG_PRNT
5791 if (CGNAPT_DEBUG > 4)
5796 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
5800 switch (protocol0) {
5802 case IP_PROTOCOL_TCP:
5803 case IP_PROTOCOL_UDP:
5804 case IP_PROTOCOL_ICMP:
5805 /*we don't need icmp check in ipv6 */
5809 /* remember invalid packets to be dropped */
5810 p_nat->invalid_packets |= pkt_mask0;
5811 p_nat->naptDroppedPktCount++;
5813 #ifdef CGNAPT_DEBUGGING
5814 p_nat->naptDroppedPktCount2++;
5820 key0.ip = rte_bswap32(dst_addr0[0]);
5821 key0.port = rte_bswap16(dst_port0);
5823 #ifdef NAT_ONLY_CONFIG_REQ
5824 if (nat_only_config_flag)
5828 memcpy(&p_nat->keys[pkt_num], &key0,
5829 sizeof(struct pipeline_cgnapt_entry_key));
5830 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5836 #ifdef CGNAPT_DBG_PRNT
5837 if (CGNAPT_DEBUG > 4)
5842 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
5846 switch (protocol1) {
5848 case IP_PROTOCOL_TCP:
5849 case IP_PROTOCOL_UDP:
5850 case IP_PROTOCOL_ICMP:
5851 /*we don't need icmp check in ipv6 */
5855 /* remember invalid packets to be dropped */
5856 p_nat->invalid_packets |= pkt_mask1;
5857 p_nat->naptDroppedPktCount++;
5859 #ifdef CGNAPT_DEBUGGING
5860 p_nat->naptDroppedPktCount2++;
5866 key1.ip = rte_bswap32(dst_addr1[0]);
5867 key1.port = rte_bswap16(dst_port1);
5869 #ifdef NAT_ONLY_CONFIG_REQ
5870 if (nat_only_config_flag)
5874 memcpy(&p_nat->keys[pkt_num + 1], &key1,
5875 sizeof(struct pipeline_cgnapt_entry_key));
5876 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
5882 #ifdef CGNAPT_DBG_PRNT
5883 if (CGNAPT_DEBUG > 4)
5888 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
5892 switch (protocol2) {
5894 case IP_PROTOCOL_TCP:
5895 case IP_PROTOCOL_UDP:
5896 case IP_PROTOCOL_ICMP:
5897 /*we don't need icmp check in ipv6 */
5901 /* remember invalid packets to be dropped */
5902 p_nat->invalid_packets |= pkt_mask2;
5903 p_nat->naptDroppedPktCount++;
5905 #ifdef CGNAPT_DEBUGGING
5906 p_nat->naptDroppedPktCount2++;
5912 key2.ip = rte_bswap32(dst_addr2[0]);
5913 key2.port = rte_bswap16(dst_port2);
5915 #ifdef NAT_ONLY_CONFIG_REQ
5916 if (nat_only_config_flag)
5920 memcpy(&p_nat->keys[pkt_num + 2], &key2,
5921 sizeof(struct pipeline_cgnapt_entry_key));
5923 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
5929 #ifdef CGNAPT_DBG_PRNT
5930 if (CGNAPT_DEBUG > 4)
5935 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
5939 switch (protocol3) {
5941 case IP_PROTOCOL_TCP:
5942 case IP_PROTOCOL_UDP:
5943 case IP_PROTOCOL_ICMP:
5944 /*we don't need icmp check in ipv6 */
5948 /* remember invalid packets to be dropped */
5949 p_nat->invalid_packets |= pkt_mask3;
5950 p_nat->naptDroppedPktCount++;
5952 #ifdef CGNAPT_DEBUGGING
5953 p_nat->naptDroppedPktCount2++;
5959 key3.ip = rte_bswap32(dst_addr3[0]);
5960 key3.port = rte_bswap16(dst_port3);
5962 #ifdef NAT_ONLY_CONFIG_REQ
5963 if (nat_only_config_flag)
5967 memcpy(&p_nat->keys[pkt_num + 3], &key3,
5968 sizeof(struct pipeline_cgnapt_entry_key));
5970 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
5974 * NAPT function for IPv6 private traffic which handles 1 pkt
5977 * A pointer to array of packet mbuf
5983 * A pointer to main CGNAPT structure
5987 pkt_work_cgnapt_ipv6_prv(
5988 struct rte_mbuf *pkt,
5990 __rte_unused void *arg,
5991 struct pipeline_cgnapt *p_nat)
5993 /* index into hash table entries */
5994 int hash_table_entry = p_nat->lkup_indx[pkt_num];
5996 /*bitmask representing only this packet */
5997 uint64_t pkt_mask = 1LLU << pkt_num;
5999 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
6001 /* Added for Multiport */
6002 uint32_t dest_if = INVALID_DESTIF;
6003 uint16_t *outport_id = RTE_MBUF_METADATA_UINT16_PTR(pkt,
6004 cgnapt_meta_offset);
6006 struct cgnapt_table_entry *entry = NULL;
6007 enum PKT_TYPE pkt_type = PKT_TYPE_IPV6to4;
6009 if (hash_table_entry < 0) {
6011 /* try to add new entry */
6012 struct rte_pipeline_table_entry *table_entry = NULL;
6014 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
6016 &p_nat->valid_packets, pkt_num,
6020 /* ICMP Error message generation for
6021 * Destination Host unreachable
6023 /* Do we need this check for ipv6? */
6024 if (protocol == IP_PROTOCOL_ICMP) {
6025 cgnapt_icmp_pkt = pkt;
6026 send_icmp_dest_unreachable_msg();
6029 /* Drop packet by adding to invalid pkt mask */
6031 p_nat->invalid_packets |= dropmask;
6033 #ifdef CGNAPT_DEBUGGING
6034 if (p_nat->kpc2++ < 5) {
6035 printf("in_ah Th: %d", p_nat->pipeline_num);
6036 print_key(p_nat->key_ptrs[pkt_num]);
6040 p_nat->naptDroppedPktCount++;
6042 #ifdef CGNAPT_DEBUGGING
6043 p_nat->naptDroppedPktCount3++;
6049 entry = (struct cgnapt_table_entry *)table_entry;
6051 /* entry found for this packet */
6052 entry = &napt_hash_tbl_entries[hash_table_entry];
6055 /* apply napt and mac changes */
6057 p_nat->entries[pkt_num] = &(entry->head);
6059 struct ipv6_hdr ipv6_hdr;
6061 struct ether_addr hw_addr;
6062 uint32_t dest_address = 0;
6067 convert_ipv6_to_ipv4(pkt, &ipv6_hdr);
6069 #ifdef CGNAPT_DBG_PRNT
6070 if (CGNAPT_DEBUG == 1)
6071 printf("pkt_work_cganpt: convert_ipv6_to_ipv4\n");
6074 struct cgnapt_nsp_node *ll = nsp_ll;
6077 while (ll != NULL) {
6079 (&ipv6_hdr.dst_addr[0], &ll->nsp.prefix[0],
6080 ll->nsp.depth / 8)) {
6088 && !memcmp(&ipv6_hdr.dst_addr[0], &well_known_prefix[0],
6094 p_nat->invalid_packets |= pkt_mask;
6095 p_nat->naptDroppedPktCount++;
6097 #ifdef CGNAPT_DEBUGGING
6098 p_nat->naptDroppedPktCount5++;
6106 /* As packet is already converted into IPv4 we must not
6107 * operate IPv6 offsets on packet
6108 * Only perform IPv4 operations
6111 uint32_t *src_addr =
6112 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP6t4);
6113 uint32_t *dst_addr =
6114 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP6t4);
6115 uint16_t *src_port =
6116 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP6t4);
6117 uint16_t *dst_port =
6118 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP6t4);
6120 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt,
6122 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt,
6123 ETH_OFST_IP6t4 + 6);
6125 if (entry->data.ttl == NAPT_ENTRY_STALE)
6126 entry->data.ttl = NAPT_ENTRY_VALID;
6129 if (unlikely(protocol == IP_PROTOCOL_UDP
6130 && rte_be_to_cpu_16(*dst_port) == 53)) {
6131 p_nat->invalid_packets |= pkt_mask;
6132 p_nat->naptDroppedPktCount++;
6134 #ifdef CGNAPT_DEBUGGING
6135 p_nat->naptDroppedPktCount6++;
6141 dest_address = rte_bswap32(*dst_addr);
6142 /*Multiport Changes */
6145 #ifdef CGNAPT_DBG_PRNT
6146 if (CGNAPT_DEBUG > 2)
6147 printf("Egress: \tphy_port:%d\t get_prv_to_pub():%d "
6148 "\tout_port:%d\n", pkt->port,
6149 dest_if, *outport_id);
6153 #ifdef CGNAPT_DBG_PRNT
6154 static int static_count;
6156 if (static_count++ < 10) {
6158 my_print_entry(entry);
6159 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6160 printf("dest_add:%x\n", entry->data.u.prv_ip);
6161 printf("dest_add:%x\n", *dst_addr);
6162 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6166 struct arp_entry_data *ret_arp_data;
6167 ret_arp_data = get_dest_mac_addr_port(dest_address,
6168 &dest_if, (struct ether_addr *)eth_dest);
6169 *outport_id = p_nat->outport_id[dest_if];
6170 if (arp_cache_dest_mac_present(dest_if)) {
6171 ether_addr_copy(get_link_hw_addr(dest_if),
6172 (struct ether_addr *)eth_src);
6173 update_nhip_access(dest_if);
6175 if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) {
6176 p_nat->naptedPktCount += ret_arp_data->num_pkts;
6177 arp_send_buffered_pkts(ret_arp_data,
6178 (struct ether_addr *)eth_dest, *outport_id);
6183 if (unlikely(ret_arp_data == NULL)) {
6185 #ifdef CGNAPT_DEBUGGING
6186 printf("%s: NHIP Not Found, nhip:%x , "
6187 "outport_id: %d\n", __func__, nhip,
6192 p_nat->invalid_packets |= pkt_mask;
6193 p_nat->naptDroppedPktCount++;
6195 #ifdef CGNAPT_DEBUGGING
6196 p_nat->naptDroppedPktCount4++;
6201 if (ret_arp_data->status == INCOMPLETE ||
6202 ret_arp_data->status == PROBE) {
6203 if (ret_arp_data->num_pkts >= NUM_DESC) {
6205 p_nat->invalid_packets |= pkt_mask;
6206 p_nat->naptDroppedPktCount++;
6208 #ifdef CGNAPT_DEBUGGING
6209 p_nat->naptDroppedPktCount4++;
6213 arp_pkts_mask |= pkt_mask;
6214 arp_queue_unresolved_packet(ret_arp_data, pkt);
6222 *src_addr = rte_bswap32(entry->data.pub_ip);
6224 #ifdef NAT_ONLY_CONFIG_REQ
6225 if (!nat_only_config_flag) {
6227 *src_port = rte_bswap16(entry->data.pub_port);
6229 #ifdef NAT_ONLY_CONFIG_REQ
6233 p_nat->enaptedPktCount++;
6236 p_nat->naptedPktCount++;
6239 if (p_nat->hw_checksum_reqd)
6240 hw_checksum(pkt, pkt_type);
6242 sw_checksum(pkt, pkt_type);
6248 * NAPT function for IPv6 public traffic which handles 1 pkt
6251 * A pointer to array of packet mbuf
6257 * A pointer to main CGNAPT structure
6261 pkt_work_cgnapt_ipv6_pub(
6262 struct rte_mbuf *pkt,
6264 __rte_unused void *arg,
6265 struct pipeline_cgnapt *p_nat)
6268 /* index into hash table entries */
6269 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6270 /*bitmask representing only this packet */
6271 uint64_t pkt_mask = 1LLU << pkt_num;
6273 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
6275 uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */
6276 uint16_t *outport_id =
6277 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6278 struct cgnapt_table_entry *entry = NULL;
6280 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4to6;
6282 if (hash_table_entry < 0) {
6284 /* Drop ingress initial traffic */
6286 p_nat->invalid_packets |= pkt_mask;
6287 p_nat->naptDroppedPktCount++;
6289 #ifdef CGNAPT_DEBUGGING
6290 p_nat->naptDroppedPktCount3++;
6291 if (p_nat->kpc2++ < 5) {
6292 printf("in_ah Th: %d", p_nat->pipeline_num);
6293 print_key(p_nat->key_ptrs[pkt_num]);
6300 /* entry found for this packet */
6301 entry = &napt_hash_tbl_entries[hash_table_entry];
6304 /* apply napt and mac changes */
6306 p_nat->entries[pkt_num] = &(entry->head);
6307 if (entry->data.type != CGNAPT_ENTRY_IPV6) {
6308 p_nat->invalid_packets |= pkt_mask;
6309 p_nat->naptDroppedPktCount++;
6313 struct ipv4_hdr ipv4_hdr;
6314 uint16_t *src_port =
6315 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP4_TCP);
6317 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
6318 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
6320 if (entry->data.ttl == NAPT_ENTRY_STALE)
6321 entry->data.ttl = NAPT_ENTRY_VALID;
6323 struct ether_addr hw_addr;
6324 uint8_t dest_addr_ipv6[16];
6325 uint8_t nh_ipv6[16];
6330 if (unlikely(protocol == IP_PROTOCOL_UDP
6331 && rte_be_to_cpu_16(*src_port) == 53)) {
6332 p_nat->invalid_packets |= pkt_mask;
6333 p_nat->naptDroppedPktCount++;
6334 #ifdef CGNAPT_DEBUGGING
6335 p_nat->naptDroppedPktCount6++;
6340 memcpy(&dest_addr_ipv6[0], &entry->data.u.prv_ipv6[0], 16);
6343 memset(nh_ipv6, 0, 16);
6344 struct nd_entry_data *ret_nd_data = NULL;
6345 ret_nd_data = get_dest_mac_address_ipv6_port(
6348 (struct ether_addr *)eth_dest,
6351 *outport_id = p_nat->outport_id[dest_if];
6353 if (nd_cache_dest_mac_present(dest_if)) {
6354 ether_addr_copy(get_link_hw_addr(dest_if),
6355 (struct ether_addr *)eth_src);
6356 update_nhip_access(dest_if);
6358 if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) {
6359 p_nat->naptedPktCount += ret_nd_data->num_pkts;
6360 nd_send_buffered_pkts(ret_nd_data,
6361 (struct ether_addr *)eth_dest, *outport_id);
6365 if (unlikely(ret_nd_data == NULL)) {
6367 #ifdef CGNAPT_DEBUGGING
6368 printf("%s: NHIP Not Found, "
6369 "outport_id: %d\n", __func__,
6374 p_nat->invalid_packets |= pkt_mask;
6375 p_nat->naptDroppedPktCount++;
6377 #ifdef CGNAPT_DEBUGGING
6378 p_nat->naptDroppedPktCount4++;
6383 if (ret_nd_data->status == INCOMPLETE ||
6384 ret_nd_data->status == PROBE) {
6385 if (ret_nd_data->num_pkts >= NUM_DESC) {
6387 p_nat->invalid_packets |= pkt_mask;
6388 p_nat->naptDroppedPktCount++;
6390 #ifdef CGNAPT_DEBUGGING
6391 p_nat->naptDroppedPktCount4++;
6395 arp_pkts_mask |= pkt_mask;
6396 nd_queue_unresolved_packet(ret_nd_data, pkt);
6406 convert_ipv4_to_ipv6(pkt, &ipv4_hdr);
6408 /* Ethernet MTU check */
6409 if ((rte_pktmbuf_data_len(pkt) - 14) > 1500) {
6410 p_nat->invalid_packets |= pkt_mask;
6411 p_nat->naptDroppedPktCount++;
6414 uint32_t *dst_addr =
6415 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4t6);
6416 uint16_t *dst_port =
6417 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP4t6);
6419 memcpy((uint8_t *) &dst_addr[0], &entry->data.u.prv_ipv6[0],
6422 #ifdef NAT_ONLY_CONFIG_REQ
6423 if (!nat_only_config_flag) {
6425 *dst_port = rte_bswap16(entry->data.prv_port);
6427 #ifdef NAT_ONLY_CONFIG_REQ
6431 p_nat->inaptedPktCount++;
6434 p_nat->naptedPktCount++;
6437 if (p_nat->hw_checksum_reqd)
6438 hw_checksum(pkt, pkt_type);
6440 sw_checksum(pkt, pkt_type);
6446 * NAPT function for IPv6 private traffic which handles 4 pkts
6449 * A pointer to array of packets mbuf
6451 * Starting pkt number of pkts
6455 * A pointer to main CGNAPT structure
6459 pkt4_work_cgnapt_ipv6_prv(
6460 struct rte_mbuf **pkts,
6461 uint32_t in_pkt_num,
6462 __rte_unused void *arg,
6463 struct pipeline_cgnapt *p_nat)
6465 struct rte_mbuf *pkt;
6469 enum PKT_TYPE pkt_type = PKT_TYPE_IPV6to4;
6471 for (i = 0; i < 4; i++) {
6472 pkt_num = in_pkt_num + i;
6475 /* index into hash table entries */
6476 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6477 /*bitmask representing only this packet */
6478 uint64_t pkt_mask = 1LLU << pkt_num;
6480 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
6481 uint32_t dest_if = INVALID_DESTIF;
6482 uint16_t *outport_id =
6483 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6484 struct cgnapt_table_entry *entry = NULL;
6486 if (hash_table_entry < 0) {
6488 /* try to add new entry */
6489 struct rte_pipeline_table_entry *table_entry = NULL;
6492 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
6494 &p_nat->valid_packets, pkt_num,
6498 /* ICMP Error message generation for
6499 * Destination Host unreachable
6501 /* Do we need this check for ipv6? */
6502 if (protocol == IP_PROTOCOL_ICMP) {
6503 cgnapt_icmp_pkt = pkt;
6504 send_icmp_dest_unreachable_msg();
6507 /* Drop packet by adding to invalid pkt mask */
6509 p_nat->invalid_packets |= dropmask;
6511 #ifdef CGNAPT_DEBUGGING
6512 if (p_nat->kpc2++ < 5) {
6513 printf("in_ah Th: %d",
6514 p_nat->pipeline_num);
6515 print_key(p_nat->key_ptrs[pkt_num]);
6519 p_nat->naptDroppedPktCount++;
6521 #ifdef CGNAPT_DEBUGGING
6522 p_nat->naptDroppedPktCount3++;
6528 entry = (struct cgnapt_table_entry *)table_entry;
6530 /* entry found for this packet */
6531 entry = &napt_hash_tbl_entries[hash_table_entry];
6534 /* apply napt and mac changes */
6536 p_nat->entries[pkt_num] = &(entry->head);
6538 struct ipv6_hdr ipv6_hdr;
6539 struct ether_addr hw_addr;
6540 uint32_t dest_address = 0;
6541 uint8_t nh_ipv6[16];
6546 convert_ipv6_to_ipv4(pkt, &ipv6_hdr);
6548 #ifdef CGNAPT_DBG_PRNT
6549 if (CGNAPT_DEBUG >= 1)
6550 printf("pkt_work_cganpt: "
6551 "convert_ipv6_to_ipv4\n");
6554 struct cgnapt_nsp_node *ll = nsp_ll;
6557 while (ll != NULL) {
6558 if (!memcmp(&ipv6_hdr.dst_addr[0],
6560 ll->nsp.depth / 8)) {
6568 && !memcmp(&ipv6_hdr.dst_addr[0],
6569 &well_known_prefix[0], 12)) {
6574 p_nat->invalid_packets |= pkt_mask;
6575 p_nat->naptDroppedPktCount++;
6577 #ifdef CGNAPT_DEBUGGING
6578 p_nat->naptDroppedPktCount5++;
6585 /* As packet is already converted into IPv4 we must not
6586 * operate IPv6 offsets on packet only perform IPv4 operations
6589 uint32_t *src_addr =
6590 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP6t4);
6591 uint32_t *dst_addr =
6592 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP6t4);
6593 uint16_t *src_port =
6594 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP6t4);
6595 uint16_t *dst_port =
6596 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP6t4);
6599 RTE_MBUF_METADATA_UINT8_PTR(pkt, ETH_OFST_IP6t4);
6601 RTE_MBUF_METADATA_UINT8_PTR(pkt, ETH_OFST_IP6t4 + 6);
6603 if (entry->data.ttl == NAPT_ENTRY_STALE)
6604 entry->data.ttl = NAPT_ENTRY_VALID;
6609 if (unlikely(protocol == IP_PROTOCOL_UDP
6610 && rte_be_to_cpu_16(*dst_port) == 53)) {
6611 p_nat->invalid_packets |= pkt_mask;
6612 p_nat->naptDroppedPktCount++;
6614 #ifdef CGNAPT_DEBUGGING
6615 p_nat->naptDroppedPktCount6++;
6620 dest_address = rte_bswap32(*dst_addr);
6623 #ifdef CGNAPT_DBG_PRNT
6624 if (CGNAPT_DEBUG > 2)
6625 printf("Egress: \tphy_port:%d\t"
6626 "get_prv_to_pub():%d \tout_port:%d\n",
6627 pkt->port, dest_if, *outport_id);
6631 #ifdef CGNAPT_DEBUGGING
6632 static int static_count;
6634 if (static_count++ < 10) {
6636 my_print_entry(entry);
6637 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6638 printf("dest_add:%x\n", entry->data.u.prv_ip);
6639 printf("dest_add:%x\n", *dst_addr);
6640 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6644 memset(nh_ipv6, 0, 16);
6647 struct arp_entry_data *ret_arp_data;
6648 ret_arp_data = get_dest_mac_addr_port(dest_address,
6649 &dest_if, (struct ether_addr *)eth_dest);
6650 *outport_id = p_nat->outport_id[dest_if];
6652 if (arp_cache_dest_mac_present(dest_if)) {
6653 ether_addr_copy(get_link_hw_addr(dest_if),
6654 (struct ether_addr *)eth_src);
6655 update_nhip_access(dest_if);
6657 if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) {
6658 p_nat->naptedPktCount += ret_arp_data->num_pkts;
6659 arp_send_buffered_pkts(ret_arp_data,
6660 (struct ether_addr *)eth_dest, *outport_id);
6665 if (unlikely(ret_arp_data == NULL)) {
6667 #ifdef CGNAPT_DEBUGGING
6668 printf("%s: NHIP Not Found, nhip:%x , "
6669 "outport_id: %d\n", __func__, nhip,
6674 p_nat->invalid_packets |= pkt_mask;
6675 p_nat->naptDroppedPktCount++;
6677 #ifdef CGNAPT_DEBUGGING
6678 p_nat->naptDroppedPktCount4++;
6683 if (ret_arp_data->status == INCOMPLETE ||
6684 ret_arp_data->status == PROBE) {
6685 if (ret_arp_data->num_pkts >= NUM_DESC) {
6687 p_nat->invalid_packets |= pkt_mask;
6688 p_nat->naptDroppedPktCount++;
6690 #ifdef CGNAPT_DEBUGGING
6691 p_nat->naptDroppedPktCount4++;
6695 arp_pkts_mask |= pkt_mask;
6696 arp_queue_unresolved_packet(ret_arp_data, pkt);
6706 *src_addr = rte_bswap32(entry->data.pub_ip);
6708 #ifdef NAT_ONLY_CONFIG_REQ
6709 if (!nat_only_config_flag) {
6711 *src_port = rte_bswap16(entry->data.pub_port);
6713 #ifdef NAT_ONLY_CONFIG_REQ
6717 p_nat->enaptedPktCount++;
6720 p_nat->naptedPktCount++;
6723 if (p_nat->hw_checksum_reqd)
6724 hw_checksum(pkt, pkt_type);
6726 sw_checksum(pkt, pkt_type);
6732 * NAPT function for IPv6 public traffic which handles 4 pkts
6735 * A pointer to array of packets mbuf
6737 * Starting pkt number of pkts
6741 * A pointer to main CGNAPT structure
6745 pkt4_work_cgnapt_ipv6_pub(
6746 struct rte_mbuf **pkts,
6747 uint32_t in_pkt_num,
6748 __rte_unused void *arg,
6749 struct pipeline_cgnapt *p_nat)
6751 struct rte_mbuf *pkt;
6755 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4to6;
6757 for (i = 0; i < 4; i++) {
6758 pkt_num = in_pkt_num + i;
6761 /* index into hash table entries */
6762 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6763 /*bitmask representing only this packet */
6764 uint64_t pkt_mask = 1LLU << pkt_num;
6766 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
6767 uint16_t *outport_id =
6768 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6769 struct cgnapt_table_entry *entry = NULL;
6771 if (hash_table_entry < 0) {
6773 /* Drop ingress initial traffic */
6775 p_nat->invalid_packets |= pkt_mask;
6776 p_nat->naptDroppedPktCount++;
6777 #ifdef CGNAPT_DEBUGGING
6778 p_nat->naptDroppedPktCount3++;
6779 if (p_nat->kpc2++ < 5) {
6780 printf("in_ah Th: %d", p_nat->pipeline_num);
6781 print_key(p_nat->key_ptrs[pkt_num]);
6788 /* entry found for this packet */
6789 entry = &napt_hash_tbl_entries[hash_table_entry];
6792 /* apply napt and mac changes */
6794 p_nat->entries[pkt_num] = &(entry->head);
6795 if (entry->data.type != CGNAPT_ENTRY_IPV6) {
6796 p_nat->invalid_packets |= pkt_mask;
6797 p_nat->naptDroppedPktCount++;
6801 struct ipv4_hdr ipv4_hdr;
6803 uint16_t *src_port =
6804 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP4_TCP);
6807 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
6809 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
6811 if (entry->data.ttl == NAPT_ENTRY_STALE)
6812 entry->data.ttl = NAPT_ENTRY_VALID;
6814 struct ether_addr hw_addr;
6815 uint8_t dest_addr_ipv6[16];
6816 uint8_t nh_ipv6[16];
6817 uint32_t dest_if = INVALID_DESTIF;
6818 { /*start of Ingress */
6820 if (unlikely(protocol == IP_PROTOCOL_UDP
6821 && rte_be_to_cpu_16(*src_port) == 53)) {
6822 p_nat->invalid_packets |= pkt_mask;
6823 p_nat->naptDroppedPktCount++;
6824 #ifdef CGNAPT_DEBUGGING
6825 p_nat->naptDroppedPktCount6++;
6830 memcpy(&dest_addr_ipv6[0], &entry->data.u.prv_ipv6[0],
6833 }/* end of ingress */
6835 #ifdef CGNAPT_DEBUGGING
6836 static int static_count;
6838 if (static_count++ < 10) {
6840 my_print_entry(entry);
6841 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6842 printf("dest_add:%x\n", entry->data.u.prv_ip);
6843 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6847 memset(nh_ipv6, 0, 16);
6848 struct nd_entry_data *ret_nd_data = NULL;
6849 ret_nd_data = get_dest_mac_address_ipv6_port
6850 (&dest_addr_ipv6[0], &dest_if,
6851 (struct ether_addr *)eth_dest, &nh_ipv6[0]);
6853 *outport_id = p_nat->outport_id[dest_if];
6855 if (nd_cache_dest_mac_present(dest_if)) {
6856 ether_addr_copy(get_link_hw_addr(dest_if),
6857 (struct ether_addr *)eth_src);
6858 update_nhip_access(dest_if);
6860 if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) {
6861 p_nat->naptedPktCount += ret_nd_data->num_pkts;
6862 nd_send_buffered_pkts(ret_nd_data,
6863 (struct ether_addr *)eth_dest, *outport_id);
6866 if (unlikely(ret_nd_data == NULL)) {
6868 #ifdef CGNAPT_DEBUGGING
6869 printf("%s: NHIP Not Found "
6870 "outport_id: %d\n", __func__,
6875 p_nat->invalid_packets |= pkt_mask;
6876 p_nat->naptDroppedPktCount++;
6878 #ifdef CGNAPT_DEBUGGING
6879 p_nat->naptDroppedPktCount4++;
6884 if (ret_nd_data->status == INCOMPLETE ||
6885 ret_nd_data->status == PROBE) {
6887 if (ret_nd_data->num_pkts >= NUM_DESC) {
6889 p_nat->invalid_packets |= pkt_mask;
6890 p_nat->naptDroppedPktCount++;
6892 #ifdef CGNAPT_DEBUGGING
6893 p_nat->naptDroppedPktCount4++;
6897 arp_pkts_mask |= pkt_mask;
6898 nd_queue_unresolved_packet(ret_nd_data, pkt);
6906 /* start of Ingress */
6908 convert_ipv4_to_ipv6(pkt, &ipv4_hdr);
6910 /* Ethernet MTU check */
6911 if ((rte_pktmbuf_data_len(pkt) - 14) > 1500) {
6912 p_nat->invalid_packets |= pkt_mask;
6913 p_nat->naptDroppedPktCount++;
6916 uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
6917 DST_ADR_OFST_IP4t6);
6918 uint16_t *dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
6919 DST_PRT_OFST_IP4t6);
6921 memcpy((uint8_t *) &dst_addr[0],
6922 &entry->data.u.prv_ipv6[0], 16);
6924 #ifdef NAT_ONLY_CONFIG_REQ
6925 if (!nat_only_config_flag) {
6927 *dst_port = rte_bswap16(entry->data.prv_port);
6929 #ifdef NAT_ONLY_CONFIG_REQ
6933 p_nat->inaptedPktCount++;
6934 } /* end of ingress */
6936 p_nat->naptedPktCount++;
6939 if (p_nat->hw_checksum_reqd)
6940 hw_checksum(pkt, pkt_type);
6942 sw_checksum(pkt, pkt_type);
6944 } /* end of for loop */
6948 * Input port handler for IPv6 private traffic
6949 * Starting from the packet burst it filters unwanted packets,
6950 * calculates keys, does lookup and then based on the lookup
6951 * updates NAPT table and does packet NAPT translation.
6954 * A pointer to struct rte_pipeline
6956 * A pointer to array of packets mbuf
6958 * Number of packets in the burst
6963 * int that is not checked by caller
6965 static int cgnapt_in_port_ah_ipv6_prv(struct rte_pipeline *rte_p,
6966 struct rte_mbuf **pkts,
6967 uint32_t n_pkts, void *arg)
6970 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
6971 struct pipeline_cgnapt *p_nat = ap->p;
6973 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
6974 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
6975 p_nat->invalid_packets = 0;
6978 #ifdef CGNAPT_DBG_PRNT
6979 if (CGNAPT_DEBUG > 1)
6980 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
6983 /* prefetching for mbufs should be done here */
6984 for (j = 0; j < n_pkts; j++)
6985 rte_prefetch0(pkts[j]);
6987 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
6988 pkt4_work_cgnapt_key_ipv6_prv(&pkts[i], i, arg, p_nat);
6990 for (; i < n_pkts; i++)
6991 pkt_work_cgnapt_key_ipv6_prv(pkts[i], i, arg, p_nat);
6993 p_nat->valid_packets &= ~(p_nat->invalid_packets);
6995 if (arp_pkts_mask) {
6996 p_nat->valid_packets &= ~(arp_pkts_mask);
6997 rte_pipeline_ah_packet_hijack(rte_p, arp_pkts_mask);
7000 if (unlikely(p_nat->valid_packets == 0)) {
7001 /* no suitable packet for lookup */
7002 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7003 return p_nat->valid_packets;
7006 /* lookup entries in the common napt table */
7008 int lookup_result = rte_hash_lookup_bulk(
7010 (const void **) &p_nat->key_ptrs,
7011 /* should be minus num invalid pkts */
7013 /*new pipeline data member */
7014 &p_nat->lkup_indx[0]);
7016 if (unlikely(lookup_result < 0)) {
7017 /* unknown error, just discard all packets */
7018 printf("Unexpected hash lookup error %d, "
7019 "discarding all packets",
7021 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
7025 /* Now call second stage of pipeline to one by one
7026 * check the result of our bulk lookup
7029 /* prefetching for table entries should be done here */
7030 for (j = 0; j < n_pkts; j++) {
7031 if (p_nat->lkup_indx[j] >= 0)
7032 rte_prefetch0(&napt_hash_tbl_entries
7033 [p_nat->lkup_indx[j]]);
7036 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7037 pkt4_work_cgnapt_ipv6_prv(&pkts[i], i, arg, p_nat);
7039 for (; i < n_pkts; i++)
7040 pkt_work_cgnapt_ipv6_prv(pkts[i], i, arg, p_nat);
7042 if (p_nat->invalid_packets) {
7043 /* get rid of invalid packets */
7044 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7046 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7048 #ifdef CGNAPT_DBG_PRNT
7049 if (CGNAPT_DEBUG > 1) {
7050 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
7051 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
7052 printf("invalid_packets:0x%jx\n",
7053 p_nat->invalid_packets);
7054 printf("rte_invalid_packets :0x%jx\n",
7055 rte_p->pkts_drop_mask);
7056 printf("Total pkts dropped :0x%jx\n",
7057 rte_p->n_pkts_ah_drop);
7062 return p_nat->valid_packets;
7067 * Input port handler for IPv6 public traffic
7068 * Starting from the packet burst it filters unwanted packets,
7069 * calculates keys, does lookup and then based on the lookup
7070 * updates NAPT table and does packet NAPT translation.
7073 * A pointer to struct rte_pipeline
7075 * A pointer to array of packets mbuf
7077 * Number of packets in the burst
7082 * int that is not checked by caller
7084 static int cgnapt_in_port_ah_ipv6_pub(struct rte_pipeline *rte_p,
7085 struct rte_mbuf **pkts,
7086 uint32_t n_pkts, void *arg)
7089 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
7090 struct pipeline_cgnapt *p_nat = ap->p;
7092 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
7093 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
7094 p_nat->invalid_packets = 0;
7097 #ifdef CGNAPT_DBG_PRNT
7098 if (CGNAPT_DEBUG > 1)
7099 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
7102 /* prefetching for mbufs should be done here */
7103 for (j = 0; j < n_pkts; j++)
7104 rte_prefetch0(pkts[j]);
7106 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7107 pkt4_work_cgnapt_key_ipv6_pub(&pkts[i], i, arg, p_nat);
7109 for (; i < n_pkts; i++)
7110 pkt_work_cgnapt_key_ipv6_pub(pkts[i], i, arg, p_nat);
7112 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7114 if (arp_pkts_mask) {
7115 p_nat->valid_packets &= ~(arp_pkts_mask);
7116 rte_pipeline_ah_packet_hijack(rte_p, arp_pkts_mask);
7119 if (unlikely(p_nat->valid_packets == 0)) {
7120 /* no suitable packet for lookup */
7121 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7122 return p_nat->valid_packets;
7125 /* lookup entries in the common napt table */
7127 int lookup_result = rte_hash_lookup_bulk(
7129 (const void **) &p_nat->key_ptrs,
7130 /* should be minus num invalid pkts */
7132 /*new pipeline data member */
7133 &p_nat->lkup_indx[0]);
7135 if (unlikely(lookup_result < 0)) {
7136 /* unknown error, just discard all packets */
7137 printf("Unexpected hash lookup error %d, "
7138 "discarding all packets",
7140 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
7144 /* Now call second stage of pipeline to one by one
7145 * check the result of our bulk lookup
7148 /* prefetching for table entries should be done here */
7149 for (j = 0; j < n_pkts; j++) {
7150 if (p_nat->lkup_indx[j] >= 0)
7151 rte_prefetch0(&napt_hash_tbl_entries
7152 [p_nat->lkup_indx[j]]);
7155 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7156 pkt4_work_cgnapt_ipv6_pub(&pkts[i], i, arg, p_nat);
7158 for (; i < n_pkts; i++)
7159 pkt_work_cgnapt_ipv6_pub(pkts[i], i, arg, p_nat);
7161 if (p_nat->invalid_packets) {
7162 /* get rid of invalid packets */
7163 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7165 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7167 #ifdef CGNAPT_DBG_PRNT
7168 if (CGNAPT_DEBUG > 1) {
7169 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
7170 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
7171 printf("invalid_packets:0x%jx\n",
7172 p_nat->invalid_packets);
7173 printf("rte_invalid_packets :0x%jx\n",
7174 rte_p->pkts_drop_mask);
7175 printf("Total pkts dropped :0x%jx\n",
7176 rte_p->n_pkts_ah_drop);
7181 return p_nat->valid_packets;
7185 * Function to send ICMP dest unreachable msg
7188 void send_icmp_dest_unreachable_msg(void)
7191 struct ether_hdr *eth_h;
7192 struct ipv4_hdr *ip_h;
7193 struct icmp_hdr *icmp_h;
7194 struct rte_mbuf *icmp_pkt = cgnapt_icmp_pkt;
7196 if (icmp_pkt == NULL) {
7198 printf("Error allocating icmp_pkt rte_mbuf\n");
7202 port_id = icmp_pkt->port;
7204 struct app_link_params *link;
7205 link = &mylink[port_id];
7206 eth_h = rte_pktmbuf_mtod(icmp_pkt, struct ether_hdr *);
7207 ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
7208 icmp_h = (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
7210 struct ether_addr gw_addr;
7211 struct ether_addr dst_addr;
7212 ether_addr_copy(ð_h->s_addr, &dst_addr);
7213 rte_eth_macaddr_get(port_id, &gw_addr);
7214 ether_addr_copy(&gw_addr, ð_h->s_addr);
7215 ether_addr_copy(&dst_addr, ð_h->d_addr);
7217 eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
7218 ip_h->version_ihl = IP_VHL_DEF;
7219 ip_h->type_of_service = 0;
7220 ip_h->total_length = rte_cpu_to_be_16(sizeof(struct ipv4_hdr) +
7221 sizeof(struct icmp_hdr));
7222 ip_h->packet_id = 0xaabb;
7223 ip_h->fragment_offset = 0x0000;
7224 ip_h->time_to_live = 64;
7225 ip_h->next_proto_id = 1;
7228 uint32_t src_addr_offset =
7229 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_SRC_ADR_OFST;
7231 RTE_MBUF_METADATA_UINT32_PTR(cgnapt_icmp_pkt, src_addr_offset);
7233 ip_h->dst_addr = *src_addr;
7234 ip_h->src_addr = rte_bswap32(link->ip);
7236 ip_h->dst_addr = *src_addr;
7237 ip_h->src_addr = rte_bswap32(link->ip);
7239 ip_h->hdr_checksum = 0;
7240 ip_h->hdr_checksum = rte_ipv4_cksum(ip_h);
7241 icmp_h->icmp_type = 3; /* Destination Unreachable */
7242 icmp_h->icmp_code = 13; /* Communication administratively prohibited */
7244 icmp_h->icmp_cksum = ~rte_raw_cksum(icmp_h, sizeof(struct icmp_hdr));
7246 icmp_pkt->pkt_len = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
7247 sizeof(struct icmp_hdr);
7248 icmp_pkt->data_len = icmp_pkt->pkt_len;
7249 if (ARPICMP_DEBUG) {
7250 printf("Sending ICMP error message - "
7251 "Destination Unreachable\n");
7253 rte_pipeline_port_out_packet_insert(myP, port_id, icmp_pkt);
7257 * Function to add a dynamic NAPT entry pair
7260 * A pointer to struct pipeline
7262 * A pointer to struct pipeline_cgnapt_entry_key
7264 * expairy time of an dynamic or PCP req entry
7266 * uint8_t pointer of source address
7269 * A pointer to struct cgnapt_table_entry for added entry
7272 struct cgnapt_table_entry *add_dynamic_cgnapt_entry(
7274 struct pipeline_cgnapt_entry_key *key,
7281 void *entry_ptr, *ret_ptr;
7284 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
7286 #ifdef CGNAPT_DBG_PRNT
7287 if (CGNAPT_DEBUG >= 1) {
7288 printf("Th%d add_dynamic_cgnapt_entry key detail Entry:"
7289 "0x%x, %d, %d\n", p_nat->pipeline_num, key->ip, key->port,
7294 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX && i < p_nat->pkt_burst_cnt;
7296 if (p_nat->cgnapt_dyn_ent_table[i].ip == key->ip
7297 && p_nat->cgnapt_dyn_ent_table[i].port == key->port
7298 && p_nat->cgnapt_dyn_ent_table[i].pid == key->pid) {
7300 #ifdef CGNAPT_DBG_PRNT
7301 if (CGNAPT_DEBUG > 1)
7302 printf("add_dynamic_cgnapt_entry:pkt_burst "
7303 "array key matched!!!\n");
7306 return &napt_hash_tbl_entries
7307 [p_nat->cgnapt_dyn_ent_index[i]];
7311 #ifdef NAT_ONLY_CONFIG_REQ
7312 if (!nat_only_config_flag) {
7315 ret = increment_max_port_counter(key->ip, key->pid, p_nat);
7316 if (ret == MAX_PORT_INC_ERROR) {
7318 #ifdef CGNAPT_DEBUGGING
7319 p_nat->missedpktcount5++;
7322 #ifdef CGNAPT_DBG_PRNT
7323 if (CGNAPT_DEBUG > 1)
7324 printf("add_dynamic_cgnapt_entry:"
7325 "increment_max_port_counter-1 failed\n");
7332 if (ret == MAX_PORT_INC_REACHED) {
7334 #ifdef CGNAPT_DEBUGGING
7335 p_nat->missedpktcount6++;
7338 #ifdef CGNAPT_DBG_PRNT
7339 if (CGNAPT_DEBUG > 1)
7340 printf("add_dynamic_cgnapt_entry:"
7341 "increment_max_port_counter-2 failed\n");
7348 #ifdef NAT_ONLY_CONFIG_REQ
7353 port_num = get_free_iport(p_nat, &public_ip);
7355 if (port_num == -1) {
7357 #ifdef CGNAPT_DBG_PRNT
7358 if (CGNAPT_DEBUG > 2) {
7359 printf("add_dynamic_cgnapt_entry: %d\n", port_num);
7360 printf("add_dynamic_cgnapt_entry key detail:0x%x, "
7361 "%d, %d\n", key->ip, key->port, key->pid);
7365 #ifdef CGNAPT_DEBUGGING
7366 p_nat->missedpktcount7++;
7373 #ifdef NAT_ONLY_CONFIG_REQ
7374 if (!nat_only_config_flag) {
7377 if (ret == 2) { //MPPC_NEW_ENTRY
7379 /* check for max_clients_per_ip */
7380 if (rte_atomic16_read
7382 [rte_jhash(&public_ip, 4, 0) %
7383 CGNAPT_MAX_PUB_IP].count) ==
7384 p_nat->max_clients_per_ip) {
7386 /* For now just bail out
7387 * In future we can think about
7388 * retrying getting a new iport
7391 release_iport(port_num, public_ip, p_nat);
7393 #ifdef CGNAPT_DEBUGGING
7394 p_nat->missedpktcount10++;
7400 rte_atomic16_inc(&all_public_ip
7401 [rte_jhash(&public_ip, 4, 0) %
7402 CGNAPT_MAX_PUB_IP].count);
7404 #ifdef CGNAPT_DBG_PRNT
7405 if ((rte_jhash(&public_ip, 4, 0) %
7406 CGNAPT_MAX_PUB_IP) == 8)
7407 printf("pub ip:%x coutn:%d\n", public_ip,
7408 rte_atomic16_read(&all_public_ip
7409 [rte_jhash(&public_ip, 4, 0) %
7410 CGNAPT_MAX_PUB_IP].count));
7414 #ifdef NAT_ONLY_CONFIG_REQ
7418 #ifdef CGNAPT_DBG_PRNT
7419 if (CGNAPT_DEBUG > 0) {
7420 printf("add_dynamic_cgnapt_entry: %d\n",
7422 printf("add_dynamic_cgnapt_entry key detail: "
7423 "0x%x, %d, %d\n", key->ip, key->port, key->pid);
7427 struct cgnapt_table_entry entry = {
7429 .action = RTE_PIPELINE_ACTION_PORT,
7430 /* made it configurable below */
7431 {.port_id = p->port_out_id[0]},
7435 .prv_port = key->port,
7436 .pub_ip = public_ip,
7437 .pub_port = port_num,
7438 .prv_phy_port = key->pid,
7439 .pub_phy_port = get_pub_to_prv_port(
7443 /* if(timeout == -1) : static entry
7444 * if(timeout == 0 ) : dynamic entry
7445 * if(timeout > 0 ) : PCP requested entry
7447 .timeout = timeout > 0 ? timeout : 0,
7454 #ifdef NAT_ONLY_CONFIG_REQ
7455 if (nat_only_config_flag) {
7456 entry.data.prv_port = 0xffff;
7457 entry.data.pub_port = 0xffff;
7461 if (pkt_type == CGNAPT_ENTRY_IPV6) {
7462 entry.data.type = CGNAPT_ENTRY_IPV6;
7463 memcpy(&entry.data.u.prv_ipv6[0], src_addr, 16);
7465 entry.data.u.prv_ip = key->ip;
7466 entry.data.type = CGNAPT_ENTRY_IPV4;
7469 //entry.head.port_id = CGNAPT_PUB_PORT_ID; /* outgoing port info */
7470 entry.head.port_id = entry.data.pub_phy_port; /* outgoing port info */
7472 struct pipeline_cgnapt_entry_key second_key;
7473 /* Need to add a second ingress entry */
7474 second_key.ip = public_ip;
7475 second_key.port = port_num;
7476 second_key.pid = 0xffff;
7478 #ifdef NAT_ONLY_CONFIG_REQ
7479 if (nat_only_config_flag)
7480 second_key.port = 0xffff;
7483 #ifdef CGNAPT_DBG_PRNT
7484 if (CGNAPT_DEBUG > 2)
7485 printf("add_dynamic_cgnapt_entry second key detail:"
7486 "0x%x, %d, %d\n", second_key.ip, second_key.port,
7490 int32_t position = rte_hash_add_key(napt_common_table, (void *)key);
7493 #ifdef CGNAPT_DEBUGGING
7494 p_nat->missedpktcount8++;
7497 printf("CG-NAPT entry add failed ...returning "
7498 "without adding ... %d\n", position);
7503 #ifdef CGNAPT_DBG_PRNT
7505 printf("add_dynamic_cgnapt_entry\n");
7507 print_cgnapt_entry(&entry);
7511 memcpy(&napt_hash_tbl_entries[position], &entry,
7512 sizeof(struct cgnapt_table_entry));
7514 /* this pointer is returned to pkt miss function */
7515 ret_ptr = &napt_hash_tbl_entries[position];
7517 p_nat->n_cgnapt_entry_added++;
7518 p_nat->dynCgnaptCount++;
7520 /* Now modify the forward port for reverse entry */
7522 /* outgoing port info */
7523 //entry.head.port_id = CGNAPT_PRV_PORT_ID;
7524 /* outgoing port info */
7525 entry.head.port_id = entry.data.prv_phy_port;
7527 int32_t position2 = rte_hash_add_key(napt_common_table, &second_key);
7529 if (position2 < 0) {
7530 #ifdef CGNAPT_DEBUGGING
7531 p_nat->missedpktcount9++;
7533 printf("CG-NAPT entry reverse bulk add failed ..."
7534 "returning with fwd add ...%d\n",
7540 memcpy(&napt_hash_tbl_entries[position2], &entry,
7541 sizeof(struct cgnapt_table_entry));
7543 entry_ptr = &napt_hash_tbl_entries[position2];
7545 timer_thread_enqueue(key, &second_key, ret_ptr,
7546 entry_ptr, (struct pipeline *)p_nat);
7548 p_nat->n_cgnapt_entry_added++;
7549 p_nat->dynCgnaptCount++;
7551 if (p_nat->pkt_burst_cnt < RTE_PORT_IN_BURST_SIZE_MAX) {
7552 memcpy(&p_nat->cgnapt_dyn_ent_table[p_nat->pkt_burst_cnt], key,
7553 sizeof(struct pipeline_cgnapt_entry_key));
7554 p_nat->cgnapt_dyn_ent_index[p_nat->pkt_burst_cnt] = position;
7555 p_nat->pkt_burst_cnt++;
7560 int pkt_miss_cgnapt_count;
7562 * Function handle a missed NAPT entry lookup
7563 * Will attempt to add a dynamic entry pair.
7566 * A pointer to struct pipeline
7568 * A pointer to struct pipeline_cgnapt_entry_key
7570 * A pointer to pkt struct rte_mbuf
7572 * uint64_t pointer to pkt mask
7573 * @param table_entry
7574 * A pointer to struct rte_pipeline_table_entry to be created and returned
7576 * number of this pkt in current burst
7579 * A uint64_t mask for drop packets
7582 pkt_miss_cgnapt(struct pipeline_cgnapt_entry_key *key,
7583 struct rte_mbuf *pkt,
7584 struct rte_pipeline_table_entry **table_entry,
7585 __rte_unused uint64_t *pkts_mask,
7586 uint32_t pkt_num, void *arg)
7589 #ifdef CGNAPT_DBG_PRNT
7590 if (CGNAPT_DEBUG > 0)
7591 printf("\n pkt_miss_cgnapt\n");
7595 * see if get_port passes for this src address
7596 * if passed add a new egress entry and a
7597 * corresponding new ingress entry
7598 * return the fwd entry to calling function using input pointer
7599 * else if get_port fails drop packet
7602 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)arg;
7604 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
7605 uint32_t src_addr_offset_ipv6 =
7606 MBUF_HDR_ROOM + ETH_HDR_SIZE + IPV6_HDR_SRC_ADR_OFST;
7607 uint16_t phy_port = pkt->port;
7609 uint16_t *eth_proto =
7610 RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
7612 uint8_t *src_addr = NULL;
7613 uint8_t src_addr_ipv6[16];
7614 uint8_t pkt_type = CGNAPT_ENTRY_IPV4;
7615 /* To drop the packet */
7616 uint64_t drop_mask = 0;
7618 if (p_nat->is_static_cgnapt) {
7619 drop_mask |= 1LLU << pkt_num;
7620 p_nat->missedPktCount++;
7622 #ifdef CGNAPT_DEBUGGING
7623 p_nat->missedpktcount1++;
7628 if (rte_be_to_cpu_16(*eth_proto) == ETHER_TYPE_IPv6) {
7630 RTE_MBUF_METADATA_UINT8_PTR(pkt, src_addr_offset_ipv6);
7631 pkt_type = CGNAPT_ENTRY_IPV6;
7632 memcpy(src_addr_ipv6, src_addr, 16);
7637 /* some validation first */
7638 if (is_phy_port_privte(phy_port)) {
7639 /* dynamic NAPT entry creation */
7640 *table_entry = (struct rte_pipeline_table_entry *)
7641 add_dynamic_cgnapt_entry(
7642 (struct pipeline *)&p_nat->p,
7644 DYNAMIC_CGNAPT_TIMEOUT,
7646 src_addr_ipv6, &err);
7648 if (!(*table_entry)) {
7650 drop_mask |= 1LLU << pkt_num;
7651 p_nat->missedPktCount++;
7653 #ifdef CGNAPT_DEBUGGING
7654 p_nat->missedpktcount2++;
7657 #ifdef CGNAPT_DBG_PRNT
7658 if (CGNAPT_DEBUG > 1)
7659 printf("Add Dynamic NAT entry failed "
7663 #ifdef CGNAPT_DEBUGGING
7664 p_nat->missedpktcount11++;
7669 } else if (!is_phy_port_privte(phy_port)) {
7671 #ifdef CGNAPT_DBG_PRNT
7672 if (CGNAPT_DEBUG >= 2) {
7673 printf("Initial Ingress entry creation NOT ALLOWED "
7678 drop_mask |= 1LLU << pkt_num;
7679 p_nat->missedPktCount++;
7681 #ifdef CGNAPT_DEBUGGING
7682 p_nat->missedpktcount3++;
7686 #ifdef CGNAPT_DBG_PRNT
7687 if (CGNAPT_DEBUG > 1)
7688 printf("NOT a PRIVATE or PUBLIC port!!!!!\n");
7691 drop_mask |= 1LLU << pkt_num;
7692 p_nat->missedPktCount++;
7694 #ifdef CGNAPT_DEBUGGING
7695 p_nat->missedpktcount4++;
7699 #ifdef CGNAPT_DBG_PRNT
7700 if (CGNAPT_DEBUG > 5)
7710 * Function to print the contents of a packet
7713 * A pointer to pkt struct rte_mbuf
7715 void print_pkt(struct rte_mbuf *pkt)
7719 printf("\nPacket Contents:\n");
7721 uint8_t *rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
7723 for (i = 0; i < 20; i++) {
7724 for (j = 0; j < 20; j++)
7725 printf("%02x ", rd[(20 * i) + j]);
7731 rte_table_hash_op_hash cgnapt_hash_func[] = {
7743 * Function to parse incoming pipeline arguments
7744 * Called during pipeline initialization
7747 * A pointer to struct pipeline_cgnapt
7749 * A pointer to struct pipeline_params
7752 * 0 if success, negative if failure
7755 pipeline_cgnapt_parse_args(struct pipeline_cgnapt *p,
7756 struct pipeline_params *params)
7758 uint32_t n_flows_present = 0;
7759 uint32_t key_offset_present = 0;
7760 uint32_t key_size_present = 0;
7761 uint32_t hash_offset_present = 0;
7762 uint32_t n_entries_present = 0;
7763 uint32_t max_port_present = 0;
7764 uint32_t max_client_present = 0;
7765 uint32_t public_ip_range_present = 0;
7766 uint32_t public_ip_port_range_present = 0;
7768 uint8_t public_ip_count = 0;
7769 uint8_t public_ip_range_count = 0;
7770 uint8_t dest_if_offset_present = 0;
7771 uint8_t cgnapt_meta_offset_present = 0;
7772 uint8_t prv_que_handler_present = 0;
7773 uint8_t n_prv_in_port = 0;
7775 if (CGNAPT_DEBUG > 2) {
7776 printf("CGNAPT pipeline_cgnapt_parse_args params->n_args: %d\n",
7779 for (i = 0; i < params->n_args; i++) {
7780 char *arg_name = params->args_name[i];
7781 char *arg_value = params->args_value[i];
7783 if (CGNAPT_DEBUG > 2) {
7784 printf("CGNAPT args[%d]: %s %d, %s\n", i, arg_name,
7785 atoi(arg_value), arg_value);
7787 if (strcmp(arg_name, "prv_que_handler") == 0) {
7789 if (prv_que_handler_present) {
7790 printf("Duplicate pktq_in_prv ..\n\n");
7793 prv_que_handler_present = 1;
7798 /* get the first token */
7799 token = strtok(arg_value, "(");
7800 token = strtok(token, ")");
7801 token = strtok(token, ",");
7802 printf("***** prv_que_handler *****\n");
7804 if (token == NULL) {
7805 printf("string is null\n");
7806 printf("invalid prv_que_handler value/n");
7809 printf("string is :%s\n", token);
7811 /* walk through other tokens */
7812 while (token != NULL) {
7813 printf(" %s\n", token);
7814 rxport = atoi(token);
7815 cgnapt_prv_que_port_index[n_prv_in_port++] =
7817 if (rxport < PIPELINE_MAX_PORT_IN)
7818 cgnapt_in_port_egress_prv[rxport] = 1;
7819 token = strtok(NULL, ",");
7822 if (n_prv_in_port == 0) {
7823 printf("VNF common parse err - "
7824 "no prv RX phy port\n");
7830 if (strcmp(arg_name, "cgnapt_meta_offset") == 0) {
7831 if (cgnapt_meta_offset_present) {
7832 printf("CG-NAPT parse error:");
7833 printf("cgnapt_meta_offset initizlized "
7834 "mulitple times\n");
7837 cgnapt_meta_offset_present = 1;
7839 temp = atoi(arg_value);
7842 printf("cgnapt_meta_offset is invalid :");
7843 printf("Not be more than metadata size\n");
7846 cgnapt_meta_offset = (uint16_t) temp;
7848 if (strcmp(arg_name, "vnf_set") == 0)
7851 if (strcmp(arg_name, "public_ip_range") == 0) {
7852 public_ip_range_present = 1;
7853 if (public_ip_port_range_present) {
7854 printf("CG-NAPT parse error:");
7855 printf("public_ip_range with "
7856 "public_ip_port_range_present\n");
7860 p->pub_ip_range = rte_realloc(p->pub_ip_range,
7863 RTE_CACHE_LINE_SIZE);
7865 if (!p->pub_ip_range) {
7866 printf("Memory allocation failed for "
7871 uint32_t sip = 0, eip = 0;
7873 if (sscanf(arg_value, "(%x,%x)", &sip, &eip) != 2) {
7874 printf("public_ip_range is invalid\n");
7878 if (sip <= 0 || eip <= 0 || sip >= eip) {
7879 printf("public_ip_range is invalid %x-%x\n",
7884 printf("public_ip_range: %d-%d\n",
7885 p->pub_ip_range[public_ip_range_count].
7887 p->pub_ip_range[public_ip_range_count].
7890 p->pub_ip_range_count = ++public_ip_range_count;
7894 if (strcmp(arg_name, "public_ip_port_range") == 0) {
7895 public_ip_port_range_present = 1;
7896 if (nat_only_config_flag || public_ip_range_present) {
7898 printf("CG-NAPT parse error:");
7899 printf("nat_only_config_flag OR ");
7900 printf("public_ip_range_present with "
7901 "public_ip_port_range_present\n");
7905 p->pub_ip_port_set = rte_realloc(
7907 sizeof(struct pub_ip_port_set),
7908 RTE_CACHE_LINE_SIZE);
7910 if (!p->pub_ip_port_set) {
7911 printf("Memory allocation failed for "
7919 if (sscanf(arg_value, "%x:(%d,%d)",
7920 &ip, &sp, &ep) != 3) {
7921 printf("Public IP or Port-range is invalid\n");
7925 if (ip <= 0 || sp <= 0 || ep <= 0 || sp > ep) {
7926 printf("Public IP or Port-range is invalid "
7927 "%x:%d-%d\n", ip, sp, ep);
7931 printf("public_ip: 0x%x Range:%d-%d\n",
7932 p->pub_ip_port_set[public_ip_count].ip = ip,
7933 p->pub_ip_port_set[public_ip_count].start_port = sp,
7934 p->pub_ip_port_set[public_ip_count].end_port = ep);
7936 napt_port_alloc_elem_count += (ep - sp + 1);
7937 printf("parse - napt_port_alloc_elem_count :%d\n",
7938 napt_port_alloc_elem_count);
7940 /* Store all public IPs of all CGNAPT threads
7941 * in the global variable
7943 /* to revisit indexing */
7944 all_public_ip[rte_jhash(&ip, 4, 0) %
7945 CGNAPT_MAX_PUB_IP].ip = ip;
7946 p->pub_ip_count = ++public_ip_count;
7947 printf("public_ip_count:%d hash:%d\n", public_ip_count,
7948 rte_jhash(&ip, 4, 0) % CGNAPT_MAX_PUB_IP);
7952 /* hw_checksum_reqd */
7953 if (strcmp(arg_name, "hw_checksum_reqd") == 0) {
7955 temp = atoi(arg_value);
7956 if ((temp != 0) && (temp != 1)) {
7957 printf("hw_checksum_reqd is invalid\n");
7960 p->hw_checksum_reqd = temp;
7964 /* nat_only_config_flag */
7965 if (strcmp(arg_name, "nat_only_config_flag") == 0) {
7966 nat_only_config_flag = 1;
7967 if (public_ip_port_range_present) {
7969 printf("CG-NAPT parse error:");
7970 printf("nat_only_config_flag with "
7971 "public_ip_port_range_present\n");
7977 /* max_port_per_client */
7978 if (strcmp(arg_name, "max_port_per_client") == 0) {
7979 if (max_port_present) {
7980 printf("CG-NAPT Parse Error: "
7981 "duplicate max_port_per_client\n");
7984 max_port_present = 1;
7987 max = atoi(arg_value);
7989 printf("max_port_per_client is invalid !!!\n");
7993 p->max_port_per_client = (uint16_t) max;
7995 if (p->max_port_per_client <= 0) {
7996 printf("max port per client is invalid\n");
8000 printf("max_port_per_client comp: %d\n",
8001 p->max_port_per_client);
8005 /* max_clients_per_ip */
8006 if (strcmp(arg_name, "max_clients_per_ip") == 0) {
8007 if (max_client_present) {
8008 printf("CG-NAPT parse Error: duplicate "
8009 "max_clients_per_ip\n");
8012 max_client_present = 1;
8014 if (nat_only_config_flag) {
8015 printf("CG-NAPT parse error:");
8016 printf("nat_only_config_flag with "
8017 "max_clients_per_ip\n");
8022 max = atoi(arg_value);
8024 printf("max_clients_per_ip is invalid !!!\n");
8028 p->max_clients_per_ip = (uint16_t) max;
8030 if (p->max_clients_per_ip <= 0) {
8031 printf("max_clients_per_ip is invalid\n");
8035 printf("max_clients_per_ip: %d\n",
8036 p->max_clients_per_ip);
8041 if (strcmp(arg_name, "n_entries") == 0) {
8042 if (n_entries_present)
8044 n_entries_present = 1;
8046 p->n_entries = atoi(arg_value);
8047 if (p->n_entries == 0)
8054 if (strcmp(arg_name, "n_flows") == 0) {
8055 if (n_flows_present)
8057 n_flows_present = 1;
8059 p->n_flows = atoi(arg_value);
8060 if (p->n_flows == 0)
8063 napt_common_table_hash_params.entries = p->n_flows;
8066 /* dest_if_offset Multiport Changes */
8067 if (strcmp(arg_name, "dest_if_offset") == 0) {
8068 if (dest_if_offset_present)
8070 //dest_if_offset_present = 1;
8072 dest_if_offset = atoi(arg_value);
8078 if (strcmp(arg_name, "key_offset") == 0) {
8079 if (key_offset_present)
8081 key_offset_present = 1;
8083 p->key_offset = atoi(arg_value);
8089 if (strcmp(arg_name, "key_size") == 0) {
8090 if (key_size_present)
8092 key_size_present = 1;
8094 p->key_size = atoi(arg_value);
8095 if ((p->key_size == 0) ||
8096 (p->key_size > PIPELINE_CGNAPT_KEY_MAX_SIZE) ||
8104 if (strcmp(arg_name, "hash_offset") == 0) {
8105 if (hash_offset_present)
8107 hash_offset_present = 1;
8109 p->hash_offset = atoi(arg_value);
8115 if (strcmp(arg_name, "pkt_type") == 0) {
8116 if (strcmp(arg_value, "ipv4") == 0) {
8117 p->traffic_type = TRAFFIC_TYPE_IPV4;
8118 printf("Traffic is set to IPv4\n");
8119 } else if (strcmp(arg_value, "ipv6") == 0) {
8120 p->traffic_type = TRAFFIC_TYPE_IPV6;
8121 printf("Traffic is set to IPv6\n");
8127 if (strcmp(arg_name, "cgnapt_debug") == 0) {
8128 CGNAPT_DEBUG = atoi(arg_value);
8133 /* any other Unknown argument return -1 */
8136 #ifdef NAT_ONLY_CONFIG_REQ
8137 if (nat_only_config_flag) {
8138 if (!public_ip_range_count) {
8139 printf("No public_ip_range %d for NAT only config.\n",
8140 public_ip_range_count);
8141 printf("Running static NAT only configuration\n");
8142 p->is_static_cgnapt = 1;
8147 if (!p->max_port_per_client)
8148 p->is_static_cgnapt = 1;
8151 /* Check that mandatory arguments are present */
8152 if ((n_flows_present == 0) ||
8153 (cgnapt_meta_offset_present == 0))
8160 * Function to initialize the pipeline
8163 * A pointer to struct pipeline_params
8165 * Void pointer - points to app params
8168 * void pointer to the pipeline, NULL 0 if failure
8170 static void *pipeline_cgnapt_init(struct pipeline_params *params, void *arg)
8171 /* (struct app_params *app) save it for use in port in handler */
8174 struct pipeline_cgnapt *p_nat;
8175 uint32_t size, i, in_ports_arg_size;
8177 /* Check input arguments */
8178 if ((params == NULL) ||
8179 (params->n_ports_in == 0) || (params->n_ports_out == 0))
8182 /* Memory allocation */
8183 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_cgnapt));
8184 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8185 p_nat = (struct pipeline_cgnapt *)p;
8186 global_pnat = p_nat;
8190 all_pipeline_cgnapt[n_cgnapt_pipeline++] = p_nat;
8192 strcpy(p->name, params->name);
8193 p->log_level = params->log_level;
8195 PLOG(p, HIGH, "CG-NAPT");
8196 /* Initialize all counters and arrays */
8198 p_nat->n_cgnapt_entry_deleted = 0;
8199 p_nat->n_cgnapt_entry_added = 0;
8200 p_nat->naptedPktCount = 0;
8201 p_nat->naptDroppedPktCount = 0;
8202 p_nat->inaptedPktCount = 0;
8203 p_nat->enaptedPktCount = 0;
8204 p_nat->receivedPktCount = 0;
8205 p_nat->missedPktCount = 0;
8206 p_nat->dynCgnaptCount = 0;
8207 p_nat->arpicmpPktCount = 0;
8209 p_nat->app_params_addr = (uint64_t) arg;
8210 for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
8211 p_nat->links_map[i] = 0xff;
8212 p_nat->outport_id[i] = 0xff;
8213 cgnapt_in_port_egress_prv[i] = 0;
8214 cgnapt_prv_que_port_index[i] = 0;
8216 p_nat->pipeline_num = 0xff;
8217 p_nat->hw_checksum_reqd = 0;
8218 p_nat->pub_ip_port_set = NULL;
8219 p_nat->pub_ip_count = 0;
8220 p_nat->traffic_type = TRAFFIC_TYPE_IPV4;
8221 p_nat->vnf_set = 0xff;
8223 /* For every init it should be reset */
8224 napt_port_alloc_elem_count = 0;
8226 #ifdef CGNAPT_TIMING_INST
8227 p_nat->in_port_exit_timestamp = 0;
8228 p_nat->external_time_sum = 0;
8229 p_nat->internal_time_sum = 0;
8230 p_nat->time_measurements = 0;
8231 p_nat->max_time_mesurements = 10000;
8232 p_nat->time_measurements_on = 0;
8235 #ifdef CGNAPT_DEBUGGING
8237 p_nat->naptDebugCount = 0;
8239 p_nat->naptDroppedPktCount1 = 0;
8240 p_nat->naptDroppedPktCount2 = 0;
8241 p_nat->naptDroppedPktCount3 = 0;
8242 p_nat->naptDroppedPktCount4 = 0;
8243 p_nat->naptDroppedPktCount5 = 0;
8244 p_nat->naptDroppedPktCount6 = 0;
8246 p_nat->missedpktcount1 = 0;
8247 p_nat->missedpktcount2 = 0;
8248 p_nat->missedpktcount3 = 0;
8249 p_nat->missedpktcount4 = 0;
8250 p_nat->missedpktcount5 = 0;
8251 p_nat->missedpktcount6 = 0;
8252 p_nat->missedpktcount7 = 0;
8253 p_nat->missedpktcount8 = 0;
8254 p_nat->missedpktcount9 = 0;
8255 p_nat->missedpktcount10 = 0;
8256 p_nat->missedpktcount11 = 0;
8257 p_nat->missedpktcount12 = 0;
8259 p_nat->max_port_dec_err1 = 0;
8260 p_nat->max_port_dec_err2 = 0;
8261 p_nat->max_port_dec_err3 = 0;
8262 p_nat->max_port_dec_success = 0;
8278 static int sip_enabled;
8282 #endif /* SIP_ALG */
8284 /*struct rte_pipeline_table_entry *entries[RTE_HASH_LOOKUP_BULK_MAX];*/
8285 /* bitmap of valid packets */
8286 p_nat->valid_packets = 0;
8287 /* bitmap of invalid packets to be dropped */
8288 p_nat->invalid_packets = 0;
8290 for (i = 0; i < RTE_HASH_LOOKUP_BULK_MAX; i++)
8291 p_nat->key_ptrs[i] = &(p_nat->keys[i]);
8293 p_nat->port_alloc_ring = NULL;
8295 /* Parse arguments */
8296 if (pipeline_cgnapt_parse_args(p_nat, params))
8299 p_nat->vnf_set = vnf_set_count;
8303 struct rte_pipeline_params pipeline_params = {
8304 .name = params->name,
8305 .socket_id = params->socket_id,
8306 .offset_port_id = cgnapt_meta_offset,
8309 p->p = rte_pipeline_create(&pipeline_params);
8317 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8319 uint32_t instr_size =
8320 RTE_CACHE_LINE_ROUNDUP((sizeof(uint64_t)) *
8323 (uint64_t *) rte_zmalloc(NULL, instr_size,
8324 RTE_CACHE_LINE_SIZE);
8326 (uint64_t *) rte_zmalloc(NULL, instr_size,
8327 RTE_CACHE_LINE_SIZE);
8329 (uint32_t *) rte_zmalloc(NULL, instr_size / 2,
8330 RTE_CACHE_LINE_SIZE);
8331 if ((inst_start_time == NULL) || (inst_end_time == NULL)
8332 || (inst_diff_time == NULL)) {
8333 printf("Inst array alloc failed .... ");
8338 /* Memory allocation for in_port_h_arg */
8339 in_ports_arg_size = RTE_CACHE_LINE_ROUNDUP(
8340 (sizeof(struct pipeline_cgnapt_in_port_h_arg)) *
8341 (params->n_ports_in));
8342 struct pipeline_cgnapt_in_port_h_arg *ap =
8343 (struct pipeline_cgnapt_in_port_h_arg *)
8346 RTE_CACHE_LINE_SIZE);
8350 myApp = (struct app_params *) arg;
8353 p->n_ports_in = params->n_ports_in;
8354 for (i = 0; i < p->n_ports_in; i++) {
8355 /* passing our cgnapt pipeline in call back arg */
8357 (ap[i]).in_port_id = i;
8359 struct rte_pipeline_port_in_params port_params = {
8361 pipeline_port_in_params_get_ops(¶ms->port_in
8364 pipeline_port_in_params_convert(¶ms->port_in
8366 .f_action = cgnapt_in_port_ah_mix,
8368 .burst_size = params->port_in[i].burst_size,
8371 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8373 instrumentation_port_in_arg = &(ap[i]);
8376 if (p_nat->traffic_type == TRAFFIC_TYPE_IPV4) {
8377 /* Private in-port handler */
8378 /* Multiport changes */
8379 if (cgnapt_in_port_egress_prv[i]) {
8380 port_params.f_action =
8381 cgnapt_in_port_ah_ipv4_prv;
8382 printf("CGNAPT port %d is IPv4 Prv\n", i);
8384 port_params.f_action =
8385 cgnapt_in_port_ah_ipv4_pub;
8386 printf("CGNAPT port %d is IPv4 Pub\n", i);
8390 if (p_nat->traffic_type == TRAFFIC_TYPE_IPV6) {
8391 if (cgnapt_in_port_egress_prv[i]) {
8392 port_params.f_action =
8393 cgnapt_in_port_ah_ipv6_prv;
8394 printf("CGNAPT port %d is IPv6 Prv\n", i);
8396 port_params.f_action =
8397 cgnapt_in_port_ah_ipv6_pub;
8398 printf("CGNAPT port %d is IPv6 Pub\n", i);
8402 int status = rte_pipeline_port_in_create(p->p,
8407 rte_pipeline_free(p->p);
8415 p->n_ports_out = params->n_ports_out;
8416 for (i = 0; i < p->n_ports_out; i++) {
8417 struct rte_pipeline_port_out_params port_params = {
8418 .ops = pipeline_port_out_params_get_ops(
8419 ¶ms->port_out[i]),
8420 .arg_create = pipeline_port_out_params_convert(
8421 ¶ms->port_out[i]),
8422 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8423 .f_action = port_out_ah_cgnapt,
8430 int status = rte_pipeline_port_out_create(p->p,
8432 &p->port_out_id[i]);
8435 rte_pipeline_free(p->p);
8441 int pipeline_num = 0;
8443 ignore = sscanf(params->name, "PIPELINE%d", &pipeline_num);
8445 printf("Not able to read pipeline number\n");
8448 p_nat->pipeline_num = (uint8_t) pipeline_num;
8449 register_pipeline_Qs(p_nat->pipeline_num, p);
8450 set_link_map(p_nat->pipeline_num, p, p_nat->links_map);
8451 set_outport_id(p_nat->pipeline_num, p, p_nat->outport_id);
8457 if (napt_common_table == NULL) {
8458 if (create_napt_common_table(p_nat->n_flows)) {
8460 "CG-NAPT create_napt_common_table failed.");
8465 struct rte_pipeline_table_params table_params = {
8466 .ops = &rte_table_stub_ops,
8468 .f_action_hit = NULL,
8469 .f_action_miss = NULL,
8471 .action_data_size = 0,
8474 int status = rte_pipeline_table_create(p->p,
8479 rte_pipeline_free(p->p);
8483 struct rte_pipeline_table_entry default_entry = {
8484 .action = RTE_PIPELINE_ACTION_PORT_META
8486 struct rte_pipeline_table_entry *default_entry_ptr;
8487 status = rte_pipeline_table_default_entry_add(
8491 &default_entry_ptr);
8493 rte_pipeline_free(p->p);
8499 /* Connecting input ports to tables */
8500 for (i = 0; i < p->n_ports_in; i++) {
8501 int status = rte_pipeline_port_in_connect_to_table(p->p,
8508 rte_pipeline_free(p->p);
8514 /* Enable input ports */
8515 for (i = 0; i < p->n_ports_in; i++) {
8516 int status = rte_pipeline_port_in_enable(p->p,
8520 rte_pipeline_free(p->p);
8526 /* Check pipeline consistency */
8527 if (rte_pipeline_check(p->p) < 0) {
8528 rte_pipeline_free(p->p);
8533 /* Message queues */
8534 p->n_msgq = params->n_msgq;
8535 for (i = 0; i < p->n_msgq; i++)
8536 p->msgq_in[i] = params->msgq_in[i];
8537 for (i = 0; i < p->n_msgq; i++)
8538 p->msgq_out[i] = params->msgq_out[i];
8540 /* Message handlers */
8541 memcpy(p->handlers, handlers, sizeof(p->handlers));
8542 memcpy(p_nat->custom_handlers,
8543 custom_handlers, sizeof(p_nat->custom_handlers));
8545 if (!p_nat->is_static_cgnapt) {
8546 printf("Initializing dyn napt components ... %d\n",
8547 p_nat->pipeline_num);
8548 if (napt_port_alloc_init(p_nat) == -1) {
8549 printf("Error - napt_port_alloc_init failed - %d\n",
8550 p_nat->pipeline_num);
8555 if (max_port_per_client_hash == NULL) {
8556 rc = init_max_port_per_client(p_nat);
8558 printf("CGNAPT Error - "
8559 "init_max_port_per_client failed %d", rc);
8566 if (!icmp_pool_init) {
8568 /* create the arp_icmp mbuf rx pool */
8569 cgnapt_icmp_pktmbuf_tx_pool =
8570 rte_pktmbuf_pool_create("icmp_mbuf_tx_pool", 63, 32, 0,
8571 RTE_MBUF_DEFAULT_BUF_SIZE,
8573 if (cgnapt_icmp_pktmbuf_tx_pool == NULL) {
8574 PLOG(p, HIGH, "ICMP mbuf pool create failed.");
8579 rte_pktmbuf_alloc(cgnapt_icmp_pktmbuf_tx_pool);
8581 if (cgnapt_icmp_pkt == NULL) {
8582 printf("Failed to allocate cgnapt_icmp_pkt\n");
8589 cgnat_cnxn_tracker = rte_zmalloc(NULL, rte_ct_get_cnxn_tracker_size(),
8590 RTE_CACHE_LINE_SIZE);
8592 if (cgnat_cnxn_tracker == NULL) {
8593 printf("CGNAPT CT memory not allocated\n");
8596 rte_ct_initialize_default_timeouts(cgnat_cnxn_tracker);
8598 printf("CGNAPT CT Flows %d\n", p_nat->n_flows);
8600 ret = rte_ct_initialize_cnxn_tracker(cgnat_cnxn_tracker,
8602 "CGNAT_CT_COMMON_TABLE");
8612 if (pcp_init() == PCP_INIT_SUCCESS)
8613 printf("PCP contents are initialized successfully\n");
8615 printf("Error in initializing PCP contents\n");
8622 * Function for pipeline cleanup
8625 * A void pointer to pipeline
8630 static int pipeline_cgnapt_free(void *pipeline)
8632 struct pipeline *p = (struct pipeline *)pipeline;
8634 /* Check input arguments */
8638 /* Free resources */
8639 rte_pipeline_free(p->p);
8645 pipeline_cgnapt_track(void *pipeline, __rte_unused uint32_t port_in,
8648 struct pipeline *p = (struct pipeline *)pipeline;
8650 /* Check input arguments */
8651 if ((p == NULL) || (port_in >= p->n_ports_in) || (port_out == NULL))
8654 if (p->n_ports_in == 1) {
8663 * Function for pipeline timers
8666 * A void pointer to pipeline
8671 static int pipeline_cgnapt_timer(void *pipeline)
8673 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)pipeline;
8675 pipeline_msg_req_handle(&p_nat->p);
8677 rte_pipeline_flush(((struct pipeline *)p_nat)->p);
8683 * Function for pipeline custom handlers
8686 * A void pointer to pipeline
8688 * void pointer for incoming data
8691 * void pointer of response
8693 void *pipeline_cgnapt_msg_req_custom_handler(struct pipeline *p, void *msg)
8695 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
8696 struct pipeline_custom_msg_req *req = msg;
8697 pipeline_msg_req_handler f_handle;
8699 f_handle = (req->subtype < PIPELINE_CGNAPT_MSG_REQS) ?
8700 p_nat->custom_handlers[req->subtype] :
8701 pipeline_msg_req_invalid_handler;
8703 if (f_handle == NULL)
8704 f_handle = pipeline_msg_req_invalid_handler;
8706 return f_handle(p, req);
8710 * Function for adding NSP data
8713 * A void pointer to pipeline
8715 * void pointer for incoming data
8718 * void pointer of response
8720 void *pipeline_cgnapt_msg_req_nsp_add_handler(
8721 __rte_unused struct pipeline *p,
8724 struct pipeline_cgnapt_nsp_add_msg_req *req = msg;
8725 struct pipeline_cgnapt_nsp_add_msg_rsp *rsp = msg;
8727 struct cgnapt_nsp_node *node = NULL, *ll = nsp_ll;
8730 (req->nsp.depth == 32 || req->nsp.depth == 40
8731 || req->nsp.depth == 48 || req->nsp.depth == 56
8732 || req->nsp.depth == 64 || req->nsp.depth == 96)) {
8738 printf("be initial cond\n");
8739 if (nsp_ll == NULL) {
8740 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_nsp_node));
8741 node = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8743 printf("be 1st cond\n");
8749 memcpy(&node->nsp, &req->nsp,
8750 sizeof(struct pipeline_cgnapt_nsp_t));
8754 while (ll != NULL) {
8755 if (!memcmp(ll->nsp.prefix, req->nsp.prefix, 16)
8756 && ll->nsp.depth == req->nsp.depth) {
8757 printf("be 2st cond\n");
8765 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_nsp_node));
8766 node = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8768 printf("be 3st cond\n");
8774 memcpy(&node->nsp, &req->nsp,
8775 sizeof(struct pipeline_cgnapt_nsp_t));
8776 node->next = nsp_ll;
8783 printf("be 4st cond\n");
8788 * Function for deleting NSP data
8791 * A void pointer to pipeline
8793 * void pointer for incoming data
8796 * void pointer of response
8798 void *pipeline_cgnapt_msg_req_nsp_del_handler(
8799 __rte_unused struct pipeline *p,
8802 struct pipeline_cgnapt_nsp_del_msg_req *req = msg;
8803 struct pipeline_cgnapt_nsp_del_msg_rsp *rsp = msg;
8804 struct cgnapt_nsp_node *prev = NULL, *ll = nsp_ll;
8806 while (ll != NULL) {
8807 if (!memcmp(ll->nsp.prefix, req->nsp.prefix, 16)
8808 && ll->nsp.depth == req->nsp.depth) {
8810 prev->next = ll->next;
8833 * Function for adding NAPT entry
8836 * A void pointer to pipeline
8838 * void pointer for incoming data
8841 * void pointer of response
8843 void *pipeline_cgnapt_msg_req_entry_add_handler(struct pipeline *p, void *msg)
8845 struct pipeline_cgnapt_entry_add_msg_req *req = msg;
8846 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
8847 uint8_t type = req->data.type;
8848 uint32_t src_ip = (type == CGNAPT_ENTRY_IPV4) ?
8849 req->data.u.prv_ip :
8850 rte_bswap32(req->data.u.u32_prv_ipv6[3]);
8852 uint8_t src_ipv6[16];
8854 uint32_t dest_ip = req->data.pub_ip;
8855 uint16_t src_port = req->data.prv_port;
8856 uint16_t dest_port = req->data.pub_port;
8857 uint16_t rx_port = req->data.prv_phy_port;
8858 uint32_t ttl = req->data.ttl;
8860 if (type == CGNAPT_ENTRY_IPV6)
8861 memcpy(src_ipv6, req->data.u.prv_ipv6, 16);
8863 printf("CG-NAPT addm - PrvIP %x, PrvPort %d,", src_ip, src_port);
8864 printf("PubIP %x, PubPort %d,", dest_ip, dest_port);
8866 printf("PhyPort %d, ttl %u,", rx_port, ttl);
8867 printf("entry_type %d\n", type);
8868 #ifdef NAT_ONLY_CONFIG_REQ
8869 if (nat_only_config_flag) {
8870 if (!p_nat->is_static_cgnapt) {
8873 for (i = 0; i < p_nat->pub_ip_range_count; i++) {
8874 if (((dest_ip >= p_nat->pub_ip_range[i].start_ip)
8875 && (dest_ip <= p_nat->pub_ip_range[i].end_ip))) {
8876 printf("Error - static port cannot be in Dynamic "
8878 printf("%x-%x\n", p_nat->pub_ip_range[i].start_ip,
8879 p_nat->pub_ip_range[i].end_ip);
8885 if (pipeline_cgnapt_msg_req_entry_addm_pair(p, msg,
8891 printf("pipeline_cgnapt_msg_req_entry_addm_handler\n");
8895 #ifdef CGNAPT_DBG_PRNT
8896 printf("Success - pipeline_cgnapt_msg_req_entry_addm_handler");
8897 printf("added %d rule pairs.\n", count);
8903 if (!p_nat->is_static_cgnapt) {
8906 for (i = 0; i < p_nat->pub_ip_count; i++) {
8907 /* Check port range if same Public-IP */
8908 if (dest_ip != p_nat->pub_ip_port_set[i].ip)
8910 if (((dest_port >= p_nat->pub_ip_port_set[i].start_port) &&
8911 (dest_port <= p_nat->pub_ip_port_set[i].end_port))) {
8912 printf("Error - port cannot be in Dynamic "
8913 "port range %d-%d\n",
8914 p_nat->pub_ip_port_set[i].start_port,
8915 p_nat->pub_ip_port_set[i].end_port);
8921 if (pipeline_cgnapt_msg_req_entry_addm_pair
8922 (p, msg, src_ip, src_port, dest_ip, dest_port, rx_port,
8923 ttl, type, src_ipv6)) {
8924 printf("Error - pipeline_cgnapt_msg_req_entry_add_handler\n");
8929 #ifdef CGNAPT_DBG_PRNT
8930 printf("\nSuccess - pipeline_cgnapt_msg_req_entry_add_handler "
8937 * Function for adding a NAPT entry pair
8940 * A void pointer to pipeline
8942 * void pointer for incoming data
8948 * destination ip address
8952 * Physical receive port
8954 * time to live value
8956 * type of entry IPv4 vs IPv6
8958 * uint8_t array of IPv6 address
8961 * 0 if success, negative if fails
8964 pipeline_cgnapt_msg_req_entry_addm_pair(
8965 struct pipeline *p, __rte_unused void *msg,
8966 uint32_t src_ip, uint16_t src_port,
8967 uint32_t dest_ip, uint16_t dest_port,
8968 uint16_t rx_port, uint32_t ttl,
8969 uint8_t type, uint8_t src_ipv6[16])
8972 struct pipeline_cgnapt_entry_key key;
8973 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
8976 key.port = src_port;
8979 struct cgnapt_table_entry entry = {
8981 .action = RTE_PIPELINE_ACTION_PORT,
8982 .port_id = CGNAPT_PUB_PORT_ID,
8986 /*.prv_ip = src_ip, */
8987 .prv_port = src_port,
8989 .pub_port = dest_port,
8990 .prv_phy_port = rx_port,
8991 .pub_phy_port = get_prv_to_pub_port(&dest_ip,
8994 .timeout = STATIC_CGNAPT_TIMEOUT,
9001 if (type == CGNAPT_ENTRY_IPV4) {
9002 entry.data.type = CGNAPT_ENTRY_IPV4;
9003 entry.data.u.prv_ip = src_ip;
9005 entry.data.type = CGNAPT_ENTRY_IPV6;
9006 memcpy(entry.data.u.prv_ipv6, src_ipv6, 16);
9009 /* Also need to add a paired entry on our own */
9011 * Need to change key
9012 * Need to change entry header
9013 * Will keep the same entry and take care
9014 * of translation in table hit handler
9016 struct pipeline_cgnapt_entry_key second_key;
9018 /* Need to add a second ingress entry */
9019 second_key.ip = dest_ip;
9020 second_key.port = dest_port;
9021 second_key.pid = 0xffff;
9023 #ifdef NAT_ONLY_CONFIG_REQ
9024 if (nat_only_config_flag) {
9026 entry.data.pub_port = 0xffff;
9027 second_key.port = 0xffff;
9031 int32_t position = rte_hash_add_key(napt_common_table, &key);
9034 printf("CG-NAPT entry bulk add failed");
9035 printf(" ... returning without adding ...\n");
9039 memcpy(&napt_hash_tbl_entries[position], &entry,
9040 sizeof(struct cgnapt_table_entry));
9042 #ifdef CGNAPT_DEBUGGING
9043 if (p_nat->kpc1++ < 5)
9047 p_nat->n_cgnapt_entry_added++;
9049 /* Now modify the forward port for reverse entry */
9050 entry.head.port_id = CGNAPT_PRV_PORT_ID;
9052 position = rte_hash_add_key(napt_common_table, &second_key);
9055 printf("CG-NAPT entry reverse bulk add failed");
9056 printf(" ... returning with fwd add ...%d\n", position);
9060 memcpy(&napt_hash_tbl_entries[position], &entry,
9061 sizeof(struct cgnapt_table_entry));
9063 #ifdef CGNAPT_DEBUGGING
9064 if (p_nat->kpc1 < 5)
9065 print_key(&second_key);
9068 p_nat->n_cgnapt_entry_added++;
9073 * Function for adding multiple NAPT entries
9076 * A void pointer to pipeline
9078 * void pointer for incoming data
9081 * void pointer of response
9083 void *pipeline_cgnapt_msg_req_entry_addm_handler(struct pipeline *p, void *msg)
9085 struct pipeline_cgnapt_entry_addm_msg_req *req = msg;
9086 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9088 uint32_t max_ue = req->data.num_ue;
9089 uint8_t type = req->data.type;
9090 uint32_t src_ip = (type == CGNAPT_ENTRY_IPV4) ?
9091 req->data.u.prv_ip :
9092 rte_bswap32(req->data.u.u32_prv_ipv6[3]);
9094 uint8_t src_ipv6[16];
9096 uint32_t dest_ip = req->data.pub_ip;
9097 uint16_t src_port = req->data.prv_port;
9098 uint16_t dest_port = req->data.pub_port;
9099 uint16_t rx_port = req->data.prv_phy_port;
9100 uint32_t ttl = req->data.ttl;
9101 uint16_t max_src_port = req->data.prv_port_max;
9102 uint16_t max_dest_port = req->data.pub_port_max;
9104 uint16_t src_port_start = src_port;
9105 uint16_t dest_port_start = dest_port;
9106 uint32_t src_ip_temp;
9108 if (type == CGNAPT_ENTRY_IPV6)
9109 memcpy(src_ipv6, req->data.u.prv_ipv6, 16);
9111 printf("CG-NAPT addm - PrvIP %x, PrvPort %d,", src_ip, src_port);
9112 printf("PubIP %x, PubPort %d,", dest_ip, dest_port);
9113 printf("PhyPort %d, ttl %u, NumUe %d,", rx_port, ttl, max_ue);
9114 printf("mPrvPort %d, mPubPort %d,", max_src_port, max_dest_port);
9115 printf("entry_type %d\n", type);
9116 #ifdef NAT_ONLY_CONFIG_REQ
9117 if (nat_only_config_flag) {
9118 if (!p_nat->is_static_cgnapt) {
9121 for (i = 0; i < p_nat->pub_ip_range_count; i++) {
9122 if (((dest_ip >= p_nat->pub_ip_range[i].start_ip)
9123 && (dest_ip <= p_nat->pub_ip_range[i].end_ip)) ||
9124 (((dest_ip + max_ue) >=
9125 p_nat->pub_ip_range[i].start_ip) &&
9126 ((dest_ip + max_ue) <=
9127 p_nat->pub_ip_range[i].end_ip))) {
9128 printf("Error - static port cannot be in Dynamic "
9130 printf("%x-%x\n", p_nat->pub_ip_range[i].start_ip,
9131 p_nat->pub_ip_range[i].end_ip);
9138 for (uenum = 0; uenum < max_ue; uenum++) {
9140 if (pipeline_cgnapt_msg_req_entry_addm_pair(p, msg,
9146 printf("pipeline_cgnapt_msg_req_entry_addm_handler\n");
9156 #ifdef CGNAPT_DBG_PRNT
9157 printf("Success - pipeline_cgnapt_msg_req_entry_addm_handler");
9158 printf("added %d rule pairs.\n", count);
9165 if (!p_nat->is_static_cgnapt) {
9168 for (i = 0; i < p_nat->pub_ip_count; i++) {
9169 /* Check port range if same Public-IP */
9170 if (dest_ip != p_nat->pub_ip_port_set[i].ip)
9172 if (((dest_port >= p_nat->pub_ip_port_set[i].start_port) &&
9173 (dest_port <= p_nat->pub_ip_port_set[i].end_port)) ||
9174 ((max_dest_port >= p_nat->pub_ip_port_set[i].start_port)
9175 && max_dest_port <= p_nat->pub_ip_port_set[i].end_port)) {
9176 printf("Error - port cannot be in Dynamic port range %d-%d\n",
9177 p_nat->pub_ip_port_set[i].start_port,
9178 p_nat->pub_ip_port_set[i].end_port);
9184 for (uenum = 0; uenum < max_ue; uenum++) {
9185 if (pipeline_cgnapt_msg_req_entry_addm_pair
9186 (p, msg, src_ip, src_port, dest_ip, dest_port, rx_port,
9187 ttl, type, src_ipv6)) {
9188 printf("Error - pipeline_cgnapt_msg_req_entry_addm_handler\n");
9195 if (src_port > max_src_port) {
9196 src_port = src_port_start;
9198 if (req->data.type == CGNAPT_ENTRY_IPV6) {
9199 src_ip_temp = rte_bswap32(src_ip);
9200 memcpy(&src_ipv6[12], &src_ip_temp, 4);
9204 if (dest_port > max_dest_port) {
9205 dest_port = dest_port_start;
9210 #ifdef CGNAPT_DBG_PRNT
9211 printf("\nSuccess - pipeline_cgnapt_msg_req_entry_addm_handler added");
9212 printf("%d rule pairs.\n", count);
9218 * Function for deleting NAPT entry
9221 * A void pointer to pipeline
9223 * void pointer for incoming data
9226 * void pointer of response
9228 void *pipeline_cgnapt_msg_req_entry_del_handler(struct pipeline *p, void *msg)
9230 struct pipeline_cgnapt_entry_delete_msg_req *req = msg;
9231 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9232 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9235 uint8_t *KeyP = (void *)(&req->key);
9238 printf("pipeline_cgnapt_msg_req_entry_del_handler - Key: ");
9239 for (i = 0; i < (int)sizeof(struct pipeline_cgnapt_entry_key);
9241 printf(" %02x", KeyP[i]);
9242 printf(" ,KeySize %u\n",
9243 (int)sizeof(struct pipeline_cgnapt_entry_key));
9246 struct cgnapt_table_entry entry;
9248 /* If ingress key */
9249 if (!is_phy_port_privte(req->key.pid))
9250 req->key.pid = 0xffff;
9252 #ifdef NAT_ONLY_CONFIG_REQ
9253 if (nat_only_config_flag)
9254 req->key.port = 0xffff;
9258 position = rte_hash_lookup(napt_common_table, &req->key);
9259 if (position == -ENOENT) {
9260 printf("Entry not found\n");
9263 memcpy(&entry, &napt_hash_tbl_entries[position],
9264 sizeof(struct cgnapt_table_entry));
9265 position = rte_hash_del_key(napt_common_table, &req->key);
9266 p_nat->n_cgnapt_entry_deleted++;
9268 struct pipeline_cgnapt_entry_key second_key;
9270 if (is_phy_port_privte(req->key.pid)) {
9271 /* key is for egress - make second key for ingress */
9272 second_key.ip = entry.data.pub_ip;
9273 second_key.port = entry.data.pub_port;
9274 second_key.pid = 0xffff;
9277 /* key is for ingress - make second key for egress */
9278 second_key.ip = entry.data.u.prv_ip;
9279 second_key.port = entry.data.prv_port;
9280 second_key.pid = entry.data.prv_phy_port;
9283 #ifdef NAT_ONLY_CONFIG_REQ
9284 if (nat_only_config_flag)
9285 second_key.port = 0xffff;
9288 position = rte_hash_del_key(napt_common_table, &second_key);
9289 p_nat->n_cgnapt_entry_deleted++;
9294 void *pipeline_cgnapt_msg_req_entry_sync_handler(struct pipeline *p, void *msg)
9296 struct pipeline_cgnapt_entry_delete_msg_req *req = msg;
9297 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9299 rsp->status = rte_pipeline_table_entry_delete(
9303 &rsp->key_found, NULL);
9309 * Function to print the NAPT key
9312 * A pointer to struct pipeline_cgnapt_entry_key
9314 void print_key(struct pipeline_cgnapt_entry_key *key)
9316 uint8_t *KeyP = (void *)(key);
9320 for (i = 0; i < (int)sizeof(struct pipeline_cgnapt_entry_key); i++)
9321 printf(" %02x", KeyP[i]);
9325 * Function to print the table entry
9328 * A pointer to struct rte_pipeline_table_entry
9330 void print_entry1(struct rte_pipeline_table_entry *entry)
9332 uint8_t *entryP = (void *)(entry);
9336 for (i = 0; i < (int)sizeof(struct rte_pipeline_table_entry); i++)
9337 printf(" %02x", entryP[i]);
9341 * Function to print the NAPT table entry
9344 * A pointer to struct cgnapt_table_entry
9346 void print_cgnapt_entry(struct cgnapt_table_entry *entry)
9348 uint8_t *entryP = (void *)(entry);
9351 printf("CGNAPT Entry: ");
9352 for (i = 0; i < (int)sizeof(struct cgnapt_table_entry); i++)
9353 printf(" %02x", entryP[i]);
9354 printf(" size:%d\n", (int)sizeof(struct cgnapt_table_entry));
9358 * Function to get a free port
9361 * A pointer to struct pipeline_cgnapt
9363 * A uint32_t pointer to return corresponding ip address
9366 * free port number, 0 if error
9368 int get_free_iport(struct pipeline_cgnapt *p_nat, uint32_t *public_ip)
9371 /* If we don't have a valid napt_port_alloc_elem get one from
9374 if (p_nat->allocated_ports == NULL) {
9378 ret = rte_ring_dequeue(p_nat->port_alloc_ring, &ports);
9380 p_nat->allocated_ports =
9381 (struct napt_port_alloc_elem *)ports;
9383 #ifdef CGNAPT_DEBUGGING
9387 #ifdef CGNAPT_DBG_PRNT
9388 if (CGNAPT_DEBUG > 3)
9389 printf("p_nat->allocated_ports %p\n",
9390 p_nat->allocated_ports);
9393 printf("CGNAPT Err - get_free_iport rte_ring_dequeue "
9395 printf("%d, %d, %d\n", rte_ring_count(
9396 p_nat->port_alloc_ring), rte_ring_free_count(
9397 p_nat->port_alloc_ring), ret);
9399 #ifdef CGNAPT_DEBUGGING
9400 #ifdef CGNAPT_DBG_PRNT
9401 printf("Th%d GFP:: %" PRIu64 ", %" PRIu64 ", "
9402 "%" PRIu64", %" PRIu64 ",\n", p_nat->pipeline_num,
9403 p_nat->gfp_get, p_nat->gfp_ret, p_nat->gfp_suc,
9413 /* get the port from index count-1 and decrease count */
9414 port = p_nat->allocated_ports->ports
9415 [p_nat->allocated_ports->count - 1];
9416 *public_ip = p_nat->allocated_ports->ip_addr
9417 [p_nat->allocated_ports->count - 1];
9419 p_nat->allocated_ports->count -= 1;
9421 /* if count is zero, return buffer to mem pool */
9422 if (p_nat->allocated_ports->count == 0) {
9423 rte_mempool_put(napt_port_pool, p_nat->allocated_ports);
9425 #ifdef CGNAPT_DEBUGGING
9427 #ifdef CGNAPT_DBG_PRNT
9428 printf("Th%d Returned to pool p_nat->allocated_ports %p,",
9429 p_nat->pipeline_num, p_nat->allocated_ports);
9430 printf("%" PRIu64 ", %" PRIu64 ",",
9431 p_nat->gfp_get, p_nat->gfp_ret);
9432 printf("%" PRIu64 ", %" PRIu64 ",\n",
9433 p_nat->gfp_suc, p_nat->gfp_err);
9437 p_nat->allocated_ports = NULL;
9440 #ifdef CGNAPT_DEBUGGING
9448 * Function to free a port
9451 * Port number to free
9453 * Corresponding ip address
9455 * A pointer to struct pipeline_cgnapt
9458 void release_iport(uint16_t port_num, uint32_t public_ip,
9459 struct pipeline_cgnapt *p_nat)
9461 /* If we don't have a valid napt_port_alloc_elem get one
9464 if (p_nat->free_ports == NULL) {
9467 #ifdef CGNAPT_DEBUGGING
9471 if (rte_mempool_get(napt_port_pool, &ports) < 0) {
9472 #ifdef CGNAPT_DEBUGGING
9475 printf("CGNAPT release_iport error in getting "
9476 "port alloc buffer\n");
9480 p_nat->free_ports = (struct napt_port_alloc_elem *)ports;
9481 p_nat->free_ports->count = 0;
9484 /* put the port at index count and increase count */
9485 p_nat->free_ports->ip_addr[p_nat->free_ports->count] = public_ip;
9486 p_nat->free_ports->ports[p_nat->free_ports->count] = port_num;
9487 p_nat->free_ports->count += 1;
9489 /* if napt_port_alloc_elem is full add it to ring */
9492 #ifdef CGNAPT_DEBUGGING
9496 #ifdef CGNAPT_DBG_PRNT
9497 if (CGNAPT_DEBUG >= 2) {
9498 printf("CGNAPT port_alloc_ring before EnQ Cnt %d, Free %d\n",
9499 rte_ring_count(p_nat->port_alloc_ring),
9500 rte_ring_free_count(p_nat->port_alloc_ring));
9504 if (rte_ring_enqueue(p_nat->port_alloc_ring,
9505 (void *)p_nat->free_ports) != 0) {
9506 printf("CGNAPT release_iport Enqueue error %p\n",
9509 #ifdef CGNAPT_DEBUGGING
9514 #ifdef CGNAPT_DBG_PRNT
9515 if (CGNAPT_DEBUG >= 2) {
9516 printf("CGNAPT port_alloc_ring after EnQ Cnt %d",
9517 rte_ring_count(p_nat->port_alloc_ring));
9519 rte_ring_free_count(p_nat->port_alloc_ring));
9523 p_nat->free_ports = NULL;
9526 #ifdef CGNAPT_DEBUGGING
9532 * Function to initialize max ports per client data structures
9533 * Called during dynamic NAPT initialization.
9536 * A pointer to struct pipeline_cgnapt
9539 * 0 if success, negative if error
9541 int init_max_port_per_client(
9542 __rte_unused struct pipeline_cgnapt *p_nat)
9544 if (max_port_per_client_hash)
9547 /*MPPC_ALREADY_EXISTS */
9551 max_port_per_client_hash =
9552 rte_hash_create(&max_port_per_client_hash_params);
9553 if (!max_port_per_client_hash)
9556 /*MPPC_HASH_CREATE_ERROR */
9558 max_port_per_client_array =
9560 sizeof(struct max_port_per_client) * MAX_DYN_ENTRY,
9561 RTE_CACHE_LINE_SIZE);
9562 if (!max_port_per_client_array)
9565 /*MPPC_ARRAY_CREATE_ERROR */
9567 for (i = 0; i < MAX_DYN_ENTRY; i++) {
9568 max_port_per_client_array[i].prv_ip = 0;
9569 max_port_per_client_array[i].prv_phy_port = 0;
9570 max_port_per_client_array[i].max_port_cnt = 0;
9578 * Function to check if max ports for a client is reached
9580 * @param prv_ip_param
9581 * A uint32_t ip address of client
9582 * @param prv_phy_port_param
9583 * A uint32_t physical port id of the client
9585 * A pointer to struct pipeline_cgnapt
9588 * 0 if max port not reached, 1 if reached, -1 if error
9590 int is_max_port_per_client_reached(uint32_t prv_ip_param,
9591 uint32_t prv_phy_port_param,
9592 struct pipeline_cgnapt *p_nat)
9594 int index = MAX_PORT_INVALID_KEY;
9596 struct max_port_per_client_key key = {
9597 .prv_ip = prv_ip_param,
9598 .prv_phy_port = prv_phy_port_param,
9601 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9604 return MAX_PORT_INVALID_KEY;
9606 if (max_port_per_client_array[index].max_port_cnt >=
9607 p_nat->max_port_per_client)
9608 return MAX_PORT_REACHED;
9610 return MAX_PORT_NOT_REACHED;
9614 * Function to increase max ports for a client
9616 * @param prv_ip_param
9617 * A uint32_t ip address of client
9618 * @param prv_phy_port_param
9619 * A uint32_t physical port id of the client
9621 * A pointer to struct pipeline_cgnapt
9624 * 0 if max port reached, 1 if success, 2 if new entry, -1 if error
9626 int increment_max_port_counter(uint32_t prv_ip_param,
9627 uint32_t prv_phy_port_param,
9628 struct pipeline_cgnapt *p_nat)
9630 int index = MAX_PORT_INC_ERROR;
9632 struct max_port_per_client_key key = {
9633 .prv_ip = prv_ip_param,
9634 .prv_phy_port = prv_phy_port_param,
9637 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9639 if (index == -EINVAL)
9640 return MAX_PORT_INC_ERROR;
9642 if (index == -ENOENT) {
9643 if (max_port_per_client_add_entry(prv_ip_param,
9646 return MAX_PORT_INC_ERROR;
9648 return 2; /*return MAX_PORT_NEW_ENTRY; */
9651 if (CGNAPT_DEBUG > 2)
9652 printf("%s: max_port_cnt(%d), p_nat_max(%d)\n", __func__,
9653 max_port_per_client_array[index].max_port_cnt,
9654 p_nat->max_port_per_client);
9656 if (max_port_per_client_array[index].max_port_cnt <
9657 p_nat->max_port_per_client) {
9658 max_port_per_client_array[index].max_port_cnt++;
9659 return MAX_PORT_INC_SUCCESS;
9662 return MAX_PORT_INC_REACHED;
9666 * Function to decrease max ports for a client
9668 * @param prv_ip_param
9669 * A uint32_t ip address of client
9670 * @param prv_phy_port_param
9671 * A uint32_t physical port id of the client
9673 * A pointer to struct pipeline_cgnapt
9676 * 0 if count already 0, 1 if success, -1 if error
9678 int decrement_max_port_counter(uint32_t prv_ip_param,
9679 uint32_t prv_phy_port_param,
9680 struct pipeline_cgnapt *p_nat)
9682 int index = MAX_PORT_DEC_ERROR;
9684 struct max_port_per_client_key key = {
9685 .prv_ip = prv_ip_param,
9686 .prv_phy_port = prv_phy_port_param,
9689 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9692 #ifdef CGNAPT_DEBUGGING
9693 p_nat->max_port_dec_err1++;
9695 return MAX_PORT_DEC_ERROR;
9699 if (max_port_per_client_array[index].max_port_cnt > 0) {
9700 /* If it is the last port,ret this info which is used for
9701 * max_cli_per_pub_ip
9704 max_port_per_client_array[index].max_port_cnt--;
9705 /* Count should be atomic but we are good as we have only
9706 * one task handling this counter at a time (core affinity)
9710 if (max_port_per_client_array[index].max_port_cnt <= 0) {
9711 if (max_port_per_client_del_entry
9712 (prv_ip_param, prv_phy_port_param, p_nat) <= 0) {
9714 #ifdef CGNAPT_DEBUGGING
9715 p_nat->max_port_dec_err2++;
9717 return MAX_PORT_DEC_ERROR;
9720 #ifdef CGNAPT_DEBUGGING
9721 p_nat->max_port_dec_err3++;
9724 return MAX_PORT_DEC_REACHED;
9727 #ifdef CGNAPT_DEBUGGING
9728 p_nat->max_port_dec_success++;
9731 return MAX_PORT_DEC_SUCCESS;
9735 * Function to add a max ports per client entry
9737 * @param prv_ip_param
9738 * A uint32_t ip address of client
9739 * @param prv_phy_port_param
9740 * A uint32_t physical port id of the client
9742 * A pointer to struct pipeline_cgnapt
9745 * 0 no success, 1 if success, -1 if error
9747 int max_port_per_client_add_entry(
9748 uint32_t prv_ip_param,
9749 uint32_t prv_phy_port_param,
9750 __rte_unused struct pipeline_cgnapt *p_nat)
9752 int index = MAX_PORT_ADD_ERROR;
9754 struct max_port_per_client_key key = {
9755 .prv_ip = prv_ip_param,
9756 .prv_phy_port = prv_phy_port_param,
9759 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9760 if (index == -EINVAL)
9761 return MAX_PORT_ADD_ERROR;
9764 return MAX_PORT_ADD_UNSUCCESS;
9766 if (index == -ENOENT) {
9768 #ifdef CGNAPT_DBG_PRNT
9769 if (CGNAPT_DEBUG > 2)
9770 printf("max_port_per_client_add_entry fn: "
9771 "Entry does not exist\n");
9775 rte_hash_add_key(max_port_per_client_hash,
9776 (const void *)&key);
9777 if (index == -ENOSPC)
9778 return MAX_PORT_ADD_UNSUCCESS;
9780 #ifdef CGNAPT_DBG_PRNT
9781 if (CGNAPT_DEBUG > 2)
9782 printf("max_port_per_client_add_entry fn:"
9783 "Add entry index(%d)\n", index);
9786 max_port_per_client_array[index].prv_ip = prv_ip_param;
9787 max_port_per_client_array[index].prv_phy_port =
9791 max_port_per_client_array[index].max_port_cnt++;
9792 return MAX_PORT_ADD_SUCCESS;
9796 * Function to delete a max ports per client entry
9798 * @param prv_ip_param
9799 * A uint32_t ip address of client
9800 * @param prv_phy_port_param
9801 * A uint32_t physical port id of the client
9803 * A pointer to struct pipeline_cgnapt
9806 * 0 no success, 1 if success, -1 if error
9808 int max_port_per_client_del_entry(
9809 uint32_t prv_ip_param,
9810 uint32_t prv_phy_port_param,
9811 __rte_unused struct pipeline_cgnapt *p_nat)
9813 int index = MAX_PORT_DEL_ERROR;
9815 struct max_port_per_client_key key = {
9816 .prv_ip = prv_ip_param,
9817 .prv_phy_port = prv_phy_port_param,
9820 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9822 if (index == -EINVAL)
9823 return MAX_PORT_DEL_ERROR;
9825 if (index == -ENOENT)
9826 return MAX_PORT_DEL_UNSUCCESS;
9828 index = rte_hash_del_key(max_port_per_client_hash, (const void *)&key);
9829 max_port_per_client_array[index].prv_ip = 0;
9830 max_port_per_client_array[index].prv_phy_port = 0;
9831 max_port_per_client_array[index].max_port_cnt = 0;
9833 return MAX_PORT_DEL_SUCCESS;
9837 * Function to execute debug commands
9840 * A pointer to struct pipeline
9842 * void pointer to incoming arguments
9844 void *pipeline_cgnapt_msg_req_entry_dbg_handler(struct pipeline *p, void *msg)
9846 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9848 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9852 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_STATS_SHOW) {
9853 printf("\nCG-NAPT Packet Stats:\n");
9854 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
9855 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
9856 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
9857 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
9858 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
9859 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
9860 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
9862 #ifdef CGNAPT_DEBUGGING
9863 printf("\n Drop detail 1:%" PRIu64 ",",
9864 p_nat->naptDroppedPktCount1);
9865 printf("\n Drop detail 2:%" PRIu64 ",",
9866 p_nat->naptDroppedPktCount2);
9867 printf("\n Drop detail 3:%" PRIu64 ",",
9868 p_nat->naptDroppedPktCount3);
9869 printf("\n Drop detail 4:%" PRIu64 ",",
9870 p_nat->naptDroppedPktCount4);
9871 printf("\n Drop detail 5:%" PRIu64 ",",
9872 p_nat->naptDroppedPktCount5);
9873 printf("\n Drop detail 6:%" PRIu64 "",
9874 p_nat->naptDroppedPktCount6);
9876 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9877 p_nat->missedpktcount1,
9878 p_nat->missedpktcount2);
9879 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9880 p_nat->missedpktcount3,
9881 p_nat->missedpktcount4);
9882 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9883 p_nat->missedpktcount5,
9884 p_nat->missedpktcount6);
9885 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9886 p_nat->missedpktcount7,
9887 p_nat->missedpktcount8);
9888 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9889 p_nat->missedpktcount9,
9890 p_nat->missedpktcount10);
9897 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_STATS_CLEAR) {
9898 printf("\nCG-NAPT Packet Stats:\n");
9899 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
9900 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
9901 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
9902 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
9903 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
9904 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
9905 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
9907 p_nat->naptedPktCount = 0;
9908 p_nat->naptDroppedPktCount = 0;
9909 p_nat->inaptedPktCount = 0;
9910 p_nat->enaptedPktCount = 0;
9911 p_nat->receivedPktCount = 0;
9912 p_nat->missedPktCount = 0;
9913 p_nat->arpicmpPktCount = 0;
9914 printf("CG-NAPT Packet Stats cleared\n");
9918 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DBG_LEVEL) {
9919 CGNAPT_DEBUG = Msg[CGNAPT_DBG_CMD_OFST + 1];
9920 printf("CG-NAPT debug level set to %d\n", CGNAPT_DEBUG);
9924 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DBG_SHOW) {
9926 printf("\nNAPT entries - added %" PRIu64 ",",
9927 p_nat->n_cgnapt_entry_added);
9928 printf("deleted %" PRIu64 ",", p_nat->n_cgnapt_entry_deleted);
9929 printf("current %" PRIu64 "", p_nat->n_cgnapt_entry_added -
9930 p_nat->n_cgnapt_entry_deleted);
9932 printf("\nCG-NAPT Packet Stats:\n");
9933 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
9934 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
9935 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
9936 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
9937 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
9938 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
9939 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
9943 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
9944 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_INSTRUMENTATION) {
9945 if (Msg[CGNAPT_DBG_CMD_OFST1] ==
9946 CGNAPT_CMD_INSTRUMENTATION_SUB0) {
9949 uint32_t diff_sum = 0;
9951 printf("CG-NAPT Instrumentation ...\n");
9952 printf("Instrumentation data collected for fn# %d\n",
9953 cgnapt_num_func_to_inst);
9954 printf("Current collection index %d\n",
9957 if (Msg[CGNAPT_DBG_CMD_OFST + 2] == 2) {
9958 printf("Timer Start:\n");
9960 for (index = 0; index < INST_ARRAY_SIZE; index++) {
9961 if ((index % 5) == 0)
9963 printf(" 0x%jx", inst_start_time[index]);
9965 printf("\n\nTimer End:\n");
9967 for (index = 0; index < INST_ARRAY_SIZE; index++) {
9968 if ((index % 5) == 0)
9970 printf(" 0x%jx", inst_end_time[index]);
9974 for (index = 0; index < INST_ARRAY_SIZE; index++) {
9975 inst_diff_time[index] = (uint32_t) (inst_end_time[index] -
9976 inst_start_time[index]);
9979 if (Msg[CGNAPT_DBG_CMD_OFST + 2] ==
9980 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
9981 printf("\n\nTimer Diff:\n");
9983 for (index = 0; index < INST_ARRAY_SIZE; index++) {
9984 if (Msg[CGNAPT_DBG_CMD_OFST + 2] ==
9985 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
9986 if ((index % 5) == 0)
9988 printf(" 0x%08x", inst_diff_time[index]);
9991 diff_sum += inst_diff_time[index];
9994 printf("\ndiff_sum %u, INST_ARRAY_SIZE %d, Ave Time %u\n",
9995 diff_sum, INST_ARRAY_SIZE, (diff_sum / INST_ARRAY_SIZE));
9996 } else if (Msg[CGNAPT_DBG_CMD_OFST + 1] ==
9997 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
9998 /* p plid entry dbg 7 1 0
9999 * p plid entry dbg 7 1 1 <--- pkt_work_cgnapt
10000 * p plid entry dbg 7 1 2 <--- pkt4_work_cgnapt
10001 * p plid entry dbg 7 1 3 <--- pkt_work_cgnapt_key
10002 * p plid entry dbg 7 1 4 <--- pkt4_work_cgnapt_key
10003 * p plid entry dbg 7 1 5 <--- in port ah to out port ah
10004 * - pkt life in the system
10005 * p plid entry dbg 7 1 6 <--- how long this instrumentation
10008 cgnapt_inst_index = 0;
10009 cgnapt_num_func_to_inst = Msg[CGNAPT_DBG_CMD_OFST + 2];
10010 printf("Instrumentation data collection started for fn# %d\n",
10011 cgnapt_num_func_to_inst);
10012 } else if (Msg[CGNAPT_DBG_CMD_OFST + 1] ==
10013 CGNAPT_CMD_INSTRUMENTATION_SUB2) {
10014 /* p plid entry dbg 7 2 0
10015 * Test all major functions by calling them multiple times
10016 * pkt_work_cgnapt, pkt4_work_cgnapt, pkt_work_cgnapt_key,
10017 * pkt4_work_cgnapt_key
10019 if (cgnapt_test_pktmbuf_pool == NULL) {
10020 cgnapt_test_pktmbuf_pool = rte_pktmbuf_pool_create(
10021 "cgnapt_test_pktmbuf_pool", 63, 32, 0,
10022 RTE_MBUF_DEFAULT_BUF_SIZE,
10026 if (cgnapt_test_pktmbuf_pool == NULL)
10027 printf("CGNAPT test mbuf pool create failed.\n");
10029 struct rte_mbuf *cgnapt_test_pkt0 =
10030 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
10031 if (cgnapt_test_pkt0 == NULL)
10032 printf("CGNAPT test pkt 0 alloc failed.");
10033 struct rte_mbuf *cgnapt_test_pkt1 =
10034 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
10035 if (cgnapt_test_pkt1 == NULL)
10036 printf("CGNAPT test pkt 1 alloc failed.");
10037 struct rte_mbuf *cgnapt_test_pkt2 =
10038 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
10039 if (cgnapt_test_pkt2 == NULL)
10040 printf("CGNAPT test pkt 2 alloc failed.");
10041 struct rte_mbuf *cgnapt_test_pkt3 =
10042 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
10043 if (cgnapt_test_pkt3 == NULL)
10044 printf("CGNAPT test pkt 3 alloc failed.");
10046 struct rte_mbuf *cgnapt_test_pkts[4];
10048 cgnapt_test_pkts[0] = cgnapt_test_pkt0;
10049 cgnapt_test_pkts[1] = cgnapt_test_pkt1;
10050 cgnapt_test_pkts[2] = cgnapt_test_pkt2;
10051 cgnapt_test_pkts[3] = cgnapt_test_pkt3;
10053 uint32_t src_addr_offset =
10054 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_SRC_ADR_OFST;
10055 /* header room + eth hdr size +
10056 * src_aadr offset in ip header
10058 uint32_t dst_addr_offset =
10059 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
10060 /* header room + eth hdr size +
10061 * dst_aadr offset in ip header
10063 uint32_t prot_offset =
10064 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_PROTOCOL_OFST;
10065 /* header room + eth hdr size +
10066 * srprotocol char offset in ip header
10068 int pktCnt = 0, entCnt = 0, exCnt = 0;
10070 for (pktCnt = 0; pktCnt < 4; pktCnt++) {
10071 uint32_t *src_addr =
10072 RTE_MBUF_METADATA_UINT32_PTR
10073 (cgnapt_test_pkts[pktCnt], src_addr_offset);
10074 uint32_t *dst_addr =
10075 RTE_MBUF_METADATA_UINT32_PTR
10076 (cgnapt_test_pkts[pktCnt], dst_addr_offset);
10077 uint8_t *protocol =
10078 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10081 uint8_t *phy_port =
10082 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10084 uint8_t *eth_dest =
10085 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10089 RTE_MBUF_METADATA_UINT8_PTR(
10090 cgnapt_test_pkts[pktCnt],
10093 uint16_t *src_port =
10094 RTE_MBUF_METADATA_UINT16_PTR
10095 (cgnapt_test_pkts[pktCnt],
10096 MBUF_HDR_ROOM + ETH_HDR_SIZE +
10098 uint16_t *dst_port =
10099 RTE_MBUF_METADATA_UINT16_PTR
10100 (cgnapt_test_pkts[pktCnt],
10101 MBUF_HDR_ROOM + ETH_HDR_SIZE +
10103 *src_addr = 0xc0a80001;
10104 *dst_addr = 0x90418634;
10115 eth_dest[0] = 0x90;
10116 eth_dest[1] = 0xE2;
10117 eth_dest[2] = 0xba;
10118 eth_dest[3] = 0x54;
10119 eth_dest[4] = 0x67;
10120 eth_dest[5] = 0xc8;
10122 struct rte_pipeline_table_entry *table_entries[4];
10123 struct cgnapt_table_entry ctable_entries[4];
10124 table_entries[0] = (struct rte_pipeline_table_entry *)
10125 &ctable_entries[0];
10126 table_entries[1] = (struct rte_pipeline_table_entry *)
10127 &ctable_entries[1];
10128 table_entries[2] = (struct rte_pipeline_table_entry *)
10129 &ctable_entries[2];
10130 table_entries[3] = (struct rte_pipeline_table_entry *)
10131 &ctable_entries[3];
10132 for (entCnt = 0; entCnt < 4; entCnt++) {
10133 ctable_entries[entCnt].head.action =
10134 RTE_PIPELINE_ACTION_PORT;
10135 ctable_entries[entCnt].head.port_id = 0;
10137 ctable_entries[entCnt].data.prv_ip = 0x01020304;
10138 ctable_entries[entCnt].data.prv_port = 1234;
10139 ctable_entries[entCnt].data.pub_ip = 0x0a0b0c0d;
10140 ctable_entries[entCnt].data.pub_port = 4000;
10141 ctable_entries[entCnt].data.prv_phy_port = 0;
10142 ctable_entries[entCnt].data.pub_phy_port = 1;
10143 ctable_entries[entCnt].data.ttl = 500;
10146 uint64_t time1 = rte_get_tsc_cycles();
10148 for (exCnt = 0; exCnt < 1000; exCnt++) {
10149 pkt_work_cgnapt_key(cgnapt_test_pkts[0],
10150 instrumentation_port_in_arg);
10152 uint64_t time2 = rte_get_tsc_cycles();
10154 printf("times for %d times execution of "
10155 "pkt_work_cgnapt_key 0x%jx",
10157 printf(", 0x%jx, diff %" PRIu64 "\n", time2,
10160 time1 = rte_get_tsc_cycles();
10161 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10162 pkt_work_cgnapt_key(cgnapt_test_pkts[0],
10163 instrumentation_port_in_arg);
10165 time2 = rte_get_tsc_cycles();
10166 printf("times for %d times execution of "
10167 "pkt_work_cgnapt_key 0x%jx", exCnt, time1);
10168 printf("0x%jx, diff %" PRIu64 "\n", time2,
10171 time1 = rte_get_tsc_cycles();
10172 for (exCnt = 0; exCnt < 1000; exCnt++) {
10173 pkt4_work_cgnapt_key(cgnapt_test_pkts,
10174 instrumentation_port_in_arg);
10176 time2 = rte_get_tsc_cycles();
10177 printf("times for %d times execution of "
10178 "pkt4_work_cgnapt_key 0x%jx",
10180 printf(" 0x%jx, diff %" PRIu64 "\n", time2,
10183 time1 = rte_get_tsc_cycles();
10184 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10185 pkt4_work_cgnapt_key(cgnapt_test_pkts,
10186 instrumentation_port_in_arg);
10188 time2 = rte_get_tsc_cycles();
10189 printf("times for %d times execution of "
10190 "pkt4_work_cgnapt_key 0x%jx",
10192 printf("0x%jx, diff %" PRIu64 "\n", time2,
10195 uint64_t mask = 0xff;
10197 time1 = rte_get_tsc_cycles();
10198 for (exCnt = 0; exCnt < 1000; exCnt++) {
10199 pkt_work_cgnapt(cgnapt_test_pkts[0],
10200 table_entries[0], 3, &mask,
10203 time2 = rte_get_tsc_cycles();
10204 printf("times for %d times execution of "
10205 "pkt_work_cgnapt 0x%jx",
10207 printf("0x%jx, diff %" PRIu64 "\n", time2,
10210 time1 = rte_get_tsc_cycles();
10211 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10212 pkt_work_cgnapt(cgnapt_test_pkts[0],
10213 table_entries[0], 3, &mask,
10216 time2 = rte_get_tsc_cycles();
10217 printf("times for %d times execution of "
10218 "pkt_work_cgnapt 0x%jx",
10220 printf("0x%jx, diff %" PRIu64 "\n", time2,
10223 time1 = rte_get_tsc_cycles();
10224 for (exCnt = 0; exCnt < 1000; exCnt++) {
10225 pkt4_work_cgnapt(cgnapt_test_pkts,
10226 table_entries, 0, &mask, NULL);
10228 time2 = rte_get_tsc_cycles();
10229 printf("times for %d times execution of "
10230 "pkt4_work_cgnapt 0x%jx",
10232 printf("0x%jx, diff % " PRIu64 "\n", time2,
10235 int idummy = ctable_entries[0].data.prv_port;
10245 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_LS_ENTRY) {
10246 printf("CG-NAPT be entries are:\n");
10247 printf("Pipeline pointer %p\n", p);
10251 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DYN) {
10252 printf("Total Number of dynamic napt entries: %" PRIu64 "\n",
10253 p_nat->dynCgnaptCount);
10255 #ifdef CGNAPT_DEBUGGING
10256 printf("MAX PORT PER CLIENT:");
10257 printf("%" PRIu64 ",%" PRIu64 ",%" PRIu64 "\n",
10258 p_nat->max_port_dec_err1, p_nat->max_port_dec_err2,
10259 p_nat->max_port_dec_err3);
10260 printf("MPPC success : %" PRIu64 "\n",
10261 p_nat->max_port_dec_success);
10263 printf("Release port:err:%" PRIu64 ",ret::%" PRIu64 ",get::%"
10264 PRIu64 ",suc::%" PRIu64 "\n", p_nat->pfb_err,
10265 p_nat->pfb_ret, p_nat->pfb_get, p_nat->pfb_suc);
10266 printf("Get port::err:%" PRIu64 ",ret::%" PRIu64 ",get::%"
10267 PRIu64 ",suc::%" PRIu64 "\n", p_nat->gfp_err,
10268 p_nat->gfp_ret, p_nat->gfp_get, p_nat->gfp_suc);
10269 printf("Ring Info:\n");
10270 rte_ring_dump(stdout, p_nat->port_alloc_ring);
10274 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_IPV6) {
10275 dual_stack_enable = Msg[CGNAPT_DBG_CMD_OFST + 1];
10276 printf("Dual Stack option set: %x\n", dual_stack_enable);
10280 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_MAPS_INFO) {
10281 pipelines_port_info();
10282 pipelines_map_info();
10286 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_ITER_COM_TBL) {
10287 uint32_t count = 0;
10295 rte_hash_iterate(napt_common_table, &key, &data,
10298 if ((index != -EINVAL) && (index != -ENOENT)) {
10299 printf("\n%04d ", count);
10300 rte_hexdump(stdout, "KEY", key,
10302 pipeline_cgnapt_entry_key));
10304 //print_key((struct pipeline_cgnapt_entry_key *)
10307 rte_hash_lookup(napt_common_table,
10309 print_cgnapt_entry(&napt_hash_tbl_entries
10314 } while (index != -ENOENT);
10318 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_IF_STATS) {
10320 struct app_params *app =
10321 (struct app_params *)p_nat->app_params_addr;
10324 cmd[0] = Msg[CGNAPT_DBG_CMD_OFST + 1];
10325 cmd[1] = Msg[CGNAPT_DBG_CMD_OFST + 2];
10327 case CGNAPT_IF_STATS_HWQ:
10328 printf("n_pktq_hwq_int :%d\n", app->n_pktq_hwq_in);
10329 printf("n_pktq_hwq_out :%d\n", app->n_pktq_hwq_out);
10333 for (i = 0; i < app->n_pktq_hwq_in; i++) {
10334 struct rte_eth_stats stats;
10336 rte_eth_stats_get(p_nat->links_map[i], &stats);
10338 if (is_phy_port_privte(i))
10339 printf("Private Port Stats %d\n", i);
10341 printf("Public Port Stats %d\n", i);
10343 printf("\n\tipackets : %" PRIu64 "",
10345 printf("\n\topackets : %" PRIu64 "",
10347 printf("\n\tierrors : %" PRIu64 "",
10349 printf("\n\toerrors : %" PRIu64 "",
10351 printf("\n\trx_nombuf: %" PRIu64 "",
10354 if (is_phy_port_privte(i))
10355 printf("Private Q:");
10357 printf("Public Q:");
10358 for (j = 0; j < RTE_ETHDEV_QUEUE_STAT_CNTRS;
10360 printf(" %" PRIu64 ", %" PRIu64 "|",
10361 stats.q_ipackets[j],
10362 stats.q_opackets[j]);
10370 case CGNAPT_IF_STATS_SWQ:
10372 printf("n_pktq_swq :%d\n", app->n_pktq_swq);
10374 if (cmd[1] < app->n_pktq_swq) {
10375 rte_ring_dump(stdout, app->swq[cmd[1]]);
10378 printf("SWQ number is invalid\n");
10381 case CGNAPT_IF_STATS_OTH:
10383 printf("config_file:%s\n", app->config_file);
10384 printf("script_file:%s\n", app->script_file);
10385 printf("parser_file:%s\n", app->parser_file);
10386 printf("output_file:%s\n", app->output_file);
10387 printf("n_msgq :%d\n", app->n_msgq);
10388 printf("n_pktq_tm :%d\n", app->n_pktq_tm);
10389 printf("n_pktq_source :%d\n", app->n_pktq_source);
10390 printf("n_pktq_sink :%d\n", app->n_pktq_sink);
10391 printf("n_pipelines :%d\n", app->n_pipelines);
10395 printf("Command does not match\n\n");
10403 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_MAX_CLI_PER_PUB_IP) {
10404 if (nat_only_config_flag) {
10405 printf("Command not supported for NAT only config.\n");
10410 printf("\tPublic IP: Num Clients\n");
10411 for (ii = 0; ii < CGNAPT_MAX_PUB_IP; ii++)
10412 printf("\t%x : %7d\n", all_public_ip[ii].ip,
10413 rte_atomic16_read(&all_public_ip[ii].count));
10417 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_PUB_IP_LIST) {
10420 for (i = 0; i < p_nat->pub_ip_count; i++)
10421 printf("%x : (%d,%d)\n", p_nat->pub_ip_port_set[i].ip,
10422 p_nat->pub_ip_port_set[i].start_port,
10423 p_nat->pub_ip_port_set[i].end_port);
10427 #ifdef CGNAPT_TIMING_INST
10428 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_TIMING_INST) {
10429 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 0) {
10430 p_nat->time_measurements_on = 1;
10431 p_nat->time_measurements = 0;
10432 printf("CGNAPT timing instrumentation turned on.\n");
10433 printf("Max samples %d\n", p_nat->max_time_mesurements);
10435 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 1) {
10436 p_nat->time_measurements_on = 0;
10437 printf("CGNAPT timing instrumentation turned off.\n");
10438 printf("Cur Samples %d\n", p_nat->time_measurements);
10440 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 2) {
10441 uint64_t sum = p_nat->external_time_sum +
10442 p_nat->internal_time_sum;
10443 uint64_t isump = (p_nat->internal_time_sum * 100) / sum;
10444 uint64_t esump = (p_nat->external_time_sum * 100) / sum;
10445 printf("CGNAPT timing instrumentation status ...\n");
10446 printf("Max Count %d, Cur Count %d, Status %d (1=ON)\n",
10447 p_nat->max_time_mesurements,
10448 p_nat->time_measurements,
10449 p_nat->time_measurements_on);
10450 printf("Internal Time Sum %" PRIu64 " , Ave %" PRIu64
10451 ", percent %" PRIu64 "\n",
10452 p_nat->internal_time_sum,
10453 (p_nat->internal_time_sum /
10454 p_nat->time_measurements), isump);
10455 printf("External Time Sum %" PRIu64 " , Ave %" PRIu64
10456 ", percent %" PRIu64 "\n",
10457 p_nat->external_time_sum,
10458 (p_nat->external_time_sum /
10459 p_nat->time_measurements), esump);
10466 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_PRINT_NSP) {
10467 struct cgnapt_nsp_node *ll = nsp_ll;
10469 while (ll != NULL) {
10470 fprintf(stderr, "NSP Prefix/Depth=>%x%x:%x%x:%x%x: "
10471 "%x%x:%x%x:%x%x:%x%x:%x%x/%d",
10472 ll->nsp.prefix[0], ll->nsp.prefix[1],
10473 ll->nsp.prefix[2], ll->nsp.prefix[3],
10474 ll->nsp.prefix[4], ll->nsp.prefix[5],
10475 ll->nsp.prefix[6], ll->nsp.prefix[7],
10476 ll->nsp.prefix[8], ll->nsp.prefix[9],
10477 ll->nsp.prefix[10], ll->nsp.prefix[11],
10478 ll->nsp.prefix[12], ll->nsp.prefix[13],
10479 ll->nsp.prefix[14], ll->nsp.prefix[15],
10488 printf("CG-NAPT debug handler called with wrong args %x %x\n", Msg[0],
10492 for (i = 0; i < 20; i++)
10493 printf("%02x ", Msg[i]);
10499 * Function to print num of clients per IP address
10502 void print_num_ip_clients(void)
10504 if (nat_only_config_flag) {
10505 printf("Command not supported for NAT only config.\n");
10510 printf("\tPublic IP: Num Clients\n");
10511 for (ii = 0; ii < CGNAPT_MAX_PUB_IP; ii++)
10512 printf("\t%08x : %7d\n", all_public_ip[ii].ip,
10513 rte_atomic16_read(&all_public_ip[ii].count));
10517 * Function to print CGNAPT version info
10520 * An unused pointer to struct pipeline
10522 * void pointer to incoming arguments
10524 void *pipeline_cgnapt_msg_req_ver_handler(__rte_unused struct pipeline *p,
10527 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
10528 uint8_t *Msg = msg;
10532 printf("CG-NAPT debug handler called with args %x %x, offset %d\n",
10533 Msg[CGNAPT_VER_CMD_OFST], Msg[CGNAPT_VER_CMD_OFST + 1],
10534 CGNAPT_VER_CMD_OFST);
10536 if (Msg[CGNAPT_VER_CMD_OFST] == CGNAPT_VER_CMD_VER) {
10537 printf("CGNAPT Version %s\n", CGNAPT_VERSION);
10540 printf("CG-NAPT Version handler called with wrong args %x %x\n",
10544 for (i = 0; i < 20; i++)
10545 printf("%02x ", Msg[i]);
10551 * Function to show CGNAPT stats
10554 void all_cgnapt_stats(void)
10557 struct pipeline_cgnapt *p_nat;
10558 uint64_t receivedPktCount = 0;
10559 uint64_t missedPktCount = 0;
10560 uint64_t naptDroppedPktCount = 0;
10561 uint64_t naptedPktCount = 0;
10562 uint64_t inaptedPktCount = 0;
10563 uint64_t enaptedPktCount = 0;
10564 uint64_t arpicmpPktCount = 0;
10566 printf("\nCG-NAPT Packet Stats:\n");
10567 for (i = 0; i < n_cgnapt_pipeline; i++) {
10568 p_nat = all_pipeline_cgnapt[i];
10570 receivedPktCount += p_nat->receivedPktCount;
10571 missedPktCount += p_nat->missedPktCount;
10572 naptDroppedPktCount += p_nat->naptDroppedPktCount;
10573 naptedPktCount += p_nat->naptedPktCount;
10574 inaptedPktCount += p_nat->inaptedPktCount;
10575 enaptedPktCount += p_nat->enaptedPktCount;
10576 arpicmpPktCount += p_nat->arpicmpPktCount;
10578 printf("pipeline %d stats:\n", p_nat->pipeline_num);
10579 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10580 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10581 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10582 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10583 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10584 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10585 printf("arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10588 #ifdef CGNAPT_DEBUGGING
10589 printf("\n Drop detail 1:%" PRIu64 ",",
10590 p_nat->naptDroppedPktCount1);
10591 printf("\n Drop detail 2:%" PRIu64 ",",
10592 p_nat->naptDroppedPktCount2);
10593 printf("\n Drop detail 3:%" PRIu64 ",",
10594 p_nat->naptDroppedPktCount3);
10595 printf("\n Drop detail 4:%" PRIu64 ",",
10596 p_nat->naptDroppedPktCount4);
10597 printf("\n Drop detail 5:%" PRIu64 ",",
10598 p_nat->naptDroppedPktCount5);
10599 printf("\n Drop detail 6:%" PRIu64 "",
10600 p_nat->naptDroppedPktCount6);
10602 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10603 p_nat->missedpktcount1,
10604 p_nat->missedpktcount2);
10605 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10606 p_nat->missedpktcount3,
10607 p_nat->missedpktcount4);
10608 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10609 p_nat->missedpktcount5,
10610 p_nat->missedpktcount6);
10611 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10612 p_nat->missedpktcount7,
10613 p_nat->missedpktcount8);
10614 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10615 p_nat->missedpktcount9,
10616 p_nat->missedpktcount10);
10622 printf("\nTotal pipeline stats:\n");
10623 printf("Received %" PRIu64 ",", receivedPktCount);
10624 printf("Missed %" PRIu64 ",", missedPktCount);
10625 printf("Dropped %" PRIu64 ",", naptDroppedPktCount);
10626 printf("Translated %" PRIu64 ",", naptedPktCount);
10627 printf("ingress %" PRIu64 ",", inaptedPktCount);
10628 printf("egress %" PRIu64 "\n", enaptedPktCount);
10629 printf("arpicmp pkts %" PRIu64 "\n", arpicmpPktCount);
10632 void all_cgnapt_clear_stats(void)
10635 struct pipeline_cgnapt *p_nat;
10636 printf("\nCG-NAPT Packet Stats:\n");
10637 for (i = 0; i < n_cgnapt_pipeline; i++) {
10638 p_nat = all_pipeline_cgnapt[i];
10640 printf("pipeline %d stats:\n", p_nat->pipeline_num);
10641 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10642 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10643 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10644 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10645 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10646 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10647 printf("arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10649 p_nat->receivedPktCount = 0;
10650 p_nat->missedPktCount = 0;
10651 p_nat->naptDroppedPktCount = 0;
10652 p_nat->naptedPktCount = 0;
10653 p_nat->inaptedPktCount = 0;
10654 p_nat->enaptedPktCount = 0;
10655 p_nat->arpicmpPktCount = 0;
10657 #ifdef CGNAPT_DEBUGGING
10658 printf("\n Drop detail 1:%" PRIu64 ",",
10659 p_nat->naptDroppedPktCount1);
10660 printf("\n Drop detail 2:%" PRIu64 ",",
10661 p_nat->naptDroppedPktCount2);
10662 printf("\n Drop detail 3:%" PRIu64 ",",
10663 p_nat->naptDroppedPktCount3);
10664 printf("\n Drop detail 4:%" PRIu64 ",",
10665 p_nat->naptDroppedPktCount4);
10666 printf("\n Drop detail 5:%" PRIu64 ",",
10667 p_nat->naptDroppedPktCount5);
10668 printf("\n Drop detail 6:%" PRIu64 "",
10669 p_nat->naptDroppedPktCount6);
10671 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10672 p_nat->missedpktcount1,
10673 p_nat->missedpktcount2);
10674 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10675 p_nat->missedpktcount3,
10676 p_nat->missedpktcount4);
10677 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10678 p_nat->missedpktcount5,
10679 p_nat->missedpktcount6);
10680 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10681 p_nat->missedpktcount7,
10682 p_nat->missedpktcount8);
10683 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10684 p_nat->missedpktcount9,
10685 p_nat->missedpktcount10);
10693 * Function to print common CGNAPT table entries
10696 void print_static_cgnapt_entries(void)
10698 uint32_t count = 0;
10703 struct cgnapt_table_entry *entry;
10705 index = rte_hash_iterate(napt_common_table,
10706 &key, &data, &next);
10708 if ((index != -EINVAL) && (index != -ENOENT)) {
10709 printf("\n%04d ", count);
10710 rte_hexdump(stdout, "KEY", key,
10711 sizeof(struct pipeline_cgnapt_entry_key));
10712 int32_t position = rte_hash_lookup(
10713 napt_common_table, key);
10714 entry = &napt_hash_tbl_entries[position];
10716 if (entry->data.timeout == STATIC_CGNAPT_TIMEOUT)
10717 rte_hexdump(stdout, "Entry",
10718 (const void *)entry,
10719 sizeof(struct cgnapt_table_entry));
10723 } while (index != -ENOENT);
10727 * Function to show CGNAPT stats
10731 struct pipeline_be_ops pipeline_cgnapt_be_ops = {
10732 .f_init = pipeline_cgnapt_init,
10733 .f_free = pipeline_cgnapt_free,
10735 .f_timer = pipeline_cgnapt_timer,
10736 .f_track = pipeline_cgnapt_track,