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 printf("hw_checksum() : Neither TCP or UDP pkt\n");
719 void sw_checksum(struct rte_mbuf *pkt, enum PKT_TYPE ver)
721 struct tcp_hdr *tcp = NULL;
722 struct udp_hdr *udp = NULL;
723 struct icmp_hdr *icmp = NULL;
725 void *ip_header = NULL;
726 uint16_t prot_offset = 0;
727 uint32_t pkt_type_is_ipv4 = 1;
731 case PKT_TYPE_IPV4to6:
735 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
736 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
738 pkt_type_is_ipv4 = 0;
739 tcp = (struct tcp_hdr *)
740 ((unsigned char *)ip_header +
741 sizeof(struct ipv6_hdr));
742 udp = (struct udp_hdr *)
743 ((unsigned char *)ip_header +
744 sizeof(struct ipv6_hdr));
745 icmp = (struct icmp_hdr *)
746 ((unsigned char *)ip_header +
747 sizeof(struct ipv6_hdr));
749 prot_offset = PROT_OFST_IP6 + temp;
751 case PKT_TYPE_IPV6to4:
755 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
756 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
758 tcp = (struct tcp_hdr *)
759 ((unsigned char *)ip_header +
760 sizeof(struct ipv4_hdr));
761 udp = (struct udp_hdr *)
762 ((unsigned char *)ip_header +
763 sizeof(struct ipv4_hdr));
764 icmp = (struct icmp_hdr *)
765 ((unsigned char *)ip_header +
766 sizeof(struct ipv4_hdr));
768 prot_offset = PROT_OFST_IP4 + temp;
771 printf("sw_checksum: pkt version is invalid\n");
773 protocol = (uint8_t *) RTE_MBUF_METADATA_UINT8_PTR(pkt,
777 case IP_PROTOCOL_TCP: /* 6 */
779 if (pkt_type_is_ipv4) {
780 struct ipv4_hdr *ip_hdr =
781 (struct ipv4_hdr *)ip_header;
782 tcp->cksum = rte_ipv4_udptcp_cksum(ip_hdr,
784 ip_hdr->hdr_checksum = 0;
785 ip_hdr->hdr_checksum = rte_ipv4_cksum(
786 (struct ipv4_hdr *)ip_hdr);
788 tcp->cksum = rte_ipv6_udptcp_cksum(
790 ip_header, (void *)tcp);
793 case IP_PROTOCOL_UDP: /* 17 */
794 udp->dgram_cksum = 0;
795 if (pkt_type_is_ipv4) {
796 struct ipv4_hdr *ip_hdr =
797 (struct ipv4_hdr *)ip_header;
798 udp->dgram_cksum = rte_ipv4_udptcp_cksum(
799 ip_hdr, (void *)udp);
800 ip_hdr->hdr_checksum = 0;
801 ip_hdr->hdr_checksum = rte_ipv4_cksum(ip_hdr);
803 udp->dgram_cksum = rte_ipv6_udptcp_cksum(
805 ip_header, (void *)udp);
808 case IP_PROTOCOL_ICMP: /* 1 */
809 if (pkt_type_is_ipv4) {
810 /* ICMP checksum code */
811 struct ipv4_hdr *ip_hdr =
812 (struct ipv4_hdr *)ip_header;
813 int size = rte_bswap16(ip_hdr->total_length) - 20;
814 icmp->icmp_cksum = 0;
818 ip_hdr->hdr_checksum = 0;
819 ip_hdr->hdr_checksum = rte_ipv4_cksum(ip_hdr);
824 printf("sw_checksum() : Neither TCP or UDP pkt\n");
829 void print_pkt_info(uint8_t *eth_dest, struct ether_addr *hw_addr,
830 uint32_t dest_address, uint32_t port_id, struct rte_mbuf *pkt)
833 if (CGNAPT_DEBUG > 2) {
834 printf("MAC Found ip 0x%x, port %d - %02x:%02x:%02x:%02x:%02x:%02x \n",
835 dest_address, port_id, hw_addr->addr_bytes[0], hw_addr->addr_bytes[1],
836 hw_addr->addr_bytes[2], hw_addr->addr_bytes[3], hw_addr->addr_bytes[4],
837 hw_addr->addr_bytes[5]);
839 printf("Dest MAC before - %02x:%02x:%02x:%02x:%02x:%02x \n",
840 eth_dest[0], eth_dest[1], eth_dest[2], eth_dest[3], eth_dest[4],
844 if (CGNAPT_DEBUG > 2) {
845 printf("Dest MAC after - "
846 "%02x:%02x:%02x:%02x:%02x:%02x \n",
847 eth_dest[0], eth_dest[1],
848 eth_dest[2], eth_dest[3],
849 eth_dest[4], eth_dest[5]);
852 if (CGNAPT_DEBUG > 4)
856 static uint8_t check_arp_icmp(
857 struct rte_mbuf *pkt,
859 struct pipeline_cgnapt *p_nat)
861 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
862 uint16_t *eth_proto = RTE_MBUF_METADATA_UINT16_PTR(
863 pkt, eth_proto_offset);
864 struct app_link_params *link;
865 uint8_t solicited_node_multicast_addr[16] = {
866 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
867 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00};
869 /* ARP outport number */
870 uint16_t out_port = p_nat->p.n_ports_out - 1;
871 printf("check_arp_icmp called*****\n");
873 uint32_t prot_offset;
875 link = &myApp->link_params[pkt->port];
878 switch (rte_be_to_cpu_16(*eth_proto)) {
882 rte_pipeline_port_out_packet_insert(
888 * Pkt mask should be changed, and not changing the
891 p_nat->invalid_packets |= pkt_mask;
892 p_nat->arpicmpPktCount++;
896 case ETH_TYPE_IPV4: {
897 /* header room + eth hdr size +
898 * src_aadr offset in ip header
900 uint32_t dst_addr_offset = MBUF_HDR_ROOM +
901 ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
903 RTE_MBUF_METADATA_UINT32_PTR(pkt,
905 prot_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
906 IP_HDR_PROTOCOL_OFST;
907 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt,
909 if ((*protocol == IP_PROTOCOL_ICMP) &&
910 link->ip == rte_be_to_cpu_32(*dst_addr)) {
912 if (is_phy_port_privte(pkt->port)) {
914 rte_pipeline_port_out_packet_insert(
915 p_nat->p.p, out_port, pkt);
918 * Pkt mask should be changed,
919 * and not changing the drop mask
922 p_nat->invalid_packets |= pkt_mask;
923 p_nat->arpicmpPktCount++;
934 if (dual_stack_enable) {
936 /* Commented code may be required for future usage,
939 //uint32_t dst_addr_offset = MBUF_HDR_ROOM +
940 // ETH_HDR_SIZE + IPV6_HDR_DST_ADR_OFST;
941 //uint32_t *dst_addr =
942 // RTE_MBUF_METADATA_UINT32_PTR(pkt,
944 uint32_t prot_offset_ipv6 = MBUF_HDR_ROOM +
945 ETH_HDR_SIZE + IPV6_HDR_PROTOCOL_OFST;
946 struct ipv6_hdr *ipv6_h;
948 ipv6_h = (struct ipv6_hdr *) MBUF_HDR_ROOM +
950 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt,
953 if (ipv6_h->proto == ICMPV6_PROTOCOL_ID) {
954 if (!memcmp(ipv6_h->dst_addr, link->ipv6, 16)
955 || !memcmp(ipv6_h->dst_addr,
956 solicited_node_multicast_addr, 13)) {
957 rte_pipeline_port_out_packet_insert(
958 p_nat->p.p, out_port, pkt);
960 * Pkt mask should be changed,
961 * and not changing the drop mask
963 p_nat->invalid_packets |= pkt_mask;
964 p_nat->arpicmpPktCount++;
966 p_nat->invalid_packets |= pkt_mask;
967 p_nat->naptDroppedPktCount++;
969 #ifdef CGNAPT_DEBUGGING
970 p_nat->naptDroppedPktCount1++;
985 * Function to create common NAPT table
986 * Called during pipeline initialization
987 * Creates the common NAPT table
988 * If it is not already created and stores its pointer
989 * in global napt_common_table pointer.
992 * Max number of NAPT flows. This parameter is configurable via config file.
995 * 0 on success, negative on error.
997 int create_napt_common_table(uint32_t nFlows)
999 if (napt_common_table != NULL) {
1000 printf("napt_common_table already exists.\n");
1004 napt_common_table = rte_hash_create(&napt_common_table_hash_params);
1006 if (napt_common_table == NULL) {
1007 printf("napt_common_table creation failed.\n");
1011 uint32_t number_of_entries = nFlows;
1014 RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_table_entry) *
1016 napt_hash_tbl_entries = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1018 if (napt_hash_tbl_entries == NULL) {
1019 printf("napt_hash_tbl_entries creation failed. %d, %d\n",
1020 nFlows, (int)sizeof(struct cgnapt_table_entry));
1028 * Function to initialize bulk port allocation data structures
1029 * Called during pipeline initialization.
1031 * Creates the port alloc ring for the VNF_set this pipeline belongs
1033 * Creates global port allocation buffer pool
1035 * Initializes the port alloc ring according to config data
1038 * A pointer to struct pipeline_cgnapt
1041 * 0 on success, negative on error.
1043 int napt_port_alloc_init(struct pipeline_cgnapt *p_nat)
1045 p_nat->allocated_ports = NULL;
1046 p_nat->free_ports = NULL;
1048 uint32_t vnf_set_num = p_nat->vnf_set;
1049 /*uint32_t vnf_set_num = get_vnf_set_num(p_nat->pipeline_num); */
1051 printf("VNF set number for CGNAPT %d is %d.\n", p_nat->pipeline_num,
1053 if (vnf_set_num == 0xFF) {
1054 printf("VNF set number for CGNAPT %d is invalid %d.\n",
1055 p_nat->pipeline_num, vnf_set_num);
1059 p_nat->port_alloc_ring = port_alloc_ring[vnf_set_num];
1060 if (p_nat->port_alloc_ring != NULL) {
1061 printf("CGNAPT%d port_alloc_ring already exists.\n",
1062 p_nat->pipeline_num);
1066 printf("napt_port_alloc_elem_count :%d\n",
1067 napt_port_alloc_elem_count);
1068 napt_port_alloc_elem_count += 1;
1069 napt_port_alloc_elem_count =
1070 nextPowerOf2(napt_port_alloc_elem_count);
1071 printf("Next power of napt_port_alloc_elem_count: %d\n",
1072 napt_port_alloc_elem_count);
1074 port_alloc_ring[vnf_set_num] =
1075 rte_ring_create(napt_port_alloc_ring_name[vnf_set_num],
1076 napt_port_alloc_elem_count, rte_socket_id(), 0);
1077 p_nat->port_alloc_ring = port_alloc_ring[vnf_set_num];
1078 if (p_nat->port_alloc_ring == NULL) {
1079 printf("CGNAPT%d - Failed to create port_alloc_ring\n",
1080 p_nat->pipeline_num);
1084 /* Create port alloc buffer */
1085 /* Only one pool is enough for all vnf sets */
1086 if (napt_port_pool == NULL) {
1088 napt_port_pool = rte_mempool_create(
1090 napt_port_alloc_elem_count,
1091 sizeof(struct napt_port_alloc_elem),
1092 0, 0, NULL, NULL, NULL,
1093 NULL, rte_socket_id(), 0);
1096 if (napt_port_pool == NULL) {
1097 printf("CGNAPT - Create port pool failed\n");
1101 /* Add all available public IP addresses and ports to the ring */
1104 #ifdef NAT_ONLY_CONFIG_REQ
1105 if (nat_only_config_flag) {
1106 printf("******* pub_ip_range_count:%d ***********\n",
1107 p_nat->pub_ip_range_count);
1108 /* Initialize all public IP's addresses */
1110 uint32_t max_ips_remain;
1112 for (if_addrs = 0; if_addrs < p_nat->pub_ip_range_count;
1114 /* Add all available addresses to the ring */
1116 for (i = p_nat->pub_ip_range[if_addrs].start_ip;
1117 i <= p_nat->pub_ip_range[if_addrs].end_ip;) {
1118 /* 1. Get a port alloc buffer from napt_port_pool */
1122 /* get new napt_port_alloc_elem from pool */
1123 if (rte_mempool_get(napt_port_pool,
1125 printf("CGNAPT - Error in getting port "
1131 /* 2. Populate it with available ports and ip addr */
1132 struct napt_port_alloc_elem *pb =
1133 (struct napt_port_alloc_elem *)portsBuf;
1136 temp = p_nat->pub_ip_range[if_addrs].end_ip -
1139 /* Check if remaining port count is greater
1140 * than or equals to bulk count, if not give
1141 * remaining count ports than giving bulk count
1143 if (temp < NUM_NAPT_PORT_BULK_ALLOC)
1144 max_ips_remain = temp;
1147 NUM_NAPT_PORT_BULK_ALLOC;
1149 for (j = 0; j < max_ips_remain; j++) {
1151 pb->ip_addr[j] = i + j;
1154 p_nat->pub_ip_range[if_addrs].
1159 /* 3. add the port alloc buffer to ring */
1160 if (rte_ring_enqueue(p_nat->port_alloc_ring,
1162 printf("CGNAPT%d - Enqueue error - i %d,",
1163 p_nat->pipeline_num, i);
1164 printf("j %d, if_addrs %d, pb %p\n",
1166 rte_ring_dump(stdout,
1167 p_nat->port_alloc_ring);
1168 rte_mempool_put(napt_port_pool,
1173 /* reset j and advance i */
1175 i += max_ips_remain;
1183 printf("******* p_nat->pub_ip_count:%d ***********\n",
1184 p_nat->pub_ip_count);
1185 /* Initialize all public IP's ports */
1187 uint32_t max_ports_remain;
1189 for (if_ports = 0; if_ports < p_nat->pub_ip_count; if_ports++) {
1190 /* Add all available ports to the ring */
1192 for (i = p_nat->pub_ip_port_set[if_ports].start_port;
1193 i <= p_nat->pub_ip_port_set[if_ports].end_port;) {
1194 /* 1. Get a port alloc buffer from napt_port_pool */
1198 /* get new napt_port_alloc_elem from pool */
1199 if (rte_mempool_get(napt_port_pool, &portsBuf) <
1201 printf("CGNAPT - Error in getting "
1202 "port alloc buffer\n");
1207 /* 2. Populate it with available ports and ip addr */
1208 struct napt_port_alloc_elem *pb =
1209 (struct napt_port_alloc_elem *)portsBuf;
1212 temp = p_nat->pub_ip_port_set[if_ports].end_port -
1214 /* Check if remaining port count is greater
1215 * than or equals to bulk count, if not give
1216 * remaining count ports than giving bulk count
1218 if (temp < NUM_NAPT_PORT_BULK_ALLOC)
1219 max_ports_remain = temp;
1222 NUM_NAPT_PORT_BULK_ALLOC;
1224 for (j = 0; j < max_ports_remain; j++) {
1227 p_nat->pub_ip_port_set[if_ports].ip;
1228 pb->ports[j] = i + j;
1229 if ((i + j) == p_nat->pub_ip_port_set
1230 [if_ports].end_port)
1234 /* 3. add the port alloc buffer to ring */
1235 if (rte_ring_enqueue(p_nat->port_alloc_ring,
1237 printf("CGNAPT%d - Enqueue error - i %d, j %d, "
1238 " if_ports %d, pb %p\n", p_nat->pipeline_num,
1239 i, j, if_ports, pb);
1241 rte_ring_dump(stdout, p_nat->port_alloc_ring);
1242 rte_mempool_put(napt_port_pool, portsBuf);
1246 /* reset j and advance i */
1248 i += max_ports_remain;
1255 static pipeline_msg_req_handler handlers[] = {
1256 [PIPELINE_MSG_REQ_PING] =
1257 pipeline_msg_req_ping_handler,
1258 [PIPELINE_MSG_REQ_STATS_PORT_IN] =
1259 pipeline_msg_req_stats_port_in_handler,
1260 [PIPELINE_MSG_REQ_STATS_PORT_OUT] =
1261 pipeline_msg_req_stats_port_out_handler,
1262 [PIPELINE_MSG_REQ_STATS_TABLE] = pipeline_msg_req_stats_table_handler,
1263 [PIPELINE_MSG_REQ_PORT_IN_ENABLE] =
1264 pipeline_msg_req_port_in_enable_handler,
1265 [PIPELINE_MSG_REQ_PORT_IN_DISABLE] =
1266 pipeline_msg_req_port_in_disable_handler,
1267 [PIPELINE_MSG_REQ_CUSTOM] =
1268 pipeline_cgnapt_msg_req_custom_handler,
1271 static pipeline_msg_req_handler custom_handlers[] = {
1272 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_ADD] =
1273 pipeline_cgnapt_msg_req_entry_add_handler,
1274 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_DEL] =
1275 pipeline_cgnapt_msg_req_entry_del_handler,
1276 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_SYNC] =
1277 pipeline_cgnapt_msg_req_entry_sync_handler,
1278 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_DBG] =
1279 pipeline_cgnapt_msg_req_entry_dbg_handler,
1280 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_ADDM] =
1281 pipeline_cgnapt_msg_req_entry_addm_handler,
1282 [PIPELINE_CGNAPT_MSG_REQ_VER] =
1283 pipeline_cgnapt_msg_req_ver_handler,
1284 [PIPELINE_CGNAPT_MSG_REQ_NSP_ADD] =
1285 pipeline_cgnapt_msg_req_nsp_add_handler,
1286 [PIPELINE_CGNAPT_MSG_REQ_NSP_DEL] =
1287 pipeline_cgnapt_msg_req_nsp_del_handler,
1290 [PIPELINE_CGNAPT_MSG_REQ_PCP] =
1291 pipeline_cgnapt_msg_req_pcp_handler,
1296 * Function to convert an IPv6 packet to IPv4 packet
1299 * A pointer to packet mbuf
1300 * @param in_ipv6_hdr
1301 * A pointer to IPv6 header in the given pkt
1305 convert_ipv6_to_ipv4(struct rte_mbuf *pkt, struct ipv6_hdr *in_ipv6_hdr)
1307 uint32_t ip_hdr_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE;
1309 uint8_t *eth_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1310 uint8_t *ipv6_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, ip_hdr_offset);
1312 struct ether_hdr eth_hdr;
1313 struct ipv4_hdr *ipv4_hdr_p;
1314 uint16_t frag_off = 0x4000;
1315 struct cgnapt_nsp_node *ll = nsp_ll;
1316 uint8_t ipv4_dest[4];
1319 memcpy(ð_hdr, eth_hdr_p, sizeof(struct ether_hdr));
1320 memcpy(in_ipv6_hdr, ipv6_hdr_p, sizeof(struct ipv6_hdr));
1322 eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
1324 char *data_area_p = rte_pktmbuf_adj(pkt, 20);
1325 if (data_area_p == NULL) {
1326 printf("convert_ipv6_to_ipv4:data_area_p is NULL\n");
1329 ipv4_hdr_p = (struct ipv4_hdr *)(data_area_p + ETH_HDR_SIZE);
1330 memset(ipv4_hdr_p, 0, sizeof(struct ipv4_hdr));
1332 memcpy(data_area_p, ð_hdr, sizeof(struct ether_hdr));
1334 #ifdef CGNAPT_DBG_PRNT
1335 if (CGNAPT_DEBUG == 1)
1336 printf("convert_ipv6_to_ipv4: eth_hdr_p(%p), data_area_p(%p), "
1337 "ipv4_hdr_p(%p)\n", eth_hdr_p, data_area_p, ipv4_hdr_p);
1340 ipv4_hdr_p->version_ihl = 0x4 << 4 | 0x5;
1341 ipv4_hdr_p->type_of_service =
1342 rte_be_to_cpu_32(in_ipv6_hdr->vtc_flow) & 0x0ff00000 >> 20;
1343 ipv4_hdr_p->total_length =
1344 rte_cpu_to_be_16(rte_be_to_cpu_16(
1345 in_ipv6_hdr->payload_len) + 20);
1346 ipv4_hdr_p->packet_id = 0;
1347 ipv4_hdr_p->fragment_offset = rte_cpu_to_be_16(frag_off);
1348 ipv4_hdr_p->time_to_live = in_ipv6_hdr->hop_limits;
1349 ipv4_hdr_p->next_proto_id = in_ipv6_hdr->proto;
1350 ipv4_hdr_p->hdr_checksum = 0;
1351 ipv4_hdr_p->src_addr = 0;
1353 while (ll != NULL) {
1355 (&in_ipv6_hdr->dst_addr[0], &ll->nsp.prefix[0],
1356 ll->nsp.depth / 8)) {
1357 if (ll->nsp.depth == 32)
1358 memcpy(&ipv4_dest[0], &in_ipv6_hdr->dst_addr[4],
1360 else if (ll->nsp.depth == 40) {
1361 ipv4_dest[0] = in_ipv6_hdr->dst_addr[5];
1362 ipv4_dest[1] = in_ipv6_hdr->dst_addr[6];
1363 ipv4_dest[2] = in_ipv6_hdr->dst_addr[7];
1364 ipv4_dest[3] = in_ipv6_hdr->dst_addr[9];
1365 } else if (ll->nsp.depth == 48) {
1366 ipv4_dest[0] = in_ipv6_hdr->dst_addr[6];
1367 ipv4_dest[1] = in_ipv6_hdr->dst_addr[7];
1368 ipv4_dest[2] = in_ipv6_hdr->dst_addr[9];
1369 ipv4_dest[3] = in_ipv6_hdr->dst_addr[10];
1370 } else if (ll->nsp.depth == 56) {
1371 ipv4_dest[0] = in_ipv6_hdr->dst_addr[7];
1372 ipv4_dest[1] = in_ipv6_hdr->dst_addr[9];
1373 ipv4_dest[2] = in_ipv6_hdr->dst_addr[10];
1374 ipv4_dest[3] = in_ipv6_hdr->dst_addr[11];
1375 } else if (ll->nsp.depth == 64) {
1376 ipv4_dest[0] = in_ipv6_hdr->dst_addr[9];
1377 ipv4_dest[1] = in_ipv6_hdr->dst_addr[10];
1378 ipv4_dest[2] = in_ipv6_hdr->dst_addr[11];
1379 ipv4_dest[3] = in_ipv6_hdr->dst_addr[12];
1380 } else if (ll->nsp.depth == 96) {
1381 ipv4_dest[0] = in_ipv6_hdr->dst_addr[12];
1382 ipv4_dest[1] = in_ipv6_hdr->dst_addr[13];
1383 ipv4_dest[2] = in_ipv6_hdr->dst_addr[14];
1384 ipv4_dest[3] = in_ipv6_hdr->dst_addr[15];
1395 memcpy(&ipv4_hdr_p->dst_addr, &ipv4_dest[0], 4);
1397 memcpy(&ipv4_hdr_p->dst_addr, &in_ipv6_hdr->dst_addr[12], 4);
1402 * Function to convert an IPv4 packet to IPv6 packet
1405 * A pointer to packet mbuf
1406 * @param in_ipv4_hdr
1407 * A pointer to IPv4 header in the given pkt
1411 convert_ipv4_to_ipv6(struct rte_mbuf *pkt, struct ipv4_hdr *in_ipv4_hdr)
1413 uint32_t ip_hdr_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE;
1415 uint8_t *eth_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1416 uint8_t *ipv4_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, ip_hdr_offset);
1418 struct ether_hdr eth_hdr;
1419 struct ipv6_hdr *ipv6_hdr_p;
1421 memcpy(ð_hdr, eth_hdr_p, sizeof(struct ether_hdr));
1422 memcpy(in_ipv4_hdr, ipv4_hdr_p, sizeof(struct ipv4_hdr));
1424 eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
1426 char *data_area_p = rte_pktmbuf_prepend(pkt, 20);
1427 if (data_area_p == NULL) {
1428 printf("convert_ipv4_to_ipv6:data_area_p is NULL\n");
1431 ipv6_hdr_p = (struct ipv6_hdr *)(data_area_p + ETH_HDR_SIZE);
1432 memset(ipv6_hdr_p, 0, sizeof(struct ipv6_hdr));
1434 memcpy(data_area_p, ð_hdr, sizeof(struct ether_hdr));
1436 ipv6_hdr_p->vtc_flow =
1437 rte_cpu_to_be_32((0x6 << 28) |
1438 (in_ipv4_hdr->type_of_service << 20));
1439 ipv6_hdr_p->payload_len =
1440 rte_cpu_to_be_16(rte_be_to_cpu_16(
1441 in_ipv4_hdr->total_length) - 20);
1442 ipv6_hdr_p->proto = in_ipv4_hdr->next_proto_id;
1443 ipv6_hdr_p->hop_limits = in_ipv4_hdr->time_to_live;
1445 ipv6_hdr_p->src_addr[0] = 0x00;
1446 ipv6_hdr_p->src_addr[1] = 0x64;
1447 ipv6_hdr_p->src_addr[2] = 0xff;
1448 ipv6_hdr_p->src_addr[3] = 0x9b;
1449 ipv6_hdr_p->src_addr[4] = 0x00;
1450 ipv6_hdr_p->src_addr[5] = 0x00;
1451 ipv6_hdr_p->src_addr[6] = 0x00;
1452 ipv6_hdr_p->src_addr[7] = 0x00;
1453 ipv6_hdr_p->src_addr[8] = 0x00;
1454 ipv6_hdr_p->src_addr[9] = 0x00;
1455 ipv6_hdr_p->src_addr[10] = 0x00;
1456 ipv6_hdr_p->src_addr[11] = 0x00;
1457 memcpy(&ipv6_hdr_p->src_addr[12], &in_ipv4_hdr->src_addr, 4);
1459 memset(&ipv6_hdr_p->dst_addr, 0, 16);
1466 * Output port handler
1469 * A pointer to packet mbuf
1471 * Unused void pointer
1474 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1476 pkt_work_cgnapt_out(__rte_unused struct rte_mbuf *pkt, __rte_unused void *arg)
1478 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1479 if ((cgnapt_num_func_to_inst == 5)
1480 && (cgnapt_inst_index < INST_ARRAY_SIZE)) {
1481 if (cgnapt_inst5_flag == 0) {
1482 uint8_t *inst5_sig =
1483 RTE_MBUF_METADATA_UINT8_PTR(pkt,
1485 if (*inst5_sig == CGNAPT_INST5_SIG) {
1486 cgnapt_inst5_flag = 1;
1487 inst_end_time[cgnapt_inst_index] =
1488 rte_get_tsc_cycles();
1489 cgnapt_inst_index++;
1495 /* cgnapt_pkt_out_count++; */
1496 #ifdef CGNAPT_DBG_PRNT
1504 * Output port handler to handle 4 pkts
1507 * A pointer to packet mbuf
1509 * Inport handler argument pointer
1512 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1513 static void pkt4_work_cgnapt_out(struct rte_mbuf **pkt, void *arg)
1517 /* TO BE IMPLEMENTED IF REQUIRED */
1521 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1522 PIPELINE_CGNAPT_PORT_OUT_AH(port_out_ah_cgnapt,
1523 pkt_work_cgnapt_out, pkt4_work_cgnapt_out);
1525 PIPELINE_CGNAPT_PORT_OUT_BAH(port_out_ah_cgnapt_bulk,
1526 pkt_work_cgnapt_out, pkt4_work_cgnapt_out);
1530 * Function to validate the packet and return version
1533 * A pointer to packet mbuf
1536 * IP version of the valid pkt, -1 if invalid pkt
1538 int rte_get_pkt_ver(struct rte_mbuf *pkt)
1540 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
1541 uint16_t *eth_proto =
1542 RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
1544 if (*eth_proto == rte_be_to_cpu_16(ETHER_TYPE_IPv4))
1545 return IP_VERSION_4;
1547 if (dual_stack_enable
1548 && (*eth_proto == rte_be_to_cpu_16(ETHER_TYPE_IPv6)))
1549 return IP_VERSION_6;
1551 /* Check the protocol first, if not UDP or TCP return */
1557 * A method to print the NAPT entry
1560 * A pointer to struct cgnapt_table_entry
1562 void my_print_entry(struct cgnapt_table_entry *ent)
1564 printf("CGNAPT key:\n");
1565 printf("entry_type :%d\n", ent->data.type);
1566 printf("prv_ip: %x %x %x %x\n", ent->data.u.u32_prv_ipv6[0],
1567 ent->data.u.u32_prv_ipv6[1], ent->data.u.u32_prv_ipv6[2],
1568 ent->data.u.u32_prv_ipv6[3]);
1569 printf("prv_port:%d\n", ent->data.prv_port);
1571 printf("pub_ip:%x\n", ent->data.pub_ip);
1572 printf("prv_phy_port:%d\n", ent->data.prv_phy_port);
1573 printf("pub_phy_port:%d\n", ent->data.pub_phy_port);
1577 * Function to print common CGNAPT table entries
1580 void print_common_table(void)
1588 index = rte_hash_iterate(napt_common_table,
1589 &key, &data, &next);
1591 if ((index != -EINVAL) && (index != -ENOENT)) {
1592 printf("\n%04d ", count);
1593 //print_key((struct pipeline_cgnapt_entry_key *)key);
1594 rte_hexdump(stdout, "KEY", key,
1595 sizeof(struct pipeline_cgnapt_entry_key));
1596 int32_t position = rte_hash_lookup(
1597 napt_common_table, key);
1598 print_cgnapt_entry(&napt_hash_tbl_entries[position]);
1602 } while (index != -ENOENT);
1606 * Input port handler for mixed traffic
1607 * This is the main method in this file when running in mixed traffic mode.
1608 * Starting from the packet burst it filters unwanted packets,
1609 * calculates keys, does lookup and then based on the lookup
1610 * updates NAPT table and does packet NAPT translation.
1613 * A pointer to struct rte_pipeline
1615 * A pointer to array of packets mbuf
1617 * Number of packets in the burst
1622 * int that is not checked by caller
1624 static int cgnapt_in_port_ah_mix(struct rte_pipeline *rte_p,
1625 struct rte_mbuf **pkts,
1626 uint32_t n_pkts, void *arg)
1631 * 1. Read packet version, if invalid drop the packet
1632 * 2. Check protocol, if not UDP or TCP drop the packet
1633 * 3. Bring all valid packets together - useful for bulk lookup
1634 * and calculate key for all packets
1635 * a. If IPv4 : calculate key with full IP
1636 * b. If IPv6 : calculate key with last 32-bit of IP
1637 * 4. Do bulk lookup with rte_hash_lookup_bulk(), if something went wrong
1639 * 5. For lookup hit packets, read entry from table
1640 * 6. For lookup miss packets, add dynamic entry to table
1642 * a. If egress pkt, convert to IPv4 and NAPT it
1643 * b. If ingress, drop the pkt
1645 * a. If egress pkt, NAPT it. Get MAC
1646 * b. If first ingress pkt (with no egress entry), drop the pkt
1647 * If not first ingress pkt
1648 * I. If IPv6 converted packet, convert back to IPv6,
1650 * II. If IPv4 packet, NAPT it & get MAC
1651 * 9. Send all packets out to corresponding ports
1653 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
1654 struct pipeline_cgnapt *p_nat = ap->p;
1655 uint8_t compacting_map[RTE_HASH_LOOKUP_BULK_MAX];
1656 uint32_t packets_for_lookup = 0;
1659 p_nat->valid_packets = 0;
1660 p_nat->invalid_packets = 0;
1662 #ifdef CGNAPT_DBG_PRNT
1663 if (CGNAPT_DEBUG > 1)
1664 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
1667 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
1669 uint16_t phy_port = 0;
1670 uint16_t *src_port = NULL;
1671 uint16_t *dst_port = NULL;
1672 uint32_t *src_addr = NULL;
1673 uint32_t *dst_addr = NULL;
1674 uint8_t *protocol = NULL;
1675 uint8_t *eth_dest = NULL;
1676 uint8_t *eth_src = NULL;
1677 uint16_t src_port_offset = 0;
1678 uint16_t dst_port_offset = 0;
1679 uint16_t src_addr_offset = 0;
1680 uint16_t dst_addr_offset = 0;
1681 uint16_t prot_offset = 0;
1682 uint16_t eth_offset = 0;
1685 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
1687 src_port_offset = SRC_PRT_OFST_IP4_TCP;
1688 dst_port_offset = DST_PRT_OFST_IP4_TCP;
1690 for (i = 0; i < n_pkts; i++) {
1691 p_nat->receivedPktCount++;
1693 /* bitmask representing only this packet */
1694 uint64_t pkt_mask = 1LLU << i;
1696 /* remember this pkt as valid pkt */
1697 p_nat->valid_packets |= pkt_mask;
1699 struct rte_mbuf *pkt = pkts[i];
1702 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
1705 int ver = rte_get_pkt_ver(pkt);
1707 #ifdef CGNAPT_DBG_PRNT
1708 printf("ver no. of the pkt:%d\n", ver);
1711 if (unlikely(ver < 0)) {
1712 /* Not a valid pkt , ignore. */
1713 /* remember invalid packets to be dropped */
1714 p_nat->invalid_packets |= pkt_mask;
1715 p_nat->naptDroppedPktCount++;
1717 #ifdef CGNAPT_DEBUGGING
1718 p_nat->naptDroppedPktCount1++;
1723 prot_offset = PROT_OFST_IP4;
1725 prot_offset = PROT_OFST_IP6;
1727 (uint8_t *) RTE_MBUF_METADATA_UINT32_PTR(pkt,
1730 (*protocol == IP_PROTOCOL_TCP
1731 || *protocol == IP_PROTOCOL_UDP
1732 || *protocol == IP_PROTOCOL_ICMP)) {
1733 /* remember invalid packets to be dropped */
1734 p_nat->invalid_packets |= pkt_mask;
1735 p_nat->naptDroppedPktCount++;
1737 #ifdef CGNAPT_DEBUGGING
1738 p_nat->naptDroppedPktCount2++;
1743 #ifdef CGNAPT_DBG_PRNT
1744 if (CGNAPT_DEBUG > 4)
1750 * 1. Handel PCP for egress traffic
1751 * 2. If PCP, then give response (send pkt) from the same port
1752 * 3. Drop the PCP packet, should not be added in the NAPT table
1755 if (*protocol == IP_PROTOCOL_UDP) {
1756 struct udp_hdr *udp;
1758 udp = (struct udp_hdr *)
1759 RTE_MBUF_METADATA_UINT8_PTR(pkt,
1762 udp = (struct udp_hdr *)
1763 RTE_MBUF_METADATA_UINT8_PTR(pkt,
1766 if (rte_bswap16(udp->dst_port) ==
1768 handle_pcp_req(pkt, ver, p_nat);
1769 p_nat->invalid_packets |= pkt_mask;
1779 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1782 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1785 if ((*protocol == IP_PROTOCOL_TCP)
1786 || (*protocol == IP_PROTOCOL_UDP)) {
1788 src_port_offset = SRC_PRT_OFST_IP4_TCP;
1789 dst_port_offset = DST_PRT_OFST_IP4_TCP;
1791 } else if (*protocol == IP_PROTOCOL_ICMP) {
1793 src_port_offset = IDEN_OFST_IP4_ICMP;
1794 /* Sequence number */
1795 dst_port_offset = SEQN_OFST_IP4_ICMP;
1799 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1802 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1807 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1810 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1813 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1816 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1819 /* need to create compacted table of pointers to
1820 * pass to bulk lookup
1823 compacting_map[packets_for_lookup] = i;
1825 //phy_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, phyport_offset);
1826 phy_port = pkt->port;
1828 struct pipeline_cgnapt_entry_key key;
1830 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
1833 if (get_in_port_dir(phy_port)) {
1836 key.ip = rte_bswap32(*src_addr);
1838 key.ip = rte_bswap32(src_addr[3]);
1839 key.port = rte_bswap16(*src_port);
1841 #ifdef NAT_ONLY_CONFIG_REQ
1842 if (nat_only_config_flag)
1847 key.ip = rte_bswap32(*dst_addr);
1849 if (*protocol == IP_PROTOCOL_ICMP) {
1850 /* common table lookupkey preparation from
1851 * incoming ICMP Packet- Indentifier field
1853 key.port = rte_bswap16(*src_port);
1855 key.port = rte_bswap16(*dst_port);
1858 #ifdef NAT_ONLY_CONFIG_REQ
1859 if (nat_only_config_flag)
1866 memcpy(&(p_nat->keys[packets_for_lookup]), &key,
1867 sizeof(struct pipeline_cgnapt_entry_key));
1868 p_nat->key_ptrs[packets_for_lookup] =
1869 &(p_nat->keys[packets_for_lookup]);
1870 packets_for_lookup++;
1873 if (unlikely(packets_for_lookup == 0)) {
1874 /* no suitable packet for lookup */
1875 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
1876 return p_nat->valid_packets;
1879 /* lookup entries in the common napt table */
1881 int lookup_result = rte_hash_lookup_bulk(napt_common_table,
1885 &p_nat->lkup_indx[0]);
1887 if (unlikely(lookup_result < 0)) {
1888 /* unknown error, just discard all packets */
1889 printf("Unexpected hash lookup error %d, discarding all "
1890 "packets", lookup_result);
1891 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
1894 //struct rte_pipeline_table_entry *entries[64];
1895 /* Now one by one check the result of our bulk lookup */
1897 for (i = 0; i < packets_for_lookup; i++) {
1898 /* index into hash table entries */
1899 int hash_table_entry = p_nat->lkup_indx[i];
1900 /* index into packet table of this packet */
1901 uint8_t pkt_index = compacting_map[i];
1902 /*bitmask representing only this packet */
1903 uint64_t pkt_mask = 1LLU << pkt_index;
1905 struct cgnapt_table_entry *entry = NULL;
1906 if (hash_table_entry < 0) {
1908 /* try to add new entry */
1909 struct rte_pipeline_table_entry *table_entry = NULL;
1912 pkt_miss_cgnapt(p_nat->key_ptrs[i],
1915 &p_nat->valid_packets,
1920 /* ICMP Error message generation for
1921 * Destination Host unreachable
1923 if (*protocol == IP_PROTOCOL_ICMP) {
1924 cgnapt_icmp_pkt = pkts[pkt_index];
1925 send_icmp_dest_unreachable_msg();
1928 /* Drop packet by adding to invalid pkt mask */
1930 p_nat->invalid_packets |= dropmask;
1931 #ifdef CGNAPT_DEBUGGING
1932 if (p_nat->kpc2++ < 5) {
1933 printf("in_ah Th: %d",
1934 p_nat->pipeline_num);
1935 print_key(p_nat->key_ptrs[i]);
1939 p_nat->naptDroppedPktCount++;
1941 #ifdef CGNAPT_DEBUGGING
1942 p_nat->naptDroppedPktCount3++;
1947 entry = (struct cgnapt_table_entry *)table_entry;
1949 /* entry found for this packet */
1950 entry = &napt_hash_tbl_entries[hash_table_entry];
1953 /* apply napt and mac changes */
1955 p_nat->entries[pkt_index] = &(entry->head);
1957 phy_port = pkts[pkt_index]->port;
1959 struct ipv6_hdr ipv6_hdr;
1960 struct ipv4_hdr ipv4_hdr;
1962 ver = rte_get_pkt_ver(pkts[pkt_index]);
1963 #ifdef CGNAPT_DEBUGGING
1964 if (CGNAPT_DEBUG >= 1) {
1965 printf("ver:%d\n", ver);
1966 printf("entry->data.type:%d\n", entry->data.type);
1969 if ((ver == 6) && (entry->data.type == CGNAPT_ENTRY_IPV6)
1970 && is_phy_port_privte(phy_port)) {
1971 convert_ipv6_to_ipv4(pkts[pkt_index], &ipv6_hdr);
1973 pkt_type = PKT_TYPE_IPV6to4;
1975 #ifdef CGNAPT_DBG_PRNT
1976 if (CGNAPT_DEBUG >= 1)
1977 printf("pkt_work_cganpt: "
1978 "convert_ipv6_to_ipv4\n");
1981 struct cgnapt_nsp_node *ll = nsp_ll;
1983 while (ll != NULL) {
1984 if (!memcmp(&ipv6_hdr.dst_addr[0],
1986 ll->nsp.depth / 8)) {
1994 && !memcmp(&ipv6_hdr.dst_addr[0],
1995 &well_known_prefix[0], 12)) {
2000 p_nat->invalid_packets |= 1LLU << pkt_index;
2001 p_nat->naptDroppedPktCount++;
2003 #ifdef CGNAPT_DEBUGGING
2004 p_nat->naptDroppedPktCount5++;
2011 /* As packet is already converted into IPv4 we must not operate
2012 * IPv6 offsets on packet
2013 * Only perform IPv4 operations
2018 src_port_offset = SRC_PRT_OFST_IP6t4;
2019 dst_port_offset = DST_PRT_OFST_IP6t4;
2020 src_addr_offset = SRC_ADR_OFST_IP6t4;
2021 dst_addr_offset = DST_ADR_OFST_IP6t4;
2022 prot_offset = PROT_OFST_IP6t4;
2023 eth_offset = ETH_OFST_IP6t4;
2027 if ((*protocol == IP_PROTOCOL_TCP)
2028 || (*protocol == IP_PROTOCOL_UDP)) {
2029 src_port_offset = SRC_PRT_OFST_IP4_TCP;
2030 dst_port_offset = DST_PRT_OFST_IP4_TCP;
2031 } else if (*protocol == IP_PROTOCOL_ICMP) {
2033 src_port_offset = IDEN_OFST_IP4_ICMP;
2034 /* Sequence number */
2035 dst_port_offset = SEQN_OFST_IP4_ICMP;
2038 src_addr_offset = SRC_ADR_OFST_IP4;
2039 dst_addr_offset = DST_ADR_OFST_IP4;
2040 prot_offset = PROT_OFST_IP4;
2041 eth_offset = MBUF_HDR_ROOM;
2046 RTE_MBUF_METADATA_UINT32_PTR(pkts[pkt_index],
2049 RTE_MBUF_METADATA_UINT32_PTR(pkts[pkt_index],
2052 RTE_MBUF_METADATA_UINT16_PTR(pkts[pkt_index],
2055 RTE_MBUF_METADATA_UINT16_PTR(pkts[pkt_index],
2058 RTE_MBUF_METADATA_UINT8_PTR(pkts[pkt_index],
2062 RTE_MBUF_METADATA_UINT8_PTR(pkts[pkt_index],
2065 RTE_MBUF_METADATA_UINT8_PTR(pkts[pkt_index],
2068 if (entry->data.ttl == NAPT_ENTRY_STALE)
2069 entry->data.ttl = NAPT_ENTRY_VALID;
2071 struct ether_addr hw_addr;
2072 uint32_t dest_address = 0;
2073 uint8_t nh_ipv6[16];
2076 uint32_t dest_if = 0xff;
2079 uint16_t *outport_id =
2080 RTE_MBUF_METADATA_UINT16_PTR(pkts[pkt_index],
2081 cgnapt_meta_offset);
2083 if (is_phy_port_privte(phy_port)) {
2085 if (*protocol == IP_PROTOCOL_UDP
2086 && rte_be_to_cpu_16(*dst_port) == 53) {
2087 p_nat->invalid_packets |= 1LLU << pkt_index;
2088 p_nat->naptDroppedPktCount++;
2089 #ifdef CGNAPT_DEBUGGING
2090 p_nat->naptDroppedPktCount6++;
2095 dest_address = rte_bswap32(*dst_addr);
2096 ret = local_get_nh_ipv4(dest_address, &dest_if,
2099 dest_if = get_prv_to_pub_port(&dest_address,
2101 if (dest_if == INVALID_DESTIF) {
2102 p_nat->invalid_packets |=
2104 p_nat->naptDroppedPktCount++;
2105 #ifdef CGNAPT_DEBUGGING
2106 p_nat->naptDroppedPktCount6++;
2110 do_local_nh_ipv4_cache(dest_if, p_nat);
2113 *outport_id = p_nat->outport_id[dest_if];
2114 struct arp_entry_data *ret_arp_data;
2115 ret_arp_data = get_dest_mac_addr_port(dest_address,
2116 &dest_if, (struct ether_addr *)eth_dest);
2118 if (unlikely(ret_arp_data == NULL)) {
2120 #ifdef CGNAPT_DEBUGGING
2121 printf("%s: NHIP Not Found, nhip: %x, "
2122 "outport_id: %d\n", __func__, nhip,
2126 p_nat->invalid_packets |= pkt_mask;
2127 p_nat->naptDroppedPktCount++;
2129 #ifdef CGNAPT_DEBUGGING
2130 p_nat->naptDroppedPktCount4++;
2135 if (ret_arp_data->status == COMPLETE) {
2137 if (ret_arp_data->num_pkts) {
2138 p_nat->naptedPktCount += ret_arp_data->num_pkts;
2139 arp_send_buffered_pkts(ret_arp_data,
2140 &hw_addr, *outport_id);
2143 memcpy(eth_dest, &hw_addr,
2144 sizeof(struct ether_addr));
2145 memcpy(eth_src, get_link_hw_addr(dest_if),
2146 sizeof(struct ether_addr));
2147 #ifdef CGNAPT_DBG_PRNT
2148 if (CGNAPT_DEBUG > 2) {
2149 printf("MAC found for ip 0x%x, port %d - "
2150 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2151 dest_address, *outport_id,
2152 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
2153 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
2154 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
2156 printf("Dest MAC before - "
2157 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2158 eth_dest[0], eth_dest[1], eth_dest[2],
2159 eth_dest[3], eth_dest[4], eth_dest[5]);
2163 #ifdef CGNAPT_DBG_PRNT
2164 if (CGNAPT_DEBUG > 2) {
2165 printf("Dest MAC after - "
2166 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2167 eth_dest[0], eth_dest[1], eth_dest[2],
2168 eth_dest[3], eth_dest[4], eth_dest[5]);
2172 #ifdef CGNAPT_DBG_PRNT
2173 if (CGNAPT_DEBUG > 4)
2174 print_pkt(pkts[pkt_index]);
2177 } else if (ret_arp_data->status == INCOMPLETE ||
2178 ret_arp_data->status == PROBE) {
2179 if (ret_arp_data->num_pkts >= NUM_DESC) {
2181 p_nat->invalid_packets |= pkt_mask;
2182 p_nat->naptDroppedPktCount++;
2184 #ifdef CGNAPT_DEBUGGING
2185 p_nat->naptDroppedPktCount4++;
2189 arp_queue_unresolved_packet(ret_arp_data,
2195 #ifdef CGNAPT_DBG_PRNT
2196 if (CGNAPT_DEBUG > 2)
2197 printf("Egress: \tphy_port:%d\t "
2198 "get_prv_to_pub():%d \tout_port:%d\n",
2204 *src_addr = rte_bswap32(entry->data.pub_ip);
2206 #ifdef NAT_ONLY_CONFIG_REQ
2207 if (!nat_only_config_flag) {
2209 *src_port = rte_bswap16(entry->data.pub_port);
2210 #ifdef NAT_ONLY_CONFIG_REQ
2214 p_nat->enaptedPktCount++;
2217 if (*protocol == IP_PROTOCOL_UDP
2218 && rte_be_to_cpu_16(*src_port) == 53) {
2219 p_nat->invalid_packets |= 1LLU << pkt_index;
2220 p_nat->naptDroppedPktCount++;
2221 #ifdef CGNAPT_DEBUGGING
2222 p_nat->naptDroppedPktCount6++;
2227 #ifdef CGNAPT_DBG_PRNT
2228 if (CGNAPT_DEBUG > 2)
2229 printf("Ingress: \tphy_port:%d\t "
2230 "get_pub_to_prv():%d \tout_port%d\n",
2235 if (entry->data.type == CGNAPT_ENTRY_IPV6) {
2236 convert_ipv4_to_ipv6(pkts[pkt_index],
2238 pkt_type = PKT_TYPE_IPV4to6;
2239 /* Ethernet MTU check */
2240 if ((rte_pktmbuf_data_len(pkts[pkt_index]) -
2242 p_nat->invalid_packets |= pkt_mask;
2243 p_nat->naptDroppedPktCount++;
2247 eth_dest = eth_dest - 20;
2248 eth_src = eth_src - 20;
2250 dst_port_offset = DST_PRT_OFST_IP4t6;
2251 dst_addr_offset = DST_ADR_OFST_IP4t6;
2253 RTE_MBUF_METADATA_UINT32_PTR(
2257 RTE_MBUF_METADATA_UINT16_PTR(
2261 memcpy((uint8_t *) &dst_addr[0],
2262 &entry->data.u.prv_ipv6[0], 16);
2263 memset(nh_ipv6, 0, 16);
2264 struct nd_entry_data *ret_nd_data = NULL;
2265 ret_nd_data = get_dest_mac_address_ipv6_port((uint8_t *)
2266 &dst_addr[0], &dest_if,
2267 &hw_addr, &nh_ipv6[0]);
2268 *outport_id = p_nat->outport_id[dest_if];
2270 if (nd_cache_dest_mac_present(dest_if)) {
2271 ether_addr_copy(get_link_hw_addr(dest_if),
2272 (struct ether_addr *)eth_src);
2273 update_nhip_access(dest_if);
2275 if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) {
2276 p_nat->naptedPktCount += ret_nd_data->num_pkts;
2277 nd_send_buffered_pkts(ret_nd_data,
2278 (struct ether_addr *)eth_dest,
2282 if (unlikely(ret_nd_data == NULL)) {
2284 #ifdef CGNAPT_DEBUGGING
2285 printf("%s: NHIP Not Found, "
2286 "outport_id: %d\n", __func__,
2291 p_nat->invalid_packets |= pkt_mask;
2292 p_nat->naptDroppedPktCount++;
2294 #ifdef CGNAPT_DEBUGGING
2295 p_nat->naptDroppedPktCount4++;
2300 if (ret_nd_data->status == INCOMPLETE ||
2301 ret_nd_data->status == PROBE) {
2302 if (ret_nd_data->num_pkts >= NUM_DESC) {
2304 p_nat->invalid_packets |= pkt_mask;
2305 p_nat->naptDroppedPktCount++;
2307 #ifdef CGNAPT_DEBUGGING
2308 p_nat->naptDroppedPktCount4++;
2312 arp_pkts_mask |= pkt_mask;
2313 nd_queue_unresolved_packet(ret_nd_data,
2321 #ifdef NAT_ONLY_CONFIG_REQ
2322 if (!nat_only_config_flag) {
2325 rte_bswap16(entry->data.prv_port);
2326 #ifdef NAT_ONLY_CONFIG_REQ
2331 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
2332 dest_address = entry->data.u.prv_ip;
2333 ret = local_get_nh_ipv4(dest_address, &dest_if,
2336 dest_if = get_pub_to_prv_port(
2337 &dest_address, IP_VERSION_4);
2338 if (dest_if == INVALID_DESTIF) {
2339 p_nat->invalid_packets |=
2341 p_nat->naptDroppedPktCount++;
2342 #ifdef CGNAPT_DEBUGGING
2343 p_nat->naptDroppedPktCount6++;
2347 do_local_nh_ipv4_cache(dest_if, p_nat);
2350 *outport_id = p_nat->outport_id[dest_if];
2351 struct arp_entry_data *ret_arp_data;
2352 ret_arp_data = get_dest_mac_addr_port(dest_address,
2353 &dest_if, (struct ether_addr *)eth_dest);
2355 if (unlikely(ret_arp_data == NULL)) {
2357 #ifdef CGNAPT_DEBUGGING
2358 printf("%s: NHIP Not Found, nhip: %x, "
2359 "outport_id: %d\n", __func__, nhip,
2364 p_nat->invalid_packets |= pkt_mask;
2365 p_nat->naptDroppedPktCount++;
2367 #ifdef CGNAPT_DEBUGGING
2368 p_nat->naptDroppedPktCount4++;
2373 if (ret_arp_data->status == COMPLETE) {
2375 if (ret_arp_data->num_pkts) {
2376 p_nat->naptedPktCount +=
2377 ret_arp_data->num_pkts;
2378 arp_send_buffered_pkts(ret_arp_data,
2379 &hw_addr, *outport_id);
2382 memcpy(eth_dest, &hw_addr,
2383 sizeof(struct ether_addr));
2384 memcpy(eth_src, get_link_hw_addr(
2386 sizeof(struct ether_addr));
2387 #ifdef CGNAPT_DBG_PRNT
2388 if (CGNAPT_DEBUG > 2) {
2389 printf("MAC found for ip 0x%x, port %d - "
2390 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2391 dest_address, *outport_id,
2392 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
2393 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
2394 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
2396 printf("Dest MAC before - "
2397 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2398 eth_dest[0], eth_dest[1], eth_dest[2],
2399 eth_dest[3], eth_dest[4], eth_dest[5]);
2403 #ifdef CGNAPT_DBG_PRNT
2404 if (CGNAPT_DEBUG > 2) {
2405 printf("Dest MAC after - "
2406 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2407 eth_dest[0], eth_dest[1], eth_dest[2],
2408 eth_dest[3], eth_dest[4], eth_dest[5]);
2412 #ifdef CGNAPT_DBG_PRNT
2413 if (CGNAPT_DEBUG > 4)
2414 print_pkt(pkts[pkt_index]);
2417 } else if (ret_arp_data->status == INCOMPLETE ||
2418 ret_arp_data->status == PROBE) {
2419 arp_queue_unresolved_packet(ret_arp_data,
2424 if (*protocol == IP_PROTOCOL_ICMP) {
2425 // Query ID reverse translation done here
2427 rte_bswap16(entry->data.prv_port);
2429 #ifdef NAT_ONLY_CONFIG_REQ
2430 if (!nat_only_config_flag) {
2435 #ifdef NAT_ONLY_CONFIG_REQ
2441 p_nat->inaptedPktCount++;
2444 p_nat->naptedPktCount++;
2447 if (p_nat->hw_checksum_reqd)
2448 hw_checksum(pkts[pkt_index], pkt_type);
2450 sw_checksum(pkts[pkt_index], pkt_type);
2454 if (p_nat->invalid_packets) {
2455 /* get rid of invalid packets */
2456 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2458 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2460 #ifdef CGNAPT_DBG_PRNT
2461 if (CGNAPT_DEBUG > 1) {
2462 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
2463 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
2464 printf("invalid_packets:0x%jx\n",
2465 p_nat->invalid_packets);
2466 printf("rte_invalid_packets :0x%jx\n",
2467 rte_p->pkts_drop_mask);
2468 printf("Total pkts dropped :0x%jx\n",
2469 rte_p->n_pkts_ah_drop);
2474 return p_nat->valid_packets;
2478 * Input port handler for IPv4 private traffic
2479 * Starting from the packet burst it filters unwanted packets,
2480 * calculates keys, does lookup and then based on the lookup
2481 * updates NAPT table and does packet NAPT translation.
2484 * A pointer to struct rte_pipeline
2486 * A pointer to array of packets mbuf
2488 * Number of packets in the burst
2493 * int that is not checked by caller
2496 static int cgnapt_in_port_ah_ipv4_prv(struct rte_pipeline *rte_p,
2497 struct rte_mbuf **pkts,
2498 uint32_t n_pkts, void *arg)
2501 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
2502 struct pipeline_cgnapt *p_nat = ap->p;
2504 #ifdef CGNAPT_TIMING_INST
2505 uint64_t entry_timestamp = 0, exit_timestamp;
2507 if (p_nat->time_measurements_on) {
2508 entry_timestamp = rte_get_tsc_cycles();
2509 /* check since exit ts not valid first time through */
2510 if (likely(p_nat->in_port_exit_timestamp))
2511 p_nat->external_time_sum +=
2512 entry_timestamp - p_nat->in_port_exit_timestamp;
2516 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
2517 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
2518 p_nat->invalid_packets = 0;
2520 #ifdef CGNAPT_DBG_PRNT
2521 if (CGNAPT_DEBUG > 1)
2522 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
2525 /* prefetching for mbufs should be done here */
2526 for (j = 0; j < n_pkts; j++)
2527 rte_prefetch0(pkts[j]);
2529 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2530 pkt4_work_cgnapt_key_ipv4_prv(&pkts[i], i, arg, p_nat);
2532 for (; i < n_pkts; i++)
2533 pkt_work_cgnapt_key_ipv4_prv(pkts[i], i, arg, p_nat);
2535 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2537 if (unlikely(p_nat->valid_packets == 0)) {
2538 /* no suitable packet for lookup */
2539 printf("no suitable valid packets\n");
2540 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2541 return p_nat->valid_packets;
2544 /* lookup entries in the common napt table */
2546 int lookup_result = rte_hash_lookup_bulk(
2548 (const void **)&p_nat->key_ptrs,
2549 /* should be minus num invalid pkts */
2551 /*new pipeline data member */
2552 &p_nat->lkup_indx[0]);
2554 if (unlikely(lookup_result < 0)) {
2555 /* unknown error, just discard all packets */
2556 printf("Unexpected hash lookup error %d, discarding "
2557 "all packets", lookup_result);
2558 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
2562 /* Now call second stage of pipeline to one by one
2563 * check the result of our bulk lookup
2566 /* prefetching for table entries should be done here */
2567 for (j = 0; j < n_pkts; j++) {
2568 if (p_nat->lkup_indx[j] >= 0)
2569 rte_prefetch0(&napt_hash_tbl_entries
2570 [p_nat->lkup_indx[j]]);
2573 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2574 pkt4_work_cgnapt_ipv4_prv(pkts, i, arg, p_nat);
2576 for (; i < n_pkts; i++)
2577 pkt_work_cgnapt_ipv4_prv(pkts, i, arg, p_nat);
2579 if (arp_pkts_mask) {
2580 p_nat->valid_packets &= ~(arp_pkts_mask);
2581 rte_pipeline_ah_packet_hijack(rte_p, arp_pkts_mask);
2584 if (p_nat->invalid_packets) {
2585 /* get rid of invalid packets */
2586 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2588 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2590 #ifdef CGNAPT_DBG_PRNT
2591 if (CGNAPT_DEBUG > 1) {
2592 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
2593 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
2594 printf("invalid_packets:0x%jx\n",
2595 p_nat->invalid_packets);
2596 printf("rte_invalid_packets :0x%jx\n",
2597 rte_p->pkts_drop_mask);
2598 printf("Total pkts dropped :0x%jx\n",
2599 rte_p->n_pkts_ah_drop);
2604 #ifdef CGNAPT_TIMING_INST
2605 if (p_nat->time_measurements_on) {
2606 exit_timestamp = rte_get_tsc_cycles();
2607 p_nat->in_port_exit_timestamp = exit_timestamp;
2608 p_nat->internal_time_sum += exit_timestamp - entry_timestamp;
2609 p_nat->time_measurements++;
2610 if (p_nat->time_measurements == p_nat->max_time_mesurements)
2611 p_nat->time_measurements_on = 0;
2615 return p_nat->valid_packets;
2619 * Input port handler for IPv4 public traffic
2620 * Starting from the packet burst it filters unwanted packets,
2621 * calculates keys, does lookup and then based on the lookup
2622 * updates NAPT table and does packet NAPT translation.
2625 * A pointer to struct rte_pipeline
2627 * A pointer to array of packets mbuf
2629 * Number of packets in the burst
2634 * int that is not checked by caller
2636 static int cgnapt_in_port_ah_ipv4_pub(struct rte_pipeline *rte_p,
2637 struct rte_mbuf **pkts,
2638 uint32_t n_pkts, void *arg)
2641 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
2642 struct pipeline_cgnapt *p_nat = ap->p;
2644 #ifdef CGNAPT_TIMING_INST
2645 uint64_t entry_timestamp = 0, exit_timestamp;
2647 if (p_nat->time_measurements_on) {
2648 entry_timestamp = rte_get_tsc_cycles();
2650 /* check since exit ts not valid first time through */
2651 if (likely(p_nat->in_port_exit_timestamp))
2652 p_nat->external_time_sum +=
2653 entry_timestamp - p_nat->in_port_exit_timestamp;
2657 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
2658 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
2659 p_nat->invalid_packets = 0;
2661 #ifdef CGNAPT_DBG_PRNT
2662 if (CGNAPT_DEBUG > 1)
2663 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
2666 /* prefetching for mbufs should be done here */
2667 for (j = 0; j < n_pkts; j++)
2668 rte_prefetch0(pkts[j]);
2670 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2671 pkt4_work_cgnapt_key_ipv4_pub(&pkts[i], i, arg, p_nat);
2673 for (; i < n_pkts; i++)
2674 pkt_work_cgnapt_key_ipv4_pub(pkts[i], i, arg, p_nat);
2676 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2678 if (unlikely(p_nat->valid_packets == 0)) {
2679 printf("no valid packets in pub\n");
2680 /* no suitable packet for lookup */
2681 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2682 return p_nat->valid_packets;
2685 /* lookup entries in the common napt table */
2687 int lookup_result = rte_hash_lookup_bulk(
2689 (const void **)&p_nat->key_ptrs,
2690 /* should be minus num invalid pkts */
2692 /*new pipeline data member */
2693 &p_nat->lkup_indx[0]);
2695 if (unlikely(lookup_result < 0)) {
2696 /* unknown error, just discard all packets */
2697 printf("Unexpected hash lookup error %d, discarding "
2698 "all packets", lookup_result);
2699 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
2703 /* Now call second stage of pipeline to one by one
2704 * check the result of our bulk lookup
2707 /* prefetching for table entries should be done here */
2708 for (j = 0; j < n_pkts; j++) {
2709 if (p_nat->lkup_indx[j] >= 0)
2710 rte_prefetch0(&napt_hash_tbl_entries
2711 [p_nat->lkup_indx[j]]);
2714 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2715 pkt4_work_cgnapt_ipv4_pub(pkts, i, arg, p_nat);
2717 for (; i < n_pkts; i++)
2718 pkt_work_cgnapt_ipv4_pub(pkts, i, arg, p_nat);
2720 if (arp_pkts_mask) {
2721 rte_pipeline_ah_packet_hijack(rte_p, arp_pkts_mask);
2722 p_nat->valid_packets &= ~(arp_pkts_mask);
2725 if (p_nat->invalid_packets) {
2726 /* get rid of invalid packets */
2727 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2729 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2731 #ifdef CGNAPT_DBG_PRNT
2732 if (CGNAPT_DEBUG > 1) {
2733 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
2734 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
2735 printf("invalid_packets:0x%jx\n",
2736 p_nat->invalid_packets);
2737 printf("rte_invalid_packets :0x%jx\n",
2738 rte_p->pkts_drop_mask);
2739 printf("Total pkts dropped :0x%jx\n",
2740 rte_p->n_pkts_ah_drop);
2745 #ifdef CGNAPT_TIMING_INST
2746 if (p_nat->time_measurements_on) {
2747 exit_timestamp = rte_get_tsc_cycles();
2748 p_nat->in_port_exit_timestamp = exit_timestamp;
2750 p_nat->internal_time_sum += exit_timestamp - entry_timestamp;
2751 p_nat->time_measurements++;
2752 if (p_nat->time_measurements == p_nat->max_time_mesurements)
2753 p_nat->time_measurements_on = 0;
2757 return p_nat->valid_packets;
2761 * NAPT key calculation function for IPv4 private traffic
2762 * which handles 4 pkts
2765 * A pointer to array of packets mbuf
2767 * Starting pkt number of pkts
2771 * A pointer to main CGNAPT structure
2775 pkt4_work_cgnapt_key_ipv4_prv(
2776 struct rte_mbuf **pkt,
2778 __rte_unused void *arg,
2779 struct pipeline_cgnapt *p_nat)
2781 p_nat->receivedPktCount += 4;
2782 /* bitmask representing only this packet */
2783 uint64_t pkt_mask0 = 1LLU << pkt_num;
2784 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
2785 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
2786 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
2788 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
2790 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
2792 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
2794 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
2797 uint32_t src_addr0 = RTE_MBUF_METADATA_UINT32(pkt[0],
2799 uint32_t src_addr1 = RTE_MBUF_METADATA_UINT32(pkt[1],
2801 uint32_t src_addr2 = RTE_MBUF_METADATA_UINT32(pkt[2],
2803 uint32_t src_addr3 = RTE_MBUF_METADATA_UINT32(pkt[3],
2806 uint16_t src_port_offset0;
2807 uint16_t src_port_offset1;
2808 uint16_t src_port_offset2;
2809 uint16_t src_port_offset3;
2816 uint16_t phy_port0 = pkt[0]->port;
2817 uint16_t phy_port1 = pkt[1]->port;
2818 uint16_t phy_port2 = pkt[2]->port;
2819 uint16_t phy_port3 = pkt[3]->port;
2821 struct pipeline_cgnapt_entry_key key0;
2822 struct pipeline_cgnapt_entry_key key1;
2823 struct pipeline_cgnapt_entry_key key2;
2824 struct pipeline_cgnapt_entry_key key3;
2826 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
2827 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
2828 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
2829 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
2832 #ifdef CGNAPT_DBG_PRNT
2833 if (CGNAPT_DEBUG > 4)
2838 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
2842 switch (protocol0) {
2843 case IP_PROTOCOL_UDP:
2847 struct udp_hdr *udp;
2849 udp = (struct udp_hdr *)
2850 RTE_MBUF_METADATA_UINT8_PTR(pkt[0],
2853 if (rte_bswap16(udp->dst_port) ==
2855 handle_pcp_req(pkt[0], IPV4_SZ, p_nat);
2856 p_nat->invalid_packets |= pkt_mask0;
2862 case IP_PROTOCOL_TCP:
2864 src_port_offset0 = SRC_PRT_OFST_IP4_TCP;
2865 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
2870 case IP_PROTOCOL_ICMP:
2872 src_port_offset0 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
2874 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
2880 /* remember invalid packets to be dropped */
2881 p_nat->invalid_packets |= pkt_mask0;
2882 p_nat->naptDroppedPktCount++;
2884 #ifdef CGNAPT_DEBUGGING
2885 p_nat->naptDroppedPktCount2++;
2890 key0.pid = phy_port0;
2891 key0.ip = rte_bswap32(src_addr0);
2892 key0.port = rte_bswap16(src_port0);
2894 #ifdef NAT_ONLY_CONFIG_REQ
2895 if (nat_only_config_flag)
2899 memcpy(&p_nat->keys[pkt_num], &key0,
2900 sizeof(struct pipeline_cgnapt_entry_key));
2901 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
2906 #ifdef CGNAPT_DBG_PRNT
2907 if (CGNAPT_DEBUG > 4)
2912 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
2915 switch (protocol1) {
2916 case IP_PROTOCOL_UDP:
2920 struct udp_hdr *udp;
2922 udp = (struct udp_hdr *)
2923 RTE_MBUF_METADATA_UINT8_PTR(pkt[1],
2926 if (rte_bswap16(udp->dst_port) ==
2928 handle_pcp_req(pkt[1], IPV4_SZ, p_nat);
2929 p_nat->invalid_packets |= pkt_mask1;
2935 case IP_PROTOCOL_TCP:
2937 src_port_offset1 = SRC_PRT_OFST_IP4_TCP;
2938 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
2943 case IP_PROTOCOL_ICMP:
2945 src_port_offset1 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
2947 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
2953 /* remember invalid packets to be dropped */
2954 p_nat->invalid_packets |= pkt_mask1;
2955 p_nat->naptDroppedPktCount++;
2957 #ifdef CGNAPT_DEBUGGING
2958 p_nat->naptDroppedPktCount2++;
2963 key1.pid = phy_port1;
2964 key1.ip = rte_bswap32(src_addr1);
2965 key1.port = rte_bswap16(src_port1);
2967 #ifdef NAT_ONLY_CONFIG_REQ
2968 if (nat_only_config_flag)
2972 memcpy(&p_nat->keys[pkt_num + 1], &key1,
2973 sizeof(struct pipeline_cgnapt_entry_key));
2974 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
2978 #ifdef CGNAPT_DBG_PRNT
2979 if (CGNAPT_DEBUG > 4)
2984 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
2988 switch (protocol2) {
2989 case IP_PROTOCOL_UDP:
2993 struct udp_hdr *udp;
2995 udp = (struct udp_hdr *)
2996 RTE_MBUF_METADATA_UINT8_PTR(pkt[2],
2999 if (rte_bswap16(udp->dst_port) ==
3001 handle_pcp_req(pkt[2], IPV4_SZ, p_nat);
3002 p_nat->invalid_packets |= pkt_mask2;
3008 case IP_PROTOCOL_TCP:
3010 src_port_offset2 = SRC_PRT_OFST_IP4_TCP;
3011 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3016 case IP_PROTOCOL_ICMP:
3018 src_port_offset2 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3020 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3026 /* remember invalid packets to be dropped */
3027 p_nat->invalid_packets |= pkt_mask2;
3028 p_nat->naptDroppedPktCount++;
3030 #ifdef CGNAPT_DEBUGGING
3031 p_nat->naptDroppedPktCount2++;
3036 key2.pid = phy_port2;
3037 key2.ip = rte_bswap32(src_addr2);
3038 key2.port = rte_bswap16(src_port2);
3040 #ifdef NAT_ONLY_CONFIG_REQ
3041 if (nat_only_config_flag)
3045 memcpy(&p_nat->keys[pkt_num + 2], &key2,
3046 sizeof(struct pipeline_cgnapt_entry_key));
3047 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
3051 #ifdef CGNAPT_DBG_PRNT
3052 if (CGNAPT_DEBUG > 4)
3056 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
3060 switch (protocol3) {
3061 case IP_PROTOCOL_UDP:
3065 struct udp_hdr *udp;
3067 udp = (struct udp_hdr *)
3068 RTE_MBUF_METADATA_UINT8_PTR(pkt[3],
3071 if (rte_bswap16(udp->dst_port) ==
3073 handle_pcp_req(pkt[3], IPV4_SZ, p_nat);
3074 p_nat->invalid_packets |= pkt_mask3;
3080 case IP_PROTOCOL_TCP:
3082 src_port_offset3 = SRC_PRT_OFST_IP4_TCP;
3083 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3088 case IP_PROTOCOL_ICMP:
3090 src_port_offset3 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3092 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3098 /* remember invalid packets to be dropped */
3099 p_nat->invalid_packets |= pkt_mask3;
3100 p_nat->naptDroppedPktCount++;
3102 #ifdef CGNAPT_DEBUGGING
3103 p_nat->naptDroppedPktCount2++;
3108 key3.pid = phy_port3;
3109 key3.ip = rte_bswap32(src_addr3);
3110 key3.port = rte_bswap16(src_port3);
3112 #ifdef NAT_ONLY_CONFIG_REQ
3113 if (nat_only_config_flag)
3117 memcpy(&p_nat->keys[pkt_num + 3], &key3,
3118 sizeof(struct pipeline_cgnapt_entry_key));
3119 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
3123 * NAPT key calculation function for IPv4 public traffic
3124 * which handles 4 pkts
3127 * A pointer to array of packets mbuf
3129 * Starting pkt number of pkts
3133 * A pointer to main CGNAPT structure
3137 pkt4_work_cgnapt_key_ipv4_pub(
3138 struct rte_mbuf **pkt,
3140 __rte_unused void *arg,
3141 struct pipeline_cgnapt *p_nat)
3143 p_nat->receivedPktCount += 4;
3144 /* bitmask representing only this packet */
3145 uint64_t pkt_mask0 = 1LLU << pkt_num;
3146 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
3147 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
3148 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
3150 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
3152 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
3154 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
3156 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
3159 uint32_t dst_addr0 = RTE_MBUF_METADATA_UINT32(pkt[0],
3161 uint32_t dst_addr1 = RTE_MBUF_METADATA_UINT32(pkt[1],
3163 uint32_t dst_addr2 = RTE_MBUF_METADATA_UINT32(pkt[2],
3165 uint32_t dst_addr3 = RTE_MBUF_METADATA_UINT32(pkt[3],
3168 uint16_t src_port_offset0;
3169 uint16_t src_port_offset1;
3170 uint16_t src_port_offset2;
3171 uint16_t src_port_offset3;
3173 uint16_t dst_port_offset0;
3174 uint16_t dst_port_offset1;
3175 uint16_t dst_port_offset2;
3176 uint16_t dst_port_offset3;
3188 struct pipeline_cgnapt_entry_key key0;
3189 struct pipeline_cgnapt_entry_key key1;
3190 struct pipeline_cgnapt_entry_key key2;
3191 struct pipeline_cgnapt_entry_key key3;
3193 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
3194 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
3195 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
3196 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
3199 #ifdef CGNAPT_DBG_PRNT
3200 if (CGNAPT_DEBUG > 4)
3205 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
3209 switch (protocol0) {
3210 case IP_PROTOCOL_UDP:
3211 case IP_PROTOCOL_TCP:
3213 src_port_offset0 = SRC_PRT_OFST_IP4_TCP;
3214 dst_port_offset0 = DST_PRT_OFST_IP4_TCP;
3216 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3218 dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3221 key0.port = rte_bswap16(dst_port0);
3225 case IP_PROTOCOL_ICMP:
3227 src_port_offset0 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3229 /*Sequence number */
3230 dst_port_offset0 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3233 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3235 dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3238 key0.port = rte_bswap16(src_port0);
3243 /* remember invalid packets to be dropped */
3244 p_nat->invalid_packets |= pkt_mask0;
3245 p_nat->naptDroppedPktCount++;
3247 #ifdef CGNAPT_DEBUGGING
3248 p_nat->naptDroppedPktCount2++;
3254 key0.ip = rte_bswap32(dst_addr0);
3256 #ifdef NAT_ONLY_CONFIG_REQ
3257 if (nat_only_config_flag)
3261 memcpy(&p_nat->keys[pkt_num], &key0,
3262 sizeof(struct pipeline_cgnapt_entry_key));
3263 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3268 #ifdef CGNAPT_DBG_PRNT
3269 if (CGNAPT_DEBUG > 4)
3274 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
3278 switch (protocol1) {
3279 case IP_PROTOCOL_UDP:
3280 case IP_PROTOCOL_TCP:
3282 src_port_offset1 = SRC_PRT_OFST_IP4_TCP;
3283 dst_port_offset1 = DST_PRT_OFST_IP4_TCP;
3285 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3287 dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3290 key1.port = rte_bswap16(dst_port1);
3294 case IP_PROTOCOL_ICMP:
3296 src_port_offset1 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3298 /*Sequence number */
3299 dst_port_offset1 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3302 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3304 dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3307 key1.port = rte_bswap16(src_port1);
3311 /* remember invalid packets to be dropped */
3312 p_nat->invalid_packets |= pkt_mask1;
3313 p_nat->naptDroppedPktCount++;
3315 #ifdef CGNAPT_DEBUGGING
3316 p_nat->naptDroppedPktCount2++;
3322 key1.ip = rte_bswap32(dst_addr1);
3324 #ifdef NAT_ONLY_CONFIG_REQ
3325 if (nat_only_config_flag)
3329 memcpy(&p_nat->keys[pkt_num + 1], &key1,
3330 sizeof(struct pipeline_cgnapt_entry_key));
3331 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
3335 #ifdef CGNAPT_DBG_PRNT
3336 if (CGNAPT_DEBUG > 4)
3341 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
3345 switch (protocol2) {
3346 case IP_PROTOCOL_UDP:
3347 case IP_PROTOCOL_TCP:
3349 src_port_offset2 = SRC_PRT_OFST_IP4_TCP;
3350 dst_port_offset2 = DST_PRT_OFST_IP4_TCP;
3352 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3354 dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3357 key2.port = rte_bswap16(dst_port2);
3361 case IP_PROTOCOL_ICMP:
3363 src_port_offset2 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3365 /*Sequence number */
3366 dst_port_offset2 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3369 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3371 dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3374 key2.port = rte_bswap16(src_port2);
3379 /* remember invalid packets to be dropped */
3380 p_nat->invalid_packets |= pkt_mask2;
3381 p_nat->naptDroppedPktCount++;
3383 #ifdef CGNAPT_DEBUGGING
3384 p_nat->naptDroppedPktCount2++;
3390 key2.ip = rte_bswap32(dst_addr2);
3392 #ifdef NAT_ONLY_CONFIG_REQ
3393 if (nat_only_config_flag)
3397 memcpy(&p_nat->keys[pkt_num + 2], &key2,
3398 sizeof(struct pipeline_cgnapt_entry_key));
3399 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
3403 #ifdef CGNAPT_DBG_PRNT
3404 if (CGNAPT_DEBUG > 4)
3409 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
3413 switch (protocol3) {
3414 case IP_PROTOCOL_UDP:
3415 case IP_PROTOCOL_TCP:
3417 src_port_offset3 = SRC_PRT_OFST_IP4_TCP;
3418 dst_port_offset3 = DST_PRT_OFST_IP4_TCP;
3420 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3422 dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3425 key3.port = rte_bswap16(dst_port3);
3429 case IP_PROTOCOL_ICMP:
3431 src_port_offset3 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3433 /*Sequence number */
3434 dst_port_offset3 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3437 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3439 dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3442 key3.port = rte_bswap16(src_port3);
3447 /* remember invalid packets to be dropped */
3448 p_nat->invalid_packets |= pkt_mask3;
3449 p_nat->naptDroppedPktCount++;
3451 #ifdef CGNAPT_DEBUGGING
3452 p_nat->naptDroppedPktCount2++;
3458 key3.ip = rte_bswap32(dst_addr3);
3460 #ifdef NAT_ONLY_CONFIG_REQ
3461 if (nat_only_config_flag)
3465 memcpy(&p_nat->keys[pkt_num + 3], &key3,
3466 sizeof(struct pipeline_cgnapt_entry_key));
3467 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
3471 * NAPT key calculation function for IPv4 private traffic
3472 * which handles 1 pkt
3475 * A pointer to array of packets mbuf
3477 * Pkt number of pkts
3481 * A pointer to main CGNAPT structure
3485 pkt_work_cgnapt_key_ipv4_prv(
3486 struct rte_mbuf *pkt,
3488 __rte_unused void *arg,
3489 struct pipeline_cgnapt *p_nat)
3492 p_nat->receivedPktCount++;
3494 /* bitmask representing only this packet */
3495 uint64_t pkt_mask = 1LLU << pkt_num;
3496 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3498 uint32_t src_addr = RTE_MBUF_METADATA_UINT32(pkt, SRC_ADR_OFST_IP4);
3500 uint16_t src_port_offset;
3504 uint16_t phy_port = pkt->port;
3505 struct pipeline_cgnapt_entry_key key;
3507 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
3510 #ifdef CGNAPT_DBG_PRNT
3511 if (CGNAPT_DEBUG > 4)
3516 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
3521 case IP_PROTOCOL_UDP:
3525 struct udp_hdr *udp;
3527 udp = (struct udp_hdr *)
3528 RTE_MBUF_METADATA_UINT8_PTR(pkt,
3531 if (rte_bswap16(udp->dst_port) ==
3533 handle_pcp_req(pkt, IPV4_SZ, p_nat);
3534 p_nat->invalid_packets |= pkt_mask;
3540 case IP_PROTOCOL_TCP:
3542 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3543 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3545 key.port = rte_bswap16(src_port);
3548 case IP_PROTOCOL_ICMP:
3550 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3552 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3554 key.port = rte_bswap16(src_port);
3558 /* remember invalid packets to be dropped */
3559 p_nat->invalid_packets |= pkt_mask;
3560 p_nat->naptDroppedPktCount++;
3562 #ifdef CGNAPT_DEBUGGING
3563 p_nat->naptDroppedPktCount2++;
3569 key.ip = rte_bswap32(src_addr);
3571 #ifdef NAT_ONLY_CONFIG_REQ
3572 if (nat_only_config_flag)
3576 memcpy(&p_nat->keys[pkt_num], &key,
3577 sizeof(struct pipeline_cgnapt_entry_key));
3578 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3582 * NAPT key calculation function for IPv4 public traffic
3583 * which handles 1 pkt
3586 * A pointer to array of packets mbuf
3588 * Pkt number of pkts
3592 * A pointer to main CGNAPT structure
3596 pkt_work_cgnapt_key_ipv4_pub(
3597 struct rte_mbuf *pkt,
3599 __rte_unused void *arg,
3600 struct pipeline_cgnapt *p_nat)
3602 p_nat->receivedPktCount++;
3604 /* bitmask representing only this packet */
3605 uint64_t pkt_mask = 1LLU << pkt_num;
3606 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3607 uint32_t dst_addr = RTE_MBUF_METADATA_UINT32(pkt, DST_ADR_OFST_IP4);
3608 uint16_t src_port_offset;
3609 uint16_t dst_port_offset;
3612 struct pipeline_cgnapt_entry_key key;
3613 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
3615 #ifdef CGNAPT_DBG_PRNT
3616 if (CGNAPT_DEBUG > 4)
3621 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
3626 case IP_PROTOCOL_UDP:
3627 case IP_PROTOCOL_TCP:
3628 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3629 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3631 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3632 dst_port = RTE_MBUF_METADATA_UINT16(pkt, dst_port_offset);
3634 key.port = rte_bswap16(dst_port);
3636 case IP_PROTOCOL_ICMP:
3638 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3640 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3643 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3644 dst_port = RTE_MBUF_METADATA_UINT16(pkt, dst_port_offset);
3646 /* common table lookupkey preparation from incoming
3647 * ICMP Packet- Indentifier field
3649 key.port = rte_bswap16(src_port);
3652 /* remember invalid packets to be dropped */
3653 p_nat->invalid_packets |= pkt_mask;
3654 p_nat->naptDroppedPktCount++;
3656 #ifdef CGNAPT_DEBUGGING
3657 p_nat->naptDroppedPktCount2++;
3662 key.ip = rte_bswap32(dst_addr);
3664 #ifdef NAT_ONLY_CONFIG_REQ
3665 if (nat_only_config_flag)
3671 memcpy(&p_nat->keys[pkt_num], &key,
3672 sizeof(struct pipeline_cgnapt_entry_key));
3673 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3678 * NAPT function for IPv4 private traffic which handles 1 pkt
3681 * A pointer to array of packet mbuf
3687 * A pointer to main CGNAPT structure
3690 uint64_t last_update;
3692 pkt_work_cgnapt_ipv4_prv(
3693 struct rte_mbuf **pkts,
3695 __rte_unused void *arg,
3696 struct pipeline_cgnapt *p_nat)
3699 struct rte_CT_helper ct_helper;
3700 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
3703 /* index into hash table entries */
3704 int hash_table_entry = p_nat->lkup_indx[pkt_num];
3705 /*bitmask representing only this packet */
3706 uint64_t pkt_mask = 1LLU << pkt_num;
3707 struct rte_mbuf *pkt = pkts[pkt_num];
3709 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3711 uint32_t dest_if = 0xff; /* Added for Multiport */
3712 uint16_t *outport_id =
3713 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
3715 struct cgnapt_table_entry *entry = NULL;
3717 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
3719 if (hash_table_entry < 0) {
3721 /* try to add new entry */
3722 struct rte_pipeline_table_entry *table_entry = NULL;
3724 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
3726 &p_nat->valid_packets, pkt_num,
3730 /* ICMP Error message generation for Destination
3733 if (protocol == IP_PROTOCOL_ICMP) {
3734 cgnapt_icmp_pkt = pkt;
3735 send_icmp_dest_unreachable_msg();
3738 /* Drop packet by adding to invalid pkt mask */
3740 p_nat->invalid_packets |= dropmask;
3741 #ifdef CGNAPT_DEBUGGING
3742 if (p_nat->kpc2++ < 5) {
3743 printf("in_ah Th: %d", p_nat->pipeline_num);
3744 print_key(p_nat->key_ptrs[pkt_num]);
3748 p_nat->naptDroppedPktCount++;
3750 #ifdef CGNAPT_DEBUGGING
3751 p_nat->naptDroppedPktCount3++;
3756 entry = (struct cgnapt_table_entry *)table_entry;
3758 /* entry found for this packet */
3759 entry = &napt_hash_tbl_entries[hash_table_entry];
3762 /* apply napt and mac changes */
3764 p_nat->entries[pkt_num] = &(entry->head);
3766 uint32_t *src_addr =
3767 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP4);
3768 uint32_t *dst_addr =
3769 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
3770 uint16_t src_port_offset = 0;
3771 uint16_t dst_port_offset = 0;
3776 case IP_PROTOCOL_TCP:
3777 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3778 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3779 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3780 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3783 if ((rte_be_to_cpu_16(*src_port) == 21) ||
3784 rte_be_to_cpu_16(*dst_port) == 21) {
3787 printf("cgnapt_ct_process: pkt_mask: % "PRIu64", "
3788 "pkt_num: %d\n", pkt_mask, pkt_num);
3791 pkt_mask = cgnapt_ct_process(cgnat_cnxn_tracker, pkts,
3792 pkt_mask, &ct_helper);
3796 case IP_PROTOCOL_UDP:
3797 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3798 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3799 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3800 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3802 case IP_PROTOCOL_ICMP:
3804 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3806 /*Sequence number */
3807 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3809 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3810 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3814 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
3815 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
3817 if (entry->data.ttl == NAPT_ENTRY_STALE)
3818 entry->data.ttl = NAPT_ENTRY_VALID;
3820 struct ether_addr hw_addr;
3821 uint32_t dest_address = 0;
3824 if (unlikely(protocol == IP_PROTOCOL_UDP
3825 && rte_be_to_cpu_16(*dst_port) == 53)) {
3826 p_nat->invalid_packets |= pkt_mask;
3827 p_nat->naptDroppedPktCount++;
3829 #ifdef CGNAPT_DEBUGGING
3830 p_nat->naptDroppedPktCount6++;
3834 last_update = rte_rdtsc();
3835 dest_address = rte_bswap32(*dst_addr);
3837 struct arp_entry_data *ret_arp_data = NULL;
3838 ret_arp_data = get_dest_mac_addr_port(dest_address,
3839 &dest_if, (struct ether_addr *)eth_dest);
3840 *outport_id = p_nat->outport_id[dest_if];
3842 if (arp_cache_dest_mac_present(dest_if)) {
3843 ether_addr_copy(get_link_hw_addr(dest_if),(struct ether_addr *)eth_src);
3844 update_nhip_access(dest_if);
3845 if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) {
3846 p_nat->naptedPktCount += ret_arp_data->num_pkts;
3847 arp_send_buffered_pkts(ret_arp_data,
3848 (struct ether_addr *)eth_dest, *outport_id);
3853 if (unlikely(ret_arp_data == NULL)) {
3855 #ifdef CGNAPT_DEBUGGING
3856 printf("%s: NHIP Not Found, nhip:%x , "
3857 "outport_id: %d\n", __func__, nhip,
3862 p_nat->invalid_packets |= pkt_mask;
3863 p_nat->naptDroppedPktCount++;
3865 #ifdef CGNAPT_DEBUGGING
3866 p_nat->naptDroppedPktCount4++;
3871 if (ret_arp_data->status == INCOMPLETE ||
3872 ret_arp_data->status == PROBE) {
3873 if (ret_arp_data->num_pkts >= NUM_DESC) {
3875 p_nat->invalid_packets |= pkt_mask;
3876 p_nat->naptDroppedPktCount++;
3878 #ifdef CGNAPT_DEBUGGING
3879 p_nat->naptDroppedPktCount4++;
3883 arp_pkts_mask |= pkt_mask;
3884 arp_queue_unresolved_packet(ret_arp_data, pkt);
3893 *src_addr = rte_bswap32(entry->data.pub_ip);
3896 #ifdef NAT_ONLY_CONFIG_REQ
3897 if (!nat_only_config_flag) {
3899 *src_port = rte_bswap16(entry->data.pub_port);
3900 #ifdef NAT_ONLY_CONFIG_REQ
3905 uint16_t rtp_port = 0, rtcp_port = 0;
3906 struct cgnapt_table_entry *entry_ptr1 = NULL,
3907 *entry_ptr2 = NULL, *entry_ptr3 = NULL,
3910 if (unlikely(protocol == IP_PROTOCOL_UDP
3911 && (rte_be_to_cpu_16(*dst_port) == 5060
3912 || rte_be_to_cpu_16(*src_port) == 5060))) {
3914 int ret = natSipAlgGetAudioPorts(pkt, &rtp_port,
3916 /* Commented code may be required for debug
3917 * and future use, Please keep it*/
3920 printf("%s: Wrong SIP ALG packet1\n",
3922 p_nat->invalid_packets |= pkt_mask;
3924 p_nat->naptDroppedPktCount++;
3926 #ifdef CGNAPT_DEBUGGING
3927 p_nat->naptDroppedPktCount4++;
3933 if (ret >= 0 && rtp_port != 0) {
3934 struct pipeline_cgnapt_entry_key rtp_key;
3935 rtp_key.ip = entry->data.u.prv_ip;
3936 rtp_key.port = rtp_port;
3937 rtp_key.pid = entry->data.prv_phy_port;
3939 if (add_dynamic_cgnapt_entry_alg(
3940 (struct pipeline *)p_nat, &rtp_key,
3941 &entry_ptr1, &entry_ptr2) == 0) {
3942 printf("%s: Wrong SIP ALG packet2\n",
3944 p_nat->invalid_packets |= pkt_mask;
3946 p_nat->naptDroppedPktCount++;
3948 #ifdef CGNAPT_DEBUGGING
3949 p_nat->naptDroppedPktCount4++;
3955 if (ret >= 0 && rtcp_port != 0) {
3956 struct pipeline_cgnapt_entry_key rtcp_key;
3957 rtcp_key.ip = entry->data.u.prv_ip;
3958 rtcp_key.port = rtcp_port;
3959 rtcp_key.pid = entry->data.prv_phy_port;
3961 if (add_dynamic_cgnapt_entry_alg(
3962 (struct pipeline *)p_nat, &rtcp_key,
3963 &entry_ptr3, &entry_ptr4) == 0) {
3964 printf("%s: Wrong SIP ALG packet3\n",
3966 p_nat->invalid_packets |= pkt_mask;
3968 p_nat->naptDroppedPktCount++;
3970 #ifdef CGNAPT_DEBUGGING
3971 p_nat->naptDroppedPktCount4++;
3977 //if(entry_ptr1 != NULL && entry_ptr3 != NULL)
3978 if (sip_alg_dpi(pkt, PRIVATE, entry->data.pub_ip,
3979 entry->data.pub_port, entry->data.u.prv_ip,
3980 entry->data.prv_port, (rtp_port == 0) ? 0 :
3981 entry_ptr1->data.pub_port,
3982 (rtcp_port == 0) ? 0 :
3983 entry_ptr3->data.pub_port) == 0) {
3985 printf("%s: Wrong SIP ALG packet4\n",
3987 p_nat->invalid_packets |= pkt_mask;
3989 p_nat->naptDroppedPktCount++;
3991 #ifdef CGNAPT_DEBUGGING
3992 p_nat->naptDroppedPktCount4++;
3997 #endif /* SIP_ALG */
4002 printf("@CGNAT-pktwork ct_position :%d, pkt_num %d pkt_mask= "
4003 "%" PRIu64 "\n", ct_position, pkt_num, pkt_mask);
4006 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4007 rte_be_to_cpu_16(*dst_port) == 21) {
4009 int32_t ct_position = cgnat_cnxn_tracker->positions[pkt_num];
4010 if (ct_position < 0){
4011 p_nat->invalid_packets |= pkt_mask;
4012 p_nat->naptDroppedPktCount++;
4015 /* Commented code may be required for future usage,
4018 //if (cgnat_cnxn_tracker->hash_table_entries
4019 // [ct_position].alg_bypass_flag != BYPASS)
4021 struct pipeline_cgnapt_entry_key data_channel_entry_key;
4023 data_channel_entry_key.ip = entry->data.pub_ip;
4024 data_channel_entry_key.port = entry->data.pub_port;
4025 data_channel_entry_key.pid = pkt->port;
4026 ftp_alg_dpi(p_nat, &data_channel_entry_key, pkt,
4027 cgnat_cnxn_tracker, ct_position, PRIVATE);
4030 #endif /* FTP_ALG */
4032 p_nat->enaptedPktCount++;
4035 p_nat->naptedPktCount++;
4038 if (p_nat->hw_checksum_reqd)
4039 hw_checksum(pkt, pkt_type);
4041 sw_checksum(pkt, pkt_type);
4048 * NAPT function for IPv4 public traffic which handles 1 pkt
4051 * A pointer to array of packet mbuf
4057 * A pointer to main CGNAPT structure
4061 pkt_work_cgnapt_ipv4_pub(
4062 struct rte_mbuf **pkts,
4064 __rte_unused void *arg,
4065 struct pipeline_cgnapt *p_nat)
4069 struct rte_CT_helper ct_helper;
4070 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4073 /* index into hash table entries */
4074 int hash_table_entry = p_nat->lkup_indx[pkt_num];
4075 /*bitmask representing only this packet */
4076 uint64_t pkt_mask = 1LLU << pkt_num;
4077 struct rte_mbuf *pkt = pkts[pkt_num];
4079 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
4081 uint32_t dest_if = 0xff; /* Added for Multiport */
4082 uint16_t *outport_id =
4083 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
4085 struct cgnapt_table_entry *entry = NULL;
4087 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4089 if (hash_table_entry < 0) {
4091 /* try to add new entry */
4092 struct rte_pipeline_table_entry *table_entry = NULL;
4094 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
4096 &p_nat->valid_packets, pkt_num,
4100 /* ICMP Error message generation for
4101 * Destination Host unreachable
4103 if (protocol == IP_PROTOCOL_ICMP) {
4104 cgnapt_icmp_pkt = pkt;
4105 send_icmp_dest_unreachable_msg();
4108 /* Drop packet by adding to invalid pkt mask */
4110 p_nat->invalid_packets |= dropmask;
4111 #ifdef CGNAPT_DEBUGGING
4112 if (p_nat->kpc2++ < 5) {
4113 printf("in_ah Th: %d", p_nat->pipeline_num);
4114 print_key(p_nat->key_ptrs[pkt_num]);
4118 p_nat->naptDroppedPktCount++;
4120 #ifdef CGNAPT_DEBUGGING
4121 p_nat->naptDroppedPktCount3++;
4126 entry = (struct cgnapt_table_entry *)table_entry;
4128 /* entry found for this packet */
4129 entry = &napt_hash_tbl_entries[hash_table_entry];
4132 /* apply napt and mac changes */
4134 p_nat->entries[pkt_num] = &(entry->head);
4136 uint32_t *dst_addr =
4137 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4138 uint16_t src_port_offset = 0;
4139 uint16_t dst_port_offset = 0;
4141 if ((protocol == IP_PROTOCOL_TCP) || (protocol == IP_PROTOCOL_UDP)) {
4142 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4143 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4144 } else if (protocol == IP_PROTOCOL_ICMP) {
4146 src_port_offset = MBUF_HDR_ROOM +
4149 /*Sequence number */
4150 dst_port_offset = MBUF_HDR_ROOM +
4155 uint16_t *src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
4156 uint16_t *dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
4158 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4159 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4161 if (entry->data.ttl == NAPT_ENTRY_STALE)
4162 entry->data.ttl = NAPT_ENTRY_VALID;
4164 struct ether_addr hw_addr;
4165 uint32_t dest_address = 0;
4167 /* Multiport Changes */
4173 if (unlikely(protocol == IP_PROTOCOL_UDP
4174 && rte_be_to_cpu_16(*src_port) == 53)) {
4175 p_nat->invalid_packets |= pkt_mask;
4176 p_nat->naptDroppedPktCount++;
4177 #ifdef CGNAPT_DEBUGGING
4178 p_nat->naptDroppedPktCount6++;
4184 dest_address = entry->data.u.prv_ip;
4185 struct arp_entry_data *ret_arp_data = NULL;
4186 ret_arp_data = get_dest_mac_addr_port(dest_address,
4187 &dest_if, (struct ether_addr *)eth_dest);
4188 *outport_id = p_nat->outport_id[dest_if];
4190 if (arp_cache_dest_mac_present(dest_if)) {
4191 ether_addr_copy(get_link_hw_addr(dest_if), (struct ether_addr *)eth_src);
4192 update_nhip_access(dest_if);
4194 if (ret_arp_data && ret_arp_data->num_pkts) {
4195 p_nat->naptedPktCount += ret_arp_data->num_pkts;
4196 arp_send_buffered_pkts(ret_arp_data,
4197 (struct ether_addr *)eth_dest, *outport_id);
4202 if (unlikely(ret_arp_data == NULL)) {
4204 /* Commented code may be required for debug
4205 * and future use, Please keep it */
4207 #ifdef CGNAPT_DEBUGGING
4208 printf("%s: NHIP Not Found, nhip: %x, "
4209 "outport_id: %d\n", __func__, nhip,
4214 p_nat->invalid_packets |= pkt_mask;
4215 p_nat->naptDroppedPktCount++;
4217 #ifdef CGNAPT_DEBUGGING
4218 p_nat->naptDroppedPktCount4++;
4224 if (ret_arp_data->status == INCOMPLETE ||
4225 ret_arp_data->status == PROBE) {
4226 if (ret_arp_data->num_pkts >= NUM_DESC) {
4228 p_nat->invalid_packets |= pkt_mask;
4229 p_nat->naptDroppedPktCount++;
4231 #ifdef CGNAPT_DEBUGGING
4232 p_nat->naptDroppedPktCount4++;
4236 arp_pkts_mask |= pkt_mask;
4237 arp_queue_unresolved_packet(ret_arp_data, pkt);
4246 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
4247 if (protocol == IP_PROTOCOL_ICMP) {
4248 /* Query ID reverse translation done here */
4249 /* dont care sequence num */
4250 *src_port = rte_bswap16(entry->data.prv_port);
4253 #ifdef NAT_ONLY_CONFIG_REQ
4254 if (!nat_only_config_flag) {
4256 *dst_port = rte_bswap16(entry->data.prv_port);
4258 #ifdef NAT_ONLY_CONFIG_REQ
4262 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4263 rte_be_to_cpu_16(*dst_port) == 21) {
4264 pkt_mask = cgnapt_ct_process(cgnat_cnxn_tracker, pkts,
4265 pkt_mask, &ct_helper);
4271 uint16_t rtp_port = 0, rtcp_port = 0;
4272 struct cgnapt_table_entry *entry_ptr1 = NULL,
4275 /* Commented code may be required for debug
4276 * and future use, Please keep it */
4278 struct cgnapt_table_entry *entry_ptr2 = NULL,
4282 if (unlikely(protocol == IP_PROTOCOL_UDP
4283 && (rte_be_to_cpu_16(*dst_port) == 5060
4284 || rte_be_to_cpu_16(*src_port) == 5060))) {
4285 /* Commented code may be required for future usage,
4289 int ret = natSipAlgGetAudioPorts(pkt, &rtp_port,
4292 printf("%s: Wrong SIP ALG packet1\n",
4294 p_nat->invalid_packets |= pkt_mask;
4296 p_nat->naptDroppedPktCount++;
4298 #ifdef CGNAPT_DEBUGGING
4299 p_nat->naptDroppedPktCount4++;
4303 if (rtp_port != 0) {
4304 struct pipeline_cgnapt_entry_key rtp_key;
4305 rtp_key.ip = entry->data.pub_ip;
4306 rtp_key.port = rtp_port;
4307 rtp_key.pid = 0xffff;
4309 if (retrieve_cgnapt_entry_alg(&rtp_key,
4310 &entry_ptr1, &entry_ptr2) == 0) {
4311 printf("%s: Wrong SIP ALG packet2\n",
4313 p_nat->invalid_packets |= pkt_mask;
4315 p_nat->naptDroppedPktCount++;
4317 #ifdef CGNAPT_DEBUGGING
4318 p_nat->naptDroppedPktCount4++;
4324 if (rtcp_port != 0) {
4325 struct pipeline_cgnapt_entry_key rtcp_key;
4326 rtcp_key.ip = entry->data.pub_ip;
4327 rtcp_key.port = rtcp_port;
4328 rtcp_key.pid = 0xffff;
4330 if (retrieve_cgnapt_entry_alg(&rtcp_key,
4331 &entry_ptr3, &entry_ptr4) == 0) {
4332 printf("%s: Wrong SIP ALG packet3\n",
4334 p_nat->invalid_packets |= pkt_mask;
4336 p_nat->naptDroppedPktCount++;
4338 #ifdef CGNAPT_DEBUGGING
4339 p_nat->naptDroppedPktCount4++;
4347 if (sip_alg_dpi(pkt, PUBLIC, entry->data.u.prv_ip,
4348 entry->data.prv_port, entry->data.pub_ip,
4349 entry->data.pub_port, (rtp_port == 0) ? 0 :
4350 entry_ptr1->data.prv_port,
4351 (rtcp_port == 0) ? 0 :
4352 entry_ptr3->data.prv_port) == 0) {
4354 printf("%s: Wrong SIP ALG packet4\n",
4356 p_nat->invalid_packets |= pkt_mask;
4358 p_nat->naptDroppedPktCount++;
4360 #ifdef CGNAPT_DEBUGGING
4361 p_nat->naptDroppedPktCount4++;
4367 #endif /* SIP_ALG */
4370 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4371 rte_be_to_cpu_16(*dst_port) == 21) {
4372 int32_t ct_position = cgnat_cnxn_tracker->
4374 if (ct_position < 0){
4375 p_nat->invalid_packets |= pkt_mask;
4377 p_nat->naptDroppedPktCount++;
4381 rte_hexdump(stdout, "CT Entry", &cgnat_cnxn_tracker->
4382 hash_table_entries[ct_position].key, 40);
4385 /* Commented code may be required for debug
4386 * and future use, Please keep it*/
4387 //if (cgnat_cnxn_tracker->hash_table_entries
4388 // [ct_position].alg_bypass_flag != BYPASS)
4391 struct pipeline_cgnapt_entry_key
4392 data_channel_entry_key;
4394 data_channel_entry_key.ip = entry->data.pub_ip;
4395 data_channel_entry_key.port = entry->data.pub_port;
4396 data_channel_entry_key.pid = 0xffff;
4397 //printf("pkt_work_pub ftp_alg_dpi\n");
4398 ftp_alg_dpi(p_nat, &data_channel_entry_key, pkt,
4399 cgnat_cnxn_tracker, ct_position, PUBLIC);
4405 p_nat->inaptedPktCount++;
4408 p_nat->naptedPktCount++;
4411 if (p_nat->hw_checksum_reqd)
4412 hw_checksum(pkt, pkt_type);
4414 sw_checksum(pkt, pkt_type);
4420 * NAPT function for IPv4 private traffic which handles 4 pkts
4423 * A pointer to array of packets mbuf
4425 * Starting pkt number of pkts
4429 * A pointer to main CGNAPT structure
4433 pkt4_work_cgnapt_ipv4_prv(
4434 struct rte_mbuf **pkts,
4435 uint32_t in_pkt_num,
4436 __rte_unused void *arg,
4437 struct pipeline_cgnapt *p_nat)
4439 uint32_t dest_if = 0xff; /* Added for Multiport */
4440 struct rte_mbuf *pkt;
4443 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4446 struct rte_CT_helper ct_helper;
4447 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4450 for (i = 0; i < 4; i++) {
4451 pkt_num = in_pkt_num + i;
4452 pkt = pkts[pkt_num];
4454 /* index into hash table entries */
4455 int hash_table_entry = p_nat->lkup_indx[pkt_num];
4456 /*bitmask representing only this packet */
4457 uint64_t pkt_mask = 1LLU << pkt_num;
4459 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
4461 uint16_t *outport_id =
4462 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
4464 struct cgnapt_table_entry *entry = NULL;
4466 if (hash_table_entry < 0) {
4468 /* try to add new entry */
4469 struct rte_pipeline_table_entry *table_entry = NULL;
4472 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
4474 &p_nat->valid_packets, pkt_num,
4478 /* ICMP Error message generation for
4479 * Destination Host unreachable
4481 if (protocol == IP_PROTOCOL_ICMP) {
4482 cgnapt_icmp_pkt = pkt;
4483 send_icmp_dest_unreachable_msg();
4486 /* Drop packet by adding to invalid pkt mask */
4488 p_nat->invalid_packets |= dropmask;
4490 #ifdef CGNAPT_DEBUGGING
4491 if (p_nat->kpc2++ < 5) {
4492 printf("in_ah Th: %d",
4493 p_nat->pipeline_num);
4494 print_key(p_nat->key_ptrs[pkt_num]);
4498 p_nat->naptDroppedPktCount++;
4500 #ifdef CGNAPT_DEBUGGING
4501 p_nat->naptDroppedPktCount3++;
4506 entry = (struct cgnapt_table_entry *)table_entry;
4508 /* entry found for this packet */
4509 entry = &napt_hash_tbl_entries[hash_table_entry];
4512 /* apply napt and mac changes */
4514 p_nat->entries[pkt_num] = &(entry->head);
4516 uint32_t *src_addr =
4517 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP4);
4518 uint32_t *dst_addr =
4519 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4520 uint16_t src_port_offset = 0;
4521 uint16_t dst_port_offset = 0;
4526 if ((protocol == IP_PROTOCOL_TCP)
4527 || (protocol == IP_PROTOCOL_UDP)) {
4528 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4529 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4530 } else if (protocol == IP_PROTOCOL_ICMP) {
4532 src_port_offset = MBUF_HDR_ROOM +
4535 /*Sequence number */
4536 dst_port_offset = MBUF_HDR_ROOM +
4543 case IP_PROTOCOL_TCP:
4544 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4545 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4546 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4548 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4552 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4553 rte_be_to_cpu_16(*dst_port) == 21) {
4555 //To process CT , pkt_mask does it need
4556 //to be complemented ??
4558 printf("cgnapt_ct_process: pkt_mask: "
4559 "% "PRIu64", pkt_num: %d\n",
4563 pkt_mask = cgnapt_ct_process(
4564 cgnat_cnxn_tracker, pkts,
4565 pkt_mask, &ct_helper);
4569 case IP_PROTOCOL_UDP:
4570 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4571 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4572 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4574 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4577 case IP_PROTOCOL_ICMP:
4579 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
4581 /*Sequence number */
4582 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
4584 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4586 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4593 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4595 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4597 if (entry->data.ttl == NAPT_ENTRY_STALE)
4598 entry->data.ttl = NAPT_ENTRY_VALID;
4600 struct ether_addr hw_addr;
4601 uint32_t dest_address = 0;
4602 /*Multiport Changes */
4609 if (unlikely(protocol == IP_PROTOCOL_UDP
4610 && rte_be_to_cpu_16(*dst_port) == 53)) {
4611 p_nat->invalid_packets |= pkt_mask;
4612 p_nat->naptDroppedPktCount++;
4614 #ifdef CGNAPT_DEBUGGING
4615 p_nat->naptDroppedPktCount6++;
4621 dest_address = rte_bswap32(*dst_addr);
4622 struct arp_entry_data *ret_arp_data = NULL;
4623 uint64_t start, end;
4624 ret_arp_data = get_dest_mac_addr_port(dest_address,
4625 &dest_if, (struct ether_addr *)eth_dest);
4626 *outport_id = p_nat->outport_id[dest_if];
4627 if (arp_cache_dest_mac_present(dest_if)) {
4628 ether_addr_copy(get_link_hw_addr(dest_if),
4629 (struct ether_addr *)eth_src);
4630 update_nhip_access(dest_if);
4632 if (ret_arp_data && ret_arp_data->num_pkts) {
4633 p_nat->naptedPktCount += ret_arp_data->num_pkts;
4634 arp_send_buffered_pkts(ret_arp_data,
4635 (struct ether_addr *)eth_dest, *outport_id);
4640 if (unlikely(ret_arp_data == NULL)) {
4642 #ifdef CGNAPT_DEBUGGING
4643 printf("%s: ARP Not Found, nhip: %x, "
4644 "outport_id: %d\n", __func__, nhip,
4649 p_nat->invalid_packets |= pkt_mask;
4650 p_nat->naptDroppedPktCount++;
4652 #ifdef CGNAPT_DEBUGGING
4653 p_nat->naptDroppedPktCount4++;
4659 if (ret_arp_data->status == INCOMPLETE ||
4660 ret_arp_data->status == PROBE) {
4661 if (ret_arp_data->num_pkts >= NUM_DESC) {
4663 p_nat->invalid_packets |= pkt_mask;
4664 p_nat->naptDroppedPktCount++;
4666 #ifdef CGNAPT_DEBUGGING
4667 p_nat->naptDroppedPktCount4++;
4671 arp_pkts_mask |= pkt_mask;
4672 arp_queue_unresolved_packet(ret_arp_data, pkt);
4680 *src_addr = rte_bswap32(entry->data.pub_ip);
4682 #ifdef NAT_ONLY_CONFIG_REQ
4683 if (!nat_only_config_flag) {
4685 *src_port = rte_bswap16(entry->data.pub_port);
4686 #ifdef NAT_ONLY_CONFIG_REQ
4691 uint16_t rtp_port = 0, rtcp_port = 0;
4692 struct cgnapt_table_entry *entry_ptr1 = NULL,
4693 *entry_ptr2 = NULL, *entry_ptr3 = NULL,
4696 if (unlikely(protocol == IP_PROTOCOL_UDP
4697 && (rte_be_to_cpu_16(*dst_port) == 5060
4698 || rte_be_to_cpu_16(*src_port) == 5060))) {
4700 int ret = natSipAlgGetAudioPorts(pkt,
4701 &rtp_port, &rtcp_port);
4702 /* Commented code may be required for future usage,
4707 printf("%s: Wrong SIP ALG packet1\n",
4709 p_nat->invalid_packets |= pkt_mask;
4711 p_nat->naptDroppedPktCount++;
4713 #ifdef CGNAPT_DEBUGGING
4714 p_nat->naptDroppedPktCount4++;
4720 if (ret >= 0 && rtp_port != 0) {
4721 struct pipeline_cgnapt_entry_key rtp_key;
4722 rtp_key.ip = entry->data.u.prv_ip;
4723 rtp_key.port = rtp_port;
4724 rtp_key.pid = entry->data.prv_phy_port;
4726 if (add_dynamic_cgnapt_entry_alg(
4727 (struct pipeline *)p_nat, &rtp_key,
4728 &entry_ptr1, &entry_ptr2) == 0) {
4729 printf("%s: Wrong SIP ALG packet2\n",
4731 p_nat->invalid_packets |= pkt_mask;
4733 p_nat->naptDroppedPktCount++;
4735 #ifdef CGNAPT_DEBUGGING
4736 p_nat->naptDroppedPktCount4++;
4742 if (ret >= 0 && rtcp_port != 0) {
4743 struct pipeline_cgnapt_entry_key rtcp_key;
4744 rtcp_key.ip = entry->data.u.prv_ip;
4745 rtcp_key.port = rtcp_port;
4746 rtcp_key.pid = entry->data.prv_phy_port;
4748 if (add_dynamic_cgnapt_entry_alg(
4749 (struct pipeline *)p_nat, &rtcp_key,
4750 &entry_ptr3, &entry_ptr4) == 0) {
4752 printf("%s: Wrong SIP ALG packet3\n",
4754 p_nat->invalid_packets |= pkt_mask;
4756 p_nat->naptDroppedPktCount++;
4758 #ifdef CGNAPT_DEBUGGING
4759 p_nat->naptDroppedPktCount4++;
4765 //if(entry_ptr1 != NULL && entry_ptr3 != NULL)
4766 if (sip_alg_dpi(pkt, PRIVATE,
4768 entry->data.pub_port,
4769 entry->data.u.prv_ip,
4770 entry->data.prv_port,
4771 (rtp_port == 0) ? 0 :
4772 entry_ptr1->data.pub_port,
4773 (rtcp_port == 0) ? 0 :
4774 entry_ptr3->data.pub_port) == 0) {
4776 printf("%s: Wrong SIP ALG packet4\n",
4778 p_nat->invalid_packets |= pkt_mask;
4780 p_nat->naptDroppedPktCount++;
4782 #ifdef CGNAPT_DEBUGGING
4783 p_nat->naptDroppedPktCount4++;
4788 #endif /* SIP_ALG */
4791 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4792 rte_be_to_cpu_16(*dst_port) == 21) {
4794 int32_t ct_position =
4795 cgnat_cnxn_tracker->positions[pkt_num];
4797 printf("@CGNAT-pkt4work ct_position :%d, pkt_num %d "
4798 "pkt_mask = %" PRIu64 "\n", ct_position,
4802 if (ct_position < 0){
4803 p_nat->invalid_packets |= pkt_mask;
4804 p_nat->naptDroppedPktCount++;
4807 if (cgnat_cnxn_tracker->hash_table_entries[ct_position].
4808 alg_bypass_flag != BYPASS){
4810 struct pipeline_cgnapt_entry_key
4811 data_channel_entry_key;
4813 data_channel_entry_key.ip =
4815 data_channel_entry_key.port =
4816 entry->data.pub_port;
4817 data_channel_entry_key.pid = 0xffff;
4819 ftp_alg_dpi(p_nat, &data_channel_entry_key,
4820 pkt, cgnat_cnxn_tracker, ct_position,
4826 p_nat->enaptedPktCount++;
4829 p_nat->naptedPktCount++;
4832 if (p_nat->hw_checksum_reqd)
4833 hw_checksum(pkt, pkt_type);
4835 sw_checksum(pkt, pkt_type);
4841 * NAPT function for IPv4 public traffic which handles 4 pkts
4844 * A pointer to array of packets mbuf
4846 * Starting pkt number of pkts
4850 * A pointer to main CGNAPT structure
4854 pkt4_work_cgnapt_ipv4_pub(
4855 struct rte_mbuf **pkts,
4856 uint32_t in_pkt_num,
4857 __rte_unused void *arg,
4858 struct pipeline_cgnapt *p_nat)
4861 struct rte_CT_helper ct_helper;
4862 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4864 struct rte_mbuf *pkt;
4867 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4869 for (i = 0; i < 4; i++) {
4870 pkt_num = in_pkt_num + i;
4871 pkt = pkts[pkt_num];
4873 /* index into hash table entries */
4874 int hash_table_entry = p_nat->lkup_indx[pkt_num];
4875 /*bitmask representing only this packet */
4876 uint64_t pkt_mask = 1LLU << pkt_num;
4878 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
4880 uint32_t dest_if = 0xff; /* Added for Multiport */
4881 uint16_t *outport_id =
4882 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
4884 struct cgnapt_table_entry *entry = NULL;
4886 if (hash_table_entry < 0) {
4888 /* try to add new entry */
4889 struct rte_pipeline_table_entry *table_entry = NULL;
4892 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
4894 &p_nat->valid_packets, pkt_num,
4898 /* ICMP Error message generation for
4899 * Destination Host unreachable
4901 if (protocol == IP_PROTOCOL_ICMP) {
4902 cgnapt_icmp_pkt = pkt;
4903 send_icmp_dest_unreachable_msg();
4906 /* Drop packet by adding to invalid pkt mask */
4908 p_nat->invalid_packets |= dropmask;
4910 #ifdef CGNAPT_DEBUGGING
4911 if (p_nat->kpc2++ < 5) {
4912 printf("in_ah Th: %d",
4913 p_nat->pipeline_num);
4914 print_key(p_nat->key_ptrs[pkt_num]);
4918 p_nat->naptDroppedPktCount++;
4920 #ifdef CGNAPT_DEBUGGING
4921 p_nat->naptDroppedPktCount3++;
4923 printf("causing p_nat->naptDroppedPktCount3\n");
4927 entry = (struct cgnapt_table_entry *)table_entry;
4929 /* entry found for this packet */
4930 entry = &napt_hash_tbl_entries[hash_table_entry];
4933 /* apply napt and mac changes */
4935 p_nat->entries[pkt_num] = &(entry->head);
4937 uint32_t *dst_addr =
4938 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4939 uint16_t src_port_offset = 0;
4940 uint16_t dst_port_offset = 0;
4942 if ((protocol == IP_PROTOCOL_TCP)
4943 || (protocol == IP_PROTOCOL_UDP)) {
4944 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4945 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4946 } else if (protocol == IP_PROTOCOL_ICMP) {
4948 src_port_offset = MBUF_HDR_ROOM +
4951 /*Sequence number */
4952 dst_port_offset = MBUF_HDR_ROOM +
4957 uint16_t *src_port =
4958 RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
4959 uint16_t *dst_port =
4960 RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
4963 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4965 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4967 if (entry->data.ttl == NAPT_ENTRY_STALE)
4968 entry->data.ttl = NAPT_ENTRY_VALID;
4970 struct ether_addr hw_addr;
4971 uint32_t dest_address = 0;
4972 /* Multiport Changes */
4978 if (unlikely(protocol == IP_PROTOCOL_UDP
4979 && rte_be_to_cpu_16(*src_port) == 53)) {
4980 p_nat->invalid_packets |= pkt_mask;
4981 p_nat->naptDroppedPktCount++;
4982 #ifdef CGNAPT_DEBUGGING
4983 p_nat->naptDroppedPktCount6++;
4988 dest_address = entry->data.u.prv_ip;
4989 struct arp_entry_data *ret_arp_data = NULL;
4990 ret_arp_data = get_dest_mac_addr_port(dest_address,
4991 &dest_if, (struct ether_addr *)eth_dest);
4992 *outport_id = p_nat->outport_id[dest_if];
4994 if (arp_cache_dest_mac_present(dest_if)) {
4995 ether_addr_copy(get_link_hw_addr(dest_if), (struct ether_addr *)eth_src);
4996 update_nhip_access(dest_if);
4998 if (ret_arp_data && ret_arp_data->num_pkts) {
4999 p_nat->naptedPktCount += ret_arp_data->num_pkts;
5000 arp_send_buffered_pkts(ret_arp_data,
5001 (struct ether_addr *)eth_dest, *outport_id);
5006 if (unlikely(ret_arp_data == NULL)) {
5008 #ifdef CGNAPT_DEBUGGING
5009 printf("%s: NHIP Not Found, nhip: %x, "
5010 "outport_id: %d\n", __func__, nhip,
5015 p_nat->invalid_packets |= pkt_mask;
5016 p_nat->naptDroppedPktCount++;
5018 #ifdef CGNAPT_DEBUGGING
5019 p_nat->naptDroppedPktCount4++;
5024 if (ret_arp_data->status == INCOMPLETE ||
5025 ret_arp_data->status == PROBE) {
5026 if (ret_arp_data->num_pkts >= NUM_DESC) {
5028 p_nat->invalid_packets |= pkt_mask;
5029 p_nat->naptDroppedPktCount++;
5031 #ifdef CGNAPT_DEBUGGING
5032 p_nat->naptDroppedPktCount4++;
5036 arp_pkts_mask |= pkt_mask;
5037 arp_queue_unresolved_packet(ret_arp_data, pkt);
5046 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
5047 if (protocol == IP_PROTOCOL_ICMP) {
5048 /* Query ID reverse translation done here */
5049 *src_port = rte_bswap16(entry->data.prv_port);
5050 /* dont care sequence num */
5052 #ifdef NAT_ONLY_CONFIG_REQ
5053 if (!nat_only_config_flag) {
5056 rte_bswap16(entry->data.prv_port);
5057 #ifdef NAT_ONLY_CONFIG_REQ
5062 if ((rte_be_to_cpu_16(*src_port) == 21) ||
5063 rte_be_to_cpu_16(*dst_port) == 21) {
5064 pkt_mask = cgnapt_ct_process(
5065 cgnat_cnxn_tracker, pkts,
5066 pkt_mask, &ct_helper);
5072 uint16_t rtp_port = 0, rtcp_port = 0;
5073 struct cgnapt_table_entry *entry_ptr1 = NULL,
5075 /* Commented code may be required for future usage,
5079 struct cgnapt_table_entry *entry_ptr2 = NULL,
5083 if (unlikely(protocol == IP_PROTOCOL_UDP
5084 && (rte_be_to_cpu_16(*dst_port) == 5060
5085 || rte_be_to_cpu_16(*src_port) == 5060))) {
5086 /* Commented code may be required for future usage,
5090 int ret = natSipAlgGetAudioPorts(pkt,
5091 &rtp_port, &rtcp_port);
5093 printf("%s: Wrong SIP ALG packet1\n",
5095 p_nat->invalid_packets |= pkt_mask;
5097 p_nat->naptDroppedPktCount++;
5099 #ifdef CGNAPT_DEBUGGING
5100 p_nat->naptDroppedPktCount4++;
5105 if (rtp_port != 0) {
5106 struct pipeline_cgnapt_entry_key rtp_key;
5107 rtp_key.ip = entry->data.pub_ip;
5108 rtp_key.port = rtp_port;
5109 rtp_key.pid = 0xffff;
5111 if (retrieve_cgnapt_entry_alg(&rtp_key,
5112 &entry_ptr1, &entry_ptr2) == 0) {
5113 printf("%s: Wrong SIP ALG packet2\n",
5115 p_nat->invalid_packets |= pkt_mask;
5117 p_nat->naptDroppedPktCount++;
5119 #ifdef CGNAPT_DEBUGGING
5120 p_nat->naptDroppedPktCount4++;
5126 if (rtcp_port != 0) {
5127 struct pipeline_cgnapt_entry_key rtcp_key;
5128 rtcp_key.ip = entry->data.pub_ip;
5129 rtcp_key.port = rtcp_port;
5130 rtcp_key.pid = 0xffff;
5132 if (retrieve_cgnapt_entry_alg(&rtcp_key,
5133 &entry_ptr3, &entry_ptr4) == 0) {
5134 printf("%s: Wrong SIP ALG packet3\n",
5136 p_nat->invalid_packets |= pkt_mask;
5137 p_nat->naptDroppedPktCount++;
5139 #ifdef CGNAPT_DEBUGGING
5140 p_nat->naptDroppedPktCount4++;
5147 if (sip_alg_dpi(pkt, PUBLIC,
5148 entry->data.u.prv_ip,
5149 entry->data.prv_port,
5151 entry->data.pub_port,
5152 (rtp_port == 0) ? 0 :
5153 entry_ptr1->data.prv_port,
5154 (rtcp_port == 0) ? 0 :
5155 entry_ptr3->data.prv_port) == 0) {
5157 printf("%s: Wrong SIP ALG packet4\n",
5159 p_nat->invalid_packets |= pkt_mask;
5161 p_nat->naptDroppedPktCount++;
5163 #ifdef CGNAPT_DEBUGGING
5164 p_nat->naptDroppedPktCount4++;
5169 #endif /* SIP_ALG */
5172 if ((rte_be_to_cpu_16(*src_port) == 21) ||
5173 rte_be_to_cpu_16(*dst_port) == 21) {
5175 int32_t ct_position =
5176 cgnat_cnxn_tracker->positions[pkt_num];
5177 if (ct_position < 0){
5178 p_nat->invalid_packets |= pkt_mask;
5180 p_nat->naptDroppedPktCount++;
5183 if (cgnat_cnxn_tracker->hash_table_entries
5184 [ct_position].alg_bypass_flag != BYPASS){
5186 struct pipeline_cgnapt_entry_key
5187 data_channel_entry_key;
5190 data_channel_entry_key.ip =
5192 data_channel_entry_key.port =
5193 entry->data.pub_port;
5194 data_channel_entry_key.pid = 0xffff;
5196 ftp_alg_dpi(p_nat, &data_channel_entry_key,
5197 pkt, cgnat_cnxn_tracker,
5198 ct_position, PUBLIC);
5203 p_nat->inaptedPktCount++;
5206 p_nat->naptedPktCount++;
5209 if (p_nat->hw_checksum_reqd)
5210 hw_checksum(pkt, pkt_type);
5212 sw_checksum(pkt, pkt_type);
5218 * NAPT key calculation function for IPv6 private traffic
5219 * which handles 1 pkt
5222 * A pointer to array of packets mbuf
5224 * Pkt number of pkts
5228 * A pointer to main CGNAPT structure
5232 pkt_work_cgnapt_key_ipv6_prv(
5233 struct rte_mbuf *pkt,
5235 __rte_unused void *arg,
5236 struct pipeline_cgnapt *p_nat)
5239 p_nat->receivedPktCount++;
5241 /* bitmask representing only this packet */
5242 uint64_t pkt_mask = 1LLU << pkt_num;
5244 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
5245 uint32_t *src_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
5247 uint16_t src_port = RTE_MBUF_METADATA_UINT16(pkt, SRC_PRT_OFST_IP6);
5249 uint16_t phy_port = pkt->port;
5250 struct pipeline_cgnapt_entry_key key;
5252 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
5254 #ifdef CGNAPT_DBG_PRNT
5255 if (CGNAPT_DEBUG > 4)
5260 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
5265 case IP_PROTOCOL_UDP:
5269 struct udp_hdr *udp;
5271 udp = (struct udp_hdr *)
5272 RTE_MBUF_METADATA_UINT8_PTR(pkt,
5275 if (rte_bswap16(udp->dst_port) ==
5277 handle_pcp_req(pkt, IPV6_SZ, p_nat);
5278 p_nat->invalid_packets |= pkt_mask;
5284 case IP_PROTOCOL_TCP:
5285 case IP_PROTOCOL_ICMP:
5286 /*we don't need icmp check in ipv6 */
5290 printf("wrong protocol: %d\n", protocol);
5291 /* remember invalid packets to be dropped */
5292 p_nat->invalid_packets |= pkt_mask;
5293 p_nat->naptDroppedPktCount++;
5295 #ifdef CGNAPT_DEBUGGING
5296 p_nat->naptDroppedPktCount2++;
5302 key.ip = rte_bswap32(src_addr[3]);
5303 key.port = rte_bswap16(src_port);
5305 #ifdef NAT_ONLY_CONFIG_REQ
5306 if (nat_only_config_flag)
5310 memcpy(&p_nat->keys[pkt_num], &key,
5311 sizeof(struct pipeline_cgnapt_entry_key));
5312 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5316 * NAPT key calculation function for IPv6 public traffic
5317 * which handles 1 pkt
5320 * A pointer to array of packets mbuf
5322 * Pkt number of pkts
5326 * A pointer to main CGNAPT structure
5330 pkt_work_cgnapt_key_ipv6_pub(
5331 struct rte_mbuf *pkt,
5333 __rte_unused void *arg,
5334 struct pipeline_cgnapt *p_nat)
5338 p_nat->receivedPktCount++;
5340 /* bitmask representing only this packet */
5341 uint64_t pkt_mask = 1LLU << pkt_num;
5343 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
5345 uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
5347 uint16_t dst_port = RTE_MBUF_METADATA_UINT16(pkt,
5348 DST_PRT_OFST_IP4_TCP);
5350 struct pipeline_cgnapt_entry_key key;
5352 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
5354 #ifdef CGNAPT_DBG_PRNT
5355 if (CGNAPT_DEBUG > 4)
5360 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
5366 case IP_PROTOCOL_UDP:
5367 case IP_PROTOCOL_TCP:
5368 case IP_PROTOCOL_ICMP:
5369 /*we don't need icmp check in ipv6 */
5373 /* remember invalid packets to be dropped */
5374 p_nat->invalid_packets |= pkt_mask;
5375 p_nat->naptDroppedPktCount++;
5377 #ifdef CGNAPT_DEBUGGING
5378 p_nat->naptDroppedPktCount2++;
5384 key.ip = rte_bswap32(dst_addr[0]);
5385 key.port = rte_bswap16(dst_port);
5387 #ifdef NAT_ONLY_CONFIG_REQ
5388 if (nat_only_config_flag)
5392 memcpy(&p_nat->keys[pkt_num], &key,
5393 sizeof(struct pipeline_cgnapt_entry_key));
5394 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5398 * NAPT key calculation function for IPv6 private traffic
5399 * which handles 4 pkts
5402 * A pointer to array of packets mbuf
5404 * Starting pkt number of pkts
5408 * A pointer to main CGNAPT structure
5412 pkt4_work_cgnapt_key_ipv6_prv(
5413 struct rte_mbuf **pkt,
5415 __rte_unused void *arg,
5416 struct pipeline_cgnapt *p_nat)
5418 p_nat->receivedPktCount += 4;
5420 /* bitmask representing only this packet */
5421 uint64_t pkt_mask0 = 1LLU << pkt_num;
5422 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
5423 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
5424 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
5426 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
5428 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
5430 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
5432 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
5435 uint32_t *src_addr0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0],
5437 uint32_t *src_addr1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1],
5439 uint32_t *src_addr2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2],
5441 uint32_t *src_addr3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3],
5444 uint16_t src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
5446 uint16_t src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
5448 uint16_t src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
5450 uint16_t src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
5453 uint16_t phy_port0 = pkt[0]->port;
5454 uint16_t phy_port1 = pkt[1]->port;
5455 uint16_t phy_port2 = pkt[2]->port;
5456 uint16_t phy_port3 = pkt[3]->port;
5458 struct pipeline_cgnapt_entry_key key0;
5459 struct pipeline_cgnapt_entry_key key1;
5460 struct pipeline_cgnapt_entry_key key2;
5461 struct pipeline_cgnapt_entry_key key3;
5463 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
5464 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
5465 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
5466 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
5470 #ifdef CGNAPT_DBG_PRNT
5471 if (CGNAPT_DEBUG > 4)
5476 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
5480 switch (protocol0) {
5482 case IP_PROTOCOL_UDP:
5486 struct udp_hdr *udp;
5488 udp = (struct udp_hdr *)
5489 RTE_MBUF_METADATA_UINT8_PTR(pkt[0],
5492 if (rte_bswap16(udp->dst_port) ==
5494 handle_pcp_req(pkt[0], IPV6_SZ, p_nat);
5495 p_nat->invalid_packets |= pkt_mask0;
5501 case IP_PROTOCOL_TCP:
5502 case IP_PROTOCOL_ICMP:
5503 /*we don't need icmp check in ipv6 */
5507 /* remember invalid packets to be dropped */
5508 p_nat->invalid_packets |= pkt_mask0;
5509 p_nat->naptDroppedPktCount++;
5511 #ifdef CGNAPT_DEBUGGING
5512 p_nat->naptDroppedPktCount2++;
5519 key0.pid = phy_port0;
5520 key0.ip = rte_bswap32(src_addr0[3]);
5521 key0.port = rte_bswap16(src_port0);
5523 #ifdef NAT_ONLY_CONFIG_REQ
5524 if (nat_only_config_flag)
5528 memcpy(&p_nat->keys[pkt_num], &key0,
5529 sizeof(struct pipeline_cgnapt_entry_key));
5530 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5533 #ifdef CGNAPT_DBG_PRNT
5534 if (CGNAPT_DEBUG > 4)
5539 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
5543 switch (protocol1) {
5544 case IP_PROTOCOL_UDP:
5548 struct udp_hdr *udp;
5550 udp = (struct udp_hdr *)
5551 RTE_MBUF_METADATA_UINT8_PTR(pkt[1],
5554 if (rte_bswap16(udp->dst_port) ==
5556 handle_pcp_req(pkt[1], IPV6_SZ, p_nat);
5557 p_nat->invalid_packets |= pkt_mask1;
5563 case IP_PROTOCOL_TCP:
5564 case IP_PROTOCOL_ICMP:
5565 /*we don't need icmp check in ipv6 */
5569 /* remember invalid packets to be dropped */
5570 p_nat->invalid_packets |= pkt_mask1;
5571 p_nat->naptDroppedPktCount++;
5573 #ifdef CGNAPT_DEBUGGING
5574 p_nat->naptDroppedPktCount2++;
5580 key1.pid = phy_port1;
5581 key1.ip = rte_bswap32(src_addr1[3]);
5582 key1.port = rte_bswap16(src_port1);
5584 #ifdef NAT_ONLY_CONFIG_REQ
5585 if (nat_only_config_flag)
5589 memcpy(&p_nat->keys[pkt_num + 1], &key1,
5590 sizeof(struct pipeline_cgnapt_entry_key));
5591 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
5594 #ifdef CGNAPT_DBG_PRNT
5595 if (CGNAPT_DEBUG > 4)
5600 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
5604 switch (protocol2) {
5605 case IP_PROTOCOL_UDP:
5609 struct udp_hdr *udp;
5611 udp = (struct udp_hdr *)
5612 RTE_MBUF_METADATA_UINT8_PTR(pkt[2],
5615 if (rte_bswap16(udp->dst_port) ==
5617 handle_pcp_req(pkt[2], IPV6_SZ, p_nat);
5618 p_nat->invalid_packets |= pkt_mask2;
5624 case IP_PROTOCOL_TCP:
5625 case IP_PROTOCOL_ICMP:
5626 /*we don't need icmp check in ipv6 */
5630 /* remember invalid packets to be dropped */
5631 p_nat->invalid_packets |= pkt_mask2;
5632 p_nat->naptDroppedPktCount++;
5634 #ifdef CGNAPT_DEBUGGING
5635 p_nat->naptDroppedPktCount2++;
5641 key2.pid = phy_port2;
5642 key2.ip = rte_bswap32(src_addr2[3]);
5643 key2.port = rte_bswap16(src_port2);
5645 #ifdef NAT_ONLY_CONFIG_REQ
5646 if (nat_only_config_flag)
5650 memcpy(&p_nat->keys[pkt_num + 2], &key2,
5651 sizeof(struct pipeline_cgnapt_entry_key));
5652 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
5655 #ifdef CGNAPT_DBG_PRNT
5656 if (CGNAPT_DEBUG > 4)
5661 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
5665 switch (protocol3) {
5666 case IP_PROTOCOL_UDP:
5670 struct udp_hdr *udp;
5672 udp = (struct udp_hdr *)
5673 RTE_MBUF_METADATA_UINT8_PTR(pkt[3],
5676 if (rte_bswap16(udp->dst_port) ==
5678 handle_pcp_req(pkt[3], IPV6_SZ, p_nat);
5679 p_nat->invalid_packets |= pkt_mask3;
5685 case IP_PROTOCOL_TCP:
5686 case IP_PROTOCOL_ICMP:
5687 /*we don't need icmp check in ipv6 */
5691 /* remember invalid packets to be dropped */
5692 p_nat->invalid_packets |= pkt_mask2;
5693 p_nat->naptDroppedPktCount++;
5695 #ifdef CGNAPT_DEBUGGING
5696 p_nat->naptDroppedPktCount2++;
5702 key3.pid = phy_port3;
5703 key3.ip = rte_bswap32(src_addr3[3]);
5704 key3.port = rte_bswap16(src_port3);
5706 #ifdef NAT_ONLY_CONFIG_REQ
5707 if (nat_only_config_flag)
5711 memcpy(&p_nat->keys[pkt_num + 3], &key3,
5712 sizeof(struct pipeline_cgnapt_entry_key));
5713 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
5719 * NAPT key calculation function for IPv4 public traffic
5720 * which handles 4 pkts
5723 * A pointer to array of packets mbuf
5725 * Starting pkt number of pkts
5729 * A pointer to main CGNAPT structure
5733 pkt4_work_cgnapt_key_ipv6_pub(
5734 struct rte_mbuf **pkt,
5736 __rte_unused void *arg,
5737 struct pipeline_cgnapt *p_nat)
5739 p_nat->receivedPktCount += 4;
5741 /* bitmask representing only this packet */
5742 uint64_t pkt_mask0 = 1LLU << pkt_num;
5743 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
5744 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
5745 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
5747 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
5749 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
5751 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
5753 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
5756 uint32_t *dst_addr0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0],
5758 uint32_t *dst_addr1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1],
5760 uint32_t *dst_addr2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2],
5762 uint32_t *dst_addr3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3],
5765 uint16_t dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
5766 DST_PRT_OFST_IP4_TCP);
5767 uint16_t dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
5768 DST_PRT_OFST_IP4_TCP);
5769 uint16_t dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
5770 DST_PRT_OFST_IP4_TCP);
5771 uint16_t dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
5772 DST_PRT_OFST_IP4_TCP);
5774 struct pipeline_cgnapt_entry_key key0;
5775 struct pipeline_cgnapt_entry_key key1;
5776 struct pipeline_cgnapt_entry_key key2;
5777 struct pipeline_cgnapt_entry_key key3;
5779 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
5780 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
5781 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
5782 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
5786 #ifdef CGNAPT_DBG_PRNT
5787 if (CGNAPT_DEBUG > 4)
5792 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
5796 switch (protocol0) {
5798 case IP_PROTOCOL_TCP:
5799 case IP_PROTOCOL_UDP:
5800 case IP_PROTOCOL_ICMP:
5801 /*we don't need icmp check in ipv6 */
5805 /* remember invalid packets to be dropped */
5806 p_nat->invalid_packets |= pkt_mask0;
5807 p_nat->naptDroppedPktCount++;
5809 #ifdef CGNAPT_DEBUGGING
5810 p_nat->naptDroppedPktCount2++;
5816 key0.ip = rte_bswap32(dst_addr0[0]);
5817 key0.port = rte_bswap16(dst_port0);
5819 #ifdef NAT_ONLY_CONFIG_REQ
5820 if (nat_only_config_flag)
5824 memcpy(&p_nat->keys[pkt_num], &key0,
5825 sizeof(struct pipeline_cgnapt_entry_key));
5826 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5832 #ifdef CGNAPT_DBG_PRNT
5833 if (CGNAPT_DEBUG > 4)
5838 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
5842 switch (protocol1) {
5844 case IP_PROTOCOL_TCP:
5845 case IP_PROTOCOL_UDP:
5846 case IP_PROTOCOL_ICMP:
5847 /*we don't need icmp check in ipv6 */
5851 /* remember invalid packets to be dropped */
5852 p_nat->invalid_packets |= pkt_mask1;
5853 p_nat->naptDroppedPktCount++;
5855 #ifdef CGNAPT_DEBUGGING
5856 p_nat->naptDroppedPktCount2++;
5862 key1.ip = rte_bswap32(dst_addr1[0]);
5863 key1.port = rte_bswap16(dst_port1);
5865 #ifdef NAT_ONLY_CONFIG_REQ
5866 if (nat_only_config_flag)
5870 memcpy(&p_nat->keys[pkt_num + 1], &key1,
5871 sizeof(struct pipeline_cgnapt_entry_key));
5872 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
5878 #ifdef CGNAPT_DBG_PRNT
5879 if (CGNAPT_DEBUG > 4)
5884 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
5888 switch (protocol2) {
5890 case IP_PROTOCOL_TCP:
5891 case IP_PROTOCOL_UDP:
5892 case IP_PROTOCOL_ICMP:
5893 /*we don't need icmp check in ipv6 */
5897 /* remember invalid packets to be dropped */
5898 p_nat->invalid_packets |= pkt_mask2;
5899 p_nat->naptDroppedPktCount++;
5901 #ifdef CGNAPT_DEBUGGING
5902 p_nat->naptDroppedPktCount2++;
5908 key2.ip = rte_bswap32(dst_addr2[0]);
5909 key2.port = rte_bswap16(dst_port2);
5911 #ifdef NAT_ONLY_CONFIG_REQ
5912 if (nat_only_config_flag)
5916 memcpy(&p_nat->keys[pkt_num + 2], &key2,
5917 sizeof(struct pipeline_cgnapt_entry_key));
5919 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
5925 #ifdef CGNAPT_DBG_PRNT
5926 if (CGNAPT_DEBUG > 4)
5931 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
5935 switch (protocol3) {
5937 case IP_PROTOCOL_TCP:
5938 case IP_PROTOCOL_UDP:
5939 case IP_PROTOCOL_ICMP:
5940 /*we don't need icmp check in ipv6 */
5944 /* remember invalid packets to be dropped */
5945 p_nat->invalid_packets |= pkt_mask3;
5946 p_nat->naptDroppedPktCount++;
5948 #ifdef CGNAPT_DEBUGGING
5949 p_nat->naptDroppedPktCount2++;
5955 key3.ip = rte_bswap32(dst_addr3[0]);
5956 key3.port = rte_bswap16(dst_port3);
5958 #ifdef NAT_ONLY_CONFIG_REQ
5959 if (nat_only_config_flag)
5963 memcpy(&p_nat->keys[pkt_num + 3], &key3,
5964 sizeof(struct pipeline_cgnapt_entry_key));
5966 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
5970 * NAPT function for IPv6 private traffic which handles 1 pkt
5973 * A pointer to array of packet mbuf
5979 * A pointer to main CGNAPT structure
5983 pkt_work_cgnapt_ipv6_prv(
5984 struct rte_mbuf *pkt,
5986 __rte_unused void *arg,
5987 struct pipeline_cgnapt *p_nat)
5989 /* index into hash table entries */
5990 int hash_table_entry = p_nat->lkup_indx[pkt_num];
5992 /*bitmask representing only this packet */
5993 uint64_t pkt_mask = 1LLU << pkt_num;
5995 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
5997 /* Added for Multiport */
5998 uint32_t dest_if = INVALID_DESTIF;
5999 uint16_t *outport_id = RTE_MBUF_METADATA_UINT16_PTR(pkt,
6000 cgnapt_meta_offset);
6002 struct cgnapt_table_entry *entry = NULL;
6003 enum PKT_TYPE pkt_type = PKT_TYPE_IPV6to4;
6005 if (hash_table_entry < 0) {
6007 /* try to add new entry */
6008 struct rte_pipeline_table_entry *table_entry = NULL;
6010 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
6012 &p_nat->valid_packets, pkt_num,
6016 /* ICMP Error message generation for
6017 * Destination Host unreachable
6019 /* Do we need this check for ipv6? */
6020 if (protocol == IP_PROTOCOL_ICMP) {
6021 cgnapt_icmp_pkt = pkt;
6022 send_icmp_dest_unreachable_msg();
6025 /* Drop packet by adding to invalid pkt mask */
6027 p_nat->invalid_packets |= dropmask;
6029 #ifdef CGNAPT_DEBUGGING
6030 if (p_nat->kpc2++ < 5) {
6031 printf("in_ah Th: %d", p_nat->pipeline_num);
6032 print_key(p_nat->key_ptrs[pkt_num]);
6036 p_nat->naptDroppedPktCount++;
6038 #ifdef CGNAPT_DEBUGGING
6039 p_nat->naptDroppedPktCount3++;
6045 entry = (struct cgnapt_table_entry *)table_entry;
6047 /* entry found for this packet */
6048 entry = &napt_hash_tbl_entries[hash_table_entry];
6051 /* apply napt and mac changes */
6053 p_nat->entries[pkt_num] = &(entry->head);
6055 struct ipv6_hdr ipv6_hdr;
6057 struct ether_addr hw_addr;
6058 uint32_t dest_address = 0;
6063 convert_ipv6_to_ipv4(pkt, &ipv6_hdr);
6065 #ifdef CGNAPT_DBG_PRNT
6066 if (CGNAPT_DEBUG == 1)
6067 printf("pkt_work_cganpt: convert_ipv6_to_ipv4\n");
6070 struct cgnapt_nsp_node *ll = nsp_ll;
6073 while (ll != NULL) {
6075 (&ipv6_hdr.dst_addr[0], &ll->nsp.prefix[0],
6076 ll->nsp.depth / 8)) {
6084 && !memcmp(&ipv6_hdr.dst_addr[0], &well_known_prefix[0],
6090 p_nat->invalid_packets |= pkt_mask;
6091 p_nat->naptDroppedPktCount++;
6093 #ifdef CGNAPT_DEBUGGING
6094 p_nat->naptDroppedPktCount5++;
6102 /* As packet is already converted into IPv4 we must not
6103 * operate IPv6 offsets on packet
6104 * Only perform IPv4 operations
6107 uint32_t *src_addr =
6108 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP6t4);
6109 uint32_t *dst_addr =
6110 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP6t4);
6111 uint16_t *src_port =
6112 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP6t4);
6113 uint16_t *dst_port =
6114 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP6t4);
6116 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt,
6118 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt,
6119 ETH_OFST_IP6t4 + 6);
6121 if (entry->data.ttl == NAPT_ENTRY_STALE)
6122 entry->data.ttl = NAPT_ENTRY_VALID;
6125 if (unlikely(protocol == IP_PROTOCOL_UDP
6126 && rte_be_to_cpu_16(*dst_port) == 53)) {
6127 p_nat->invalid_packets |= pkt_mask;
6128 p_nat->naptDroppedPktCount++;
6130 #ifdef CGNAPT_DEBUGGING
6131 p_nat->naptDroppedPktCount6++;
6137 dest_address = rte_bswap32(*dst_addr);
6138 /*Multiport Changes */
6141 #ifdef CGNAPT_DBG_PRNT
6142 if (CGNAPT_DEBUG > 2)
6143 printf("Egress: \tphy_port:%d\t get_prv_to_pub():%d "
6144 "\tout_port:%d\n", pkt->port,
6145 dest_if, *outport_id);
6149 #ifdef CGNAPT_DBG_PRNT
6150 static int static_count;
6152 if (static_count++ < 10) {
6154 my_print_entry(entry);
6155 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6156 printf("dest_add:%x\n", entry->data.u.prv_ip);
6157 printf("dest_add:%x\n", *dst_addr);
6158 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6162 struct arp_entry_data *ret_arp_data;
6163 ret_arp_data = get_dest_mac_addr_port(dest_address,
6164 &dest_if, (struct ether_addr *)eth_dest);
6165 *outport_id = p_nat->outport_id[dest_if];
6166 if (arp_cache_dest_mac_present(dest_if)) {
6167 ether_addr_copy(get_link_hw_addr(dest_if),
6168 (struct ether_addr *)eth_src);
6169 update_nhip_access(dest_if);
6171 if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) {
6172 p_nat->naptedPktCount += ret_arp_data->num_pkts;
6173 arp_send_buffered_pkts(ret_arp_data,
6174 (struct ether_addr *)eth_dest, *outport_id);
6179 if (unlikely(ret_arp_data == NULL)) {
6181 #ifdef CGNAPT_DEBUGGING
6182 printf("%s: NHIP Not Found, nhip:%x , "
6183 "outport_id: %d\n", __func__, nhip,
6188 p_nat->invalid_packets |= pkt_mask;
6189 p_nat->naptDroppedPktCount++;
6191 #ifdef CGNAPT_DEBUGGING
6192 p_nat->naptDroppedPktCount4++;
6197 if (ret_arp_data->status == INCOMPLETE ||
6198 ret_arp_data->status == PROBE) {
6199 if (ret_arp_data->num_pkts >= NUM_DESC) {
6201 p_nat->invalid_packets |= pkt_mask;
6202 p_nat->naptDroppedPktCount++;
6204 #ifdef CGNAPT_DEBUGGING
6205 p_nat->naptDroppedPktCount4++;
6209 arp_pkts_mask |= pkt_mask;
6210 arp_queue_unresolved_packet(ret_arp_data, pkt);
6218 *src_addr = rte_bswap32(entry->data.pub_ip);
6220 #ifdef NAT_ONLY_CONFIG_REQ
6221 if (!nat_only_config_flag) {
6223 *src_port = rte_bswap16(entry->data.pub_port);
6225 #ifdef NAT_ONLY_CONFIG_REQ
6229 p_nat->enaptedPktCount++;
6232 p_nat->naptedPktCount++;
6235 if (p_nat->hw_checksum_reqd)
6236 hw_checksum(pkt, pkt_type);
6238 sw_checksum(pkt, pkt_type);
6244 * NAPT function for IPv6 public traffic which handles 1 pkt
6247 * A pointer to array of packet mbuf
6253 * A pointer to main CGNAPT structure
6257 pkt_work_cgnapt_ipv6_pub(
6258 struct rte_mbuf *pkt,
6260 __rte_unused void *arg,
6261 struct pipeline_cgnapt *p_nat)
6264 /* index into hash table entries */
6265 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6266 /*bitmask representing only this packet */
6267 uint64_t pkt_mask = 1LLU << pkt_num;
6269 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
6271 uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */
6272 uint16_t *outport_id =
6273 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6274 struct cgnapt_table_entry *entry = NULL;
6276 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4to6;
6278 if (hash_table_entry < 0) {
6280 /* Drop ingress initial traffic */
6282 p_nat->invalid_packets |= pkt_mask;
6283 p_nat->naptDroppedPktCount++;
6285 #ifdef CGNAPT_DEBUGGING
6286 p_nat->naptDroppedPktCount3++;
6287 if (p_nat->kpc2++ < 5) {
6288 printf("in_ah Th: %d", p_nat->pipeline_num);
6289 print_key(p_nat->key_ptrs[pkt_num]);
6296 /* entry found for this packet */
6297 entry = &napt_hash_tbl_entries[hash_table_entry];
6300 /* apply napt and mac changes */
6302 p_nat->entries[pkt_num] = &(entry->head);
6303 if (entry->data.type != CGNAPT_ENTRY_IPV6) {
6304 p_nat->invalid_packets |= pkt_mask;
6305 p_nat->naptDroppedPktCount++;
6309 struct ipv4_hdr ipv4_hdr;
6310 uint16_t *src_port =
6311 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP4_TCP);
6313 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
6314 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
6316 if (entry->data.ttl == NAPT_ENTRY_STALE)
6317 entry->data.ttl = NAPT_ENTRY_VALID;
6319 struct ether_addr hw_addr;
6320 uint8_t dest_addr_ipv6[16];
6321 uint8_t nh_ipv6[16];
6326 if (unlikely(protocol == IP_PROTOCOL_UDP
6327 && rte_be_to_cpu_16(*src_port) == 53)) {
6328 p_nat->invalid_packets |= pkt_mask;
6329 p_nat->naptDroppedPktCount++;
6330 #ifdef CGNAPT_DEBUGGING
6331 p_nat->naptDroppedPktCount6++;
6336 memcpy(&dest_addr_ipv6[0], &entry->data.u.prv_ipv6[0], 16);
6339 memset(nh_ipv6, 0, 16);
6340 struct nd_entry_data *ret_nd_data = NULL;
6341 ret_nd_data = get_dest_mac_address_ipv6_port(
6344 (struct ether_addr *)eth_dest,
6347 *outport_id = p_nat->outport_id[dest_if];
6349 if (nd_cache_dest_mac_present(dest_if)) {
6350 ether_addr_copy(get_link_hw_addr(dest_if),
6351 (struct ether_addr *)eth_src);
6352 update_nhip_access(dest_if);
6354 if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) {
6355 p_nat->naptedPktCount += ret_nd_data->num_pkts;
6356 nd_send_buffered_pkts(ret_nd_data,
6357 (struct ether_addr *)eth_dest, *outport_id);
6361 if (unlikely(ret_nd_data == NULL)) {
6363 #ifdef CGNAPT_DEBUGGING
6364 printf("%s: NHIP Not Found, "
6365 "outport_id: %d\n", __func__,
6370 p_nat->invalid_packets |= pkt_mask;
6371 p_nat->naptDroppedPktCount++;
6373 #ifdef CGNAPT_DEBUGGING
6374 p_nat->naptDroppedPktCount4++;
6379 if (ret_nd_data->status == INCOMPLETE ||
6380 ret_nd_data->status == PROBE) {
6381 if (ret_nd_data->num_pkts >= NUM_DESC) {
6383 p_nat->invalid_packets |= pkt_mask;
6384 p_nat->naptDroppedPktCount++;
6386 #ifdef CGNAPT_DEBUGGING
6387 p_nat->naptDroppedPktCount4++;
6391 arp_pkts_mask |= pkt_mask;
6392 nd_queue_unresolved_packet(ret_nd_data, pkt);
6402 convert_ipv4_to_ipv6(pkt, &ipv4_hdr);
6404 /* Ethernet MTU check */
6405 if ((rte_pktmbuf_data_len(pkt) - 14) > 1500) {
6406 p_nat->invalid_packets |= pkt_mask;
6407 p_nat->naptDroppedPktCount++;
6410 uint32_t *dst_addr =
6411 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4t6);
6412 uint16_t *dst_port =
6413 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP4t6);
6415 memcpy((uint8_t *) &dst_addr[0], &entry->data.u.prv_ipv6[0],
6418 #ifdef NAT_ONLY_CONFIG_REQ
6419 if (!nat_only_config_flag) {
6421 *dst_port = rte_bswap16(entry->data.prv_port);
6423 #ifdef NAT_ONLY_CONFIG_REQ
6427 p_nat->inaptedPktCount++;
6430 p_nat->naptedPktCount++;
6433 if (p_nat->hw_checksum_reqd)
6434 hw_checksum(pkt, pkt_type);
6436 sw_checksum(pkt, pkt_type);
6442 * NAPT function for IPv6 private traffic which handles 4 pkts
6445 * A pointer to array of packets mbuf
6447 * Starting pkt number of pkts
6451 * A pointer to main CGNAPT structure
6455 pkt4_work_cgnapt_ipv6_prv(
6456 struct rte_mbuf **pkts,
6457 uint32_t in_pkt_num,
6458 __rte_unused void *arg,
6459 struct pipeline_cgnapt *p_nat)
6461 struct rte_mbuf *pkt;
6465 enum PKT_TYPE pkt_type = PKT_TYPE_IPV6to4;
6467 for (i = 0; i < 4; i++) {
6468 pkt_num = in_pkt_num + i;
6471 /* index into hash table entries */
6472 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6473 /*bitmask representing only this packet */
6474 uint64_t pkt_mask = 1LLU << pkt_num;
6476 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
6477 uint32_t dest_if = INVALID_DESTIF;
6478 uint16_t *outport_id =
6479 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6480 struct cgnapt_table_entry *entry = NULL;
6482 if (hash_table_entry < 0) {
6484 /* try to add new entry */
6485 struct rte_pipeline_table_entry *table_entry = NULL;
6488 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
6490 &p_nat->valid_packets, pkt_num,
6494 /* ICMP Error message generation for
6495 * Destination Host unreachable
6497 /* Do we need this check for ipv6? */
6498 if (protocol == IP_PROTOCOL_ICMP) {
6499 cgnapt_icmp_pkt = pkt;
6500 send_icmp_dest_unreachable_msg();
6503 /* Drop packet by adding to invalid pkt mask */
6505 p_nat->invalid_packets |= dropmask;
6507 #ifdef CGNAPT_DEBUGGING
6508 if (p_nat->kpc2++ < 5) {
6509 printf("in_ah Th: %d",
6510 p_nat->pipeline_num);
6511 print_key(p_nat->key_ptrs[pkt_num]);
6515 p_nat->naptDroppedPktCount++;
6517 #ifdef CGNAPT_DEBUGGING
6518 p_nat->naptDroppedPktCount3++;
6524 entry = (struct cgnapt_table_entry *)table_entry;
6526 /* entry found for this packet */
6527 entry = &napt_hash_tbl_entries[hash_table_entry];
6530 /* apply napt and mac changes */
6532 p_nat->entries[pkt_num] = &(entry->head);
6534 struct ipv6_hdr ipv6_hdr;
6535 struct ether_addr hw_addr;
6536 uint32_t dest_address = 0;
6537 uint8_t nh_ipv6[16];
6542 convert_ipv6_to_ipv4(pkt, &ipv6_hdr);
6544 #ifdef CGNAPT_DBG_PRNT
6545 if (CGNAPT_DEBUG >= 1)
6546 printf("pkt_work_cganpt: "
6547 "convert_ipv6_to_ipv4\n");
6550 struct cgnapt_nsp_node *ll = nsp_ll;
6553 while (ll != NULL) {
6554 if (!memcmp(&ipv6_hdr.dst_addr[0],
6556 ll->nsp.depth / 8)) {
6564 && !memcmp(&ipv6_hdr.dst_addr[0],
6565 &well_known_prefix[0], 12)) {
6570 p_nat->invalid_packets |= pkt_mask;
6571 p_nat->naptDroppedPktCount++;
6573 #ifdef CGNAPT_DEBUGGING
6574 p_nat->naptDroppedPktCount5++;
6581 /* As packet is already converted into IPv4 we must not
6582 * operate IPv6 offsets on packet only perform IPv4 operations
6585 uint32_t *src_addr =
6586 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP6t4);
6587 uint32_t *dst_addr =
6588 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP6t4);
6589 uint16_t *src_port =
6590 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP6t4);
6591 uint16_t *dst_port =
6592 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP6t4);
6595 RTE_MBUF_METADATA_UINT8_PTR(pkt, ETH_OFST_IP6t4);
6597 RTE_MBUF_METADATA_UINT8_PTR(pkt, ETH_OFST_IP6t4 + 6);
6599 if (entry->data.ttl == NAPT_ENTRY_STALE)
6600 entry->data.ttl = NAPT_ENTRY_VALID;
6605 if (unlikely(protocol == IP_PROTOCOL_UDP
6606 && rte_be_to_cpu_16(*dst_port) == 53)) {
6607 p_nat->invalid_packets |= pkt_mask;
6608 p_nat->naptDroppedPktCount++;
6610 #ifdef CGNAPT_DEBUGGING
6611 p_nat->naptDroppedPktCount6++;
6616 dest_address = rte_bswap32(*dst_addr);
6619 #ifdef CGNAPT_DBG_PRNT
6620 if (CGNAPT_DEBUG > 2)
6621 printf("Egress: \tphy_port:%d\t"
6622 "get_prv_to_pub():%d \tout_port:%d\n",
6623 pkt->port, dest_if, *outport_id);
6627 #ifdef CGNAPT_DEBUGGING
6628 static int static_count;
6630 if (static_count++ < 10) {
6632 my_print_entry(entry);
6633 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6634 printf("dest_add:%x\n", entry->data.u.prv_ip);
6635 printf("dest_add:%x\n", *dst_addr);
6636 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6640 memset(nh_ipv6, 0, 16);
6643 struct arp_entry_data *ret_arp_data;
6644 ret_arp_data = get_dest_mac_addr_port(dest_address,
6645 &dest_if, (struct ether_addr *)eth_dest);
6646 *outport_id = p_nat->outport_id[dest_if];
6648 if (arp_cache_dest_mac_present(dest_if)) {
6649 ether_addr_copy(get_link_hw_addr(dest_if),
6650 (struct ether_addr *)eth_src);
6651 update_nhip_access(dest_if);
6653 if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) {
6654 p_nat->naptedPktCount += ret_arp_data->num_pkts;
6655 arp_send_buffered_pkts(ret_arp_data,
6656 (struct ether_addr *)eth_dest, *outport_id);
6661 if (unlikely(ret_arp_data == NULL)) {
6663 #ifdef CGNAPT_DEBUGGING
6664 printf("%s: NHIP Not Found, nhip:%x , "
6665 "outport_id: %d\n", __func__, nhip,
6670 p_nat->invalid_packets |= pkt_mask;
6671 p_nat->naptDroppedPktCount++;
6673 #ifdef CGNAPT_DEBUGGING
6674 p_nat->naptDroppedPktCount4++;
6679 if (ret_arp_data->status == INCOMPLETE ||
6680 ret_arp_data->status == PROBE) {
6681 if (ret_arp_data->num_pkts >= NUM_DESC) {
6683 p_nat->invalid_packets |= pkt_mask;
6684 p_nat->naptDroppedPktCount++;
6686 #ifdef CGNAPT_DEBUGGING
6687 p_nat->naptDroppedPktCount4++;
6691 arp_pkts_mask |= pkt_mask;
6692 arp_queue_unresolved_packet(ret_arp_data, pkt);
6702 *src_addr = rte_bswap32(entry->data.pub_ip);
6704 #ifdef NAT_ONLY_CONFIG_REQ
6705 if (!nat_only_config_flag) {
6707 *src_port = rte_bswap16(entry->data.pub_port);
6709 #ifdef NAT_ONLY_CONFIG_REQ
6713 p_nat->enaptedPktCount++;
6716 p_nat->naptedPktCount++;
6719 if (p_nat->hw_checksum_reqd)
6720 hw_checksum(pkt, pkt_type);
6722 sw_checksum(pkt, pkt_type);
6728 * NAPT function for IPv6 public traffic which handles 4 pkts
6731 * A pointer to array of packets mbuf
6733 * Starting pkt number of pkts
6737 * A pointer to main CGNAPT structure
6741 pkt4_work_cgnapt_ipv6_pub(
6742 struct rte_mbuf **pkts,
6743 uint32_t in_pkt_num,
6744 __rte_unused void *arg,
6745 struct pipeline_cgnapt *p_nat)
6747 struct rte_mbuf *pkt;
6751 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4to6;
6753 for (i = 0; i < 4; i++) {
6754 pkt_num = in_pkt_num + i;
6757 /* index into hash table entries */
6758 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6759 /*bitmask representing only this packet */
6760 uint64_t pkt_mask = 1LLU << pkt_num;
6762 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
6763 uint16_t *outport_id =
6764 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6765 struct cgnapt_table_entry *entry = NULL;
6767 if (hash_table_entry < 0) {
6769 /* Drop ingress initial traffic */
6771 p_nat->invalid_packets |= pkt_mask;
6772 p_nat->naptDroppedPktCount++;
6773 #ifdef CGNAPT_DEBUGGING
6774 p_nat->naptDroppedPktCount3++;
6775 if (p_nat->kpc2++ < 5) {
6776 printf("in_ah Th: %d", p_nat->pipeline_num);
6777 print_key(p_nat->key_ptrs[pkt_num]);
6784 /* entry found for this packet */
6785 entry = &napt_hash_tbl_entries[hash_table_entry];
6788 /* apply napt and mac changes */
6790 p_nat->entries[pkt_num] = &(entry->head);
6791 if (entry->data.type != CGNAPT_ENTRY_IPV6) {
6792 p_nat->invalid_packets |= pkt_mask;
6793 p_nat->naptDroppedPktCount++;
6797 struct ipv4_hdr ipv4_hdr;
6799 uint16_t *src_port =
6800 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP4_TCP);
6803 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
6805 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
6807 if (entry->data.ttl == NAPT_ENTRY_STALE)
6808 entry->data.ttl = NAPT_ENTRY_VALID;
6810 struct ether_addr hw_addr;
6811 uint8_t dest_addr_ipv6[16];
6812 uint8_t nh_ipv6[16];
6813 uint32_t dest_if = INVALID_DESTIF;
6814 { /*start of Ingress */
6816 if (unlikely(protocol == IP_PROTOCOL_UDP
6817 && rte_be_to_cpu_16(*src_port) == 53)) {
6818 p_nat->invalid_packets |= pkt_mask;
6819 p_nat->naptDroppedPktCount++;
6820 #ifdef CGNAPT_DEBUGGING
6821 p_nat->naptDroppedPktCount6++;
6826 memcpy(&dest_addr_ipv6[0], &entry->data.u.prv_ipv6[0],
6829 }/* end of ingress */
6831 #ifdef CGNAPT_DEBUGGING
6832 static int static_count;
6834 if (static_count++ < 10) {
6836 my_print_entry(entry);
6837 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6838 printf("dest_add:%x\n", entry->data.u.prv_ip);
6839 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6843 memset(nh_ipv6, 0, 16);
6844 struct nd_entry_data *ret_nd_data = NULL;
6845 ret_nd_data = get_dest_mac_address_ipv6_port
6846 (&dest_addr_ipv6[0], &dest_if,
6847 (struct ether_addr *)eth_dest, &nh_ipv6[0]);
6849 *outport_id = p_nat->outport_id[dest_if];
6851 if (nd_cache_dest_mac_present(dest_if)) {
6852 ether_addr_copy(get_link_hw_addr(dest_if),
6853 (struct ether_addr *)eth_src);
6854 update_nhip_access(dest_if);
6856 if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) {
6857 p_nat->naptedPktCount += ret_nd_data->num_pkts;
6858 nd_send_buffered_pkts(ret_nd_data,
6859 (struct ether_addr *)eth_dest, *outport_id);
6862 if (unlikely(ret_nd_data == NULL)) {
6864 #ifdef CGNAPT_DEBUGGING
6865 printf("%s: NHIP Not Found "
6866 "outport_id: %d\n", __func__,
6871 p_nat->invalid_packets |= pkt_mask;
6872 p_nat->naptDroppedPktCount++;
6874 #ifdef CGNAPT_DEBUGGING
6875 p_nat->naptDroppedPktCount4++;
6880 if (ret_nd_data->status == INCOMPLETE ||
6881 ret_nd_data->status == PROBE) {
6883 if (ret_nd_data->num_pkts >= NUM_DESC) {
6885 p_nat->invalid_packets |= pkt_mask;
6886 p_nat->naptDroppedPktCount++;
6888 #ifdef CGNAPT_DEBUGGING
6889 p_nat->naptDroppedPktCount4++;
6893 arp_pkts_mask |= pkt_mask;
6894 nd_queue_unresolved_packet(ret_nd_data, pkt);
6902 /* start of Ingress */
6904 convert_ipv4_to_ipv6(pkt, &ipv4_hdr);
6906 /* Ethernet MTU check */
6907 if ((rte_pktmbuf_data_len(pkt) - 14) > 1500) {
6908 p_nat->invalid_packets |= pkt_mask;
6909 p_nat->naptDroppedPktCount++;
6912 uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
6913 DST_ADR_OFST_IP4t6);
6914 uint16_t *dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
6915 DST_PRT_OFST_IP4t6);
6917 memcpy((uint8_t *) &dst_addr[0],
6918 &entry->data.u.prv_ipv6[0], 16);
6920 #ifdef NAT_ONLY_CONFIG_REQ
6921 if (!nat_only_config_flag) {
6923 *dst_port = rte_bswap16(entry->data.prv_port);
6925 #ifdef NAT_ONLY_CONFIG_REQ
6929 p_nat->inaptedPktCount++;
6930 } /* end of ingress */
6932 p_nat->naptedPktCount++;
6935 if (p_nat->hw_checksum_reqd)
6936 hw_checksum(pkt, pkt_type);
6938 sw_checksum(pkt, pkt_type);
6940 } /* end of for loop */
6944 * Input port handler for IPv6 private traffic
6945 * Starting from the packet burst it filters unwanted packets,
6946 * calculates keys, does lookup and then based on the lookup
6947 * updates NAPT table and does packet NAPT translation.
6950 * A pointer to struct rte_pipeline
6952 * A pointer to array of packets mbuf
6954 * Number of packets in the burst
6959 * int that is not checked by caller
6961 static int cgnapt_in_port_ah_ipv6_prv(struct rte_pipeline *rte_p,
6962 struct rte_mbuf **pkts,
6963 uint32_t n_pkts, void *arg)
6966 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
6967 struct pipeline_cgnapt *p_nat = ap->p;
6969 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
6970 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
6971 p_nat->invalid_packets = 0;
6974 #ifdef CGNAPT_DBG_PRNT
6975 if (CGNAPT_DEBUG > 1)
6976 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
6979 /* prefetching for mbufs should be done here */
6980 for (j = 0; j < n_pkts; j++)
6981 rte_prefetch0(pkts[j]);
6983 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
6984 pkt4_work_cgnapt_key_ipv6_prv(&pkts[i], i, arg, p_nat);
6986 for (; i < n_pkts; i++)
6987 pkt_work_cgnapt_key_ipv6_prv(pkts[i], i, arg, p_nat);
6989 p_nat->valid_packets &= ~(p_nat->invalid_packets);
6991 if (arp_pkts_mask) {
6992 p_nat->valid_packets &= ~(arp_pkts_mask);
6993 rte_pipeline_ah_packet_hijack(rte_p, arp_pkts_mask);
6996 if (unlikely(p_nat->valid_packets == 0)) {
6997 /* no suitable packet for lookup */
6998 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
6999 return p_nat->valid_packets;
7002 /* lookup entries in the common napt table */
7004 int lookup_result = rte_hash_lookup_bulk(
7006 (const void **) &p_nat->key_ptrs,
7007 /* should be minus num invalid pkts */
7009 /*new pipeline data member */
7010 &p_nat->lkup_indx[0]);
7012 if (unlikely(lookup_result < 0)) {
7013 /* unknown error, just discard all packets */
7014 printf("Unexpected hash lookup error %d, "
7015 "discarding all packets",
7017 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
7021 /* Now call second stage of pipeline to one by one
7022 * check the result of our bulk lookup
7025 /* prefetching for table entries should be done here */
7026 for (j = 0; j < n_pkts; j++) {
7027 if (p_nat->lkup_indx[j] >= 0)
7028 rte_prefetch0(&napt_hash_tbl_entries
7029 [p_nat->lkup_indx[j]]);
7032 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7033 pkt4_work_cgnapt_ipv6_prv(&pkts[i], i, arg, p_nat);
7035 for (; i < n_pkts; i++)
7036 pkt_work_cgnapt_ipv6_prv(pkts[i], i, arg, p_nat);
7038 if (p_nat->invalid_packets) {
7039 /* get rid of invalid packets */
7040 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7042 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7044 #ifdef CGNAPT_DBG_PRNT
7045 if (CGNAPT_DEBUG > 1) {
7046 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
7047 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
7048 printf("invalid_packets:0x%jx\n",
7049 p_nat->invalid_packets);
7050 printf("rte_invalid_packets :0x%jx\n",
7051 rte_p->pkts_drop_mask);
7052 printf("Total pkts dropped :0x%jx\n",
7053 rte_p->n_pkts_ah_drop);
7058 return p_nat->valid_packets;
7063 * Input port handler for IPv6 public traffic
7064 * Starting from the packet burst it filters unwanted packets,
7065 * calculates keys, does lookup and then based on the lookup
7066 * updates NAPT table and does packet NAPT translation.
7069 * A pointer to struct rte_pipeline
7071 * A pointer to array of packets mbuf
7073 * Number of packets in the burst
7078 * int that is not checked by caller
7080 static int cgnapt_in_port_ah_ipv6_pub(struct rte_pipeline *rte_p,
7081 struct rte_mbuf **pkts,
7082 uint32_t n_pkts, void *arg)
7085 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
7086 struct pipeline_cgnapt *p_nat = ap->p;
7088 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
7089 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
7090 p_nat->invalid_packets = 0;
7093 #ifdef CGNAPT_DBG_PRNT
7094 if (CGNAPT_DEBUG > 1)
7095 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
7098 /* prefetching for mbufs should be done here */
7099 for (j = 0; j < n_pkts; j++)
7100 rte_prefetch0(pkts[j]);
7102 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7103 pkt4_work_cgnapt_key_ipv6_pub(&pkts[i], i, arg, p_nat);
7105 for (; i < n_pkts; i++)
7106 pkt_work_cgnapt_key_ipv6_pub(pkts[i], i, arg, p_nat);
7108 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7110 if (arp_pkts_mask) {
7111 p_nat->valid_packets &= ~(arp_pkts_mask);
7112 rte_pipeline_ah_packet_hijack(rte_p, arp_pkts_mask);
7115 if (unlikely(p_nat->valid_packets == 0)) {
7116 /* no suitable packet for lookup */
7117 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7118 return p_nat->valid_packets;
7121 /* lookup entries in the common napt table */
7123 int lookup_result = rte_hash_lookup_bulk(
7125 (const void **) &p_nat->key_ptrs,
7126 /* should be minus num invalid pkts */
7128 /*new pipeline data member */
7129 &p_nat->lkup_indx[0]);
7131 if (unlikely(lookup_result < 0)) {
7132 /* unknown error, just discard all packets */
7133 printf("Unexpected hash lookup error %d, "
7134 "discarding all packets",
7136 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
7140 /* Now call second stage of pipeline to one by one
7141 * check the result of our bulk lookup
7144 /* prefetching for table entries should be done here */
7145 for (j = 0; j < n_pkts; j++) {
7146 if (p_nat->lkup_indx[j] >= 0)
7147 rte_prefetch0(&napt_hash_tbl_entries
7148 [p_nat->lkup_indx[j]]);
7151 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7152 pkt4_work_cgnapt_ipv6_pub(&pkts[i], i, arg, p_nat);
7154 for (; i < n_pkts; i++)
7155 pkt_work_cgnapt_ipv6_pub(pkts[i], i, arg, p_nat);
7157 if (p_nat->invalid_packets) {
7158 /* get rid of invalid packets */
7159 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7161 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7163 #ifdef CGNAPT_DBG_PRNT
7164 if (CGNAPT_DEBUG > 1) {
7165 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
7166 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
7167 printf("invalid_packets:0x%jx\n",
7168 p_nat->invalid_packets);
7169 printf("rte_invalid_packets :0x%jx\n",
7170 rte_p->pkts_drop_mask);
7171 printf("Total pkts dropped :0x%jx\n",
7172 rte_p->n_pkts_ah_drop);
7177 return p_nat->valid_packets;
7181 * Function to send ICMP dest unreachable msg
7184 void send_icmp_dest_unreachable_msg(void)
7187 struct ether_hdr *eth_h;
7188 struct ipv4_hdr *ip_h;
7189 struct icmp_hdr *icmp_h;
7190 struct rte_mbuf *icmp_pkt = cgnapt_icmp_pkt;
7192 if (icmp_pkt == NULL) {
7194 printf("Error allocating icmp_pkt rte_mbuf\n");
7198 port_id = icmp_pkt->port;
7200 struct app_link_params *link;
7201 link = &mylink[port_id];
7202 eth_h = rte_pktmbuf_mtod(icmp_pkt, struct ether_hdr *);
7203 ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
7204 icmp_h = (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
7206 struct ether_addr gw_addr;
7207 struct ether_addr dst_addr;
7208 ether_addr_copy(ð_h->s_addr, &dst_addr);
7209 rte_eth_macaddr_get(port_id, &gw_addr);
7210 ether_addr_copy(&gw_addr, ð_h->s_addr);
7211 ether_addr_copy(&dst_addr, ð_h->d_addr);
7213 eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
7214 ip_h->version_ihl = IP_VHL_DEF;
7215 ip_h->type_of_service = 0;
7216 ip_h->total_length = rte_cpu_to_be_16(sizeof(struct ipv4_hdr) +
7217 sizeof(struct icmp_hdr));
7218 ip_h->packet_id = 0xaabb;
7219 ip_h->fragment_offset = 0x0000;
7220 ip_h->time_to_live = 64;
7221 ip_h->next_proto_id = 1;
7224 uint32_t src_addr_offset =
7225 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_SRC_ADR_OFST;
7227 RTE_MBUF_METADATA_UINT32_PTR(cgnapt_icmp_pkt, src_addr_offset);
7229 ip_h->dst_addr = *src_addr;
7230 ip_h->src_addr = rte_bswap32(link->ip);
7232 ip_h->dst_addr = *src_addr;
7233 ip_h->src_addr = rte_bswap32(link->ip);
7235 ip_h->hdr_checksum = 0;
7236 ip_h->hdr_checksum = rte_ipv4_cksum(ip_h);
7237 icmp_h->icmp_type = 3; /* Destination Unreachable */
7238 icmp_h->icmp_code = 13; /* Communication administratively prohibited */
7240 icmp_h->icmp_cksum = ~rte_raw_cksum(icmp_h, sizeof(struct icmp_hdr));
7242 icmp_pkt->pkt_len = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
7243 sizeof(struct icmp_hdr);
7244 icmp_pkt->data_len = icmp_pkt->pkt_len;
7245 if (ARPICMP_DEBUG) {
7246 printf("Sending ICMP error message - "
7247 "Destination Unreachable\n");
7249 rte_pipeline_port_out_packet_insert(myP, port_id, icmp_pkt);
7253 * Function to add a dynamic NAPT entry pair
7256 * A pointer to struct pipeline
7258 * A pointer to struct pipeline_cgnapt_entry_key
7260 * expairy time of an dynamic or PCP req entry
7262 * uint8_t pointer of source address
7265 * A pointer to struct cgnapt_table_entry for added entry
7268 struct cgnapt_table_entry *add_dynamic_cgnapt_entry(
7270 struct pipeline_cgnapt_entry_key *key,
7277 void *entry_ptr, *ret_ptr;
7280 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
7282 #ifdef CGNAPT_DBG_PRNT
7283 if (CGNAPT_DEBUG >= 1) {
7284 printf("Th%d add_dynamic_cgnapt_entry key detail Entry:"
7285 "0x%x, %d, %d\n", p_nat->pipeline_num, key->ip, key->port,
7290 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX && i < p_nat->pkt_burst_cnt;
7292 if (p_nat->cgnapt_dyn_ent_table[i].ip == key->ip
7293 && p_nat->cgnapt_dyn_ent_table[i].port == key->port
7294 && p_nat->cgnapt_dyn_ent_table[i].pid == key->pid) {
7296 #ifdef CGNAPT_DBG_PRNT
7297 if (CGNAPT_DEBUG > 1)
7298 printf("add_dynamic_cgnapt_entry:pkt_burst "
7299 "array key matched!!!\n");
7302 return &napt_hash_tbl_entries
7303 [p_nat->cgnapt_dyn_ent_index[i]];
7307 #ifdef NAT_ONLY_CONFIG_REQ
7308 if (!nat_only_config_flag) {
7311 ret = increment_max_port_counter(key->ip, key->pid, p_nat);
7312 if (ret == MAX_PORT_INC_ERROR) {
7314 #ifdef CGNAPT_DEBUGGING
7315 p_nat->missedpktcount5++;
7318 #ifdef CGNAPT_DBG_PRNT
7319 if (CGNAPT_DEBUG > 1)
7320 printf("add_dynamic_cgnapt_entry:"
7321 "increment_max_port_counter-1 failed\n");
7328 if (ret == MAX_PORT_INC_REACHED) {
7330 #ifdef CGNAPT_DEBUGGING
7331 p_nat->missedpktcount6++;
7334 #ifdef CGNAPT_DBG_PRNT
7335 if (CGNAPT_DEBUG > 1)
7336 printf("add_dynamic_cgnapt_entry:"
7337 "increment_max_port_counter-2 failed\n");
7344 #ifdef NAT_ONLY_CONFIG_REQ
7349 port_num = get_free_iport(p_nat, &public_ip);
7351 if (port_num == -1) {
7353 #ifdef CGNAPT_DBG_PRNT
7354 if (CGNAPT_DEBUG > 2) {
7355 printf("add_dynamic_cgnapt_entry: %d\n", port_num);
7356 printf("add_dynamic_cgnapt_entry key detail:0x%x, "
7357 "%d, %d\n", key->ip, key->port, key->pid);
7361 #ifdef CGNAPT_DEBUGGING
7362 p_nat->missedpktcount7++;
7369 #ifdef NAT_ONLY_CONFIG_REQ
7370 if (!nat_only_config_flag) {
7373 if (ret == 2) { //MPPC_NEW_ENTRY
7375 /* check for max_clients_per_ip */
7376 if (rte_atomic16_read
7378 [rte_jhash(&public_ip, 4, 0) %
7379 CGNAPT_MAX_PUB_IP].count) ==
7380 p_nat->max_clients_per_ip) {
7382 /* For now just bail out
7383 * In future we can think about
7384 * retrying getting a new iport
7387 release_iport(port_num, public_ip, p_nat);
7389 #ifdef CGNAPT_DEBUGGING
7390 p_nat->missedpktcount10++;
7396 rte_atomic16_inc(&all_public_ip
7397 [rte_jhash(&public_ip, 4, 0) %
7398 CGNAPT_MAX_PUB_IP].count);
7400 #ifdef CGNAPT_DBG_PRNT
7401 if ((rte_jhash(&public_ip, 4, 0) %
7402 CGNAPT_MAX_PUB_IP) == 8)
7403 printf("pub ip:%x coutn:%d\n", public_ip,
7404 rte_atomic16_read(&all_public_ip
7405 [rte_jhash(&public_ip, 4, 0) %
7406 CGNAPT_MAX_PUB_IP].count));
7410 #ifdef NAT_ONLY_CONFIG_REQ
7414 #ifdef CGNAPT_DBG_PRNT
7415 if (CGNAPT_DEBUG > 0) {
7416 printf("add_dynamic_cgnapt_entry: %d\n",
7418 printf("add_dynamic_cgnapt_entry key detail: "
7419 "0x%x, %d, %d\n", key->ip, key->port, key->pid);
7423 struct cgnapt_table_entry entry = {
7425 .action = RTE_PIPELINE_ACTION_PORT,
7426 /* made it configurable below */
7427 {.port_id = p->port_out_id[0]},
7431 .prv_port = key->port,
7432 .pub_ip = public_ip,
7433 .pub_port = port_num,
7434 .prv_phy_port = key->pid,
7435 .pub_phy_port = get_pub_to_prv_port(
7439 /* if(timeout == -1) : static entry
7440 * if(timeout == 0 ) : dynamic entry
7441 * if(timeout > 0 ) : PCP requested entry
7443 .timeout = timeout > 0 ? timeout : 0,
7450 #ifdef NAT_ONLY_CONFIG_REQ
7451 if (nat_only_config_flag) {
7452 entry.data.prv_port = 0xffff;
7453 entry.data.pub_port = 0xffff;
7457 if (pkt_type == CGNAPT_ENTRY_IPV6) {
7458 entry.data.type = CGNAPT_ENTRY_IPV6;
7459 memcpy(&entry.data.u.prv_ipv6[0], src_addr, 16);
7461 entry.data.u.prv_ip = key->ip;
7462 entry.data.type = CGNAPT_ENTRY_IPV4;
7465 //entry.head.port_id = CGNAPT_PUB_PORT_ID; /* outgoing port info */
7466 entry.head.port_id = entry.data.pub_phy_port; /* outgoing port info */
7468 struct pipeline_cgnapt_entry_key second_key;
7469 /* Need to add a second ingress entry */
7470 second_key.ip = public_ip;
7471 second_key.port = port_num;
7472 second_key.pid = 0xffff;
7474 #ifdef NAT_ONLY_CONFIG_REQ
7475 if (nat_only_config_flag)
7476 second_key.port = 0xffff;
7479 #ifdef CGNAPT_DBG_PRNT
7480 if (CGNAPT_DEBUG > 2)
7481 printf("add_dynamic_cgnapt_entry second key detail:"
7482 "0x%x, %d, %d\n", second_key.ip, second_key.port,
7486 int32_t position = rte_hash_add_key(napt_common_table, (void *)key);
7489 #ifdef CGNAPT_DEBUGGING
7490 p_nat->missedpktcount8++;
7493 printf("CG-NAPT entry add failed ...returning "
7494 "without adding ... %d\n", position);
7499 #ifdef CGNAPT_DBG_PRNT
7501 printf("add_dynamic_cgnapt_entry\n");
7503 print_cgnapt_entry(&entry);
7507 memcpy(&napt_hash_tbl_entries[position], &entry,
7508 sizeof(struct cgnapt_table_entry));
7510 /* this pointer is returned to pkt miss function */
7511 ret_ptr = &napt_hash_tbl_entries[position];
7513 p_nat->n_cgnapt_entry_added++;
7514 p_nat->dynCgnaptCount++;
7516 /* Now modify the forward port for reverse entry */
7518 /* outgoing port info */
7519 //entry.head.port_id = CGNAPT_PRV_PORT_ID;
7520 /* outgoing port info */
7521 entry.head.port_id = entry.data.prv_phy_port;
7523 int32_t position2 = rte_hash_add_key(napt_common_table, &second_key);
7525 if (position2 < 0) {
7526 #ifdef CGNAPT_DEBUGGING
7527 p_nat->missedpktcount9++;
7529 printf("CG-NAPT entry reverse bulk add failed ..."
7530 "returning with fwd add ...%d\n",
7536 memcpy(&napt_hash_tbl_entries[position2], &entry,
7537 sizeof(struct cgnapt_table_entry));
7539 entry_ptr = &napt_hash_tbl_entries[position2];
7541 timer_thread_enqueue(key, &second_key, ret_ptr,
7542 entry_ptr, (struct pipeline *)p_nat);
7544 p_nat->n_cgnapt_entry_added++;
7545 p_nat->dynCgnaptCount++;
7547 if (p_nat->pkt_burst_cnt < RTE_PORT_IN_BURST_SIZE_MAX) {
7548 memcpy(&p_nat->cgnapt_dyn_ent_table[p_nat->pkt_burst_cnt], key,
7549 sizeof(struct pipeline_cgnapt_entry_key));
7550 p_nat->cgnapt_dyn_ent_index[p_nat->pkt_burst_cnt] = position;
7551 p_nat->pkt_burst_cnt++;
7556 int pkt_miss_cgnapt_count;
7558 * Function handle a missed NAPT entry lookup
7559 * Will attempt to add a dynamic entry pair.
7562 * A pointer to struct pipeline
7564 * A pointer to struct pipeline_cgnapt_entry_key
7566 * A pointer to pkt struct rte_mbuf
7568 * uint64_t pointer to pkt mask
7569 * @param table_entry
7570 * A pointer to struct rte_pipeline_table_entry to be created and returned
7572 * number of this pkt in current burst
7575 * A uint64_t mask for drop packets
7578 pkt_miss_cgnapt(struct pipeline_cgnapt_entry_key *key,
7579 struct rte_mbuf *pkt,
7580 struct rte_pipeline_table_entry **table_entry,
7581 __rte_unused uint64_t *pkts_mask,
7582 uint32_t pkt_num, void *arg)
7585 #ifdef CGNAPT_DBG_PRNT
7586 if (CGNAPT_DEBUG > 0)
7587 printf("\n pkt_miss_cgnapt\n");
7591 * see if get_port passes for this src address
7592 * if passed add a new egress entry and a
7593 * corresponding new ingress entry
7594 * return the fwd entry to calling function using input pointer
7595 * else if get_port fails drop packet
7598 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)arg;
7600 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
7601 uint32_t src_addr_offset_ipv6 =
7602 MBUF_HDR_ROOM + ETH_HDR_SIZE + IPV6_HDR_SRC_ADR_OFST;
7603 uint16_t phy_port = pkt->port;
7605 uint16_t *eth_proto =
7606 RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
7608 uint8_t *src_addr = NULL;
7609 uint8_t src_addr_ipv6[16];
7610 uint8_t pkt_type = CGNAPT_ENTRY_IPV4;
7611 /* To drop the packet */
7612 uint64_t drop_mask = 0;
7614 if (p_nat->is_static_cgnapt) {
7615 drop_mask |= 1LLU << pkt_num;
7616 p_nat->missedPktCount++;
7618 #ifdef CGNAPT_DEBUGGING
7619 p_nat->missedpktcount1++;
7624 if (rte_be_to_cpu_16(*eth_proto) == ETHER_TYPE_IPv6) {
7626 RTE_MBUF_METADATA_UINT8_PTR(pkt, src_addr_offset_ipv6);
7627 pkt_type = CGNAPT_ENTRY_IPV6;
7628 memcpy(src_addr_ipv6, src_addr, 16);
7633 /* some validation first */
7634 if (is_phy_port_privte(phy_port)) {
7635 /* dynamic NAPT entry creation */
7636 *table_entry = (struct rte_pipeline_table_entry *)
7637 add_dynamic_cgnapt_entry(
7638 (struct pipeline *)&p_nat->p,
7640 DYNAMIC_CGNAPT_TIMEOUT,
7642 src_addr_ipv6, &err);
7644 if (!(*table_entry)) {
7646 drop_mask |= 1LLU << pkt_num;
7647 p_nat->missedPktCount++;
7649 #ifdef CGNAPT_DEBUGGING
7650 p_nat->missedpktcount2++;
7653 #ifdef CGNAPT_DBG_PRNT
7654 if (CGNAPT_DEBUG > 1)
7655 printf("Add Dynamic NAT entry failed "
7659 #ifdef CGNAPT_DEBUGGING
7660 p_nat->missedpktcount11++;
7665 } else if (!is_phy_port_privte(phy_port)) {
7667 #ifdef CGNAPT_DBG_PRNT
7668 if (CGNAPT_DEBUG >= 2) {
7669 printf("Initial Ingress entry creation NOT ALLOWED "
7674 drop_mask |= 1LLU << pkt_num;
7675 p_nat->missedPktCount++;
7677 #ifdef CGNAPT_DEBUGGING
7678 p_nat->missedpktcount3++;
7682 #ifdef CGNAPT_DBG_PRNT
7683 if (CGNAPT_DEBUG > 1)
7684 printf("NOT a PRIVATE or PUBLIC port!!!!!\n");
7687 drop_mask |= 1LLU << pkt_num;
7688 p_nat->missedPktCount++;
7690 #ifdef CGNAPT_DEBUGGING
7691 p_nat->missedpktcount4++;
7695 #ifdef CGNAPT_DBG_PRNT
7696 if (CGNAPT_DEBUG > 5)
7706 * Function to print the contents of a packet
7709 * A pointer to pkt struct rte_mbuf
7711 void print_pkt(struct rte_mbuf *pkt)
7715 printf("\nPacket Contents:\n");
7717 uint8_t *rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
7719 for (i = 0; i < 20; i++) {
7720 for (j = 0; j < 20; j++)
7721 printf("%02x ", rd[(20 * i) + j]);
7727 rte_table_hash_op_hash cgnapt_hash_func[] = {
7739 * Function to parse incoming pipeline arguments
7740 * Called during pipeline initialization
7743 * A pointer to struct pipeline_cgnapt
7745 * A pointer to struct pipeline_params
7748 * 0 if success, negative if failure
7751 pipeline_cgnapt_parse_args(struct pipeline_cgnapt *p,
7752 struct pipeline_params *params)
7754 uint32_t n_flows_present = 0;
7755 uint32_t key_offset_present = 0;
7756 uint32_t key_size_present = 0;
7757 uint32_t hash_offset_present = 0;
7758 uint32_t n_entries_present = 0;
7759 uint32_t max_port_present = 0;
7760 uint32_t max_client_present = 0;
7761 uint32_t public_ip_range_present = 0;
7762 uint32_t public_ip_port_range_present = 0;
7764 uint8_t public_ip_count = 0;
7765 uint8_t public_ip_range_count = 0;
7766 uint8_t dest_if_offset_present = 0;
7767 uint8_t cgnapt_meta_offset_present = 0;
7768 uint8_t prv_que_handler_present = 0;
7769 uint8_t n_prv_in_port = 0;
7771 if (CGNAPT_DEBUG > 2) {
7772 printf("CGNAPT pipeline_cgnapt_parse_args params->n_args: %d\n",
7775 for (i = 0; i < params->n_args; i++) {
7776 char *arg_name = params->args_name[i];
7777 char *arg_value = params->args_value[i];
7779 if (CGNAPT_DEBUG > 2) {
7780 printf("CGNAPT args[%d]: %s %d, %s\n", i, arg_name,
7781 atoi(arg_value), arg_value);
7783 if (strcmp(arg_name, "prv_que_handler") == 0) {
7785 if (prv_que_handler_present) {
7786 printf("Duplicate pktq_in_prv ..\n\n");
7789 prv_que_handler_present = 1;
7794 /* get the first token */
7795 token = strtok(arg_value, "(");
7796 token = strtok(token, ")");
7797 token = strtok(token, ",");
7798 printf("***** prv_que_handler *****\n");
7800 if (token == NULL) {
7801 printf("string is null\n");
7802 printf("invalid prv_que_handler value/n");
7805 printf("string is :%s\n", token);
7807 /* walk through other tokens */
7808 while (token != NULL) {
7809 printf(" %s\n", token);
7810 rxport = atoi(token);
7811 cgnapt_prv_que_port_index[n_prv_in_port++] =
7813 if (rxport < PIPELINE_MAX_PORT_IN)
7814 cgnapt_in_port_egress_prv[rxport] = 1;
7815 token = strtok(NULL, ",");
7818 if (n_prv_in_port == 0) {
7819 printf("VNF common parse err - "
7820 "no prv RX phy port\n");
7826 if (strcmp(arg_name, "cgnapt_meta_offset") == 0) {
7827 if (cgnapt_meta_offset_present) {
7828 printf("CG-NAPT parse error:");
7829 printf("cgnapt_meta_offset initizlized "
7830 "mulitple times\n");
7833 cgnapt_meta_offset_present = 1;
7835 temp = atoi(arg_value);
7838 printf("cgnapt_meta_offset is invalid :");
7839 printf("Not be more than metadata size\n");
7842 cgnapt_meta_offset = (uint16_t) temp;
7844 if (strcmp(arg_name, "vnf_set") == 0)
7847 if (strcmp(arg_name, "public_ip_range") == 0) {
7848 public_ip_range_present = 1;
7849 if (public_ip_port_range_present) {
7850 printf("CG-NAPT parse error:");
7851 printf("public_ip_range with "
7852 "public_ip_port_range_present\n");
7856 p->pub_ip_range = rte_realloc(p->pub_ip_range,
7859 RTE_CACHE_LINE_SIZE);
7861 if (!p->pub_ip_range) {
7862 printf("Memory allocation failed for "
7867 uint32_t sip = 0, eip = 0;
7869 if (sscanf(arg_value, "(%x,%x)", &sip, &eip) != 2) {
7870 printf("public_ip_range is invalid\n");
7874 if (sip <= 0 || eip <= 0 || sip >= eip) {
7875 printf("public_ip_range is invalid %x-%x\n",
7880 printf("public_ip_range: %d-%d\n",
7881 p->pub_ip_range[public_ip_range_count].
7883 p->pub_ip_range[public_ip_range_count].
7886 p->pub_ip_range_count = ++public_ip_range_count;
7890 if (strcmp(arg_name, "public_ip_port_range") == 0) {
7891 public_ip_port_range_present = 1;
7892 if (nat_only_config_flag || public_ip_range_present) {
7894 printf("CG-NAPT parse error:");
7895 printf("nat_only_config_flag OR ");
7896 printf("public_ip_range_present with "
7897 "public_ip_port_range_present\n");
7901 p->pub_ip_port_set = rte_realloc(
7903 sizeof(struct pub_ip_port_set),
7904 RTE_CACHE_LINE_SIZE);
7906 if (!p->pub_ip_port_set) {
7907 printf("Memory allocation failed for "
7915 if (sscanf(arg_value, "%x:(%d,%d)",
7916 &ip, &sp, &ep) != 3) {
7917 printf("Public IP or Port-range is invalid\n");
7921 if (ip <= 0 || sp <= 0 || ep <= 0 || sp > ep) {
7922 printf("Public IP or Port-range is invalid "
7923 "%x:%d-%d\n", ip, sp, ep);
7927 printf("public_ip: 0x%x Range:%d-%d\n",
7928 p->pub_ip_port_set[public_ip_count].ip = ip,
7929 p->pub_ip_port_set[public_ip_count].start_port = sp,
7930 p->pub_ip_port_set[public_ip_count].end_port = ep);
7932 napt_port_alloc_elem_count += (ep - sp + 1);
7933 printf("parse - napt_port_alloc_elem_count :%d\n",
7934 napt_port_alloc_elem_count);
7936 /* Store all public IPs of all CGNAPT threads
7937 * in the global variable
7939 /* to revisit indexing */
7940 all_public_ip[rte_jhash(&ip, 4, 0) %
7941 CGNAPT_MAX_PUB_IP].ip = ip;
7942 p->pub_ip_count = ++public_ip_count;
7943 printf("public_ip_count:%d hash:%d\n", public_ip_count,
7944 rte_jhash(&ip, 4, 0) % CGNAPT_MAX_PUB_IP);
7948 /* hw_checksum_reqd */
7949 if (strcmp(arg_name, "hw_checksum_reqd") == 0) {
7951 temp = atoi(arg_value);
7952 if ((temp != 0) && (temp != 1)) {
7953 printf("hw_checksum_reqd is invalid\n");
7956 p->hw_checksum_reqd = temp;
7960 /* nat_only_config_flag */
7961 if (strcmp(arg_name, "nat_only_config_flag") == 0) {
7962 nat_only_config_flag = 1;
7963 if (public_ip_port_range_present) {
7965 printf("CG-NAPT parse error:");
7966 printf("nat_only_config_flag with "
7967 "public_ip_port_range_present\n");
7973 /* max_port_per_client */
7974 if (strcmp(arg_name, "max_port_per_client") == 0) {
7975 if (max_port_present) {
7976 printf("CG-NAPT Parse Error: "
7977 "duplicate max_port_per_client\n");
7980 max_port_present = 1;
7983 max = atoi(arg_value);
7985 printf("max_port_per_client is invalid !!!\n");
7989 p->max_port_per_client = (uint16_t) max;
7991 if (p->max_port_per_client <= 0) {
7992 printf("max port per client is invalid\n");
7996 printf("max_port_per_client comp: %d\n",
7997 p->max_port_per_client);
8001 /* max_clients_per_ip */
8002 if (strcmp(arg_name, "max_clients_per_ip") == 0) {
8003 if (max_client_present) {
8004 printf("CG-NAPT parse Error: duplicate "
8005 "max_clients_per_ip\n");
8008 max_client_present = 1;
8010 if (nat_only_config_flag) {
8011 printf("CG-NAPT parse error:");
8012 printf("nat_only_config_flag with "
8013 "max_clients_per_ip\n");
8018 max = atoi(arg_value);
8020 printf("max_clients_per_ip is invalid !!!\n");
8024 p->max_clients_per_ip = (uint16_t) max;
8026 if (p->max_clients_per_ip <= 0) {
8027 printf("max_clients_per_ip is invalid\n");
8031 printf("max_clients_per_ip: %d\n",
8032 p->max_clients_per_ip);
8037 if (strcmp(arg_name, "n_entries") == 0) {
8038 if (n_entries_present)
8040 n_entries_present = 1;
8042 p->n_entries = atoi(arg_value);
8043 if (p->n_entries == 0)
8050 if (strcmp(arg_name, "n_flows") == 0) {
8051 if (n_flows_present)
8053 n_flows_present = 1;
8055 p->n_flows = atoi(arg_value);
8056 if (p->n_flows == 0)
8059 napt_common_table_hash_params.entries = p->n_flows;
8062 /* dest_if_offset Multiport Changes */
8063 if (strcmp(arg_name, "dest_if_offset") == 0) {
8064 if (dest_if_offset_present)
8066 //dest_if_offset_present = 1;
8068 dest_if_offset = atoi(arg_value);
8074 if (strcmp(arg_name, "key_offset") == 0) {
8075 if (key_offset_present)
8077 key_offset_present = 1;
8079 p->key_offset = atoi(arg_value);
8085 if (strcmp(arg_name, "key_size") == 0) {
8086 if (key_size_present)
8088 key_size_present = 1;
8090 p->key_size = atoi(arg_value);
8091 if ((p->key_size == 0) ||
8092 (p->key_size > PIPELINE_CGNAPT_KEY_MAX_SIZE) ||
8100 if (strcmp(arg_name, "hash_offset") == 0) {
8101 if (hash_offset_present)
8103 hash_offset_present = 1;
8105 p->hash_offset = atoi(arg_value);
8111 if (strcmp(arg_name, "pkt_type") == 0) {
8112 if (strcmp(arg_value, "ipv4") == 0) {
8113 p->traffic_type = TRAFFIC_TYPE_IPV4;
8114 printf("Traffic is set to IPv4\n");
8115 } else if (strcmp(arg_value, "ipv6") == 0) {
8116 p->traffic_type = TRAFFIC_TYPE_IPV6;
8117 printf("Traffic is set to IPv6\n");
8123 if (strcmp(arg_name, "cgnapt_debug") == 0) {
8124 CGNAPT_DEBUG = atoi(arg_value);
8129 /* any other Unknown argument return -1 */
8132 #ifdef NAT_ONLY_CONFIG_REQ
8133 if (nat_only_config_flag) {
8134 if (!public_ip_range_count) {
8135 printf("No public_ip_range %d for NAT only config.\n",
8136 public_ip_range_count);
8137 printf("Running static NAT only configuration\n");
8138 p->is_static_cgnapt = 1;
8143 if (!p->max_port_per_client)
8144 p->is_static_cgnapt = 1;
8147 /* Check that mandatory arguments are present */
8148 if ((n_flows_present == 0) ||
8149 (cgnapt_meta_offset_present == 0))
8156 * Function to initialize the pipeline
8159 * A pointer to struct pipeline_params
8161 * Void pointer - points to app params
8164 * void pointer to the pipeline, NULL 0 if failure
8166 static void *pipeline_cgnapt_init(struct pipeline_params *params, void *arg)
8167 /* (struct app_params *app) save it for use in port in handler */
8170 struct pipeline_cgnapt *p_nat;
8171 uint32_t size, i, in_ports_arg_size;
8173 /* Check input arguments */
8174 if ((params == NULL) ||
8175 (params->n_ports_in == 0) || (params->n_ports_out == 0))
8178 /* Memory allocation */
8179 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_cgnapt));
8180 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8181 p_nat = (struct pipeline_cgnapt *)p;
8182 global_pnat = p_nat;
8186 all_pipeline_cgnapt[n_cgnapt_pipeline++] = p_nat;
8188 strcpy(p->name, params->name);
8189 p->log_level = params->log_level;
8191 PLOG(p, HIGH, "CG-NAPT");
8192 /* Initialize all counters and arrays */
8194 p_nat->n_cgnapt_entry_deleted = 0;
8195 p_nat->n_cgnapt_entry_added = 0;
8196 p_nat->naptedPktCount = 0;
8197 p_nat->naptDroppedPktCount = 0;
8198 p_nat->inaptedPktCount = 0;
8199 p_nat->enaptedPktCount = 0;
8200 p_nat->receivedPktCount = 0;
8201 p_nat->missedPktCount = 0;
8202 p_nat->dynCgnaptCount = 0;
8203 p_nat->arpicmpPktCount = 0;
8205 p_nat->app_params_addr = (uint64_t) arg;
8206 for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
8207 p_nat->links_map[i] = 0xff;
8208 p_nat->outport_id[i] = 0xff;
8209 cgnapt_in_port_egress_prv[i] = 0;
8210 cgnapt_prv_que_port_index[i] = 0;
8212 p_nat->pipeline_num = 0xff;
8213 p_nat->hw_checksum_reqd = 0;
8214 p_nat->pub_ip_port_set = NULL;
8215 p_nat->pub_ip_count = 0;
8216 p_nat->traffic_type = TRAFFIC_TYPE_MIX;
8217 p_nat->vnf_set = 0xff;
8219 /* For every init it should be reset */
8220 napt_port_alloc_elem_count = 0;
8222 #ifdef CGNAPT_TIMING_INST
8223 p_nat->in_port_exit_timestamp = 0;
8224 p_nat->external_time_sum = 0;
8225 p_nat->internal_time_sum = 0;
8226 p_nat->time_measurements = 0;
8227 p_nat->max_time_mesurements = 10000;
8228 p_nat->time_measurements_on = 0;
8231 #ifdef CGNAPT_DEBUGGING
8233 p_nat->naptDebugCount = 0;
8235 p_nat->naptDroppedPktCount1 = 0;
8236 p_nat->naptDroppedPktCount2 = 0;
8237 p_nat->naptDroppedPktCount3 = 0;
8238 p_nat->naptDroppedPktCount4 = 0;
8239 p_nat->naptDroppedPktCount5 = 0;
8240 p_nat->naptDroppedPktCount6 = 0;
8242 p_nat->missedpktcount1 = 0;
8243 p_nat->missedpktcount2 = 0;
8244 p_nat->missedpktcount3 = 0;
8245 p_nat->missedpktcount4 = 0;
8246 p_nat->missedpktcount5 = 0;
8247 p_nat->missedpktcount6 = 0;
8248 p_nat->missedpktcount7 = 0;
8249 p_nat->missedpktcount8 = 0;
8250 p_nat->missedpktcount9 = 0;
8251 p_nat->missedpktcount10 = 0;
8252 p_nat->missedpktcount11 = 0;
8253 p_nat->missedpktcount12 = 0;
8255 p_nat->max_port_dec_err1 = 0;
8256 p_nat->max_port_dec_err2 = 0;
8257 p_nat->max_port_dec_err3 = 0;
8258 p_nat->max_port_dec_success = 0;
8274 static int sip_enabled;
8278 #endif /* SIP_ALG */
8280 /*struct rte_pipeline_table_entry *entries[RTE_HASH_LOOKUP_BULK_MAX];*/
8281 /* bitmap of valid packets */
8282 p_nat->valid_packets = 0;
8283 /* bitmap of invalid packets to be dropped */
8284 p_nat->invalid_packets = 0;
8286 for (i = 0; i < RTE_HASH_LOOKUP_BULK_MAX; i++)
8287 p_nat->key_ptrs[i] = &(p_nat->keys[i]);
8289 p_nat->port_alloc_ring = NULL;
8291 /* Parse arguments */
8292 if (pipeline_cgnapt_parse_args(p_nat, params))
8295 p_nat->vnf_set = vnf_set_count;
8299 struct rte_pipeline_params pipeline_params = {
8300 .name = params->name,
8301 .socket_id = params->socket_id,
8302 .offset_port_id = cgnapt_meta_offset,
8305 p->p = rte_pipeline_create(&pipeline_params);
8313 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8315 uint32_t instr_size =
8316 RTE_CACHE_LINE_ROUNDUP((sizeof(uint64_t)) *
8319 (uint64_t *) rte_zmalloc(NULL, instr_size,
8320 RTE_CACHE_LINE_SIZE);
8322 (uint64_t *) rte_zmalloc(NULL, instr_size,
8323 RTE_CACHE_LINE_SIZE);
8325 (uint32_t *) rte_zmalloc(NULL, instr_size / 2,
8326 RTE_CACHE_LINE_SIZE);
8327 if ((inst_start_time == NULL) || (inst_end_time == NULL)
8328 || (inst_diff_time == NULL)) {
8329 printf("Inst array alloc failed .... ");
8334 /* Memory allocation for in_port_h_arg */
8335 in_ports_arg_size = RTE_CACHE_LINE_ROUNDUP(
8336 (sizeof(struct pipeline_cgnapt_in_port_h_arg)) *
8337 (params->n_ports_in));
8338 struct pipeline_cgnapt_in_port_h_arg *ap =
8339 (struct pipeline_cgnapt_in_port_h_arg *)
8342 RTE_CACHE_LINE_SIZE);
8346 myApp = (struct app_params *) arg;
8349 p->n_ports_in = params->n_ports_in;
8350 for (i = 0; i < p->n_ports_in; i++) {
8351 /* passing our cgnapt pipeline in call back arg */
8353 (ap[i]).in_port_id = i;
8355 struct rte_pipeline_port_in_params port_params = {
8357 pipeline_port_in_params_get_ops(¶ms->port_in
8360 pipeline_port_in_params_convert(¶ms->port_in
8362 .f_action = cgnapt_in_port_ah_mix,
8364 .burst_size = params->port_in[i].burst_size,
8367 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8369 instrumentation_port_in_arg = &(ap[i]);
8372 if (p_nat->traffic_type == TRAFFIC_TYPE_IPV4) {
8373 /* Private in-port handler */
8374 /* Multiport changes */
8375 if (cgnapt_in_port_egress_prv[i]) {
8376 port_params.f_action =
8377 cgnapt_in_port_ah_ipv4_prv;
8378 printf("CGNAPT port %d is IPv4 Prv\n", i);
8380 port_params.f_action =
8381 cgnapt_in_port_ah_ipv4_pub;
8382 printf("CGNAPT port %d is IPv4 Pub\n", i);
8386 if (p_nat->traffic_type == TRAFFIC_TYPE_IPV6) {
8387 if (cgnapt_in_port_egress_prv[i]) {
8388 port_params.f_action =
8389 cgnapt_in_port_ah_ipv6_prv;
8390 printf("CGNAPT port %d is IPv6 Prv\n", i);
8392 port_params.f_action =
8393 cgnapt_in_port_ah_ipv6_pub;
8394 printf("CGNAPT port %d is IPv6 Pub\n", i);
8398 int status = rte_pipeline_port_in_create(p->p,
8403 rte_pipeline_free(p->p);
8411 p->n_ports_out = params->n_ports_out;
8412 for (i = 0; i < p->n_ports_out; i++) {
8413 struct rte_pipeline_port_out_params port_params = {
8414 .ops = pipeline_port_out_params_get_ops(
8415 ¶ms->port_out[i]),
8416 .arg_create = pipeline_port_out_params_convert(
8417 ¶ms->port_out[i]),
8418 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8419 .f_action = port_out_ah_cgnapt,
8426 int status = rte_pipeline_port_out_create(p->p,
8428 &p->port_out_id[i]);
8431 rte_pipeline_free(p->p);
8437 int pipeline_num = 0;
8439 ignore = sscanf(params->name, "PIPELINE%d", &pipeline_num);
8441 printf("Not able to read pipeline number\n");
8444 p_nat->pipeline_num = (uint8_t) pipeline_num;
8445 register_pipeline_Qs(p_nat->pipeline_num, p);
8446 set_link_map(p_nat->pipeline_num, p, p_nat->links_map);
8447 set_outport_id(p_nat->pipeline_num, p, p_nat->outport_id);
8453 if (napt_common_table == NULL) {
8454 if (create_napt_common_table(p_nat->n_flows)) {
8456 "CG-NAPT create_napt_common_table failed.");
8461 struct rte_pipeline_table_params table_params = {
8462 .ops = &rte_table_stub_ops,
8464 .f_action_hit = NULL,
8465 .f_action_miss = NULL,
8467 .action_data_size = 0,
8470 int status = rte_pipeline_table_create(p->p,
8475 rte_pipeline_free(p->p);
8479 struct rte_pipeline_table_entry default_entry = {
8480 .action = RTE_PIPELINE_ACTION_PORT_META
8482 struct rte_pipeline_table_entry *default_entry_ptr;
8483 status = rte_pipeline_table_default_entry_add(
8487 &default_entry_ptr);
8489 rte_pipeline_free(p->p);
8495 /* Connecting input ports to tables */
8496 for (i = 0; i < p->n_ports_in; i++) {
8497 int status = rte_pipeline_port_in_connect_to_table(p->p,
8504 rte_pipeline_free(p->p);
8510 /* Enable input ports */
8511 for (i = 0; i < p->n_ports_in; i++) {
8512 int status = rte_pipeline_port_in_enable(p->p,
8516 rte_pipeline_free(p->p);
8522 /* Check pipeline consistency */
8523 if (rte_pipeline_check(p->p) < 0) {
8524 rte_pipeline_free(p->p);
8529 /* Message queues */
8530 p->n_msgq = params->n_msgq;
8531 for (i = 0; i < p->n_msgq; i++)
8532 p->msgq_in[i] = params->msgq_in[i];
8533 for (i = 0; i < p->n_msgq; i++)
8534 p->msgq_out[i] = params->msgq_out[i];
8536 /* Message handlers */
8537 memcpy(p->handlers, handlers, sizeof(p->handlers));
8538 memcpy(p_nat->custom_handlers,
8539 custom_handlers, sizeof(p_nat->custom_handlers));
8541 if (!p_nat->is_static_cgnapt) {
8542 printf("Initializing dyn napt components ... %d\n",
8543 p_nat->pipeline_num);
8544 if (napt_port_alloc_init(p_nat) == -1) {
8545 printf("Error - napt_port_alloc_init failed - %d\n",
8546 p_nat->pipeline_num);
8551 if (max_port_per_client_hash == NULL) {
8552 rc = init_max_port_per_client(p_nat);
8554 printf("CGNAPT Error - "
8555 "init_max_port_per_client failed %d", rc);
8562 if (!icmp_pool_init) {
8564 /* create the arp_icmp mbuf rx pool */
8565 cgnapt_icmp_pktmbuf_tx_pool =
8566 rte_pktmbuf_pool_create("icmp_mbuf_tx_pool", 63, 32, 0,
8567 RTE_MBUF_DEFAULT_BUF_SIZE,
8569 if (cgnapt_icmp_pktmbuf_tx_pool == NULL) {
8570 PLOG(p, HIGH, "ICMP mbuf pool create failed.");
8575 rte_pktmbuf_alloc(cgnapt_icmp_pktmbuf_tx_pool);
8577 if (cgnapt_icmp_pkt == NULL) {
8578 printf("Failed to allocate cgnapt_icmp_pkt\n");
8585 cgnat_cnxn_tracker = rte_zmalloc(NULL, rte_ct_get_cnxn_tracker_size(),
8586 RTE_CACHE_LINE_SIZE);
8588 if (cgnat_cnxn_tracker == NULL) {
8589 printf("CGNAPT CT memory not allocated\n");
8592 rte_ct_initialize_default_timeouts(cgnat_cnxn_tracker);
8594 printf("CGNAPT CT Flows %d\n", p_nat->n_flows);
8596 ret = rte_ct_initialize_cnxn_tracker(cgnat_cnxn_tracker,
8598 "CGNAT_CT_COMMON_TABLE");
8608 if (pcp_init() == PCP_INIT_SUCCESS)
8609 printf("PCP contents are initialized successfully\n");
8611 printf("Error in initializing PCP contents\n");
8618 * Function for pipeline cleanup
8621 * A void pointer to pipeline
8626 static int pipeline_cgnapt_free(void *pipeline)
8628 struct pipeline *p = (struct pipeline *)pipeline;
8630 /* Check input arguments */
8634 /* Free resources */
8635 rte_pipeline_free(p->p);
8641 pipeline_cgnapt_track(void *pipeline, __rte_unused uint32_t port_in,
8644 struct pipeline *p = (struct pipeline *)pipeline;
8646 /* Check input arguments */
8647 if ((p == NULL) || (port_in >= p->n_ports_in) || (port_out == NULL))
8650 if (p->n_ports_in == 1) {
8659 * Function for pipeline timers
8662 * A void pointer to pipeline
8667 static int pipeline_cgnapt_timer(void *pipeline)
8669 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)pipeline;
8671 pipeline_msg_req_handle(&p_nat->p);
8673 rte_pipeline_flush(((struct pipeline *)p_nat)->p);
8679 * Function for pipeline custom handlers
8682 * A void pointer to pipeline
8684 * void pointer for incoming data
8687 * void pointer of response
8689 void *pipeline_cgnapt_msg_req_custom_handler(struct pipeline *p, void *msg)
8691 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
8692 struct pipeline_custom_msg_req *req = msg;
8693 pipeline_msg_req_handler f_handle;
8695 f_handle = (req->subtype < PIPELINE_CGNAPT_MSG_REQS) ?
8696 p_nat->custom_handlers[req->subtype] :
8697 pipeline_msg_req_invalid_handler;
8699 if (f_handle == NULL)
8700 f_handle = pipeline_msg_req_invalid_handler;
8702 return f_handle(p, req);
8706 * Function for adding NSP data
8709 * A void pointer to pipeline
8711 * void pointer for incoming data
8714 * void pointer of response
8716 void *pipeline_cgnapt_msg_req_nsp_add_handler(
8717 __rte_unused struct pipeline *p,
8720 struct pipeline_cgnapt_nsp_add_msg_req *req = msg;
8721 struct pipeline_cgnapt_nsp_add_msg_rsp *rsp = msg;
8723 struct cgnapt_nsp_node *node = NULL, *ll = nsp_ll;
8726 (req->nsp.depth == 32 || req->nsp.depth == 40
8727 || req->nsp.depth == 48 || req->nsp.depth == 56
8728 || req->nsp.depth == 64 || req->nsp.depth == 96)) {
8734 printf("be initial cond\n");
8735 if (nsp_ll == NULL) {
8736 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_nsp_node));
8737 node = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8739 printf("be 1st cond\n");
8745 memcpy(&node->nsp, &req->nsp,
8746 sizeof(struct pipeline_cgnapt_nsp_t));
8750 while (ll != NULL) {
8751 if (!memcmp(ll->nsp.prefix, req->nsp.prefix, 16)
8752 && ll->nsp.depth == req->nsp.depth) {
8753 printf("be 2st cond\n");
8761 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_nsp_node));
8762 node = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8764 printf("be 3st cond\n");
8770 memcpy(&node->nsp, &req->nsp,
8771 sizeof(struct pipeline_cgnapt_nsp_t));
8772 node->next = nsp_ll;
8779 printf("be 4st cond\n");
8784 * Function for deleting NSP data
8787 * A void pointer to pipeline
8789 * void pointer for incoming data
8792 * void pointer of response
8794 void *pipeline_cgnapt_msg_req_nsp_del_handler(
8795 __rte_unused struct pipeline *p,
8798 struct pipeline_cgnapt_nsp_del_msg_req *req = msg;
8799 struct pipeline_cgnapt_nsp_del_msg_rsp *rsp = msg;
8800 struct cgnapt_nsp_node *prev = NULL, *ll = nsp_ll;
8802 while (ll != NULL) {
8803 if (!memcmp(ll->nsp.prefix, req->nsp.prefix, 16)
8804 && ll->nsp.depth == req->nsp.depth) {
8806 prev->next = ll->next;
8829 * Function for adding NAPT entry
8832 * A void pointer to pipeline
8834 * void pointer for incoming data
8837 * void pointer of response
8839 void *pipeline_cgnapt_msg_req_entry_add_handler(struct pipeline *p, void *msg)
8841 struct pipeline_cgnapt_entry_add_msg_req *req = msg;
8842 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
8843 uint8_t type = req->data.type;
8844 uint32_t src_ip = (type == CGNAPT_ENTRY_IPV4) ?
8845 req->data.u.prv_ip :
8846 rte_bswap32(req->data.u.u32_prv_ipv6[3]);
8848 uint8_t src_ipv6[16];
8850 uint32_t dest_ip = req->data.pub_ip;
8851 uint16_t src_port = req->data.prv_port;
8852 uint16_t dest_port = req->data.pub_port;
8853 uint16_t rx_port = req->data.prv_phy_port;
8854 uint32_t ttl = req->data.ttl;
8856 if (type == CGNAPT_ENTRY_IPV6)
8857 memcpy(src_ipv6, req->data.u.prv_ipv6, 16);
8859 printf("CG-NAPT addm - PrvIP %x, PrvPort %d,", src_ip, src_port);
8860 printf("PubIP %x, PubPort %d,", dest_ip, dest_port);
8862 printf("PhyPort %d, ttl %u,", rx_port, ttl);
8863 printf("entry_type %d\n", type);
8865 #ifdef NAT_ONLY_CONFIG_REQ
8866 if (nat_only_config_flag) {
8867 if (!p_nat->is_static_cgnapt) {
8870 for (i = 0; i < p_nat->pub_ip_range_count; i++) {
8871 if (((dest_ip >= p_nat->pub_ip_range[i].start_ip)
8872 && (dest_ip <= p_nat->pub_ip_range[i].end_ip))) {
8873 printf("Error - static port cannot be in Dynamic "
8875 printf("%x-%x\n", p_nat->pub_ip_range[i].start_ip,
8876 p_nat->pub_ip_range[i].end_ip);
8882 if (pipeline_cgnapt_msg_req_entry_addm_pair(p, msg,
8888 printf("pipeline_cgnapt_msg_req_entry_addm_handler\n");
8892 printf("Success - pipeline_cgnapt_msg_req_entry_addm_handler");
8893 printf("added %d rule pairs.\n", count);
8899 if (!p_nat->is_static_cgnapt) {
8902 for (i = 0; i < p_nat->pub_ip_count; i++) {
8903 /* Check port range if same Public-IP */
8904 if (dest_ip != p_nat->pub_ip_port_set[i].ip)
8906 if (((dest_port >= p_nat->pub_ip_port_set[i].start_port) &&
8907 (dest_port <= p_nat->pub_ip_port_set[i].end_port))) {
8908 printf("Error - port cannot be in Dynamic "
8909 "port range %d-%d\n",
8910 p_nat->pub_ip_port_set[i].start_port,
8911 p_nat->pub_ip_port_set[i].end_port);
8917 if (pipeline_cgnapt_msg_req_entry_addm_pair
8918 (p, msg, src_ip, src_port, dest_ip, dest_port, rx_port,
8919 ttl, type, src_ipv6)) {
8920 printf("Error - pipeline_cgnapt_msg_req_entry_add_handler\n");
8925 printf("\nSuccess - pipeline_cgnapt_msg_req_entry_add_handler "
8932 * Function for adding a NAPT entry pair
8935 * A void pointer to pipeline
8937 * void pointer for incoming data
8943 * destination ip address
8947 * Physical receive port
8949 * time to live value
8951 * type of entry IPv4 vs IPv6
8953 * uint8_t array of IPv6 address
8956 * 0 if success, negative if fails
8959 pipeline_cgnapt_msg_req_entry_addm_pair(
8960 struct pipeline *p, __rte_unused void *msg,
8961 uint32_t src_ip, uint16_t src_port,
8962 uint32_t dest_ip, uint16_t dest_port,
8963 uint16_t rx_port, uint32_t ttl,
8964 uint8_t type, uint8_t src_ipv6[16])
8967 struct pipeline_cgnapt_entry_key key;
8968 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
8971 key.port = src_port;
8974 struct cgnapt_table_entry entry = {
8976 .action = RTE_PIPELINE_ACTION_PORT,
8977 .port_id = CGNAPT_PUB_PORT_ID,
8981 /*.prv_ip = src_ip, */
8982 .prv_port = src_port,
8984 .pub_port = dest_port,
8985 .prv_phy_port = rx_port,
8986 .pub_phy_port = get_prv_to_pub_port(&dest_ip,
8989 .timeout = STATIC_CGNAPT_TIMEOUT,
8996 if (type == CGNAPT_ENTRY_IPV4) {
8997 entry.data.type = CGNAPT_ENTRY_IPV4;
8998 entry.data.u.prv_ip = src_ip;
9000 entry.data.type = CGNAPT_ENTRY_IPV6;
9001 memcpy(entry.data.u.prv_ipv6, src_ipv6, 16);
9004 /* Also need to add a paired entry on our own */
9006 * Need to change key
9007 * Need to change entry header
9008 * Will keep the same entry and take care
9009 * of translation in table hit handler
9011 struct pipeline_cgnapt_entry_key second_key;
9013 /* Need to add a second ingress entry */
9014 second_key.ip = dest_ip;
9015 second_key.port = dest_port;
9016 second_key.pid = 0xffff;
9018 #ifdef NAT_ONLY_CONFIG_REQ
9019 if (nat_only_config_flag) {
9021 entry.data.pub_port = 0xffff;
9022 second_key.port = 0xffff;
9026 int32_t position = rte_hash_add_key(napt_common_table, &key);
9029 printf("CG-NAPT entry bulk add failed");
9030 printf(" ... returning without adding ...\n");
9034 memcpy(&napt_hash_tbl_entries[position], &entry,
9035 sizeof(struct cgnapt_table_entry));
9037 #ifdef CGNAPT_DEBUGGING
9038 if (p_nat->kpc1++ < 5)
9042 p_nat->n_cgnapt_entry_added++;
9044 /* Now modify the forward port for reverse entry */
9045 entry.head.port_id = CGNAPT_PRV_PORT_ID;
9047 position = rte_hash_add_key(napt_common_table, &second_key);
9050 printf("CG-NAPT entry reverse bulk add failed");
9051 printf(" ... returning with fwd add ...%d\n", position);
9055 memcpy(&napt_hash_tbl_entries[position], &entry,
9056 sizeof(struct cgnapt_table_entry));
9058 #ifdef CGNAPT_DEBUGGING
9059 if (p_nat->kpc1 < 5)
9060 print_key(&second_key);
9063 p_nat->n_cgnapt_entry_added++;
9068 * Function for adding multiple NAPT entries
9071 * A void pointer to pipeline
9073 * void pointer for incoming data
9076 * void pointer of response
9078 void *pipeline_cgnapt_msg_req_entry_addm_handler(struct pipeline *p, void *msg)
9080 struct pipeline_cgnapt_entry_addm_msg_req *req = msg;
9081 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9083 uint32_t max_ue = req->data.num_ue;
9084 uint8_t type = req->data.type;
9085 uint32_t src_ip = (type == CGNAPT_ENTRY_IPV4) ?
9086 req->data.u.prv_ip :
9087 rte_bswap32(req->data.u.u32_prv_ipv6[3]);
9089 uint8_t src_ipv6[16];
9091 uint32_t dest_ip = req->data.pub_ip;
9092 uint16_t src_port = req->data.prv_port;
9093 uint16_t dest_port = req->data.pub_port;
9094 uint16_t rx_port = req->data.prv_phy_port;
9095 uint32_t ttl = req->data.ttl;
9096 uint16_t max_src_port = req->data.prv_port_max;
9097 uint16_t max_dest_port = req->data.pub_port_max;
9099 uint16_t src_port_start = src_port;
9100 uint16_t dest_port_start = dest_port;
9101 uint32_t src_ip_temp;
9103 if (type == CGNAPT_ENTRY_IPV6)
9104 memcpy(src_ipv6, req->data.u.prv_ipv6, 16);
9106 printf("CG-NAPT addm - PrvIP %x, PrvPort %d,", src_ip, src_port);
9107 printf("PubIP %x, PubPort %d,", dest_ip, dest_port);
9108 printf("PhyPort %d, ttl %u, NumUe %d,", rx_port, ttl, max_ue);
9109 printf("mPrvPort %d, mPubPort %d,", max_src_port, max_dest_port);
9110 printf("entry_type %d\n", type);
9112 #ifdef NAT_ONLY_CONFIG_REQ
9113 if (nat_only_config_flag) {
9114 if (!p_nat->is_static_cgnapt) {
9117 for (i = 0; i < p_nat->pub_ip_range_count; i++) {
9118 if (((dest_ip >= p_nat->pub_ip_range[i].start_ip)
9119 && (dest_ip <= p_nat->pub_ip_range[i].end_ip)) ||
9120 (((dest_ip + max_ue) >=
9121 p_nat->pub_ip_range[i].start_ip) &&
9122 ((dest_ip + max_ue) <=
9123 p_nat->pub_ip_range[i].end_ip))) {
9124 printf("Error - static port cannot be in Dynamic "
9126 printf("%x-%x\n", p_nat->pub_ip_range[i].start_ip,
9127 p_nat->pub_ip_range[i].end_ip);
9134 for (uenum = 0; uenum < max_ue; uenum++) {
9136 if (pipeline_cgnapt_msg_req_entry_addm_pair(p, msg,
9142 printf("pipeline_cgnapt_msg_req_entry_addm_handler\n");
9152 printf("Success - pipeline_cgnapt_msg_req_entry_addm_handler");
9153 printf("added %d rule pairs.\n", count);
9159 if (!p_nat->is_static_cgnapt) {
9162 for (i = 0; i < p_nat->pub_ip_count; i++) {
9163 /* Check port range if same Public-IP */
9164 if (dest_ip != p_nat->pub_ip_port_set[i].ip)
9166 if (((dest_port >= p_nat->pub_ip_port_set[i].start_port) &&
9167 (dest_port <= p_nat->pub_ip_port_set[i].end_port)) ||
9168 ((max_dest_port >= p_nat->pub_ip_port_set[i].start_port)
9169 && max_dest_port <= p_nat->pub_ip_port_set[i].end_port)) {
9170 printf("Error - port cannot be in Dynamic port range %d-%d\n",
9171 p_nat->pub_ip_port_set[i].start_port,
9172 p_nat->pub_ip_port_set[i].end_port);
9178 for (uenum = 0; uenum < max_ue; uenum++) {
9179 if (pipeline_cgnapt_msg_req_entry_addm_pair
9180 (p, msg, src_ip, src_port, dest_ip, dest_port, rx_port,
9181 ttl, type, src_ipv6)) {
9182 printf("Error - pipeline_cgnapt_msg_req_entry_addm_handler\n");
9189 if (src_port > max_src_port) {
9190 src_port = src_port_start;
9192 if (req->data.type == CGNAPT_ENTRY_IPV6) {
9193 src_ip_temp = rte_bswap32(src_ip);
9194 memcpy(&src_ipv6[12], &src_ip_temp, 4);
9198 if (dest_port > max_dest_port) {
9199 dest_port = dest_port_start;
9204 printf("\nSuccess - pipeline_cgnapt_msg_req_entry_addm_handler added");
9205 printf("%d rule pairs.\n", count);
9211 * Function for deleting NAPT entry
9214 * A void pointer to pipeline
9216 * void pointer for incoming data
9219 * void pointer of response
9221 void *pipeline_cgnapt_msg_req_entry_del_handler(struct pipeline *p, void *msg)
9223 struct pipeline_cgnapt_entry_delete_msg_req *req = msg;
9224 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9225 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9228 uint8_t *KeyP = (void *)(&req->key);
9231 printf("pipeline_cgnapt_msg_req_entry_del_handler - Key: ");
9232 for (i = 0; i < (int)sizeof(struct pipeline_cgnapt_entry_key);
9234 printf(" %02x", KeyP[i]);
9235 printf(" ,KeySize %u\n",
9236 (int)sizeof(struct pipeline_cgnapt_entry_key));
9239 struct cgnapt_table_entry entry;
9241 /* If ingress key */
9242 if (!is_phy_port_privte(req->key.pid))
9243 req->key.pid = 0xffff;
9245 #ifdef NAT_ONLY_CONFIG_REQ
9246 if (nat_only_config_flag)
9247 req->key.port = 0xffff;
9251 position = rte_hash_lookup(napt_common_table, &req->key);
9252 if (position == -ENOENT) {
9253 printf("Entry not found\n");
9256 memcpy(&entry, &napt_hash_tbl_entries[position],
9257 sizeof(struct cgnapt_table_entry));
9258 position = rte_hash_del_key(napt_common_table, &req->key);
9259 p_nat->n_cgnapt_entry_deleted++;
9261 struct pipeline_cgnapt_entry_key second_key;
9263 if (is_phy_port_privte(req->key.pid)) {
9264 /* key is for egress - make second key for ingress */
9265 second_key.ip = entry.data.pub_ip;
9266 second_key.port = entry.data.pub_port;
9267 second_key.pid = 0xffff;
9270 /* key is for ingress - make second key for egress */
9271 second_key.ip = entry.data.u.prv_ip;
9272 second_key.port = entry.data.prv_port;
9273 second_key.pid = entry.data.prv_phy_port;
9276 #ifdef NAT_ONLY_CONFIG_REQ
9277 if (nat_only_config_flag)
9278 second_key.port = 0xffff;
9281 position = rte_hash_del_key(napt_common_table, &second_key);
9282 p_nat->n_cgnapt_entry_deleted++;
9287 void *pipeline_cgnapt_msg_req_entry_sync_handler(struct pipeline *p, void *msg)
9289 struct pipeline_cgnapt_entry_delete_msg_req *req = msg;
9290 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9292 rsp->status = rte_pipeline_table_entry_delete(
9296 &rsp->key_found, NULL);
9302 * Function to print the NAPT key
9305 * A pointer to struct pipeline_cgnapt_entry_key
9307 void print_key(struct pipeline_cgnapt_entry_key *key)
9309 uint8_t *KeyP = (void *)(key);
9313 for (i = 0; i < (int)sizeof(struct pipeline_cgnapt_entry_key); i++)
9314 printf(" %02x", KeyP[i]);
9318 * Function to print the table entry
9321 * A pointer to struct rte_pipeline_table_entry
9323 void print_entry1(struct rte_pipeline_table_entry *entry)
9325 uint8_t *entryP = (void *)(entry);
9329 for (i = 0; i < (int)sizeof(struct rte_pipeline_table_entry); i++)
9330 printf(" %02x", entryP[i]);
9334 * Function to print the NAPT table entry
9337 * A pointer to struct cgnapt_table_entry
9339 void print_cgnapt_entry(struct cgnapt_table_entry *entry)
9341 uint8_t *entryP = (void *)(entry);
9344 printf("CGNAPT Entry: ");
9345 for (i = 0; i < (int)sizeof(struct cgnapt_table_entry); i++)
9346 printf(" %02x", entryP[i]);
9347 printf(" size:%d\n", (int)sizeof(struct cgnapt_table_entry));
9351 * Function to get a free port
9354 * A pointer to struct pipeline_cgnapt
9356 * A uint32_t pointer to return corresponding ip address
9359 * free port number, 0 if error
9361 int get_free_iport(struct pipeline_cgnapt *p_nat, uint32_t *public_ip)
9364 /* If we don't have a valid napt_port_alloc_elem get one from
9367 if (p_nat->allocated_ports == NULL) {
9371 ret = rte_ring_dequeue(p_nat->port_alloc_ring, &ports);
9373 p_nat->allocated_ports =
9374 (struct napt_port_alloc_elem *)ports;
9376 #ifdef CGNAPT_DEBUGGING
9380 #ifdef CGNAPT_DBG_PRNT
9381 if (CGNAPT_DEBUG > 3)
9382 printf("p_nat->allocated_ports %p\n",
9383 p_nat->allocated_ports);
9386 printf("CGNAPT Err - get_free_iport rte_ring_dequeue "
9388 printf("%d, %d, %d\n", rte_ring_count(
9389 p_nat->port_alloc_ring), rte_ring_free_count(
9390 p_nat->port_alloc_ring), ret);
9392 #ifdef CGNAPT_DEBUGGING
9393 #ifdef CGNAPT_DBG_PRNT
9394 printf("Th%d GFP:: %" PRIu64 ", %" PRIu64 ", "
9395 "%" PRIu64", %" PRIu64 ",\n", p_nat->pipeline_num,
9396 p_nat->gfp_get, p_nat->gfp_ret, p_nat->gfp_suc,
9406 /* get the port from index count-1 and decrease count */
9407 port = p_nat->allocated_ports->ports
9408 [p_nat->allocated_ports->count - 1];
9409 *public_ip = p_nat->allocated_ports->ip_addr
9410 [p_nat->allocated_ports->count - 1];
9412 p_nat->allocated_ports->count -= 1;
9414 /* if count is zero, return buffer to mem pool */
9415 if (p_nat->allocated_ports->count == 0) {
9416 rte_mempool_put(napt_port_pool, p_nat->allocated_ports);
9418 #ifdef CGNAPT_DEBUGGING
9420 #ifdef CGNAPT_DBG_PRNT
9421 printf("Th%d Returned to pool p_nat->allocated_ports %p,",
9422 p_nat->pipeline_num, p_nat->allocated_ports);
9423 printf("%" PRIu64 ", %" PRIu64 ",",
9424 p_nat->gfp_get, p_nat->gfp_ret);
9425 printf("%" PRIu64 ", %" PRIu64 ",\n",
9426 p_nat->gfp_suc, p_nat->gfp_err);
9430 p_nat->allocated_ports = NULL;
9433 #ifdef CGNAPT_DEBUGGING
9441 * Function to free a port
9444 * Port number to free
9446 * Corresponding ip address
9448 * A pointer to struct pipeline_cgnapt
9451 void release_iport(uint16_t port_num, uint32_t public_ip,
9452 struct pipeline_cgnapt *p_nat)
9454 /* If we don't have a valid napt_port_alloc_elem get one
9457 if (p_nat->free_ports == NULL) {
9460 #ifdef CGNAPT_DEBUGGING
9464 if (rte_mempool_get(napt_port_pool, &ports) < 0) {
9465 #ifdef CGNAPT_DEBUGGING
9468 printf("CGNAPT release_iport error in getting "
9469 "port alloc buffer\n");
9473 p_nat->free_ports = (struct napt_port_alloc_elem *)ports;
9474 p_nat->free_ports->count = 0;
9477 /* put the port at index count and increase count */
9478 p_nat->free_ports->ip_addr[p_nat->free_ports->count] = public_ip;
9479 p_nat->free_ports->ports[p_nat->free_ports->count] = port_num;
9480 p_nat->free_ports->count += 1;
9482 /* if napt_port_alloc_elem is full add it to ring */
9485 #ifdef CGNAPT_DEBUGGING
9489 #ifdef CGNAPT_DBG_PRNT
9490 if (CGNAPT_DEBUG >= 2) {
9491 printf("CGNAPT port_alloc_ring before EnQ Cnt %d, Free %d\n",
9492 rte_ring_count(p_nat->port_alloc_ring),
9493 rte_ring_free_count(p_nat->port_alloc_ring));
9497 if (rte_ring_enqueue(p_nat->port_alloc_ring,
9498 (void *)p_nat->free_ports) != 0) {
9499 printf("CGNAPT release_iport Enqueue error %p\n",
9502 #ifdef CGNAPT_DEBUGGING
9507 #ifdef CGNAPT_DBG_PRNT
9508 if (CGNAPT_DEBUG >= 2) {
9509 printf("CGNAPT port_alloc_ring after EnQ Cnt %d",
9510 rte_ring_count(p_nat->port_alloc_ring));
9512 rte_ring_free_count(p_nat->port_alloc_ring));
9516 p_nat->free_ports = NULL;
9519 #ifdef CGNAPT_DEBUGGING
9525 * Function to initialize max ports per client data structures
9526 * Called during dynamic NAPT initialization.
9529 * A pointer to struct pipeline_cgnapt
9532 * 0 if success, negative if error
9534 int init_max_port_per_client(
9535 __rte_unused struct pipeline_cgnapt *p_nat)
9537 if (max_port_per_client_hash)
9540 /*MPPC_ALREADY_EXISTS */
9544 max_port_per_client_hash =
9545 rte_hash_create(&max_port_per_client_hash_params);
9546 if (!max_port_per_client_hash)
9549 /*MPPC_HASH_CREATE_ERROR */
9551 max_port_per_client_array =
9553 sizeof(struct max_port_per_client) * MAX_DYN_ENTRY,
9554 RTE_CACHE_LINE_SIZE);
9555 if (!max_port_per_client_array)
9558 /*MPPC_ARRAY_CREATE_ERROR */
9560 for (i = 0; i < MAX_DYN_ENTRY; i++) {
9561 max_port_per_client_array[i].prv_ip = 0;
9562 max_port_per_client_array[i].prv_phy_port = 0;
9563 max_port_per_client_array[i].max_port_cnt = 0;
9571 * Function to check if max ports for a client is reached
9573 * @param prv_ip_param
9574 * A uint32_t ip address of client
9575 * @param prv_phy_port_param
9576 * A uint32_t physical port id of the client
9578 * A pointer to struct pipeline_cgnapt
9581 * 0 if max port not reached, 1 if reached, -1 if error
9583 int is_max_port_per_client_reached(uint32_t prv_ip_param,
9584 uint32_t prv_phy_port_param,
9585 struct pipeline_cgnapt *p_nat)
9587 int index = MAX_PORT_INVALID_KEY;
9589 struct max_port_per_client_key key = {
9590 .prv_ip = prv_ip_param,
9591 .prv_phy_port = prv_phy_port_param,
9594 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9597 return MAX_PORT_INVALID_KEY;
9599 if (max_port_per_client_array[index].max_port_cnt >=
9600 p_nat->max_port_per_client)
9601 return MAX_PORT_REACHED;
9603 return MAX_PORT_NOT_REACHED;
9607 * Function to increase max ports for a client
9609 * @param prv_ip_param
9610 * A uint32_t ip address of client
9611 * @param prv_phy_port_param
9612 * A uint32_t physical port id of the client
9614 * A pointer to struct pipeline_cgnapt
9617 * 0 if max port reached, 1 if success, 2 if new entry, -1 if error
9619 int increment_max_port_counter(uint32_t prv_ip_param,
9620 uint32_t prv_phy_port_param,
9621 struct pipeline_cgnapt *p_nat)
9623 int index = MAX_PORT_INC_ERROR;
9625 struct max_port_per_client_key key = {
9626 .prv_ip = prv_ip_param,
9627 .prv_phy_port = prv_phy_port_param,
9630 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9632 if (index == -EINVAL)
9633 return MAX_PORT_INC_ERROR;
9635 if (index == -ENOENT) {
9636 if (max_port_per_client_add_entry(prv_ip_param,
9639 return MAX_PORT_INC_ERROR;
9641 return 2; /*return MAX_PORT_NEW_ENTRY; */
9644 if (CGNAPT_DEBUG > 2)
9645 printf("%s: max_port_cnt(%d), p_nat_max(%d)\n", __func__,
9646 max_port_per_client_array[index].max_port_cnt,
9647 p_nat->max_port_per_client);
9649 if (max_port_per_client_array[index].max_port_cnt <
9650 p_nat->max_port_per_client) {
9651 max_port_per_client_array[index].max_port_cnt++;
9652 return MAX_PORT_INC_SUCCESS;
9655 return MAX_PORT_INC_REACHED;
9659 * Function to decrease max ports for a client
9661 * @param prv_ip_param
9662 * A uint32_t ip address of client
9663 * @param prv_phy_port_param
9664 * A uint32_t physical port id of the client
9666 * A pointer to struct pipeline_cgnapt
9669 * 0 if count already 0, 1 if success, -1 if error
9671 int decrement_max_port_counter(uint32_t prv_ip_param,
9672 uint32_t prv_phy_port_param,
9673 struct pipeline_cgnapt *p_nat)
9675 int index = MAX_PORT_DEC_ERROR;
9677 struct max_port_per_client_key key = {
9678 .prv_ip = prv_ip_param,
9679 .prv_phy_port = prv_phy_port_param,
9682 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9685 #ifdef CGNAPT_DEBUGGING
9686 p_nat->max_port_dec_err1++;
9688 return MAX_PORT_DEC_ERROR;
9692 if (max_port_per_client_array[index].max_port_cnt > 0) {
9693 /* If it is the last port,ret this info which is used for
9694 * max_cli_per_pub_ip
9697 max_port_per_client_array[index].max_port_cnt--;
9698 /* Count should be atomic but we are good as we have only
9699 * one task handling this counter at a time (core affinity)
9703 if (max_port_per_client_array[index].max_port_cnt <= 0) {
9704 if (max_port_per_client_del_entry
9705 (prv_ip_param, prv_phy_port_param, p_nat) <= 0) {
9707 #ifdef CGNAPT_DEBUGGING
9708 p_nat->max_port_dec_err2++;
9710 return MAX_PORT_DEC_ERROR;
9713 #ifdef CGNAPT_DEBUGGING
9714 p_nat->max_port_dec_err3++;
9717 return MAX_PORT_DEC_REACHED;
9720 #ifdef CGNAPT_DEBUGGING
9721 p_nat->max_port_dec_success++;
9724 return MAX_PORT_DEC_SUCCESS;
9728 * Function to add a max ports per client entry
9730 * @param prv_ip_param
9731 * A uint32_t ip address of client
9732 * @param prv_phy_port_param
9733 * A uint32_t physical port id of the client
9735 * A pointer to struct pipeline_cgnapt
9738 * 0 no success, 1 if success, -1 if error
9740 int max_port_per_client_add_entry(
9741 uint32_t prv_ip_param,
9742 uint32_t prv_phy_port_param,
9743 __rte_unused struct pipeline_cgnapt *p_nat)
9745 int index = MAX_PORT_ADD_ERROR;
9747 struct max_port_per_client_key key = {
9748 .prv_ip = prv_ip_param,
9749 .prv_phy_port = prv_phy_port_param,
9752 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9753 if (index == -EINVAL)
9754 return MAX_PORT_ADD_ERROR;
9757 return MAX_PORT_ADD_UNSUCCESS;
9759 if (index == -ENOENT) {
9761 #ifdef CGNAPT_DBG_PRNT
9762 if (CGNAPT_DEBUG > 2)
9763 printf("max_port_per_client_add_entry fn: "
9764 "Entry does not exist\n");
9768 rte_hash_add_key(max_port_per_client_hash,
9769 (const void *)&key);
9770 if (index == -ENOSPC)
9771 return MAX_PORT_ADD_UNSUCCESS;
9773 #ifdef CGNAPT_DBG_PRNT
9774 if (CGNAPT_DEBUG > 2)
9775 printf("max_port_per_client_add_entry fn:"
9776 "Add entry index(%d)\n", index);
9779 max_port_per_client_array[index].prv_ip = prv_ip_param;
9780 max_port_per_client_array[index].prv_phy_port =
9784 max_port_per_client_array[index].max_port_cnt++;
9785 return MAX_PORT_ADD_SUCCESS;
9789 * Function to delete a max ports per client entry
9791 * @param prv_ip_param
9792 * A uint32_t ip address of client
9793 * @param prv_phy_port_param
9794 * A uint32_t physical port id of the client
9796 * A pointer to struct pipeline_cgnapt
9799 * 0 no success, 1 if success, -1 if error
9801 int max_port_per_client_del_entry(
9802 uint32_t prv_ip_param,
9803 uint32_t prv_phy_port_param,
9804 __rte_unused struct pipeline_cgnapt *p_nat)
9806 int index = MAX_PORT_DEL_ERROR;
9808 struct max_port_per_client_key key = {
9809 .prv_ip = prv_ip_param,
9810 .prv_phy_port = prv_phy_port_param,
9813 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9815 if (index == -EINVAL)
9816 return MAX_PORT_DEL_ERROR;
9818 if (index == -ENOENT)
9819 return MAX_PORT_DEL_UNSUCCESS;
9821 index = rte_hash_del_key(max_port_per_client_hash, (const void *)&key);
9822 max_port_per_client_array[index].prv_ip = 0;
9823 max_port_per_client_array[index].prv_phy_port = 0;
9824 max_port_per_client_array[index].max_port_cnt = 0;
9826 return MAX_PORT_DEL_SUCCESS;
9830 * Function to execute debug commands
9833 * A pointer to struct pipeline
9835 * void pointer to incoming arguments
9837 void *pipeline_cgnapt_msg_req_entry_dbg_handler(struct pipeline *p, void *msg)
9839 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9841 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9845 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_STATS_SHOW) {
9846 printf("\nCG-NAPT Packet Stats:\n");
9847 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
9848 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
9849 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
9850 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
9851 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
9852 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
9853 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
9855 #ifdef CGNAPT_DEBUGGING
9856 printf("\n Drop detail 1:%" PRIu64 ",",
9857 p_nat->naptDroppedPktCount1);
9858 printf("\n Drop detail 2:%" PRIu64 ",",
9859 p_nat->naptDroppedPktCount2);
9860 printf("\n Drop detail 3:%" PRIu64 ",",
9861 p_nat->naptDroppedPktCount3);
9862 printf("\n Drop detail 4:%" PRIu64 ",",
9863 p_nat->naptDroppedPktCount4);
9864 printf("\n Drop detail 5:%" PRIu64 ",",
9865 p_nat->naptDroppedPktCount5);
9866 printf("\n Drop detail 6:%" PRIu64 "",
9867 p_nat->naptDroppedPktCount6);
9869 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9870 p_nat->missedpktcount1,
9871 p_nat->missedpktcount2);
9872 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9873 p_nat->missedpktcount3,
9874 p_nat->missedpktcount4);
9875 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9876 p_nat->missedpktcount5,
9877 p_nat->missedpktcount6);
9878 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9879 p_nat->missedpktcount7,
9880 p_nat->missedpktcount8);
9881 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9882 p_nat->missedpktcount9,
9883 p_nat->missedpktcount10);
9890 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_STATS_CLEAR) {
9891 printf("\nCG-NAPT Packet Stats:\n");
9892 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
9893 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
9894 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
9895 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
9896 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
9897 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
9898 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
9900 p_nat->naptedPktCount = 0;
9901 p_nat->naptDroppedPktCount = 0;
9902 p_nat->inaptedPktCount = 0;
9903 p_nat->enaptedPktCount = 0;
9904 p_nat->receivedPktCount = 0;
9905 p_nat->missedPktCount = 0;
9906 p_nat->arpicmpPktCount = 0;
9907 printf("CG-NAPT Packet Stats cleared\n");
9911 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DBG_LEVEL) {
9912 CGNAPT_DEBUG = Msg[CGNAPT_DBG_CMD_OFST + 1];
9913 printf("CG-NAPT debug level set to %d\n", CGNAPT_DEBUG);
9917 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DBG_SHOW) {
9919 printf("\nNAPT entries - added %" PRIu64 ",",
9920 p_nat->n_cgnapt_entry_added);
9921 printf("deleted %" PRIu64 ",", p_nat->n_cgnapt_entry_deleted);
9922 printf("current %" PRIu64 "", p_nat->n_cgnapt_entry_added -
9923 p_nat->n_cgnapt_entry_deleted);
9925 printf("\nCG-NAPT Packet Stats:\n");
9926 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
9927 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
9928 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
9929 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
9930 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
9931 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
9932 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
9936 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
9937 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_INSTRUMENTATION) {
9938 if (Msg[CGNAPT_DBG_CMD_OFST1] ==
9939 CGNAPT_CMD_INSTRUMENTATION_SUB0) {
9942 uint32_t diff_sum = 0;
9944 printf("CG-NAPT Instrumentation ...\n");
9945 printf("Instrumentation data collected for fn# %d\n",
9946 cgnapt_num_func_to_inst);
9947 printf("Current collection index %d\n",
9950 if (Msg[CGNAPT_DBG_CMD_OFST + 2] == 2) {
9951 printf("Timer Start:\n");
9953 for (index = 0; index < INST_ARRAY_SIZE; index++) {
9954 if ((index % 5) == 0)
9956 printf(" 0x%jx", inst_start_time[index]);
9958 printf("\n\nTimer End:\n");
9960 for (index = 0; index < INST_ARRAY_SIZE; index++) {
9961 if ((index % 5) == 0)
9963 printf(" 0x%jx", inst_end_time[index]);
9967 for (index = 0; index < INST_ARRAY_SIZE; index++) {
9968 inst_diff_time[index] = (uint32_t) (inst_end_time[index] -
9969 inst_start_time[index]);
9972 if (Msg[CGNAPT_DBG_CMD_OFST + 2] ==
9973 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
9974 printf("\n\nTimer Diff:\n");
9976 for (index = 0; index < INST_ARRAY_SIZE; index++) {
9977 if (Msg[CGNAPT_DBG_CMD_OFST + 2] ==
9978 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
9979 if ((index % 5) == 0)
9981 printf(" 0x%08x", inst_diff_time[index]);
9984 diff_sum += inst_diff_time[index];
9987 printf("\ndiff_sum %u, INST_ARRAY_SIZE %d, Ave Time %u\n",
9988 diff_sum, INST_ARRAY_SIZE, (diff_sum / INST_ARRAY_SIZE));
9989 } else if (Msg[CGNAPT_DBG_CMD_OFST + 1] ==
9990 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
9991 /* p plid entry dbg 7 1 0
9992 * p plid entry dbg 7 1 1 <--- pkt_work_cgnapt
9993 * p plid entry dbg 7 1 2 <--- pkt4_work_cgnapt
9994 * p plid entry dbg 7 1 3 <--- pkt_work_cgnapt_key
9995 * p plid entry dbg 7 1 4 <--- pkt4_work_cgnapt_key
9996 * p plid entry dbg 7 1 5 <--- in port ah to out port ah
9997 * - pkt life in the system
9998 * p plid entry dbg 7 1 6 <--- how long this instrumentation
10001 cgnapt_inst_index = 0;
10002 cgnapt_num_func_to_inst = Msg[CGNAPT_DBG_CMD_OFST + 2];
10003 printf("Instrumentation data collection started for fn# %d\n",
10004 cgnapt_num_func_to_inst);
10005 } else if (Msg[CGNAPT_DBG_CMD_OFST + 1] ==
10006 CGNAPT_CMD_INSTRUMENTATION_SUB2) {
10007 /* p plid entry dbg 7 2 0
10008 * Test all major functions by calling them multiple times
10009 * pkt_work_cgnapt, pkt4_work_cgnapt, pkt_work_cgnapt_key,
10010 * pkt4_work_cgnapt_key
10012 if (cgnapt_test_pktmbuf_pool == NULL) {
10013 cgnapt_test_pktmbuf_pool = rte_pktmbuf_pool_create(
10014 "cgnapt_test_pktmbuf_pool", 63, 32, 0,
10015 RTE_MBUF_DEFAULT_BUF_SIZE,
10019 if (cgnapt_test_pktmbuf_pool == NULL)
10020 printf("CGNAPT test mbuf pool create failed.\n");
10022 struct rte_mbuf *cgnapt_test_pkt0 =
10023 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
10024 if (cgnapt_test_pkt0 == NULL)
10025 printf("CGNAPT test pkt 0 alloc failed.");
10026 struct rte_mbuf *cgnapt_test_pkt1 =
10027 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
10028 if (cgnapt_test_pkt1 == NULL)
10029 printf("CGNAPT test pkt 1 alloc failed.");
10030 struct rte_mbuf *cgnapt_test_pkt2 =
10031 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
10032 if (cgnapt_test_pkt2 == NULL)
10033 printf("CGNAPT test pkt 2 alloc failed.");
10034 struct rte_mbuf *cgnapt_test_pkt3 =
10035 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
10036 if (cgnapt_test_pkt3 == NULL)
10037 printf("CGNAPT test pkt 3 alloc failed.");
10039 struct rte_mbuf *cgnapt_test_pkts[4];
10041 cgnapt_test_pkts[0] = cgnapt_test_pkt0;
10042 cgnapt_test_pkts[1] = cgnapt_test_pkt1;
10043 cgnapt_test_pkts[2] = cgnapt_test_pkt2;
10044 cgnapt_test_pkts[3] = cgnapt_test_pkt3;
10046 uint32_t src_addr_offset =
10047 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_SRC_ADR_OFST;
10048 /* header room + eth hdr size +
10049 * src_aadr offset in ip header
10051 uint32_t dst_addr_offset =
10052 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
10053 /* header room + eth hdr size +
10054 * dst_aadr offset in ip header
10056 uint32_t prot_offset =
10057 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_PROTOCOL_OFST;
10058 /* header room + eth hdr size +
10059 * srprotocol char offset in ip header
10061 int pktCnt = 0, entCnt = 0, exCnt = 0;
10063 for (pktCnt = 0; pktCnt < 4; pktCnt++) {
10064 uint32_t *src_addr =
10065 RTE_MBUF_METADATA_UINT32_PTR
10066 (cgnapt_test_pkts[pktCnt], src_addr_offset);
10067 uint32_t *dst_addr =
10068 RTE_MBUF_METADATA_UINT32_PTR
10069 (cgnapt_test_pkts[pktCnt], dst_addr_offset);
10070 uint8_t *protocol =
10071 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10074 uint8_t *phy_port =
10075 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10077 uint8_t *eth_dest =
10078 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10082 RTE_MBUF_METADATA_UINT8_PTR(
10083 cgnapt_test_pkts[pktCnt],
10086 uint16_t *src_port =
10087 RTE_MBUF_METADATA_UINT16_PTR
10088 (cgnapt_test_pkts[pktCnt],
10089 MBUF_HDR_ROOM + ETH_HDR_SIZE +
10091 uint16_t *dst_port =
10092 RTE_MBUF_METADATA_UINT16_PTR
10093 (cgnapt_test_pkts[pktCnt],
10094 MBUF_HDR_ROOM + ETH_HDR_SIZE +
10096 *src_addr = 0xc0a80001;
10097 *dst_addr = 0x90418634;
10108 eth_dest[0] = 0x90;
10109 eth_dest[1] = 0xE2;
10110 eth_dest[2] = 0xba;
10111 eth_dest[3] = 0x54;
10112 eth_dest[4] = 0x67;
10113 eth_dest[5] = 0xc8;
10115 struct rte_pipeline_table_entry *table_entries[4];
10116 struct cgnapt_table_entry ctable_entries[4];
10117 table_entries[0] = (struct rte_pipeline_table_entry *)
10118 &ctable_entries[0];
10119 table_entries[1] = (struct rte_pipeline_table_entry *)
10120 &ctable_entries[1];
10121 table_entries[2] = (struct rte_pipeline_table_entry *)
10122 &ctable_entries[2];
10123 table_entries[3] = (struct rte_pipeline_table_entry *)
10124 &ctable_entries[3];
10125 for (entCnt = 0; entCnt < 4; entCnt++) {
10126 ctable_entries[entCnt].head.action =
10127 RTE_PIPELINE_ACTION_PORT;
10128 ctable_entries[entCnt].head.port_id = 0;
10130 ctable_entries[entCnt].data.prv_ip = 0x01020304;
10131 ctable_entries[entCnt].data.prv_port = 1234;
10132 ctable_entries[entCnt].data.pub_ip = 0x0a0b0c0d;
10133 ctable_entries[entCnt].data.pub_port = 4000;
10134 ctable_entries[entCnt].data.prv_phy_port = 0;
10135 ctable_entries[entCnt].data.pub_phy_port = 1;
10136 ctable_entries[entCnt].data.ttl = 500;
10139 uint64_t time1 = rte_get_tsc_cycles();
10141 for (exCnt = 0; exCnt < 1000; exCnt++) {
10142 pkt_work_cgnapt_key(cgnapt_test_pkts[0],
10143 instrumentation_port_in_arg);
10145 uint64_t time2 = rte_get_tsc_cycles();
10147 printf("times for %d times execution of "
10148 "pkt_work_cgnapt_key 0x%jx",
10150 printf(", 0x%jx, diff %" PRIu64 "\n", time2,
10153 time1 = rte_get_tsc_cycles();
10154 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10155 pkt_work_cgnapt_key(cgnapt_test_pkts[0],
10156 instrumentation_port_in_arg);
10158 time2 = rte_get_tsc_cycles();
10159 printf("times for %d times execution of "
10160 "pkt_work_cgnapt_key 0x%jx", exCnt, time1);
10161 printf("0x%jx, diff %" PRIu64 "\n", time2,
10164 time1 = rte_get_tsc_cycles();
10165 for (exCnt = 0; exCnt < 1000; exCnt++) {
10166 pkt4_work_cgnapt_key(cgnapt_test_pkts,
10167 instrumentation_port_in_arg);
10169 time2 = rte_get_tsc_cycles();
10170 printf("times for %d times execution of "
10171 "pkt4_work_cgnapt_key 0x%jx",
10173 printf(" 0x%jx, diff %" PRIu64 "\n", time2,
10176 time1 = rte_get_tsc_cycles();
10177 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10178 pkt4_work_cgnapt_key(cgnapt_test_pkts,
10179 instrumentation_port_in_arg);
10181 time2 = rte_get_tsc_cycles();
10182 printf("times for %d times execution of "
10183 "pkt4_work_cgnapt_key 0x%jx",
10185 printf("0x%jx, diff %" PRIu64 "\n", time2,
10188 uint64_t mask = 0xff;
10190 time1 = rte_get_tsc_cycles();
10191 for (exCnt = 0; exCnt < 1000; exCnt++) {
10192 pkt_work_cgnapt(cgnapt_test_pkts[0],
10193 table_entries[0], 3, &mask,
10196 time2 = rte_get_tsc_cycles();
10197 printf("times for %d times execution of "
10198 "pkt_work_cgnapt 0x%jx",
10200 printf("0x%jx, diff %" PRIu64 "\n", time2,
10203 time1 = rte_get_tsc_cycles();
10204 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10205 pkt_work_cgnapt(cgnapt_test_pkts[0],
10206 table_entries[0], 3, &mask,
10209 time2 = rte_get_tsc_cycles();
10210 printf("times for %d times execution of "
10211 "pkt_work_cgnapt 0x%jx",
10213 printf("0x%jx, diff %" PRIu64 "\n", time2,
10216 time1 = rte_get_tsc_cycles();
10217 for (exCnt = 0; exCnt < 1000; exCnt++) {
10218 pkt4_work_cgnapt(cgnapt_test_pkts,
10219 table_entries, 0, &mask, NULL);
10221 time2 = rte_get_tsc_cycles();
10222 printf("times for %d times execution of "
10223 "pkt4_work_cgnapt 0x%jx",
10225 printf("0x%jx, diff % " PRIu64 "\n", time2,
10228 int idummy = ctable_entries[0].data.prv_port;
10238 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_LS_ENTRY) {
10239 printf("CG-NAPT be entries are:\n");
10240 printf("Pipeline pointer %p\n", p);
10244 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DYN) {
10245 printf("Total Number of dynamic napt entries: %" PRIu64 "\n",
10246 p_nat->dynCgnaptCount);
10248 #ifdef CGNAPT_DEBUGGING
10249 printf("MAX PORT PER CLIENT:");
10250 printf("%" PRIu64 ",%" PRIu64 ",%" PRIu64 "\n",
10251 p_nat->max_port_dec_err1, p_nat->max_port_dec_err2,
10252 p_nat->max_port_dec_err3);
10253 printf("MPPC success : %" PRIu64 "\n",
10254 p_nat->max_port_dec_success);
10256 printf("Release port:err:%" PRIu64 ",ret::%" PRIu64 ",get::%"
10257 PRIu64 ",suc::%" PRIu64 "\n", p_nat->pfb_err,
10258 p_nat->pfb_ret, p_nat->pfb_get, p_nat->pfb_suc);
10259 printf("Get port::err:%" PRIu64 ",ret::%" PRIu64 ",get::%"
10260 PRIu64 ",suc::%" PRIu64 "\n", p_nat->gfp_err,
10261 p_nat->gfp_ret, p_nat->gfp_get, p_nat->gfp_suc);
10262 printf("Ring Info:\n");
10263 rte_ring_dump(stdout, p_nat->port_alloc_ring);
10267 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_IPV6) {
10268 dual_stack_enable = Msg[CGNAPT_DBG_CMD_OFST + 1];
10269 printf("Dual Stack option set: %x\n", dual_stack_enable);
10273 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_MAPS_INFO) {
10274 pipelines_port_info();
10275 pipelines_map_info();
10279 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_ITER_COM_TBL) {
10280 uint32_t count = 0;
10288 rte_hash_iterate(napt_common_table, &key, &data,
10291 if ((index != -EINVAL) && (index != -ENOENT)) {
10292 printf("\n%04d ", count);
10293 rte_hexdump(stdout, "KEY", key,
10295 pipeline_cgnapt_entry_key));
10297 //print_key((struct pipeline_cgnapt_entry_key *)
10300 rte_hash_lookup(napt_common_table,
10302 print_cgnapt_entry(&napt_hash_tbl_entries
10307 } while (index != -ENOENT);
10311 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_IF_STATS) {
10313 struct app_params *app =
10314 (struct app_params *)p_nat->app_params_addr;
10317 cmd[0] = Msg[CGNAPT_DBG_CMD_OFST + 1];
10318 cmd[1] = Msg[CGNAPT_DBG_CMD_OFST + 2];
10320 case CGNAPT_IF_STATS_HWQ:
10321 printf("n_pktq_hwq_int :%d\n", app->n_pktq_hwq_in);
10322 printf("n_pktq_hwq_out :%d\n", app->n_pktq_hwq_out);
10326 for (i = 0; i < app->n_pktq_hwq_in; i++) {
10327 struct rte_eth_stats stats;
10329 rte_eth_stats_get(p_nat->links_map[i], &stats);
10331 if (is_phy_port_privte(i))
10332 printf("Private Port Stats %d\n", i);
10334 printf("Public Port Stats %d\n", i);
10336 printf("\n\tipackets : %" PRIu64 "",
10338 printf("\n\topackets : %" PRIu64 "",
10340 printf("\n\tierrors : %" PRIu64 "",
10342 printf("\n\toerrors : %" PRIu64 "",
10344 printf("\n\trx_nombuf: %" PRIu64 "",
10347 if (is_phy_port_privte(i))
10348 printf("Private Q:");
10350 printf("Public Q:");
10351 for (j = 0; j < RTE_ETHDEV_QUEUE_STAT_CNTRS;
10353 printf(" %" PRIu64 ", %" PRIu64 "|",
10354 stats.q_ipackets[j],
10355 stats.q_opackets[j]);
10363 case CGNAPT_IF_STATS_SWQ:
10365 printf("n_pktq_swq :%d\n", app->n_pktq_swq);
10367 if (cmd[1] < app->n_pktq_swq) {
10368 rte_ring_dump(stdout, app->swq[cmd[1]]);
10371 printf("SWQ number is invalid\n");
10374 case CGNAPT_IF_STATS_OTH:
10376 printf("config_file:%s\n", app->config_file);
10377 printf("script_file:%s\n", app->script_file);
10378 printf("parser_file:%s\n", app->parser_file);
10379 printf("output_file:%s\n", app->output_file);
10380 printf("n_msgq :%d\n", app->n_msgq);
10381 printf("n_pktq_tm :%d\n", app->n_pktq_tm);
10382 printf("n_pktq_source :%d\n", app->n_pktq_source);
10383 printf("n_pktq_sink :%d\n", app->n_pktq_sink);
10384 printf("n_pipelines :%d\n", app->n_pipelines);
10388 printf("Command does not match\n\n");
10396 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_MAX_CLI_PER_PUB_IP) {
10397 if (nat_only_config_flag) {
10398 printf("Command not supported for NAT only config.\n");
10403 printf("\tPublic IP: Num Clients\n");
10404 for (ii = 0; ii < CGNAPT_MAX_PUB_IP; ii++)
10405 printf("\t%x : %7d\n", all_public_ip[ii].ip,
10406 rte_atomic16_read(&all_public_ip[ii].count));
10410 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_PUB_IP_LIST) {
10413 for (i = 0; i < p_nat->pub_ip_count; i++)
10414 printf("%x : (%d,%d)\n", p_nat->pub_ip_port_set[i].ip,
10415 p_nat->pub_ip_port_set[i].start_port,
10416 p_nat->pub_ip_port_set[i].end_port);
10420 #ifdef CGNAPT_TIMING_INST
10421 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_TIMING_INST) {
10422 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 0) {
10423 p_nat->time_measurements_on = 1;
10424 p_nat->time_measurements = 0;
10425 printf("CGNAPT timing instrumentation turned on.\n");
10426 printf("Max samples %d\n", p_nat->max_time_mesurements);
10428 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 1) {
10429 p_nat->time_measurements_on = 0;
10430 printf("CGNAPT timing instrumentation turned off.\n");
10431 printf("Cur Samples %d\n", p_nat->time_measurements);
10433 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 2) {
10434 uint64_t sum = p_nat->external_time_sum +
10435 p_nat->internal_time_sum;
10436 uint64_t isump = (p_nat->internal_time_sum * 100) / sum;
10437 uint64_t esump = (p_nat->external_time_sum * 100) / sum;
10438 printf("CGNAPT timing instrumentation status ...\n");
10439 printf("Max Count %d, Cur Count %d, Status %d (1=ON)\n",
10440 p_nat->max_time_mesurements,
10441 p_nat->time_measurements,
10442 p_nat->time_measurements_on);
10443 printf("Internal Time Sum %" PRIu64 " , Ave %" PRIu64
10444 ", percent %" PRIu64 "\n",
10445 p_nat->internal_time_sum,
10446 (p_nat->internal_time_sum /
10447 p_nat->time_measurements), isump);
10448 printf("External Time Sum %" PRIu64 " , Ave %" PRIu64
10449 ", percent %" PRIu64 "\n",
10450 p_nat->external_time_sum,
10451 (p_nat->external_time_sum /
10452 p_nat->time_measurements), esump);
10459 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_PRINT_NSP) {
10460 struct cgnapt_nsp_node *ll = nsp_ll;
10462 while (ll != NULL) {
10463 fprintf(stderr, "NSP Prefix/Depth=>%x%x:%x%x:%x%x: "
10464 "%x%x:%x%x:%x%x:%x%x:%x%x/%d",
10465 ll->nsp.prefix[0], ll->nsp.prefix[1],
10466 ll->nsp.prefix[2], ll->nsp.prefix[3],
10467 ll->nsp.prefix[4], ll->nsp.prefix[5],
10468 ll->nsp.prefix[6], ll->nsp.prefix[7],
10469 ll->nsp.prefix[8], ll->nsp.prefix[9],
10470 ll->nsp.prefix[10], ll->nsp.prefix[11],
10471 ll->nsp.prefix[12], ll->nsp.prefix[13],
10472 ll->nsp.prefix[14], ll->nsp.prefix[15],
10481 printf("CG-NAPT debug handler called with wrong args %x %x\n", Msg[0],
10485 for (i = 0; i < 20; i++)
10486 printf("%02x ", Msg[i]);
10492 * Function to print num of clients per IP address
10495 void print_num_ip_clients(void)
10497 if (nat_only_config_flag) {
10498 printf("Command not supported for NAT only config.\n");
10503 printf("\tPublic IP: Num Clients\n");
10504 for (ii = 0; ii < CGNAPT_MAX_PUB_IP; ii++)
10505 printf("\t%08x : %7d\n", all_public_ip[ii].ip,
10506 rte_atomic16_read(&all_public_ip[ii].count));
10510 * Function to print CGNAPT version info
10513 * An unused pointer to struct pipeline
10515 * void pointer to incoming arguments
10517 void *pipeline_cgnapt_msg_req_ver_handler(__rte_unused struct pipeline *p,
10520 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
10521 uint8_t *Msg = msg;
10525 printf("CG-NAPT debug handler called with args %x %x, offset %d\n",
10526 Msg[CGNAPT_VER_CMD_OFST], Msg[CGNAPT_VER_CMD_OFST + 1],
10527 CGNAPT_VER_CMD_OFST);
10529 if (Msg[CGNAPT_VER_CMD_OFST] == CGNAPT_VER_CMD_VER) {
10530 printf("CGNAPT Version %s\n", CGNAPT_VERSION);
10533 printf("CG-NAPT Version handler called with wrong args %x %x\n",
10537 for (i = 0; i < 20; i++)
10538 printf("%02x ", Msg[i]);
10544 * Function to show CGNAPT stats
10547 void all_cgnapt_stats(void)
10550 struct pipeline_cgnapt *p_nat;
10551 uint64_t receivedPktCount = 0;
10552 uint64_t missedPktCount = 0;
10553 uint64_t naptDroppedPktCount = 0;
10554 uint64_t naptedPktCount = 0;
10555 uint64_t inaptedPktCount = 0;
10556 uint64_t enaptedPktCount = 0;
10557 uint64_t arpicmpPktCount = 0;
10559 printf("\nCG-NAPT Packet Stats:\n");
10560 for (i = 0; i < n_cgnapt_pipeline; i++) {
10561 p_nat = all_pipeline_cgnapt[i];
10563 receivedPktCount += p_nat->receivedPktCount;
10564 missedPktCount += p_nat->missedPktCount;
10565 naptDroppedPktCount += p_nat->naptDroppedPktCount;
10566 naptedPktCount += p_nat->naptedPktCount;
10567 inaptedPktCount += p_nat->inaptedPktCount;
10568 enaptedPktCount += p_nat->enaptedPktCount;
10569 arpicmpPktCount += p_nat->arpicmpPktCount;
10571 printf("pipeline %d stats:\n", p_nat->pipeline_num);
10572 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10573 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10574 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10575 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10576 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10577 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10578 printf("arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10581 #ifdef CGNAPT_DEBUGGING
10582 printf("\n Drop detail 1:%" PRIu64 ",",
10583 p_nat->naptDroppedPktCount1);
10584 printf("\n Drop detail 2:%" PRIu64 ",",
10585 p_nat->naptDroppedPktCount2);
10586 printf("\n Drop detail 3:%" PRIu64 ",",
10587 p_nat->naptDroppedPktCount3);
10588 printf("\n Drop detail 4:%" PRIu64 ",",
10589 p_nat->naptDroppedPktCount4);
10590 printf("\n Drop detail 5:%" PRIu64 ",",
10591 p_nat->naptDroppedPktCount5);
10592 printf("\n Drop detail 6:%" PRIu64 "",
10593 p_nat->naptDroppedPktCount6);
10595 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10596 p_nat->missedpktcount1,
10597 p_nat->missedpktcount2);
10598 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10599 p_nat->missedpktcount3,
10600 p_nat->missedpktcount4);
10601 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10602 p_nat->missedpktcount5,
10603 p_nat->missedpktcount6);
10604 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10605 p_nat->missedpktcount7,
10606 p_nat->missedpktcount8);
10607 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10608 p_nat->missedpktcount9,
10609 p_nat->missedpktcount10);
10615 printf("\nTotal pipeline stats:\n");
10616 printf("Received %" PRIu64 ",", receivedPktCount);
10617 printf("Missed %" PRIu64 ",", missedPktCount);
10618 printf("Dropped %" PRIu64 ",", naptDroppedPktCount);
10619 printf("Translated %" PRIu64 ",", naptedPktCount);
10620 printf("ingress %" PRIu64 ",", inaptedPktCount);
10621 printf("egress %" PRIu64 "\n", enaptedPktCount);
10622 printf("arpicmp pkts %" PRIu64 "\n", arpicmpPktCount);
10625 void all_cgnapt_clear_stats(void)
10628 struct pipeline_cgnapt *p_nat;
10629 printf("\nCG-NAPT Packet Stats:\n");
10630 for (i = 0; i < n_cgnapt_pipeline; i++) {
10631 p_nat = all_pipeline_cgnapt[i];
10633 printf("pipeline %d stats:\n", p_nat->pipeline_num);
10634 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10635 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10636 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10637 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10638 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10639 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10640 printf("arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10642 p_nat->receivedPktCount = 0;
10643 p_nat->missedPktCount = 0;
10644 p_nat->naptDroppedPktCount = 0;
10645 p_nat->naptedPktCount = 0;
10646 p_nat->inaptedPktCount = 0;
10647 p_nat->enaptedPktCount = 0;
10648 p_nat->arpicmpPktCount = 0;
10650 #ifdef CGNAPT_DEBUGGING
10651 printf("\n Drop detail 1:%" PRIu64 ",",
10652 p_nat->naptDroppedPktCount1);
10653 printf("\n Drop detail 2:%" PRIu64 ",",
10654 p_nat->naptDroppedPktCount2);
10655 printf("\n Drop detail 3:%" PRIu64 ",",
10656 p_nat->naptDroppedPktCount3);
10657 printf("\n Drop detail 4:%" PRIu64 ",",
10658 p_nat->naptDroppedPktCount4);
10659 printf("\n Drop detail 5:%" PRIu64 ",",
10660 p_nat->naptDroppedPktCount5);
10661 printf("\n Drop detail 6:%" PRIu64 "",
10662 p_nat->naptDroppedPktCount6);
10664 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10665 p_nat->missedpktcount1,
10666 p_nat->missedpktcount2);
10667 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10668 p_nat->missedpktcount3,
10669 p_nat->missedpktcount4);
10670 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10671 p_nat->missedpktcount5,
10672 p_nat->missedpktcount6);
10673 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10674 p_nat->missedpktcount7,
10675 p_nat->missedpktcount8);
10676 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10677 p_nat->missedpktcount9,
10678 p_nat->missedpktcount10);
10686 * Function to print common CGNAPT table entries
10689 void print_static_cgnapt_entries(void)
10691 uint32_t count = 0;
10696 struct cgnapt_table_entry *entry;
10698 index = rte_hash_iterate(napt_common_table,
10699 &key, &data, &next);
10701 if ((index != -EINVAL) && (index != -ENOENT)) {
10702 printf("\n%04d ", count);
10703 rte_hexdump(stdout, "KEY", key,
10704 sizeof(struct pipeline_cgnapt_entry_key));
10705 int32_t position = rte_hash_lookup(
10706 napt_common_table, key);
10707 entry = &napt_hash_tbl_entries[position];
10709 if (entry->data.timeout == STATIC_CGNAPT_TIMEOUT)
10710 rte_hexdump(stdout, "Entry",
10711 (const void *)entry,
10712 sizeof(struct cgnapt_table_entry));
10716 } while (index != -ENOENT);
10720 * Function to show CGNAPT stats
10724 struct pipeline_be_ops pipeline_cgnapt_be_ops = {
10725 .f_init = pipeline_cgnapt_init,
10726 .f_free = pipeline_cgnapt_free,
10728 .f_timer = pipeline_cgnapt_timer,
10729 .f_track = pipeline_cgnapt_track,