2 // Copyright (c) 2017 Intel Corporation
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
19 * Pipeline CG-NAPT BE Implementation.
21 * Implementation of Pipeline CG-NAPT Back End (BE).
22 * Provides NAPT service on dataplane packets.
23 * Runs on a core as defined in the config file.
33 #include <rte_common.h>
34 #include <rte_malloc.h>
40 #include <rte_byteorder.h>
41 #include <rte_table_lpm.h>
42 #include <rte_table_hash.h>
43 #include <rte_table_stub.h>
45 #include <rte_mempool.h>
47 #include <rte_jhash.h>
48 #include <rte_cycles.h>
49 #include <rte_ethdev.h>
50 #include <rte_pipeline.h>
51 #include <rte_timer.h>
52 #include <rte_config.h>
53 #include <rte_prefetch.h>
54 #include <rte_hexdump.h>
56 #include "pipeline_cgnapt_be.h"
57 #include "pipeline_cgnapt_common.h"
58 #include "pipeline_actions_common.h"
59 #include "hash_func.h"
60 #include "pipeline_arpicmp_be.h"
61 #include "vnf_common.h"
63 #include "pipeline_common_be.h"
64 #include "vnf_common.h"
65 #include "lib_sip_alg.h"
66 #include "lib_icmpv6.h"
68 #include "pipeline_common_fe.h"
70 #include "rte_ct_tcp.h"
71 #include "rte_cnxn_tracking.h"
74 #include "lib_ftp_alg.h"
77 #include "cgnapt_pcp_be.h"
80 /* To maintain all cgnapt pipeline pointers used for all stats */
81 struct pipeline_cgnapt *all_pipeline_cgnapt[128];
82 uint8_t n_cgnapt_pipeline;
84 /* To know egress or ingress port */
85 static uint8_t cgnapt_in_port_egress_prv[PIPELINE_MAX_PORT_IN];
86 static uint8_t cgnapt_prv_que_port_index[PIPELINE_MAX_PORT_IN];
88 /* Max port per client declarations */
90 struct rte_hash_parameters max_port_per_client_hash_params = {
91 .name = "MAX_PORT_PER_CLIENT",
92 .entries = MAX_DYN_ENTRY,
93 .key_len = sizeof(struct max_port_per_client_key),
94 .hash_func = rte_jhash,
95 .hash_func_init_val = 0,
98 struct rte_ct_cnxn_tracker *cgnat_cnxn_tracker;
101 /***** Common Port Allocation declarations *****/
103 struct rte_ring *port_alloc_ring[MAX_CGNAPT_SETS] = { NULL, NULL, NULL, NULL,
104 NULL, NULL, NULL, NULL };
105 const char *napt_port_alloc_ring_name[MAX_CGNAPT_SETS] = {
106 "NAPT_PORT_ALLOC_0 ",
107 "NAPT_PORT_ALLOC_1 ",
108 "NAPT_PORT_ALLOC_2 ",
109 "NAPT_PORT_ALLOC_3 ",
110 "NAPT_PORT_ALLOC_4 ",
111 "NAPT_PORT_ALLOC_5 ",
112 "NAPT_PORT_ALLOC_6 ",
116 int vnf_set_count = -1;
118 struct app_params *myApp;
120 /***** Common Port Allocation declarations *****/
121 int napt_port_alloc_elem_count;
123 /***** Common Table declarations *****/
124 struct rte_hash_parameters napt_common_table_hash_params = {
125 .name = "NAPT_COM_TBL",
126 .entries = MAX_NAPT_ENTRIES,
127 .key_len = sizeof(struct pipeline_cgnapt_entry_key),
128 .hash_func = rte_jhash,
129 .hash_func_init_val = 0,
133 /***** ARP local cache *****/
134 uint8_t link_hw_laddr_valid[MAX_NUM_LOCAL_MAC_ADDRESS] = {
135 0, 0, 0, 0, 0, 0, 0, 0,
136 0, 0, 0, 0, 0, 0, 0, 0
139 struct ether_addr link_hw_laddr[MAX_NUM_LOCAL_MAC_ADDRESS] = {
140 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
141 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
142 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
143 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
144 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
145 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
146 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
147 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
148 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
149 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
150 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
151 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
152 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
153 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
154 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
155 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }
158 /****** NAT64 declarations *****/
160 uint8_t well_known_prefix[16] = {
161 0x00, 0x64, 0xff, 0x9b,
162 0x00, 0x00, 0x00, 0x00,
163 0x00, 0x00, 0x00, 0x00,
164 0x00, 0x00, 0x00, 0x00
167 static uint32_t local_get_nh_ipv4(
171 struct pipeline_cgnapt *p_nat);
173 static void do_local_nh_ipv4_cache(
175 struct pipeline_cgnapt *p_nat);
177 static uint32_t local_get_nh_ipv6(
181 struct pipeline_cgnapt *p_nat);
183 static void do_local_nh_ipv6_cache(
185 struct pipeline_cgnapt *p_nat);
187 static uint8_t check_arp_icmp(
188 struct rte_mbuf *pkt,
190 struct pipeline_cgnapt *p_nat);
192 /* Finds next power of two for n. If n itself
193 * is a power of two then returns n
196 * Value usually 32-bit value
199 * Value after roundup to power of 2
201 uint64_t nextPowerOf2(uint64_t n)
215 * Function to get MAC addr of local link
218 * Physical port number
221 * Outport Link MAC addr
224 struct ether_addr *get_local_link_hw_addr(uint8_t out_port)
226 return &link_hw_laddr[out_port];
230 * Function to get MAC addr from array instead of hash table
233 * Physical port number
236 * Outport Link MAC addr
239 uint8_t local_dest_mac_present(uint8_t out_port)
241 return link_hw_laddr_valid[out_port];
245 * Function to get IPv4-IP NH from thread local array
254 * CGNAPT pipeline ptr
257 * 1 on success, 0 for failure
260 static uint32_t local_get_nh_ipv4(
264 struct pipeline_cgnapt *p_nat)
267 for (i = 0; i < p_nat->local_lib_arp_route_ent_cnt; i++) {
268 if (((p_nat->local_lib_arp_route_table[i].ip &
269 p_nat->local_lib_arp_route_table[i].mask) ==
270 (ip & p_nat->local_lib_arp_route_table[i].mask))) {
271 *port = p_nat->local_lib_arp_route_table[i].port;
273 *nhip = p_nat->local_lib_arp_route_table[i].nh;
281 * Function to make local copy for NH of type IPv4
284 * Physical port number
286 * CGNAPT pipeline ptr
290 static void do_local_nh_ipv4_cache(
292 struct pipeline_cgnapt *p_nat)
295 /* Search for the entry and do local copy */
298 for (i = 0; i < MAX_ARP_RT_ENTRY; i++) {
299 if (lib_arp_route_table[i].port == dest_if) {
301 struct lib_arp_route_table_entry *lentry =
302 &p_nat->local_lib_arp_route_table
303 [p_nat->local_lib_arp_route_ent_cnt];
305 lentry->ip = lib_arp_route_table[i].ip;
306 lentry->mask = lib_arp_route_table[i].mask;
307 lentry->port = lib_arp_route_table[i].port;
308 lentry->nh = lib_arp_route_table[i].nh;
310 p_nat->local_lib_arp_route_ent_cnt++;
318 * Function to get IPv6-IP NH from thread local array
321 * Pointer to starting addr of IPv6
327 * CGNAPT pipeline ptr
330 * 1 on success, 0 for failure
333 static uint32_t local_get_nh_ipv6(
337 struct pipeline_cgnapt *p_nat)
340 uint8_t netmask_ipv6[16];
341 uint8_t k = 0, l = 0, depthflags = 0, depthflags1 = 0;
343 for (i = 0; i < p_nat->local_lib_nd_route_ent_cnt; i++) {
345 convert_prefixlen_to_netmask_ipv6(
346 p_nat->local_lib_nd_route_table[i].depth,
349 for (k = 0; k < 16; k++)
350 if (p_nat->local_lib_nd_route_table[i].ipv6[k] &
354 for (l = 0; l < 16; l++)
355 if (ip[l] & netmask_ipv6[l])
359 if (depthflags == depthflags1) {
360 *port = p_nat->local_lib_nd_route_table[i].port;
362 for (j = 0; j < 16; j++)
363 nhip[j] = p_nat->local_lib_nd_route_table[i].
376 * Function to make local copy for NH of type IPv6
379 * Physical port number
381 * CGNAPT pipeline ptr
385 static void do_local_nh_ipv6_cache(
387 struct pipeline_cgnapt *p_nat)
389 /* Search for the entry and do local copy */
391 for (i = 0; i < MAX_ND_RT_ENTRY; i++) {
393 if (lib_nd_route_table[i].port == dest_if) {
395 struct lib_nd_route_table_entry *lentry =
396 &p_nat->local_lib_nd_route_table
397 [p_nat->local_lib_nd_route_ent_cnt];
399 for (l = 0; l < 16; l++) {
401 lib_nd_route_table[i].ipv6[l];
403 lib_nd_route_table[i].nhipv6[l];
405 lentry->depth = lib_nd_route_table[i].depth;
406 lentry->port = lib_nd_route_table[i].port;
408 p_nat->local_lib_nd_route_ent_cnt++;
415 /* Commented code may be required for future usage, Please keep it*/
417 static int retrieve_cgnapt_entry_alg(
418 struct pipeline_cgnapt_entry_key *key,
419 struct cgnapt_table_entry **entry_ptr1,
420 struct cgnapt_table_entry **entry_ptr2)
422 #ifdef CGNAPT_DBG_PRNT
423 printf("retrieve_cgnapt_entry key detail Entry:"
424 "0x%x, %d, %d\n", key->ip, key->port,
428 int position = rte_hash_lookup(napt_common_table, key);
430 printf("Invalid cgnapt entry position(first_key): %d\n",
435 *entry_ptr1 = &napt_hash_tbl_entries[position];
437 uint32_t prv_ip = (*entry_ptr1)->data.prv_ip;
438 uint32_t prv_port = (*entry_ptr1)->data.prv_port;
439 uint32_t prv_phy_port = (*entry_ptr1)->data.prv_phy_port;
441 struct pipeline_cgnapt_entry_key second_key;
442 second_key.ip = prv_ip;
443 second_key.port = prv_port;
444 second_key.pid = prv_phy_port;
446 position = rte_hash_lookup(napt_common_table, &second_key);
448 printf("Invalid cgnapt entry position(second_key): %d\n",
453 *entry_ptr2 = &napt_hash_tbl_entries[position];
459 int add_dynamic_cgnapt_entry_alg(
461 struct pipeline_cgnapt_entry_key *key,
462 struct cgnapt_table_entry **entry_ptr1,
463 struct cgnapt_table_entry **entry_ptr2)
465 int port_num = 0, ret;
467 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
469 #ifdef CGNAPT_DBG_PRNT
470 if (CGNAPT_DEBUG >= 1) {
471 printf("Th%d add_dynamic_cgnapt_entry key detail Entry:"
472 "0x%x, %d, %d\n", p_nat->pipeline_num, key->ip, key->port,
477 int32_t position = rte_hash_lookup(napt_common_table, key);
479 #ifdef CGNAPT_DBG_PRNT
480 if (CGNAPT_DEBUG >= 1) {
481 printf("%s: cgnapt entry exists in "
482 "position(first_key): %d\n", __func__, position);
485 *entry_ptr1 = &napt_hash_tbl_entries[position];
486 /* not required, as it is not used in the caller */
492 ret = increment_max_port_counter(key->ip, key->pid, p_nat);
493 if (ret == MAX_PORT_INC_ERROR) {
495 #ifdef CGNAPT_DBG_PRNT
496 if (CGNAPT_DEBUG > 1)
497 printf("add_dynamic_cgnapt_entry:"
498 "increment_max_port_counter-1 failed\n");
504 if (ret == MAX_PORT_INC_REACHED) {
506 #ifdef CGNAPT_DBG_PRNT
507 if (CGNAPT_DEBUG > 1)
508 printf("add_dynamic_cgnapt_entry:"
509 "increment_max_port_counter-2 failed\n");
516 port_num = get_free_iport(p_nat, &public_ip);
518 if (port_num == -1) {
520 #ifdef CGNAPT_DBG_PRNT
521 if (CGNAPT_DEBUG > 2) {
522 printf("add_dynamic_cgnapt_entry: %d\n", port_num);
523 printf("add_dynamic_cgnapt_entry key detail:0x%x, "
524 "%d, %d\n", key->ip, key->port, key->pid);
531 /* check for max_clients_per_ip */
532 if (rte_atomic16_read
534 [rte_jhash(&public_ip, 4, 0) % 16].count) ==
535 p_nat->max_clients_per_ip) {
536 /* For now just bail out
537 * In future we can think about
538 * retrying getting a new iport
540 release_iport(port_num, public_ip, p_nat);
545 rte_atomic16_inc(&all_public_ip
546 [rte_jhash(&public_ip, 4, 0) %
549 #ifdef CGNAPT_DBG_PRNT
550 if ((rte_jhash(&public_ip, 4, 0) % 16) == 8)
551 printf("pub ip:%x coutn:%d\n", public_ip,
552 rte_atomic16_read(&all_public_ip
553 [rte_jhash(&public_ip, 4, 0) % 16].count));
556 #ifdef CGNAPT_DBG_PRNT
557 if (CGNAPT_DEBUG > 0) {
558 printf("add_dynamic_cgnapt_entry: %d\n",
560 printf("add_dynamic_cgnapt_entry key detail: "
561 "0x%x, %d, %d\n", key->ip, key->port, key->pid);
565 struct cgnapt_table_entry entry = {
567 .action = RTE_PIPELINE_ACTION_PORT,
568 /* made it configurable below */
569 {.port_id = p->port_out_id[0]},
573 .prv_port = key->port,
575 .pub_port = port_num,
576 .prv_phy_port = key->pid,
577 .pub_phy_port = get_pub_to_prv_port(
581 /* if(timeout == -1) : static entry
582 * if(timeout == 0 ) : dynamic entry
583 * if(timeout > 0 ) : PCP requested entry
592 entry.data.u.prv_ip = key->ip;
593 entry.data.type = CGNAPT_ENTRY_IPV4;
595 entry.head.port_id = entry.data.pub_phy_port; /* outgoing port info */
597 struct pipeline_cgnapt_entry_key second_key;
598 /* Need to add a second ingress entry */
599 second_key.ip = public_ip;
600 second_key.port = port_num;
601 second_key.pid = 0xffff;
603 #ifdef CGNAPT_DBG_PRNT
604 if (CGNAPT_DEBUG > 2)
605 printf("add_dynamic_cgnapt_entry second key detail:"
606 "0x%x, %d, %d\n", second_key.ip, second_key.port,
610 int32_t position1 = rte_hash_add_key(napt_common_table, (void *)key);
613 printf("CG-NAPT entry add failed ...returning "
614 "without adding ... %d\n", position1);
619 #ifdef CGNAPT_DBG_PRNT
621 printf("add_dynamic_cgnapt_entry:");
623 print_cgnapt_entry(&entry);
627 memcpy(&napt_hash_tbl_entries[position1], &entry,
628 sizeof(struct cgnapt_table_entry));
630 /* this pointer is returned to pkt miss function */
631 *entry_ptr1 = &napt_hash_tbl_entries[position1];
633 p_nat->n_cgnapt_entry_added++;
634 p_nat->dynCgnaptCount++;
636 /* Now modify the forward port for reverse entry */
638 /* outgoing port info */
639 entry.head.port_id = entry.data.prv_phy_port;
641 int32_t position2 = rte_hash_add_key(napt_common_table, &second_key);
644 printf("CG-NAPT entry reverse bulk add failed ..."
645 "returning with fwd add ...%d\n",
650 memcpy(&napt_hash_tbl_entries[position2], &entry,
651 sizeof(struct cgnapt_table_entry));
653 *entry_ptr2 = &napt_hash_tbl_entries[position2];
655 #ifdef CGNAPT_DBG_PRNT
656 if (CGNAPT_DEBUG >= 1) {
657 printf("add_dynamic_cgnapt_entry position: %d, %d\n",
658 position1, position2);
659 printf("add_dynamic_cgnapt_entry: entry_ptr1: %p, "
660 "entry_ptr2: %p\n", *entry_ptr1, *entry_ptr2);
664 timer_thread_enqueue(key, &second_key, *entry_ptr1,
665 *entry_ptr2, (struct pipeline *)p_nat);
667 p_nat->n_cgnapt_entry_added++;
668 p_nat->dynCgnaptCount++;
675 void hw_checksum(struct rte_mbuf *pkt, enum PKT_TYPE ver)
677 struct tcp_hdr *tcp = NULL;
678 struct udp_hdr *udp = NULL;
679 struct icmp_hdr *icmp = NULL;
681 void *ip_header = NULL;
682 uint16_t prot_offset = 0;
683 uint32_t pkt_type_is_ipv4 = 1;
685 pkt->ol_flags |= PKT_TX_IP_CKSUM;
686 pkt->l2_len = ETH_HDR_SIZE;
691 case PKT_TYPE_IPV4to6:
695 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
696 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
698 pkt_type_is_ipv4 = 0;
699 pkt->ol_flags |= PKT_TX_IPV6;
701 sizeof(struct ipv6_hdr);
702 tcp = (struct tcp_hdr *)
703 ((unsigned char *)ip_header +
704 sizeof(struct ipv6_hdr));
705 udp = (struct udp_hdr *)
706 ((unsigned char *)ip_header +
707 sizeof(struct ipv6_hdr));
708 icmp = (struct icmp_hdr *)
709 ((unsigned char *)ip_header +
710 sizeof(struct ipv6_hdr));
712 prot_offset = PROT_OFST_IP6 + temp;
714 case PKT_TYPE_IPV6to4:
718 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
719 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
721 pkt->ol_flags |= PKT_TX_IPV4;
723 sizeof(struct ipv4_hdr);
724 tcp = (struct tcp_hdr *)
725 ((unsigned char *)ip_header +
726 sizeof(struct ipv4_hdr));
727 udp = (struct udp_hdr *)
728 ((unsigned char *)ip_header +
729 sizeof(struct ipv4_hdr));
730 icmp = (struct icmp_hdr *)
731 ((unsigned char *)ip_header +
732 sizeof(struct ipv4_hdr));
733 struct ipv4_hdr *ip_hdr =
734 (struct ipv4_hdr *)ip_header;
735 ip_hdr->hdr_checksum = 0;
737 prot_offset = PROT_OFST_IP4 + temp;
740 printf("hw_checksum: pkt version is invalid\n");
742 protocol = (uint8_t *) RTE_MBUF_METADATA_UINT8_PTR(pkt,
746 case IP_PROTOCOL_TCP: /* 6 */
748 pkt->ol_flags |= PKT_TX_TCP_CKSUM;
749 if (pkt_type_is_ipv4) {
750 tcp->cksum = rte_ipv4_phdr_cksum(
751 (struct ipv4_hdr *)ip_header,
754 tcp->cksum = rte_ipv6_phdr_cksum(
755 (struct ipv6_hdr *)ip_header,
759 case IP_PROTOCOL_UDP: /* 17 */
760 udp->dgram_cksum = 0;
761 pkt->ol_flags |= PKT_TX_UDP_CKSUM;
762 if (pkt_type_is_ipv4) {
765 (struct ipv4_hdr *)ip_header,
770 (struct ipv6_hdr *)ip_header,
774 case IP_PROTOCOL_ICMP: /* 1 */
775 if (pkt_type_is_ipv4) {
776 /* ICMP checksum code */
777 struct ipv4_hdr *ip_hdr =
778 (struct ipv4_hdr *)ip_header;
779 int size = rte_bswap16(ip_hdr->total_length) - 20;
780 icmp->icmp_cksum = 0;
788 printf("hw_checksum() : Neither TCP or UDP pkt\n");
794 void sw_checksum(struct rte_mbuf *pkt, enum PKT_TYPE ver)
796 struct tcp_hdr *tcp = NULL;
797 struct udp_hdr *udp = NULL;
798 struct icmp_hdr *icmp = NULL;
800 void *ip_header = NULL;
801 uint16_t prot_offset = 0;
802 uint32_t pkt_type_is_ipv4 = 1;
806 case PKT_TYPE_IPV4to6:
810 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
811 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
813 pkt_type_is_ipv4 = 0;
814 tcp = (struct tcp_hdr *)
815 ((unsigned char *)ip_header +
816 sizeof(struct ipv6_hdr));
817 udp = (struct udp_hdr *)
818 ((unsigned char *)ip_header +
819 sizeof(struct ipv6_hdr));
820 icmp = (struct icmp_hdr *)
821 ((unsigned char *)ip_header +
822 sizeof(struct ipv6_hdr));
824 prot_offset = PROT_OFST_IP6 + temp;
826 case PKT_TYPE_IPV6to4:
830 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
831 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
833 tcp = (struct tcp_hdr *)
834 ((unsigned char *)ip_header +
835 sizeof(struct ipv4_hdr));
836 udp = (struct udp_hdr *)
837 ((unsigned char *)ip_header +
838 sizeof(struct ipv4_hdr));
839 icmp = (struct icmp_hdr *)
840 ((unsigned char *)ip_header +
841 sizeof(struct ipv4_hdr));
843 prot_offset = PROT_OFST_IP4 + temp;
846 printf("sw_checksum: pkt version is invalid\n");
848 protocol = (uint8_t *) RTE_MBUF_METADATA_UINT8_PTR(pkt,
852 case IP_PROTOCOL_TCP: /* 6 */
854 if (pkt_type_is_ipv4) {
855 struct ipv4_hdr *ip_hdr =
856 (struct ipv4_hdr *)ip_header;
857 tcp->cksum = rte_ipv4_udptcp_cksum(ip_hdr,
859 ip_hdr->hdr_checksum = 0;
860 ip_hdr->hdr_checksum = rte_ipv4_cksum(
861 (struct ipv4_hdr *)ip_hdr);
863 tcp->cksum = rte_ipv6_udptcp_cksum(
865 ip_header, (void *)tcp);
868 case IP_PROTOCOL_UDP: /* 17 */
869 udp->dgram_cksum = 0;
870 if (pkt_type_is_ipv4) {
871 struct ipv4_hdr *ip_hdr =
872 (struct ipv4_hdr *)ip_header;
873 udp->dgram_cksum = rte_ipv4_udptcp_cksum(
874 ip_hdr, (void *)udp);
875 ip_hdr->hdr_checksum = 0;
876 ip_hdr->hdr_checksum = rte_ipv4_cksum(ip_hdr);
878 udp->dgram_cksum = rte_ipv6_udptcp_cksum(
880 ip_header, (void *)udp);
883 case IP_PROTOCOL_ICMP: /* 1 */
884 if (pkt_type_is_ipv4) {
885 /* ICMP checksum code */
886 struct ipv4_hdr *ip_hdr =
887 (struct ipv4_hdr *)ip_header;
888 int size = rte_bswap16(ip_hdr->total_length) - 20;
889 icmp->icmp_cksum = 0;
893 ip_hdr->hdr_checksum = 0;
894 ip_hdr->hdr_checksum = rte_ipv4_cksum(ip_hdr);
899 printf("sw_checksum() : Neither TCP or UDP pkt\n");
904 static uint8_t check_arp_icmp(
905 struct rte_mbuf *pkt,
907 struct pipeline_cgnapt *p_nat)
909 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
910 uint16_t *eth_proto = RTE_MBUF_METADATA_UINT16_PTR(
911 pkt, eth_proto_offset);
912 struct app_link_params *link;
913 uint8_t solicited_node_multicast_addr[16] = {
914 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
915 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00};
917 /* ARP outport number */
918 uint16_t out_port = p_nat->p.n_ports_out - 1;
921 uint32_t prot_offset;
923 link = &myApp->link_params[pkt->port];
926 switch (rte_be_to_cpu_16(*eth_proto)) {
930 rte_pipeline_port_out_packet_insert(
936 * Pkt mask should be changed, and not changing the
939 p_nat->invalid_packets |= pkt_mask;
940 p_nat->arpicmpPktCount++;
944 case ETH_TYPE_IPV4: {
945 /* header room + eth hdr size +
946 * src_aadr offset in ip header
948 uint32_t dst_addr_offset = MBUF_HDR_ROOM +
949 ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
951 RTE_MBUF_METADATA_UINT32_PTR(pkt,
953 prot_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
954 IP_HDR_PROTOCOL_OFST;
955 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt,
957 if ((*protocol == IP_PROTOCOL_ICMP) &&
958 link->ip == rte_be_to_cpu_32(*dst_addr)) {
960 if (is_phy_port_privte(pkt->port)) {
962 rte_pipeline_port_out_packet_insert(
963 p_nat->p.p, out_port, pkt);
966 * Pkt mask should be changed,
967 * and not changing the drop mask
970 p_nat->invalid_packets |= pkt_mask;
971 p_nat->arpicmpPktCount++;
982 if (dual_stack_enable) {
984 /* Commented code may be required for future usage,
987 //uint32_t dst_addr_offset = MBUF_HDR_ROOM +
988 // ETH_HDR_SIZE + IPV6_HDR_DST_ADR_OFST;
989 //uint32_t *dst_addr =
990 // RTE_MBUF_METADATA_UINT32_PTR(pkt,
992 uint32_t prot_offset_ipv6 = MBUF_HDR_ROOM +
993 ETH_HDR_SIZE + IPV6_HDR_PROTOCOL_OFST;
994 struct ipv6_hdr *ipv6_h;
996 ipv6_h = (struct ipv6_hdr *) MBUF_HDR_ROOM +
998 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt,
1001 if (ipv6_h->proto == ICMPV6_PROTOCOL_ID) {
1002 if (!memcmp(ipv6_h->dst_addr, link->ipv6, 16)
1003 || !memcmp(ipv6_h->dst_addr,
1004 solicited_node_multicast_addr, 13)) {
1005 rte_pipeline_port_out_packet_insert(
1006 p_nat->p.p, out_port, pkt);
1008 * Pkt mask should be changed,
1009 * and not changing the drop mask
1011 p_nat->invalid_packets |= pkt_mask;
1012 p_nat->arpicmpPktCount++;
1014 p_nat->invalid_packets |= pkt_mask;
1015 p_nat->naptDroppedPktCount++;
1017 #ifdef CGNAPT_DEBUGGING
1018 p_nat->naptDroppedPktCount1++;
1033 * Function to create common NAPT table
1034 * Called during pipeline initialization
1035 * Creates the common NAPT table
1036 * If it is not already created and stores its pointer
1037 * in global napt_common_table pointer.
1040 * Max number of NAPT flows. This parameter is configurable via config file.
1043 * 0 on success, negative on error.
1045 int create_napt_common_table(uint32_t nFlows)
1047 if (napt_common_table != NULL) {
1048 printf("napt_common_table already exists.\n");
1052 napt_common_table = rte_hash_create(&napt_common_table_hash_params);
1054 if (napt_common_table == NULL) {
1055 printf("napt_common_table creation failed.\n");
1059 uint32_t number_of_entries = nFlows;
1062 RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_table_entry) *
1064 napt_hash_tbl_entries = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1066 if (napt_hash_tbl_entries == NULL) {
1067 printf("napt_hash_tbl_entries creation failed. %d, %d\n",
1068 nFlows, (int)sizeof(struct cgnapt_table_entry));
1076 * Function to initialize bulk port allocation data structures
1077 * Called during pipeline initialization.
1079 * Creates the port alloc ring for the VNF_set this pipeline belongs
1081 * Creates global port allocation buffer pool
1083 * Initializes the port alloc ring according to config data
1086 * A pointer to struct pipeline_cgnapt
1089 * 0 on success, negative on error.
1091 int napt_port_alloc_init(struct pipeline_cgnapt *p_nat)
1093 p_nat->allocated_ports = NULL;
1094 p_nat->free_ports = NULL;
1096 uint32_t vnf_set_num = p_nat->vnf_set;
1097 /*uint32_t vnf_set_num = get_vnf_set_num(p_nat->pipeline_num); */
1099 printf("VNF set number for CGNAPT %d is %d.\n", p_nat->pipeline_num,
1101 if (vnf_set_num == 0xFF) {
1102 printf("VNF set number for CGNAPT %d is invalid %d.\n",
1103 p_nat->pipeline_num, vnf_set_num);
1107 p_nat->port_alloc_ring = port_alloc_ring[vnf_set_num];
1108 if (p_nat->port_alloc_ring != NULL) {
1109 printf("CGNAPT%d port_alloc_ring already exists.\n",
1110 p_nat->pipeline_num);
1114 printf("napt_port_alloc_elem_count :%d\n",
1115 napt_port_alloc_elem_count);
1116 napt_port_alloc_elem_count += 1;
1117 napt_port_alloc_elem_count =
1118 nextPowerOf2(napt_port_alloc_elem_count);
1119 printf("Next power of napt_port_alloc_elem_count: %d\n",
1120 napt_port_alloc_elem_count);
1122 port_alloc_ring[vnf_set_num] =
1123 rte_ring_create(napt_port_alloc_ring_name[vnf_set_num],
1124 napt_port_alloc_elem_count, rte_socket_id(), 0);
1125 p_nat->port_alloc_ring = port_alloc_ring[vnf_set_num];
1126 if (p_nat->port_alloc_ring == NULL) {
1127 printf("CGNAPT%d - Failed to create port_alloc_ring\n",
1128 p_nat->pipeline_num);
1132 /* Create port alloc buffer */
1133 /* Only one pool is enough for all vnf sets */
1134 if (napt_port_pool == NULL) {
1136 napt_port_pool = rte_mempool_create(
1138 napt_port_alloc_elem_count,
1139 sizeof(struct napt_port_alloc_elem),
1140 0, 0, NULL, NULL, NULL,
1141 NULL, rte_socket_id(), 0);
1144 if (napt_port_pool == NULL) {
1145 printf("CGNAPT - Create port pool failed\n");
1149 /* Add all available public IP addresses and ports to the ring */
1152 #ifdef NAT_ONLY_CONFIG_REQ
1153 if (nat_only_config_flag) {
1154 printf("******* pub_ip_range_count:%d ***********\n",
1155 p_nat->pub_ip_range_count);
1156 /* Initialize all public IP's addresses */
1158 uint32_t max_ips_remain;
1160 for (if_addrs = 0; if_addrs < p_nat->pub_ip_range_count;
1162 /* Add all available addresses to the ring */
1164 for (i = p_nat->pub_ip_range[if_addrs].start_ip;
1165 i <= p_nat->pub_ip_range[if_addrs].end_ip;) {
1166 /* 1. Get a port alloc buffer from napt_port_pool */
1170 /* get new napt_port_alloc_elem from pool */
1171 if (rte_mempool_get(napt_port_pool,
1173 printf("CGNAPT - Error in getting port "
1179 /* 2. Populate it with available ports and ip addr */
1180 struct napt_port_alloc_elem *pb =
1181 (struct napt_port_alloc_elem *)portsBuf;
1184 temp = p_nat->pub_ip_range[if_addrs].end_ip -
1187 /* Check if remaining port count is greater
1188 * than or equals to bulk count, if not give
1189 * remaining count ports than giving bulk count
1191 if (temp < NUM_NAPT_PORT_BULK_ALLOC)
1192 max_ips_remain = temp;
1195 NUM_NAPT_PORT_BULK_ALLOC;
1197 for (j = 0; j < max_ips_remain; j++) {
1199 pb->ip_addr[j] = i + j;
1202 p_nat->pub_ip_range[if_addrs].
1207 /* 3. add the port alloc buffer to ring */
1208 if (rte_ring_enqueue(p_nat->port_alloc_ring,
1210 printf("CGNAPT%d - Enqueue error - i %d,",
1211 p_nat->pipeline_num, i);
1212 printf("j %d, if_addrs %d, pb %p\n",
1214 rte_ring_dump(stdout,
1215 p_nat->port_alloc_ring);
1216 rte_mempool_put(napt_port_pool,
1221 /* reset j and advance i */
1223 i += max_ips_remain;
1231 printf("******* p_nat->pub_ip_count:%d ***********\n",
1232 p_nat->pub_ip_count);
1233 /* Initialize all public IP's ports */
1235 uint32_t max_ports_remain;
1237 for (if_ports = 0; if_ports < p_nat->pub_ip_count; if_ports++) {
1238 /* Add all available ports to the ring */
1240 for (i = p_nat->pub_ip_port_set[if_ports].start_port;
1241 i <= p_nat->pub_ip_port_set[if_ports].end_port;) {
1242 /* 1. Get a port alloc buffer from napt_port_pool */
1246 /* get new napt_port_alloc_elem from pool */
1247 if (rte_mempool_get(napt_port_pool, &portsBuf) <
1249 printf("CGNAPT - Error in getting "
1250 "port alloc buffer\n");
1255 /* 2. Populate it with available ports and ip addr */
1256 struct napt_port_alloc_elem *pb =
1257 (struct napt_port_alloc_elem *)portsBuf;
1260 temp = p_nat->pub_ip_port_set[if_ports].end_port -
1262 /* Check if remaining port count is greater
1263 * than or equals to bulk count, if not give
1264 * remaining count ports than giving bulk count
1266 if (temp < NUM_NAPT_PORT_BULK_ALLOC)
1267 max_ports_remain = temp;
1270 NUM_NAPT_PORT_BULK_ALLOC;
1272 for (j = 0; j < max_ports_remain; j++) {
1275 p_nat->pub_ip_port_set[if_ports].ip;
1276 pb->ports[j] = i + j;
1277 if ((i + j) == p_nat->pub_ip_port_set
1278 [if_ports].end_port)
1282 /* 3. add the port alloc buffer to ring */
1283 if (rte_ring_enqueue(p_nat->port_alloc_ring,
1285 printf("CGNAPT%d - Enqueue error - i %d, j %d, "
1286 " if_ports %d, pb %p\n", p_nat->pipeline_num,
1287 i, j, if_ports, pb);
1289 rte_ring_dump(stdout, p_nat->port_alloc_ring);
1290 rte_mempool_put(napt_port_pool, portsBuf);
1294 /* reset j and advance i */
1296 i += max_ports_remain;
1303 static pipeline_msg_req_handler handlers[] = {
1304 [PIPELINE_MSG_REQ_PING] =
1305 pipeline_msg_req_ping_handler,
1306 [PIPELINE_MSG_REQ_STATS_PORT_IN] =
1307 pipeline_msg_req_stats_port_in_handler,
1308 [PIPELINE_MSG_REQ_STATS_PORT_OUT] =
1309 pipeline_msg_req_stats_port_out_handler,
1310 [PIPELINE_MSG_REQ_STATS_TABLE] = pipeline_msg_req_stats_table_handler,
1311 [PIPELINE_MSG_REQ_PORT_IN_ENABLE] =
1312 pipeline_msg_req_port_in_enable_handler,
1313 [PIPELINE_MSG_REQ_PORT_IN_DISABLE] =
1314 pipeline_msg_req_port_in_disable_handler,
1315 [PIPELINE_MSG_REQ_CUSTOM] =
1316 pipeline_cgnapt_msg_req_custom_handler,
1319 static pipeline_msg_req_handler custom_handlers[] = {
1320 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_ADD] =
1321 pipeline_cgnapt_msg_req_entry_add_handler,
1322 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_DEL] =
1323 pipeline_cgnapt_msg_req_entry_del_handler,
1324 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_SYNC] =
1325 pipeline_cgnapt_msg_req_entry_sync_handler,
1326 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_DBG] =
1327 pipeline_cgnapt_msg_req_entry_dbg_handler,
1328 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_ADDM] =
1329 pipeline_cgnapt_msg_req_entry_addm_handler,
1330 [PIPELINE_CGNAPT_MSG_REQ_VER] =
1331 pipeline_cgnapt_msg_req_ver_handler,
1332 [PIPELINE_CGNAPT_MSG_REQ_NSP_ADD] =
1333 pipeline_cgnapt_msg_req_nsp_add_handler,
1334 [PIPELINE_CGNAPT_MSG_REQ_NSP_DEL] =
1335 pipeline_cgnapt_msg_req_nsp_del_handler,
1338 [PIPELINE_CGNAPT_MSG_REQ_PCP] =
1339 pipeline_cgnapt_msg_req_pcp_handler,
1344 * Function to convert an IPv6 packet to IPv4 packet
1347 * A pointer to packet mbuf
1348 * @param in_ipv6_hdr
1349 * A pointer to IPv6 header in the given pkt
1353 convert_ipv6_to_ipv4(struct rte_mbuf *pkt, struct ipv6_hdr *in_ipv6_hdr)
1355 uint32_t ip_hdr_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE;
1357 uint8_t *eth_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1358 uint8_t *ipv6_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, ip_hdr_offset);
1360 struct ether_hdr eth_hdr;
1361 struct ipv4_hdr *ipv4_hdr_p;
1362 uint16_t frag_off = 0x4000;
1363 struct cgnapt_nsp_node *ll = nsp_ll;
1364 uint8_t ipv4_dest[4];
1367 memcpy(ð_hdr, eth_hdr_p, sizeof(struct ether_hdr));
1368 memcpy(in_ipv6_hdr, ipv6_hdr_p, sizeof(struct ipv6_hdr));
1370 eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
1372 char *data_area_p = rte_pktmbuf_adj(pkt, 20);
1373 if (data_area_p == NULL) {
1374 printf("convert_ipv6_to_ipv4:data_area_p is NULL\n");
1377 ipv4_hdr_p = (struct ipv4_hdr *)(data_area_p + ETH_HDR_SIZE);
1378 memset(ipv4_hdr_p, 0, sizeof(struct ipv4_hdr));
1380 memcpy(data_area_p, ð_hdr, sizeof(struct ether_hdr));
1382 #ifdef CGNAPT_DBG_PRNT
1383 if (CGNAPT_DEBUG == 1)
1384 printf("convert_ipv6_to_ipv4: eth_hdr_p(%p), data_area_p(%p), "
1385 "ipv4_hdr_p(%p)\n", eth_hdr_p, data_area_p, ipv4_hdr_p);
1388 ipv4_hdr_p->version_ihl = 0x4 << 4 | 0x5;
1389 ipv4_hdr_p->type_of_service =
1390 rte_be_to_cpu_32(in_ipv6_hdr->vtc_flow) & 0x0ff00000 >> 20;
1391 ipv4_hdr_p->total_length =
1392 rte_cpu_to_be_16(rte_be_to_cpu_16(
1393 in_ipv6_hdr->payload_len) + 20);
1394 ipv4_hdr_p->packet_id = 0;
1395 ipv4_hdr_p->fragment_offset = rte_cpu_to_be_16(frag_off);
1396 ipv4_hdr_p->time_to_live = in_ipv6_hdr->hop_limits;
1397 ipv4_hdr_p->next_proto_id = in_ipv6_hdr->proto;
1398 ipv4_hdr_p->hdr_checksum = 0;
1399 ipv4_hdr_p->src_addr = 0;
1401 while (ll != NULL) {
1403 (&in_ipv6_hdr->dst_addr[0], &ll->nsp.prefix[0],
1404 ll->nsp.depth / 8)) {
1405 if (ll->nsp.depth == 32)
1406 memcpy(&ipv4_dest[0], &in_ipv6_hdr->dst_addr[4],
1408 else if (ll->nsp.depth == 40) {
1409 ipv4_dest[0] = in_ipv6_hdr->dst_addr[5];
1410 ipv4_dest[1] = in_ipv6_hdr->dst_addr[6];
1411 ipv4_dest[2] = in_ipv6_hdr->dst_addr[7];
1412 ipv4_dest[3] = in_ipv6_hdr->dst_addr[9];
1413 } else if (ll->nsp.depth == 48) {
1414 ipv4_dest[0] = in_ipv6_hdr->dst_addr[6];
1415 ipv4_dest[1] = in_ipv6_hdr->dst_addr[7];
1416 ipv4_dest[2] = in_ipv6_hdr->dst_addr[9];
1417 ipv4_dest[3] = in_ipv6_hdr->dst_addr[10];
1418 } else if (ll->nsp.depth == 56) {
1419 ipv4_dest[0] = in_ipv6_hdr->dst_addr[7];
1420 ipv4_dest[1] = in_ipv6_hdr->dst_addr[9];
1421 ipv4_dest[2] = in_ipv6_hdr->dst_addr[10];
1422 ipv4_dest[3] = in_ipv6_hdr->dst_addr[11];
1423 } else if (ll->nsp.depth == 64) {
1424 ipv4_dest[0] = in_ipv6_hdr->dst_addr[9];
1425 ipv4_dest[1] = in_ipv6_hdr->dst_addr[10];
1426 ipv4_dest[2] = in_ipv6_hdr->dst_addr[11];
1427 ipv4_dest[3] = in_ipv6_hdr->dst_addr[12];
1428 } else if (ll->nsp.depth == 96) {
1429 ipv4_dest[0] = in_ipv6_hdr->dst_addr[12];
1430 ipv4_dest[1] = in_ipv6_hdr->dst_addr[13];
1431 ipv4_dest[2] = in_ipv6_hdr->dst_addr[14];
1432 ipv4_dest[3] = in_ipv6_hdr->dst_addr[15];
1443 memcpy(&ipv4_hdr_p->dst_addr, &ipv4_dest[0], 4);
1445 memcpy(&ipv4_hdr_p->dst_addr, &in_ipv6_hdr->dst_addr[12], 4);
1450 * Function to convert an IPv4 packet to IPv6 packet
1453 * A pointer to packet mbuf
1454 * @param in_ipv4_hdr
1455 * A pointer to IPv4 header in the given pkt
1459 convert_ipv4_to_ipv6(struct rte_mbuf *pkt, struct ipv4_hdr *in_ipv4_hdr)
1461 uint32_t ip_hdr_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE;
1463 uint8_t *eth_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1464 uint8_t *ipv4_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, ip_hdr_offset);
1466 struct ether_hdr eth_hdr;
1467 struct ipv6_hdr *ipv6_hdr_p;
1469 memcpy(ð_hdr, eth_hdr_p, sizeof(struct ether_hdr));
1470 memcpy(in_ipv4_hdr, ipv4_hdr_p, sizeof(struct ipv4_hdr));
1472 eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
1474 char *data_area_p = rte_pktmbuf_prepend(pkt, 20);
1475 if (data_area_p == NULL) {
1476 printf("convert_ipv4_to_ipv6:data_area_p is NULL\n");
1479 ipv6_hdr_p = (struct ipv6_hdr *)(data_area_p + ETH_HDR_SIZE);
1480 memset(ipv6_hdr_p, 0, sizeof(struct ipv6_hdr));
1482 memcpy(data_area_p, ð_hdr, sizeof(struct ether_hdr));
1484 ipv6_hdr_p->vtc_flow =
1485 rte_cpu_to_be_32((0x6 << 28) |
1486 (in_ipv4_hdr->type_of_service << 20));
1487 ipv6_hdr_p->payload_len =
1488 rte_cpu_to_be_16(rte_be_to_cpu_16(
1489 in_ipv4_hdr->total_length) - 20);
1490 ipv6_hdr_p->proto = in_ipv4_hdr->next_proto_id;
1491 ipv6_hdr_p->hop_limits = in_ipv4_hdr->time_to_live;
1493 ipv6_hdr_p->src_addr[0] = 0x00;
1494 ipv6_hdr_p->src_addr[1] = 0x64;
1495 ipv6_hdr_p->src_addr[2] = 0xff;
1496 ipv6_hdr_p->src_addr[3] = 0x9b;
1497 ipv6_hdr_p->src_addr[4] = 0x00;
1498 ipv6_hdr_p->src_addr[5] = 0x00;
1499 ipv6_hdr_p->src_addr[6] = 0x00;
1500 ipv6_hdr_p->src_addr[7] = 0x00;
1501 ipv6_hdr_p->src_addr[8] = 0x00;
1502 ipv6_hdr_p->src_addr[9] = 0x00;
1503 ipv6_hdr_p->src_addr[10] = 0x00;
1504 ipv6_hdr_p->src_addr[11] = 0x00;
1505 memcpy(&ipv6_hdr_p->src_addr[12], &in_ipv4_hdr->src_addr, 4);
1507 memset(&ipv6_hdr_p->dst_addr, 0, 16);
1514 * Output port handler
1517 * A pointer to packet mbuf
1519 * Unused void pointer
1522 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1524 pkt_work_cgnapt_out(__rte_unused struct rte_mbuf *pkt, __rte_unused void *arg)
1526 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1527 if ((cgnapt_num_func_to_inst == 5)
1528 && (cgnapt_inst_index < INST_ARRAY_SIZE)) {
1529 if (cgnapt_inst5_flag == 0) {
1530 uint8_t *inst5_sig =
1531 RTE_MBUF_METADATA_UINT8_PTR(pkt,
1533 if (*inst5_sig == CGNAPT_INST5_SIG) {
1534 cgnapt_inst5_flag = 1;
1535 inst_end_time[cgnapt_inst_index] =
1536 rte_get_tsc_cycles();
1537 cgnapt_inst_index++;
1543 /* cgnapt_pkt_out_count++; */
1544 #ifdef CGNAPT_DBG_PRNT
1552 * Output port handler to handle 4 pkts
1555 * A pointer to packet mbuf
1557 * Inport handler argument pointer
1560 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1561 static void pkt4_work_cgnapt_out(struct rte_mbuf **pkt, void *arg)
1565 /* TO BE IMPLEMENTED IF REQUIRED */
1569 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1570 PIPELINE_CGNAPT_PORT_OUT_AH(port_out_ah_cgnapt,
1571 pkt_work_cgnapt_out, pkt4_work_cgnapt_out);
1573 PIPELINE_CGNAPT_PORT_OUT_BAH(port_out_ah_cgnapt_bulk,
1574 pkt_work_cgnapt_out, pkt4_work_cgnapt_out);
1578 * Function to validate the packet and return version
1581 * A pointer to packet mbuf
1584 * IP version of the valid pkt, -1 if invalid pkt
1586 int rte_get_pkt_ver(struct rte_mbuf *pkt)
1588 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
1589 uint16_t *eth_proto =
1590 RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
1592 if (*eth_proto == rte_be_to_cpu_16(ETHER_TYPE_IPv4))
1593 return IP_VERSION_4;
1595 if (dual_stack_enable
1596 && (*eth_proto == rte_be_to_cpu_16(ETHER_TYPE_IPv6)))
1597 return IP_VERSION_6;
1599 /* Check the protocol first, if not UDP or TCP return */
1605 * A method to print the NAPT entry
1608 * A pointer to struct cgnapt_table_entry
1610 void my_print_entry(struct cgnapt_table_entry *ent)
1612 printf("CGNAPT key:\n");
1613 printf("entry_type :%d\n", ent->data.type);
1614 printf("prv_ip: %x %x %x %x\n", ent->data.u.u32_prv_ipv6[0],
1615 ent->data.u.u32_prv_ipv6[1], ent->data.u.u32_prv_ipv6[2],
1616 ent->data.u.u32_prv_ipv6[3]);
1617 printf("prv_port:%d\n", ent->data.prv_port);
1619 printf("pub_ip:%x\n", ent->data.pub_ip);
1620 printf("prv_phy_port:%d\n", ent->data.prv_phy_port);
1621 printf("pub_phy_port:%d\n", ent->data.pub_phy_port);
1625 * Function to print common CGNAPT table entries
1628 void print_common_table(void)
1636 index = rte_hash_iterate(napt_common_table,
1637 &key, &data, &next);
1639 if ((index != -EINVAL) && (index != -ENOENT)) {
1640 printf("\n%04d ", count);
1641 //print_key((struct pipeline_cgnapt_entry_key *)key);
1642 rte_hexdump(stdout, "KEY", key,
1643 sizeof(struct pipeline_cgnapt_entry_key));
1644 int32_t position = rte_hash_lookup(
1645 napt_common_table, key);
1646 print_cgnapt_entry(&napt_hash_tbl_entries[position]);
1650 } while (index != -ENOENT);
1654 * Input port handler for mixed traffic
1655 * This is the main method in this file when running in mixed traffic mode.
1656 * Starting from the packet burst it filters unwanted packets,
1657 * calculates keys, does lookup and then based on the lookup
1658 * updates NAPT table and does packet NAPT translation.
1661 * A pointer to struct rte_pipeline
1663 * A pointer to array of packets mbuf
1665 * Number of packets in the burst
1670 * int that is not checked by caller
1673 static int cgnapt_in_port_ah_mix(struct rte_pipeline *rte_p,
1674 struct rte_mbuf **pkts,
1675 uint32_t n_pkts, void *arg)
1680 * 1. Read packet version, if invalid drop the packet
1681 * 2. Check protocol, if not UDP or TCP drop the packet
1682 * 3. Bring all valid packets together - useful for bulk lookup
1683 * and calculate key for all packets
1684 * a. If IPv4 : calculate key with full IP
1685 * b. If IPv6 : calculate key with last 32-bit of IP
1686 * 4. Do bulk lookup with rte_hash_lookup_bulk(), if something went wrong
1688 * 5. For lookup hit packets, read entry from table
1689 * 6. For lookup miss packets, add dynamic entry to table
1691 * a. If egress pkt, convert to IPv4 and NAPT it
1692 * b. If ingress, drop the pkt
1694 * a. If egress pkt, NAPT it. Get MAC
1695 * b. If first ingress pkt (with no egress entry), drop the pkt
1696 * If not first ingress pkt
1697 * I. If IPv6 converted packet, convert back to IPv6,
1699 * II. If IPv4 packet, NAPT it & get MAC
1700 * 9. Send all packets out to corresponding ports
1702 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
1703 struct pipeline_cgnapt *p_nat = ap->p;
1704 uint8_t compacting_map[RTE_HASH_LOOKUP_BULK_MAX];
1705 uint32_t packets_for_lookup = 0;
1708 p_nat->valid_packets = 0;
1709 p_nat->invalid_packets = 0;
1711 #ifdef CGNAPT_DBG_PRNT
1712 if (CGNAPT_DEBUG > 1)
1713 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
1716 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
1718 uint16_t phy_port = 0;
1719 uint16_t *src_port = NULL;
1720 uint16_t *dst_port = NULL;
1721 uint32_t *src_addr = NULL;
1722 uint32_t *dst_addr = NULL;
1723 uint8_t *protocol = NULL;
1724 uint8_t *eth_dest = NULL;
1725 uint8_t *eth_src = NULL;
1726 uint16_t src_port_offset = 0;
1727 uint16_t dst_port_offset = 0;
1728 uint16_t src_addr_offset = 0;
1729 uint16_t dst_addr_offset = 0;
1730 uint16_t prot_offset = 0;
1731 uint16_t eth_offset = 0;
1734 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
1736 src_port_offset = SRC_PRT_OFST_IP4_TCP;
1737 dst_port_offset = DST_PRT_OFST_IP4_TCP;
1739 for (i = 0; i < n_pkts; i++) {
1740 p_nat->receivedPktCount++;
1742 /* bitmask representing only this packet */
1743 uint64_t pkt_mask = 1LLU << i;
1745 /* remember this pkt as valid pkt */
1746 p_nat->valid_packets |= pkt_mask;
1748 struct rte_mbuf *pkt = pkts[i];
1751 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
1754 int ver = rte_get_pkt_ver(pkt);
1756 #ifdef CGNAPT_DBG_PRNT
1757 printf("ver no. of the pkt:%d\n", ver);
1760 if (unlikely(ver < 0)) {
1761 /* Not a valid pkt , ignore. */
1762 /* remember invalid packets to be dropped */
1763 p_nat->invalid_packets |= pkt_mask;
1764 p_nat->naptDroppedPktCount++;
1766 #ifdef CGNAPT_DEBUGGING
1767 p_nat->naptDroppedPktCount1++;
1772 prot_offset = PROT_OFST_IP4;
1774 prot_offset = PROT_OFST_IP6;
1776 (uint8_t *) RTE_MBUF_METADATA_UINT32_PTR(pkt,
1779 (*protocol == IP_PROTOCOL_TCP
1780 || *protocol == IP_PROTOCOL_UDP
1781 || *protocol == IP_PROTOCOL_ICMP)) {
1782 /* remember invalid packets to be dropped */
1783 p_nat->invalid_packets |= pkt_mask;
1784 p_nat->naptDroppedPktCount++;
1786 #ifdef CGNAPT_DEBUGGING
1787 p_nat->naptDroppedPktCount2++;
1792 #ifdef CGNAPT_DBG_PRNT
1793 if (CGNAPT_DEBUG > 4)
1799 * 1. Handel PCP for egress traffic
1800 * 2. If PCP, then give response (send pkt) from the same port
1801 * 3. Drop the PCP packet, should not be added in the NAPT table
1804 if (*protocol == IP_PROTOCOL_UDP) {
1805 struct udp_hdr *udp;
1807 udp = (struct udp_hdr *)
1808 RTE_MBUF_METADATA_UINT8_PTR(pkt,
1811 udp = (struct udp_hdr *)
1812 RTE_MBUF_METADATA_UINT8_PTR(pkt,
1815 if (rte_bswap16(udp->dst_port) ==
1817 handle_pcp_req(pkt, ver, p_nat);
1818 p_nat->invalid_packets |= pkt_mask;
1828 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1831 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1834 if ((*protocol == IP_PROTOCOL_TCP)
1835 || (*protocol == IP_PROTOCOL_UDP)) {
1837 src_port_offset = SRC_PRT_OFST_IP4_TCP;
1838 dst_port_offset = DST_PRT_OFST_IP4_TCP;
1840 } else if (*protocol == IP_PROTOCOL_ICMP) {
1842 src_port_offset = IDEN_OFST_IP4_ICMP;
1843 /* Sequence number */
1844 dst_port_offset = SEQN_OFST_IP4_ICMP;
1848 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1851 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1856 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1859 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1862 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1865 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1868 /* need to create compacted table of pointers to
1869 * pass to bulk lookup
1872 compacting_map[packets_for_lookup] = i;
1874 //phy_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, phyport_offset);
1875 phy_port = pkt->port;
1877 struct pipeline_cgnapt_entry_key key;
1879 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
1882 if (get_in_port_dir(phy_port)) {
1885 key.ip = rte_bswap32(*src_addr);
1887 key.ip = rte_bswap32(src_addr[3]);
1888 key.port = rte_bswap16(*src_port);
1890 #ifdef NAT_ONLY_CONFIG_REQ
1891 if (nat_only_config_flag)
1896 key.ip = rte_bswap32(*dst_addr);
1898 if (*protocol == IP_PROTOCOL_ICMP) {
1899 /* common table lookupkey preparation from
1900 * incoming ICMP Packet- Indentifier field
1902 key.port = rte_bswap16(*src_port);
1904 key.port = rte_bswap16(*dst_port);
1907 #ifdef NAT_ONLY_CONFIG_REQ
1908 if (nat_only_config_flag)
1915 memcpy(&(p_nat->keys[packets_for_lookup]), &key,
1916 sizeof(struct pipeline_cgnapt_entry_key));
1917 p_nat->key_ptrs[packets_for_lookup] =
1918 &(p_nat->keys[packets_for_lookup]);
1919 packets_for_lookup++;
1922 if (unlikely(packets_for_lookup == 0)) {
1923 /* no suitable packet for lookup */
1924 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
1925 return p_nat->valid_packets;
1928 /* lookup entries in the common napt table */
1930 int lookup_result = rte_hash_lookup_bulk(napt_common_table,
1934 &p_nat->lkup_indx[0]);
1936 if (unlikely(lookup_result < 0)) {
1937 /* unknown error, just discard all packets */
1938 printf("Unexpected hash lookup error %d, discarding all "
1939 "packets", lookup_result);
1940 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
1943 //struct rte_pipeline_table_entry *entries[64];
1944 /* Now one by one check the result of our bulk lookup */
1946 for (i = 0; i < packets_for_lookup; i++) {
1947 /* index into hash table entries */
1948 int hash_table_entry = p_nat->lkup_indx[i];
1949 /* index into packet table of this packet */
1950 uint8_t pkt_index = compacting_map[i];
1951 /*bitmask representing only this packet */
1952 uint64_t pkt_mask = 1LLU << pkt_index;
1954 struct cgnapt_table_entry *entry = NULL;
1955 if (hash_table_entry < 0) {
1957 /* try to add new entry */
1958 struct rte_pipeline_table_entry *table_entry = NULL;
1961 pkt_miss_cgnapt(p_nat->key_ptrs[i],
1964 &p_nat->valid_packets,
1969 /* ICMP Error message generation for
1970 * Destination Host unreachable
1972 if (*protocol == IP_PROTOCOL_ICMP) {
1973 cgnapt_icmp_pkt = pkts[pkt_index];
1974 send_icmp_dest_unreachable_msg();
1977 /* Drop packet by adding to invalid pkt mask */
1979 p_nat->invalid_packets |= dropmask;
1980 #ifdef CGNAPT_DEBUGGING
1981 if (p_nat->kpc2++ < 5) {
1982 printf("in_ah Th: %d",
1983 p_nat->pipeline_num);
1984 print_key(p_nat->key_ptrs[i]);
1988 p_nat->naptDroppedPktCount++;
1990 #ifdef CGNAPT_DEBUGGING
1991 p_nat->naptDroppedPktCount3++;
1996 entry = (struct cgnapt_table_entry *)table_entry;
1998 /* entry found for this packet */
1999 entry = &napt_hash_tbl_entries[hash_table_entry];
2002 /* apply napt and mac changes */
2004 p_nat->entries[pkt_index] = &(entry->head);
2006 phy_port = pkts[pkt_index]->port;
2008 struct ipv6_hdr ipv6_hdr;
2009 struct ipv4_hdr ipv4_hdr;
2011 ver = rte_get_pkt_ver(pkts[pkt_index]);
2012 #ifdef CGNAPT_DEBUGGING
2013 if (CGNAPT_DEBUG >= 1) {
2014 printf("ver:%d\n", ver);
2015 printf("entry->data.type:%d\n", entry->data.type);
2018 if ((ver == 6) && (entry->data.type == CGNAPT_ENTRY_IPV6)
2019 && is_phy_port_privte(phy_port)) {
2020 convert_ipv6_to_ipv4(pkts[pkt_index], &ipv6_hdr);
2022 pkt_type = PKT_TYPE_IPV6to4;
2024 #ifdef CGNAPT_DBG_PRNT
2025 if (CGNAPT_DEBUG >= 1)
2026 printf("pkt_work_cganpt: "
2027 "convert_ipv6_to_ipv4\n");
2030 struct cgnapt_nsp_node *ll = nsp_ll;
2032 while (ll != NULL) {
2033 if (!memcmp(&ipv6_hdr.dst_addr[0],
2035 ll->nsp.depth / 8)) {
2043 && !memcmp(&ipv6_hdr.dst_addr[0],
2044 &well_known_prefix[0], 12)) {
2049 p_nat->invalid_packets |= 1LLU << pkt_index;
2050 p_nat->naptDroppedPktCount++;
2052 #ifdef CGNAPT_DEBUGGING
2053 p_nat->naptDroppedPktCount5++;
2060 /* As packet is already converted into IPv4 we must not operate
2061 * IPv6 offsets on packet
2062 * Only perform IPv4 operations
2067 src_port_offset = SRC_PRT_OFST_IP6t4;
2068 dst_port_offset = DST_PRT_OFST_IP6t4;
2069 src_addr_offset = SRC_ADR_OFST_IP6t4;
2070 dst_addr_offset = DST_ADR_OFST_IP6t4;
2071 prot_offset = PROT_OFST_IP6t4;
2072 eth_offset = ETH_OFST_IP6t4;
2076 if ((*protocol == IP_PROTOCOL_TCP)
2077 || (*protocol == IP_PROTOCOL_UDP)) {
2078 src_port_offset = SRC_PRT_OFST_IP4_TCP;
2079 dst_port_offset = DST_PRT_OFST_IP4_TCP;
2080 } else if (*protocol == IP_PROTOCOL_ICMP) {
2082 src_port_offset = IDEN_OFST_IP4_ICMP;
2083 /* Sequence number */
2084 dst_port_offset = SEQN_OFST_IP4_ICMP;
2087 src_addr_offset = SRC_ADR_OFST_IP4;
2088 dst_addr_offset = DST_ADR_OFST_IP4;
2089 prot_offset = PROT_OFST_IP4;
2090 eth_offset = MBUF_HDR_ROOM;
2095 RTE_MBUF_METADATA_UINT32_PTR(pkts[pkt_index],
2098 RTE_MBUF_METADATA_UINT32_PTR(pkts[pkt_index],
2101 RTE_MBUF_METADATA_UINT16_PTR(pkts[pkt_index],
2104 RTE_MBUF_METADATA_UINT16_PTR(pkts[pkt_index],
2107 RTE_MBUF_METADATA_UINT8_PTR(pkts[pkt_index],
2111 RTE_MBUF_METADATA_UINT8_PTR(pkts[pkt_index],
2114 RTE_MBUF_METADATA_UINT8_PTR(pkts[pkt_index],
2117 if (entry->data.ttl == NAPT_ENTRY_STALE)
2118 entry->data.ttl = NAPT_ENTRY_VALID;
2120 struct ether_addr hw_addr;
2121 uint32_t dest_address = 0;
2122 uint8_t nh_ipv6[16];
2125 uint32_t dest_if = 0xff;
2128 uint16_t *outport_id =
2129 RTE_MBUF_METADATA_UINT16_PTR(pkts[pkt_index],
2130 cgnapt_meta_offset);
2132 if (is_phy_port_privte(phy_port)) {
2134 if (*protocol == IP_PROTOCOL_UDP
2135 && rte_be_to_cpu_16(*dst_port) == 53) {
2136 p_nat->invalid_packets |= 1LLU << pkt_index;
2137 p_nat->naptDroppedPktCount++;
2138 #ifdef CGNAPT_DEBUGGING
2139 p_nat->naptDroppedPktCount6++;
2144 dest_address = rte_bswap32(*dst_addr);
2145 ret = local_get_nh_ipv4(dest_address, &dest_if,
2148 dest_if = get_prv_to_pub_port(&dest_address,
2150 if (dest_if == INVALID_DESTIF) {
2151 p_nat->invalid_packets |=
2153 p_nat->naptDroppedPktCount++;
2154 #ifdef CGNAPT_DEBUGGING
2155 p_nat->naptDroppedPktCount6++;
2159 do_local_nh_ipv4_cache(dest_if, p_nat);
2162 *outport_id = p_nat->outport_id[dest_if];
2164 ret = get_dest_mac_addr_port(dest_address,
2165 &dest_if, &hw_addr);
2167 if (ret == ARP_FOUND) {
2168 memcpy(eth_dest, &hw_addr,
2169 sizeof(struct ether_addr));
2170 memcpy(eth_src, get_link_hw_addr(dest_if),
2171 sizeof(struct ether_addr));
2172 #ifdef CGNAPT_DBG_PRNT
2173 if (CGNAPT_DEBUG > 2) {
2174 printf("MAC found for ip 0x%x, port %d - "
2175 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2176 dest_address, *outport_id,
2177 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
2178 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
2179 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
2181 printf("Dest MAC before - "
2182 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2183 eth_dest[0], eth_dest[1], eth_dest[2],
2184 eth_dest[3], eth_dest[4], eth_dest[5]);
2188 #ifdef CGNAPT_DBG_PRNT
2189 if (CGNAPT_DEBUG > 2) {
2190 printf("Dest MAC after - "
2191 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2192 eth_dest[0], eth_dest[1], eth_dest[2],
2193 eth_dest[3], eth_dest[4], eth_dest[5]);
2197 #ifdef CGNAPT_DBG_PRNT
2198 if (CGNAPT_DEBUG > 4)
2199 print_pkt(pkts[pkt_index]);
2203 if (ret == ARP_NOT_FOUND) {
2204 /* Commented code may be required
2205 * for future use, Please keep it */
2206 //request_arp(*outport_id, nhip,
2208 printf("%s: ARP Not Found, nhip: %x, "
2209 "outport_id: %d\n", __func__, nhip,
2213 p_nat->invalid_packets |= pkt_mask;
2214 p_nat->naptDroppedPktCount++;
2215 #ifdef CGNAPT_DEBUGGING
2216 p_nat->naptDroppedPktCount4++;
2221 #ifdef CGNAPT_DBG_PRNT
2222 if (CGNAPT_DEBUG > 2)
2223 printf("Egress: \tphy_port:%d\t "
2224 "get_prv_to_pub():%d \tout_port:%d\n",
2230 *src_addr = rte_bswap32(entry->data.pub_ip);
2232 #ifdef NAT_ONLY_CONFIG_REQ
2233 if (!nat_only_config_flag) {
2235 *src_port = rte_bswap16(entry->data.pub_port);
2236 #ifdef NAT_ONLY_CONFIG_REQ
2240 p_nat->enaptedPktCount++;
2243 if (*protocol == IP_PROTOCOL_UDP
2244 && rte_be_to_cpu_16(*src_port) == 53) {
2245 p_nat->invalid_packets |= 1LLU << pkt_index;
2246 p_nat->naptDroppedPktCount++;
2247 #ifdef CGNAPT_DEBUGGING
2248 p_nat->naptDroppedPktCount6++;
2253 #ifdef CGNAPT_DBG_PRNT
2254 if (CGNAPT_DEBUG > 2)
2255 printf("Ingress: \tphy_port:%d\t "
2256 "get_pub_to_prv():%d \tout_port%d\n",
2261 if (entry->data.type == CGNAPT_ENTRY_IPV6) {
2262 convert_ipv4_to_ipv6(pkts[pkt_index],
2264 pkt_type = PKT_TYPE_IPV4to6;
2265 /* Ethernet MTU check */
2266 if ((rte_pktmbuf_data_len(pkts[pkt_index]) -
2268 p_nat->invalid_packets |= pkt_mask;
2269 p_nat->naptDroppedPktCount++;
2273 eth_dest = eth_dest - 20;
2274 eth_src = eth_src - 20;
2276 dst_port_offset = DST_PRT_OFST_IP4t6;
2277 dst_addr_offset = DST_ADR_OFST_IP4t6;
2279 RTE_MBUF_METADATA_UINT32_PTR(
2283 RTE_MBUF_METADATA_UINT16_PTR(
2287 memcpy((uint8_t *) &dst_addr[0],
2288 &entry->data.u.prv_ipv6[0], 16);
2289 memset(nh_ipv6, 0, 16);
2291 ret = local_get_nh_ipv6((uint8_t *)&dst_addr[0],
2292 &dest_if, &nh_ipv6[0], p_nat);
2295 dest_if = get_prv_to_pub_port(
2298 if (dest_if == INVALID_DESTIF) {
2299 p_nat->invalid_packets |=
2301 p_nat->naptDroppedPktCount++;
2302 #ifdef CGNAPT_DEBUGGING
2303 p_nat->naptDroppedPktCount6++;
2307 do_local_nh_ipv6_cache(dest_if, p_nat);
2309 *outport_id = p_nat->outport_id[dest_if];
2311 if (get_dest_mac_address_ipv6_port((uint8_t *)
2312 &dst_addr[0], &dest_if,
2313 &hw_addr, &nh_ipv6[0])){
2315 #ifdef CGNAPT_DBG_PRNT
2316 if (CGNAPT_DEBUG > 2) {
2317 printf("MAC found for ip 0x%x, port %d - "
2318 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2319 dest_address, *outport_id,
2320 hw_addr.addr_bytes[0],
2321 hw_addr.addr_bytes[1], hw_addr.addr_bytes[2],
2322 hw_addr.addr_bytes[3], hw_addr.addr_bytes[4],
2323 hw_addr.addr_bytes[5]);
2325 printf("Dest MAC before - "
2326 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2327 eth_dest[0], eth_dest[1], eth_dest[2],
2328 eth_dest[3], eth_dest[4], eth_dest[5]);
2331 memcpy(eth_dest, &hw_addr,
2332 sizeof(struct ether_addr));
2333 memcpy(eth_src, get_link_hw_addr(
2335 sizeof(struct ether_addr));
2337 #ifdef CGNAPT_DBG_PRNT
2338 if (CGNAPT_DEBUG > 2) {
2339 printf("Dest MAC after - "
2340 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2341 eth_dest[0], eth_dest[1], eth_dest[2],
2342 eth_dest[3], eth_dest[4], eth_dest[5]);
2346 #ifdef CGNAPT_DBG_PRNT
2347 if (CGNAPT_DEBUG > 4)
2348 print_pkt(pkts[pkt_index]);
2352 p_nat->invalid_packets |= pkt_mask;
2353 p_nat->naptDroppedPktCount++;
2354 #ifdef CGNAPT_DEBUGGING
2355 p_nat->naptDroppedPktCount4++;
2360 #ifdef NAT_ONLY_CONFIG_REQ
2361 if (!nat_only_config_flag) {
2364 rte_bswap16(entry->data.prv_port);
2365 #ifdef NAT_ONLY_CONFIG_REQ
2370 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
2371 dest_address = entry->data.u.prv_ip;
2372 ret = local_get_nh_ipv4(dest_address, &dest_if,
2375 dest_if = get_pub_to_prv_port(
2376 &dest_address, IP_VERSION_4);
2377 if (dest_if == INVALID_DESTIF) {
2378 p_nat->invalid_packets |=
2380 p_nat->naptDroppedPktCount++;
2381 #ifdef CGNAPT_DEBUGGING
2382 p_nat->naptDroppedPktCount6++;
2386 do_local_nh_ipv4_cache(dest_if, p_nat);
2389 *outport_id = p_nat->outport_id[dest_if];
2391 ret = get_dest_mac_addr_port(dest_address,
2392 &dest_if, &hw_addr);
2394 if (ret == ARP_FOUND) {
2395 memcpy(eth_dest, &hw_addr,
2396 sizeof(struct ether_addr));
2397 memcpy(eth_src, get_link_hw_addr(
2399 sizeof(struct ether_addr));
2400 #ifdef CGNAPT_DBG_PRNT
2401 if (CGNAPT_DEBUG > 2) {
2402 printf("MAC found for ip 0x%x, port %d - "
2403 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2404 dest_address, *outport_id,
2405 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
2406 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
2407 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
2409 printf("Dest MAC before - "
2410 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2411 eth_dest[0], eth_dest[1], eth_dest[2],
2412 eth_dest[3], eth_dest[4], eth_dest[5]);
2416 #ifdef CGNAPT_DBG_PRNT
2417 if (CGNAPT_DEBUG > 2) {
2418 printf("Dest MAC after - "
2419 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2420 eth_dest[0], eth_dest[1], eth_dest[2],
2421 eth_dest[3], eth_dest[4], eth_dest[5]);
2425 #ifdef CGNAPT_DBG_PRNT
2426 if (CGNAPT_DEBUG > 4)
2427 print_pkt(pkts[pkt_index]);
2431 if (ret == ARP_NOT_FOUND) {
2432 printf("%s: ARP Not Found, nhip: %x, "
2433 "outport_id: %d\n", __func__, nhip,
2436 //request_arp(*outport_id,
2437 // nhip, p_nat->p.p);
2438 p_nat->invalid_packets |= pkt_mask;
2439 p_nat->naptDroppedPktCount++;
2440 #ifdef CGNAPT_DEBUGGING
2441 p_nat->naptDroppedPktCount4++;
2446 if (*protocol == IP_PROTOCOL_ICMP) {
2447 // Query ID reverse translation done here
2449 rte_bswap16(entry->data.prv_port);
2451 #ifdef NAT_ONLY_CONFIG_REQ
2452 if (!nat_only_config_flag) {
2457 #ifdef NAT_ONLY_CONFIG_REQ
2463 p_nat->inaptedPktCount++;
2466 p_nat->naptedPktCount++;
2468 #ifdef HW_CHECKSUM_REQ
2469 if (p_nat->hw_checksum_reqd)
2470 hw_checksum(pkts[pkt_index], pkt_type);
2473 sw_checksum(pkts[pkt_index], pkt_type);
2476 if (p_nat->invalid_packets) {
2477 /* get rid of invalid packets */
2478 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2480 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2482 #ifdef CGNAPT_DBG_PRNT
2483 if (CGNAPT_DEBUG > 1) {
2484 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
2485 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
2486 printf("invalid_packets:0x%jx\n",
2487 p_nat->invalid_packets);
2488 printf("rte_invalid_packets :0x%jx\n",
2489 rte_p->pkts_drop_mask);
2490 printf("Total pkts dropped :0x%jx\n",
2491 rte_p->n_pkts_ah_drop);
2496 return p_nat->valid_packets;
2500 * Input port handler for IPv4 private traffic
2501 * Starting from the packet burst it filters unwanted packets,
2502 * calculates keys, does lookup and then based on the lookup
2503 * updates NAPT table and does packet NAPT translation.
2506 * A pointer to struct rte_pipeline
2508 * A pointer to array of packets mbuf
2510 * Number of packets in the burst
2515 * int that is not checked by caller
2518 static int cgnapt_in_port_ah_ipv4_prv(struct rte_pipeline *rte_p,
2519 struct rte_mbuf **pkts,
2520 uint32_t n_pkts, void *arg)
2523 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
2524 struct pipeline_cgnapt *p_nat = ap->p;
2526 #ifdef CGNAPT_TIMING_INST
2527 uint64_t entry_timestamp = 0, exit_timestamp;
2529 if (p_nat->time_measurements_on) {
2530 entry_timestamp = rte_get_tsc_cycles();
2531 /* check since exit ts not valid first time through */
2532 if (likely(p_nat->in_port_exit_timestamp))
2533 p_nat->external_time_sum +=
2534 entry_timestamp - p_nat->in_port_exit_timestamp;
2538 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
2539 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
2540 p_nat->invalid_packets = 0;
2542 #ifdef CGNAPT_DBG_PRNT
2543 if (CGNAPT_DEBUG > 1)
2544 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
2547 /* prefetching for mbufs should be done here */
2548 for (j = 0; j < n_pkts; j++)
2549 rte_prefetch0(pkts[j]);
2551 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2552 pkt4_work_cgnapt_key_ipv4_prv(&pkts[i], i, arg, p_nat);
2554 for (; i < n_pkts; i++)
2555 pkt_work_cgnapt_key_ipv4_prv(pkts[i], i, arg, p_nat);
2557 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2559 if (unlikely(p_nat->valid_packets == 0)) {
2560 /* no suitable packet for lookup */
2561 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2562 return p_nat->valid_packets;
2565 /* lookup entries in the common napt table */
2567 int lookup_result = rte_hash_lookup_bulk(
2569 (const void **)&p_nat->key_ptrs,
2570 /* should be minus num invalid pkts */
2572 /*new pipeline data member */
2573 &p_nat->lkup_indx[0]);
2575 if (unlikely(lookup_result < 0)) {
2576 /* unknown error, just discard all packets */
2577 printf("Unexpected hash lookup error %d, discarding "
2578 "all packets", lookup_result);
2579 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
2583 /* Now call second stage of pipeline to one by one
2584 * check the result of our bulk lookup
2587 /* prefetching for table entries should be done here */
2588 for (j = 0; j < n_pkts; j++) {
2589 if (p_nat->lkup_indx[j] >= 0)
2590 rte_prefetch0(&napt_hash_tbl_entries
2591 [p_nat->lkup_indx[j]]);
2594 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2595 pkt4_work_cgnapt_ipv4_prv(pkts, i, arg, p_nat);
2597 for (; i < n_pkts; i++)
2598 pkt_work_cgnapt_ipv4_prv(pkts, i, arg, p_nat);
2600 if (p_nat->invalid_packets) {
2601 /* get rid of invalid packets */
2602 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2604 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2606 #ifdef CGNAPT_DBG_PRNT
2607 if (CGNAPT_DEBUG > 1) {
2608 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
2609 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
2610 printf("invalid_packets:0x%jx\n",
2611 p_nat->invalid_packets);
2612 printf("rte_invalid_packets :0x%jx\n",
2613 rte_p->pkts_drop_mask);
2614 printf("Total pkts dropped :0x%jx\n",
2615 rte_p->n_pkts_ah_drop);
2620 #ifdef CGNAPT_TIMING_INST
2621 if (p_nat->time_measurements_on) {
2622 exit_timestamp = rte_get_tsc_cycles();
2623 p_nat->in_port_exit_timestamp = exit_timestamp;
2624 p_nat->internal_time_sum += exit_timestamp - entry_timestamp;
2625 p_nat->time_measurements++;
2626 if (p_nat->time_measurements == p_nat->max_time_mesurements)
2627 p_nat->time_measurements_on = 0;
2631 return p_nat->valid_packets;
2635 * Input port handler for IPv4 public traffic
2636 * Starting from the packet burst it filters unwanted packets,
2637 * calculates keys, does lookup and then based on the lookup
2638 * updates NAPT table and does packet NAPT translation.
2641 * A pointer to struct rte_pipeline
2643 * A pointer to array of packets mbuf
2645 * Number of packets in the burst
2650 * int that is not checked by caller
2652 static int cgnapt_in_port_ah_ipv4_pub(struct rte_pipeline *rte_p,
2653 struct rte_mbuf **pkts,
2654 uint32_t n_pkts, void *arg)
2657 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
2658 struct pipeline_cgnapt *p_nat = ap->p;
2660 #ifdef CGNAPT_TIMING_INST
2661 uint64_t entry_timestamp = 0, exit_timestamp;
2663 if (p_nat->time_measurements_on) {
2664 entry_timestamp = rte_get_tsc_cycles();
2666 /* check since exit ts not valid first time through */
2667 if (likely(p_nat->in_port_exit_timestamp))
2668 p_nat->external_time_sum +=
2669 entry_timestamp - p_nat->in_port_exit_timestamp;
2673 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
2674 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
2675 p_nat->invalid_packets = 0;
2677 #ifdef CGNAPT_DBG_PRNT
2678 if (CGNAPT_DEBUG > 1)
2679 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
2682 /* prefetching for mbufs should be done here */
2683 for (j = 0; j < n_pkts; j++)
2684 rte_prefetch0(pkts[j]);
2686 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2687 pkt4_work_cgnapt_key_ipv4_pub(&pkts[i], i, arg, p_nat);
2689 for (; i < n_pkts; i++)
2690 pkt_work_cgnapt_key_ipv4_pub(pkts[i], i, arg, p_nat);
2692 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2694 if (unlikely(p_nat->valid_packets == 0)) {
2695 /* no suitable packet for lookup */
2696 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2697 return p_nat->valid_packets;
2700 /* lookup entries in the common napt table */
2702 int lookup_result = rte_hash_lookup_bulk(
2704 (const void **)&p_nat->key_ptrs,
2705 /* should be minus num invalid pkts */
2707 /*new pipeline data member */
2708 &p_nat->lkup_indx[0]);
2710 if (unlikely(lookup_result < 0)) {
2711 /* unknown error, just discard all packets */
2712 printf("Unexpected hash lookup error %d, discarding "
2713 "all packets", lookup_result);
2714 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
2718 /* Now call second stage of pipeline to one by one
2719 * check the result of our bulk lookup
2722 /* prefetching for table entries should be done here */
2723 for (j = 0; j < n_pkts; j++) {
2724 if (p_nat->lkup_indx[j] >= 0)
2725 rte_prefetch0(&napt_hash_tbl_entries
2726 [p_nat->lkup_indx[j]]);
2729 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2730 pkt4_work_cgnapt_ipv4_pub(pkts, i, arg, p_nat);
2732 for (; i < n_pkts; i++)
2733 pkt_work_cgnapt_ipv4_pub(pkts, i, arg, p_nat);
2735 if (p_nat->invalid_packets) {
2736 /* get rid of invalid packets */
2737 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2739 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2741 #ifdef CGNAPT_DBG_PRNT
2742 if (CGNAPT_DEBUG > 1) {
2743 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
2744 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
2745 printf("invalid_packets:0x%jx\n",
2746 p_nat->invalid_packets);
2747 printf("rte_invalid_packets :0x%jx\n",
2748 rte_p->pkts_drop_mask);
2749 printf("Total pkts dropped :0x%jx\n",
2750 rte_p->n_pkts_ah_drop);
2755 #ifdef CGNAPT_TIMING_INST
2756 if (p_nat->time_measurements_on) {
2757 exit_timestamp = rte_get_tsc_cycles();
2758 p_nat->in_port_exit_timestamp = exit_timestamp;
2760 p_nat->internal_time_sum += exit_timestamp - entry_timestamp;
2761 p_nat->time_measurements++;
2762 if (p_nat->time_measurements == p_nat->max_time_mesurements)
2763 p_nat->time_measurements_on = 0;
2767 return p_nat->valid_packets;
2771 * NAPT key calculation function for IPv4 private traffic
2772 * which handles 4 pkts
2775 * A pointer to array of packets mbuf
2777 * Starting pkt number of pkts
2781 * A pointer to main CGNAPT structure
2785 pkt4_work_cgnapt_key_ipv4_prv(
2786 struct rte_mbuf **pkt,
2788 __rte_unused void *arg,
2789 struct pipeline_cgnapt *p_nat)
2791 p_nat->receivedPktCount += 4;
2792 /* bitmask representing only this packet */
2793 uint64_t pkt_mask0 = 1LLU << pkt_num;
2794 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
2795 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
2796 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
2798 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
2800 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
2802 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
2804 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
2807 uint32_t src_addr0 = RTE_MBUF_METADATA_UINT32(pkt[0],
2809 uint32_t src_addr1 = RTE_MBUF_METADATA_UINT32(pkt[1],
2811 uint32_t src_addr2 = RTE_MBUF_METADATA_UINT32(pkt[2],
2813 uint32_t src_addr3 = RTE_MBUF_METADATA_UINT32(pkt[3],
2816 uint16_t src_port_offset0;
2817 uint16_t src_port_offset1;
2818 uint16_t src_port_offset2;
2819 uint16_t src_port_offset3;
2826 uint16_t phy_port0 = pkt[0]->port;
2827 uint16_t phy_port1 = pkt[1]->port;
2828 uint16_t phy_port2 = pkt[2]->port;
2829 uint16_t phy_port3 = pkt[3]->port;
2831 struct pipeline_cgnapt_entry_key key0;
2832 struct pipeline_cgnapt_entry_key key1;
2833 struct pipeline_cgnapt_entry_key key2;
2834 struct pipeline_cgnapt_entry_key key3;
2836 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
2837 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
2838 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
2839 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
2842 #ifdef CGNAPT_DBG_PRNT
2843 if (CGNAPT_DEBUG > 4)
2848 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
2852 switch (protocol0) {
2853 case IP_PROTOCOL_UDP:
2857 struct udp_hdr *udp;
2859 udp = (struct udp_hdr *)
2860 RTE_MBUF_METADATA_UINT8_PTR(pkt[0],
2863 if (rte_bswap16(udp->dst_port) ==
2865 handle_pcp_req(pkt[0], IPV4_SZ, p_nat);
2866 p_nat->invalid_packets |= pkt_mask0;
2872 case IP_PROTOCOL_TCP:
2874 src_port_offset0 = SRC_PRT_OFST_IP4_TCP;
2875 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
2880 case IP_PROTOCOL_ICMP:
2882 src_port_offset0 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
2884 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
2890 /* remember invalid packets to be dropped */
2891 p_nat->invalid_packets |= pkt_mask0;
2892 p_nat->naptDroppedPktCount++;
2894 #ifdef CGNAPT_DEBUGGING
2895 p_nat->naptDroppedPktCount2++;
2900 key0.pid = phy_port0;
2901 key0.ip = rte_bswap32(src_addr0);
2902 key0.port = rte_bswap16(src_port0);
2904 #ifdef NAT_ONLY_CONFIG_REQ
2905 if (nat_only_config_flag)
2909 memcpy(&p_nat->keys[pkt_num], &key0,
2910 sizeof(struct pipeline_cgnapt_entry_key));
2911 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
2916 #ifdef CGNAPT_DBG_PRNT
2917 if (CGNAPT_DEBUG > 4)
2922 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
2925 switch (protocol1) {
2926 case IP_PROTOCOL_UDP:
2930 struct udp_hdr *udp;
2932 udp = (struct udp_hdr *)
2933 RTE_MBUF_METADATA_UINT8_PTR(pkt[1],
2936 if (rte_bswap16(udp->dst_port) ==
2938 handle_pcp_req(pkt[1], IPV4_SZ, p_nat);
2939 p_nat->invalid_packets |= pkt_mask1;
2945 case IP_PROTOCOL_TCP:
2947 src_port_offset1 = SRC_PRT_OFST_IP4_TCP;
2948 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
2953 case IP_PROTOCOL_ICMP:
2955 src_port_offset1 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
2957 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
2963 /* remember invalid packets to be dropped */
2964 p_nat->invalid_packets |= pkt_mask1;
2965 p_nat->naptDroppedPktCount++;
2967 #ifdef CGNAPT_DEBUGGING
2968 p_nat->naptDroppedPktCount2++;
2973 key1.pid = phy_port1;
2974 key1.ip = rte_bswap32(src_addr1);
2975 key1.port = rte_bswap16(src_port1);
2977 #ifdef NAT_ONLY_CONFIG_REQ
2978 if (nat_only_config_flag)
2982 memcpy(&p_nat->keys[pkt_num + 1], &key1,
2983 sizeof(struct pipeline_cgnapt_entry_key));
2984 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
2988 #ifdef CGNAPT_DBG_PRNT
2989 if (CGNAPT_DEBUG > 4)
2994 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
2998 switch (protocol2) {
2999 case IP_PROTOCOL_UDP:
3003 struct udp_hdr *udp;
3005 udp = (struct udp_hdr *)
3006 RTE_MBUF_METADATA_UINT8_PTR(pkt[2],
3009 if (rte_bswap16(udp->dst_port) ==
3011 handle_pcp_req(pkt[2], IPV4_SZ, p_nat);
3012 p_nat->invalid_packets |= pkt_mask2;
3018 case IP_PROTOCOL_TCP:
3020 src_port_offset2 = SRC_PRT_OFST_IP4_TCP;
3021 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3026 case IP_PROTOCOL_ICMP:
3028 src_port_offset2 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3030 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3036 /* remember invalid packets to be dropped */
3037 p_nat->invalid_packets |= pkt_mask2;
3038 p_nat->naptDroppedPktCount++;
3040 #ifdef CGNAPT_DEBUGGING
3041 p_nat->naptDroppedPktCount2++;
3046 key2.pid = phy_port2;
3047 key2.ip = rte_bswap32(src_addr2);
3048 key2.port = rte_bswap16(src_port2);
3050 #ifdef NAT_ONLY_CONFIG_REQ
3051 if (nat_only_config_flag)
3055 memcpy(&p_nat->keys[pkt_num + 2], &key2,
3056 sizeof(struct pipeline_cgnapt_entry_key));
3057 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
3061 #ifdef CGNAPT_DBG_PRNT
3062 if (CGNAPT_DEBUG > 4)
3066 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
3070 switch (protocol3) {
3071 case IP_PROTOCOL_UDP:
3075 struct udp_hdr *udp;
3077 udp = (struct udp_hdr *)
3078 RTE_MBUF_METADATA_UINT8_PTR(pkt[3],
3081 if (rte_bswap16(udp->dst_port) ==
3083 handle_pcp_req(pkt[3], IPV4_SZ, p_nat);
3084 p_nat->invalid_packets |= pkt_mask3;
3090 case IP_PROTOCOL_TCP:
3092 src_port_offset3 = SRC_PRT_OFST_IP4_TCP;
3093 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3098 case IP_PROTOCOL_ICMP:
3100 src_port_offset3 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3102 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3108 /* remember invalid packets to be dropped */
3109 p_nat->invalid_packets |= pkt_mask3;
3110 p_nat->naptDroppedPktCount++;
3112 #ifdef CGNAPT_DEBUGGING
3113 p_nat->naptDroppedPktCount2++;
3118 key3.pid = phy_port3;
3119 key3.ip = rte_bswap32(src_addr3);
3120 key3.port = rte_bswap16(src_port3);
3122 #ifdef NAT_ONLY_CONFIG_REQ
3123 if (nat_only_config_flag)
3127 memcpy(&p_nat->keys[pkt_num + 3], &key3,
3128 sizeof(struct pipeline_cgnapt_entry_key));
3129 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
3133 * NAPT key calculation function for IPv4 public traffic
3134 * which handles 4 pkts
3137 * A pointer to array of packets mbuf
3139 * Starting pkt number of pkts
3143 * A pointer to main CGNAPT structure
3147 pkt4_work_cgnapt_key_ipv4_pub(
3148 struct rte_mbuf **pkt,
3150 __rte_unused void *arg,
3151 struct pipeline_cgnapt *p_nat)
3153 p_nat->receivedPktCount += 4;
3154 /* bitmask representing only this packet */
3155 uint64_t pkt_mask0 = 1LLU << pkt_num;
3156 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
3157 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
3158 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
3160 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
3162 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
3164 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
3166 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
3169 uint32_t dst_addr0 = RTE_MBUF_METADATA_UINT32(pkt[0],
3171 uint32_t dst_addr1 = RTE_MBUF_METADATA_UINT32(pkt[1],
3173 uint32_t dst_addr2 = RTE_MBUF_METADATA_UINT32(pkt[2],
3175 uint32_t dst_addr3 = RTE_MBUF_METADATA_UINT32(pkt[3],
3178 uint16_t src_port_offset0;
3179 uint16_t src_port_offset1;
3180 uint16_t src_port_offset2;
3181 uint16_t src_port_offset3;
3183 uint16_t dst_port_offset0;
3184 uint16_t dst_port_offset1;
3185 uint16_t dst_port_offset2;
3186 uint16_t dst_port_offset3;
3198 struct pipeline_cgnapt_entry_key key0;
3199 struct pipeline_cgnapt_entry_key key1;
3200 struct pipeline_cgnapt_entry_key key2;
3201 struct pipeline_cgnapt_entry_key key3;
3203 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
3204 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
3205 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
3206 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
3209 #ifdef CGNAPT_DBG_PRNT
3210 if (CGNAPT_DEBUG > 4)
3215 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
3219 switch (protocol0) {
3220 case IP_PROTOCOL_UDP:
3221 case IP_PROTOCOL_TCP:
3223 src_port_offset0 = SRC_PRT_OFST_IP4_TCP;
3224 dst_port_offset0 = DST_PRT_OFST_IP4_TCP;
3226 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3228 dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3231 key0.port = rte_bswap16(dst_port0);
3235 case IP_PROTOCOL_ICMP:
3237 src_port_offset0 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3239 /*Sequence number */
3240 dst_port_offset0 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3243 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3245 dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3248 key0.port = rte_bswap16(src_port0);
3253 /* remember invalid packets to be dropped */
3254 p_nat->invalid_packets |= pkt_mask0;
3255 p_nat->naptDroppedPktCount++;
3257 #ifdef CGNAPT_DEBUGGING
3258 p_nat->naptDroppedPktCount2++;
3264 key0.ip = rte_bswap32(dst_addr0);
3266 #ifdef NAT_ONLY_CONFIG_REQ
3267 if (nat_only_config_flag)
3271 memcpy(&p_nat->keys[pkt_num], &key0,
3272 sizeof(struct pipeline_cgnapt_entry_key));
3273 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3278 #ifdef CGNAPT_DBG_PRNT
3279 if (CGNAPT_DEBUG > 4)
3284 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
3288 switch (protocol1) {
3289 case IP_PROTOCOL_UDP:
3290 case IP_PROTOCOL_TCP:
3292 src_port_offset1 = SRC_PRT_OFST_IP4_TCP;
3293 dst_port_offset1 = DST_PRT_OFST_IP4_TCP;
3295 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3297 dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3300 key1.port = rte_bswap16(dst_port1);
3304 case IP_PROTOCOL_ICMP:
3306 src_port_offset1 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3308 /*Sequence number */
3309 dst_port_offset1 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3312 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3314 dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3317 key1.port = rte_bswap16(src_port1);
3321 /* remember invalid packets to be dropped */
3322 p_nat->invalid_packets |= pkt_mask1;
3323 p_nat->naptDroppedPktCount++;
3325 #ifdef CGNAPT_DEBUGGING
3326 p_nat->naptDroppedPktCount2++;
3332 key1.ip = rte_bswap32(dst_addr1);
3334 #ifdef NAT_ONLY_CONFIG_REQ
3335 if (nat_only_config_flag)
3339 memcpy(&p_nat->keys[pkt_num + 1], &key1,
3340 sizeof(struct pipeline_cgnapt_entry_key));
3341 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
3345 #ifdef CGNAPT_DBG_PRNT
3346 if (CGNAPT_DEBUG > 4)
3351 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
3355 switch (protocol2) {
3356 case IP_PROTOCOL_UDP:
3357 case IP_PROTOCOL_TCP:
3359 src_port_offset2 = SRC_PRT_OFST_IP4_TCP;
3360 dst_port_offset2 = DST_PRT_OFST_IP4_TCP;
3362 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3364 dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3367 key2.port = rte_bswap16(dst_port2);
3371 case IP_PROTOCOL_ICMP:
3373 src_port_offset2 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3375 /*Sequence number */
3376 dst_port_offset2 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3379 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3381 dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3384 key2.port = rte_bswap16(src_port2);
3389 /* remember invalid packets to be dropped */
3390 p_nat->invalid_packets |= pkt_mask2;
3391 p_nat->naptDroppedPktCount++;
3393 #ifdef CGNAPT_DEBUGGING
3394 p_nat->naptDroppedPktCount2++;
3400 key2.ip = rte_bswap32(dst_addr2);
3402 #ifdef NAT_ONLY_CONFIG_REQ
3403 if (nat_only_config_flag)
3407 memcpy(&p_nat->keys[pkt_num + 2], &key2,
3408 sizeof(struct pipeline_cgnapt_entry_key));
3409 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
3413 #ifdef CGNAPT_DBG_PRNT
3414 if (CGNAPT_DEBUG > 4)
3419 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
3423 switch (protocol3) {
3424 case IP_PROTOCOL_UDP:
3425 case IP_PROTOCOL_TCP:
3427 src_port_offset3 = SRC_PRT_OFST_IP4_TCP;
3428 dst_port_offset3 = DST_PRT_OFST_IP4_TCP;
3430 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3432 dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3435 key3.port = rte_bswap16(dst_port3);
3439 case IP_PROTOCOL_ICMP:
3441 src_port_offset3 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3443 /*Sequence number */
3444 dst_port_offset3 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3447 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3449 dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3452 key3.port = rte_bswap16(src_port3);
3457 /* remember invalid packets to be dropped */
3458 p_nat->invalid_packets |= pkt_mask3;
3459 p_nat->naptDroppedPktCount++;
3461 #ifdef CGNAPT_DEBUGGING
3462 p_nat->naptDroppedPktCount2++;
3468 key3.ip = rte_bswap32(dst_addr3);
3470 #ifdef NAT_ONLY_CONFIG_REQ
3471 if (nat_only_config_flag)
3475 memcpy(&p_nat->keys[pkt_num + 3], &key3,
3476 sizeof(struct pipeline_cgnapt_entry_key));
3477 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
3481 * NAPT key calculation function for IPv4 private traffic
3482 * which handles 1 pkt
3485 * A pointer to array of packets mbuf
3487 * Pkt number of pkts
3491 * A pointer to main CGNAPT structure
3495 pkt_work_cgnapt_key_ipv4_prv(
3496 struct rte_mbuf *pkt,
3498 __rte_unused void *arg,
3499 struct pipeline_cgnapt *p_nat)
3502 p_nat->receivedPktCount++;
3504 /* bitmask representing only this packet */
3505 uint64_t pkt_mask = 1LLU << pkt_num;
3506 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3508 uint32_t src_addr = RTE_MBUF_METADATA_UINT32(pkt, SRC_ADR_OFST_IP4);
3510 uint16_t src_port_offset;
3514 uint16_t phy_port = pkt->port;
3515 struct pipeline_cgnapt_entry_key key;
3517 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
3520 #ifdef CGNAPT_DBG_PRNT
3521 if (CGNAPT_DEBUG > 4)
3526 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
3531 case IP_PROTOCOL_UDP:
3535 struct udp_hdr *udp;
3537 udp = (struct udp_hdr *)
3538 RTE_MBUF_METADATA_UINT8_PTR(pkt,
3541 if (rte_bswap16(udp->dst_port) ==
3543 handle_pcp_req(pkt, IPV4_SZ, p_nat);
3544 p_nat->invalid_packets |= pkt_mask;
3550 case IP_PROTOCOL_TCP:
3552 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3553 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3555 key.port = rte_bswap16(src_port);
3558 case IP_PROTOCOL_ICMP:
3560 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3562 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3564 key.port = rte_bswap16(src_port);
3568 /* remember invalid packets to be dropped */
3569 p_nat->invalid_packets |= pkt_mask;
3570 p_nat->naptDroppedPktCount++;
3572 #ifdef CGNAPT_DEBUGGING
3573 p_nat->naptDroppedPktCount2++;
3579 key.ip = rte_bswap32(src_addr);
3581 #ifdef NAT_ONLY_CONFIG_REQ
3582 if (nat_only_config_flag)
3586 memcpy(&p_nat->keys[pkt_num], &key,
3587 sizeof(struct pipeline_cgnapt_entry_key));
3588 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3592 * NAPT key calculation function for IPv4 public traffic
3593 * which handles 1 pkt
3596 * A pointer to array of packets mbuf
3598 * Pkt number of pkts
3602 * A pointer to main CGNAPT structure
3606 pkt_work_cgnapt_key_ipv4_pub(
3607 struct rte_mbuf *pkt,
3609 __rte_unused void *arg,
3610 struct pipeline_cgnapt *p_nat)
3612 p_nat->receivedPktCount++;
3614 /* bitmask representing only this packet */
3615 uint64_t pkt_mask = 1LLU << pkt_num;
3616 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3617 uint32_t dst_addr = RTE_MBUF_METADATA_UINT32(pkt, DST_ADR_OFST_IP4);
3618 uint16_t src_port_offset;
3619 uint16_t dst_port_offset;
3622 struct pipeline_cgnapt_entry_key key;
3623 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
3625 #ifdef CGNAPT_DBG_PRNT
3626 if (CGNAPT_DEBUG > 4)
3631 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
3636 case IP_PROTOCOL_UDP:
3637 case IP_PROTOCOL_TCP:
3638 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3639 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3641 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3642 dst_port = RTE_MBUF_METADATA_UINT16(pkt, dst_port_offset);
3644 key.port = rte_bswap16(dst_port);
3646 case IP_PROTOCOL_ICMP:
3648 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3650 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3653 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3654 dst_port = RTE_MBUF_METADATA_UINT16(pkt, dst_port_offset);
3656 /* common table lookupkey preparation from incoming
3657 * ICMP Packet- Indentifier field
3659 key.port = rte_bswap16(src_port);
3662 /* remember invalid packets to be dropped */
3663 p_nat->invalid_packets |= pkt_mask;
3664 p_nat->naptDroppedPktCount++;
3666 #ifdef CGNAPT_DEBUGGING
3667 p_nat->naptDroppedPktCount2++;
3672 key.ip = rte_bswap32(dst_addr);
3674 #ifdef NAT_ONLY_CONFIG_REQ
3675 if (nat_only_config_flag)
3681 memcpy(&p_nat->keys[pkt_num], &key,
3682 sizeof(struct pipeline_cgnapt_entry_key));
3683 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3688 * NAPT function for IPv4 private traffic which handles 1 pkt
3691 * A pointer to array of packet mbuf
3697 * A pointer to main CGNAPT structure
3701 pkt_work_cgnapt_ipv4_prv(
3702 struct rte_mbuf **pkts,
3704 __rte_unused void *arg,
3705 struct pipeline_cgnapt *p_nat)
3708 struct rte_CT_helper ct_helper;
3709 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
3712 /* index into hash table entries */
3713 int hash_table_entry = p_nat->lkup_indx[pkt_num];
3714 /*bitmask representing only this packet */
3715 uint64_t pkt_mask = 1LLU << pkt_num;
3716 struct rte_mbuf *pkt = pkts[pkt_num];
3718 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3720 uint32_t dest_if = 0xff; /* Added for Multiport */
3721 uint16_t *outport_id =
3722 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
3724 struct cgnapt_table_entry *entry = NULL;
3726 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
3728 if (hash_table_entry < 0) {
3730 /* try to add new entry */
3731 struct rte_pipeline_table_entry *table_entry = NULL;
3733 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
3735 &p_nat->valid_packets, pkt_num,
3739 /* ICMP Error message generation for Destination
3742 if (protocol == IP_PROTOCOL_ICMP) {
3743 cgnapt_icmp_pkt = pkt;
3744 send_icmp_dest_unreachable_msg();
3747 /* Drop packet by adding to invalid pkt mask */
3749 p_nat->invalid_packets |= dropmask;
3750 #ifdef CGNAPT_DEBUGGING
3751 if (p_nat->kpc2++ < 5) {
3752 printf("in_ah Th: %d", p_nat->pipeline_num);
3753 print_key(p_nat->key_ptrs[pkt_num]);
3757 p_nat->naptDroppedPktCount++;
3759 #ifdef CGNAPT_DEBUGGING
3760 p_nat->naptDroppedPktCount3++;
3765 entry = (struct cgnapt_table_entry *)table_entry;
3767 /* entry found for this packet */
3768 entry = &napt_hash_tbl_entries[hash_table_entry];
3771 /* apply napt and mac changes */
3773 p_nat->entries[pkt_num] = &(entry->head);
3775 uint32_t *src_addr =
3776 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP4);
3777 uint32_t *dst_addr =
3778 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
3779 uint16_t src_port_offset = 0;
3780 uint16_t dst_port_offset = 0;
3785 case IP_PROTOCOL_TCP:
3786 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3787 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3788 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3789 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3792 if ((rte_be_to_cpu_16(*src_port) == 21) ||
3793 rte_be_to_cpu_16(*dst_port) == 21) {
3796 printf("cgnapt_ct_process: pkt_mask: % "PRIu64", "
3797 "pkt_num: %d\n", pkt_mask, pkt_num);
3800 pkt_mask = cgnapt_ct_process(cgnat_cnxn_tracker, pkts,
3801 pkt_mask, &ct_helper);
3805 case IP_PROTOCOL_UDP:
3806 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3807 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3808 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3809 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3811 case IP_PROTOCOL_ICMP:
3813 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3815 /*Sequence number */
3816 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3818 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3819 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3823 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
3824 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
3826 if (entry->data.ttl == NAPT_ENTRY_STALE)
3827 entry->data.ttl = NAPT_ENTRY_VALID;
3829 struct ether_addr hw_addr;
3830 uint32_t dest_address = 0;
3833 if (unlikely(protocol == IP_PROTOCOL_UDP
3834 && rte_be_to_cpu_16(*dst_port) == 53)) {
3835 p_nat->invalid_packets |= pkt_mask;
3836 p_nat->naptDroppedPktCount++;
3838 #ifdef CGNAPT_DEBUGGING
3839 p_nat->naptDroppedPktCount6++;
3844 dest_address = rte_bswap32(*dst_addr);
3845 /*Multiport Changes */
3848 ret = local_get_nh_ipv4(dest_address, &dest_if, &nhip, p_nat);
3850 dest_if = get_prv_to_pub_port(&dest_address, IP_VERSION_4);
3852 if (dest_if == INVALID_DESTIF) {
3853 p_nat->invalid_packets |= pkt_mask;
3854 p_nat->naptDroppedPktCount++;
3855 #ifdef CGNAPT_DEBUGGING
3856 p_nat->naptDroppedPktCount6++;
3861 do_local_nh_ipv4_cache(dest_if, p_nat);
3864 *outport_id = p_nat->outport_id[dest_if];
3866 #ifdef CGNAPT_DBG_PRNT
3867 if (CGNAPT_DEBUG > 2)
3868 printf("Egress: \tphy_port:%d\t get_prv_to_pub():%d "
3869 "\tout_port:%d\n", pkt->port, dest_if,
3873 if (local_dest_mac_present(dest_if)) {
3875 get_local_link_hw_addr(dest_if),
3876 sizeof(struct ether_addr));
3877 memcpy(eth_src, get_link_hw_addr(dest_if),
3878 sizeof(struct ether_addr));
3881 ret = get_dest_mac_addr_port(dest_address, &dest_if, &hw_addr);
3883 if (unlikely(ret != ARP_FOUND)) {
3885 if (unlikely(ret == ARP_NOT_FOUND)) {
3886 //request_arp(*outport_id, nhip, p_nat->p.p);
3887 printf("%s: ARP Not Found, nhip: %x, "
3888 "outport_id: %d\n", __func__, nhip,
3893 p_nat->invalid_packets |= pkt_mask;
3894 p_nat->naptDroppedPktCount++;
3896 #ifdef CGNAPT_DEBUGGING
3897 p_nat->naptDroppedPktCount4++;
3903 #ifdef CGNAPT_DBG_PRNT
3904 if (CGNAPT_DEBUG > 2) {
3905 printf("MAC found for ip 0x%x, port %d - %02x:%02x: "
3906 "%02x:%02x:%02x:%02x\n", dest_address,
3908 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
3909 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
3910 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
3912 printf("Dest MAC before - %02x:%02x:%02x: "
3913 "%02x:%02x:%02x\n", eth_dest[0], eth_dest[1],
3914 eth_dest[2], eth_dest[3], eth_dest[4], eth_dest[5]);
3919 memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
3921 link_hw_laddr_valid[dest_if] = 1;
3922 memcpy(&link_hw_laddr[dest_if], &hw_addr,
3923 sizeof(struct ether_addr));
3925 #ifdef CGNAPT_DBG_PRNT
3926 if (CGNAPT_DEBUG > 2) {
3927 printf("Dest MAC after - %02x:%02x:%02x:%02x:%02x"
3928 ":%02x\n", eth_dest[0], eth_dest[1], eth_dest[2],
3929 eth_dest[3], eth_dest[4], eth_dest[5]);
3933 memcpy(eth_src, get_link_hw_addr(dest_if),
3934 sizeof(struct ether_addr));
3939 *src_addr = rte_bswap32(entry->data.pub_ip);
3942 #ifdef NAT_ONLY_CONFIG_REQ
3943 if (!nat_only_config_flag) {
3945 *src_port = rte_bswap16(entry->data.pub_port);
3946 #ifdef NAT_ONLY_CONFIG_REQ
3951 uint16_t rtp_port = 0, rtcp_port = 0;
3952 struct cgnapt_table_entry *entry_ptr1 = NULL,
3953 *entry_ptr2 = NULL, *entry_ptr3 = NULL,
3956 if (unlikely(protocol == IP_PROTOCOL_UDP
3957 && (rte_be_to_cpu_16(*dst_port) == 5060
3958 || rte_be_to_cpu_16(*src_port) == 5060))) {
3960 int ret = natSipAlgGetAudioPorts(pkt, &rtp_port,
3962 /* Commented code may be required for debug
3963 * and future use, Please keep it*/
3966 printf("%s: Wrong SIP ALG packet1\n",
3968 p_nat->invalid_packets |= pkt_mask;
3970 p_nat->naptDroppedPktCount++;
3972 #ifdef CGNAPT_DEBUGGING
3973 p_nat->naptDroppedPktCount4++;
3979 if (ret >= 0 && rtp_port != 0) {
3980 struct pipeline_cgnapt_entry_key rtp_key;
3981 rtp_key.ip = entry->data.u.prv_ip;
3982 rtp_key.port = rtp_port;
3983 rtp_key.pid = entry->data.prv_phy_port;
3985 if (add_dynamic_cgnapt_entry_alg(
3986 (struct pipeline *)p_nat, &rtp_key,
3987 &entry_ptr1, &entry_ptr2) == 0) {
3988 printf("%s: Wrong SIP ALG packet2\n",
3990 p_nat->invalid_packets |= pkt_mask;
3992 p_nat->naptDroppedPktCount++;
3994 #ifdef CGNAPT_DEBUGGING
3995 p_nat->naptDroppedPktCount4++;
4001 if (ret >= 0 && rtcp_port != 0) {
4002 struct pipeline_cgnapt_entry_key rtcp_key;
4003 rtcp_key.ip = entry->data.u.prv_ip;
4004 rtcp_key.port = rtcp_port;
4005 rtcp_key.pid = entry->data.prv_phy_port;
4007 if (add_dynamic_cgnapt_entry_alg(
4008 (struct pipeline *)p_nat, &rtcp_key,
4009 &entry_ptr3, &entry_ptr4) == 0) {
4010 printf("%s: Wrong SIP ALG packet3\n",
4012 p_nat->invalid_packets |= pkt_mask;
4014 p_nat->naptDroppedPktCount++;
4016 #ifdef CGNAPT_DEBUGGING
4017 p_nat->naptDroppedPktCount4++;
4023 //if(entry_ptr1 != NULL && entry_ptr3 != NULL)
4024 if (sip_alg_dpi(pkt, PRIVATE, entry->data.pub_ip,
4025 entry->data.pub_port, entry->data.u.prv_ip,
4026 entry->data.prv_port, (rtp_port == 0) ? 0 :
4027 entry_ptr1->data.pub_port,
4028 (rtcp_port == 0) ? 0 :
4029 entry_ptr3->data.pub_port) == 0) {
4031 printf("%s: Wrong SIP ALG packet4\n",
4033 p_nat->invalid_packets |= pkt_mask;
4035 p_nat->naptDroppedPktCount++;
4037 #ifdef CGNAPT_DEBUGGING
4038 p_nat->naptDroppedPktCount4++;
4043 #endif /* SIP_ALG */
4048 printf("@CGNAT-pktwork ct_position :%d, pkt_num %d pkt_mask= "
4049 "%" PRIu64 "\n", ct_position, pkt_num, pkt_mask);
4052 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4053 rte_be_to_cpu_16(*dst_port) == 21) {
4055 int32_t ct_position = cgnat_cnxn_tracker->positions[pkt_num];
4056 if (ct_position < 0){
4057 p_nat->invalid_packets |= pkt_mask;
4058 p_nat->naptDroppedPktCount++;
4061 /* Commented code may be required for future usage,
4064 //if (cgnat_cnxn_tracker->hash_table_entries
4065 // [ct_position].alg_bypass_flag != BYPASS)
4067 struct pipeline_cgnapt_entry_key data_channel_entry_key;
4069 data_channel_entry_key.ip = entry->data.pub_ip;
4070 data_channel_entry_key.port = entry->data.pub_port;
4071 data_channel_entry_key.pid = pkt->port;
4072 ftp_alg_dpi(p_nat, &data_channel_entry_key, pkt,
4073 cgnat_cnxn_tracker, ct_position, PRIVATE);
4076 #endif /* FTP_ALG */
4078 p_nat->enaptedPktCount++;
4081 p_nat->naptedPktCount++;
4083 #ifdef HW_CHECKSUM_REQ
4084 if (p_nat->hw_checksum_reqd)
4085 hw_checksum(pkt, pkt_type);
4088 sw_checksum(pkt, pkt_type);
4094 * NAPT function for IPv4 public traffic which handles 1 pkt
4097 * A pointer to array of packet mbuf
4103 * A pointer to main CGNAPT structure
4107 pkt_work_cgnapt_ipv4_pub(
4108 struct rte_mbuf **pkts,
4110 __rte_unused void *arg,
4111 struct pipeline_cgnapt *p_nat)
4115 struct rte_CT_helper ct_helper;
4116 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4119 /* index into hash table entries */
4120 int hash_table_entry = p_nat->lkup_indx[pkt_num];
4121 /*bitmask representing only this packet */
4122 uint64_t pkt_mask = 1LLU << pkt_num;
4123 struct rte_mbuf *pkt = pkts[pkt_num];
4125 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
4127 uint32_t dest_if = 0xff; /* Added for Multiport */
4128 uint16_t *outport_id =
4129 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
4131 struct cgnapt_table_entry *entry = NULL;
4133 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4135 if (hash_table_entry < 0) {
4137 /* try to add new entry */
4138 struct rte_pipeline_table_entry *table_entry = NULL;
4140 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
4142 &p_nat->valid_packets, pkt_num,
4146 /* ICMP Error message generation for
4147 * Destination Host unreachable
4149 if (protocol == IP_PROTOCOL_ICMP) {
4150 cgnapt_icmp_pkt = pkt;
4151 send_icmp_dest_unreachable_msg();
4154 /* Drop packet by adding to invalid pkt mask */
4156 p_nat->invalid_packets |= dropmask;
4157 #ifdef CGNAPT_DEBUGGING
4158 if (p_nat->kpc2++ < 5) {
4159 printf("in_ah Th: %d", p_nat->pipeline_num);
4160 print_key(p_nat->key_ptrs[pkt_num]);
4164 p_nat->naptDroppedPktCount++;
4166 #ifdef CGNAPT_DEBUGGING
4167 p_nat->naptDroppedPktCount3++;
4172 entry = (struct cgnapt_table_entry *)table_entry;
4174 /* entry found for this packet */
4175 entry = &napt_hash_tbl_entries[hash_table_entry];
4178 /* apply napt and mac changes */
4180 p_nat->entries[pkt_num] = &(entry->head);
4182 uint32_t *dst_addr =
4183 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4184 uint16_t src_port_offset = 0;
4185 uint16_t dst_port_offset = 0;
4187 if ((protocol == IP_PROTOCOL_TCP) || (protocol == IP_PROTOCOL_UDP)) {
4188 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4189 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4190 } else if (protocol == IP_PROTOCOL_ICMP) {
4192 src_port_offset = MBUF_HDR_ROOM +
4195 /*Sequence number */
4196 dst_port_offset = MBUF_HDR_ROOM +
4201 uint16_t *src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
4202 uint16_t *dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
4204 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4205 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4207 if (entry->data.ttl == NAPT_ENTRY_STALE)
4208 entry->data.ttl = NAPT_ENTRY_VALID;
4210 struct ether_addr hw_addr;
4211 uint32_t dest_address = 0;
4213 /* Multiport Changes */
4219 if (unlikely(protocol == IP_PROTOCOL_UDP
4220 && rte_be_to_cpu_16(*src_port) == 53)) {
4221 p_nat->invalid_packets |= pkt_mask;
4222 p_nat->naptDroppedPktCount++;
4223 #ifdef CGNAPT_DEBUGGING
4224 p_nat->naptDroppedPktCount6++;
4229 dest_address = entry->data.u.prv_ip;
4231 ret = local_get_nh_ipv4(dest_address, &dest_if, &nhip, p_nat);
4233 dest_if = get_prv_to_pub_port(&dest_address, IP_VERSION_4);
4235 if (dest_if == INVALID_DESTIF) {
4236 p_nat->invalid_packets |= pkt_mask;
4237 p_nat->naptDroppedPktCount++;
4238 #ifdef CGNAPT_DEBUGGING
4239 p_nat->naptDroppedPktCount6++;
4244 do_local_nh_ipv4_cache(dest_if, p_nat);
4247 *outport_id = p_nat->outport_id[dest_if];
4249 #ifdef CGNAPT_DBG_PRNT
4250 if (CGNAPT_DEBUG > 2)
4251 printf("Ingress: \tphy_port:%d\t get_pub_to_prv():%d "
4252 "\tout_port%d\n", pkt->port, dest_if, *outport_id);
4256 if (local_dest_mac_present(dest_if)) {
4258 get_local_link_hw_addr(dest_if),
4259 sizeof(struct ether_addr));
4260 memcpy(eth_src, get_link_hw_addr(dest_if),
4261 sizeof(struct ether_addr));
4264 ret = get_dest_mac_addr_port(dest_address, &dest_if, &hw_addr);
4266 if (unlikely(ret != ARP_FOUND)) {
4268 if (unlikely(ret == ARP_NOT_FOUND)) {
4269 /* Commented code may be required for debug
4270 * and future use, Please keep it */
4271 //request_arp(*outport_id, nhip, p_nat->p.p);
4272 printf("%s: ARP Not Found, nhip: %x, "
4273 "outport_id: %d\n", __func__, nhip,
4279 p_nat->invalid_packets |= pkt_mask;
4280 p_nat->naptDroppedPktCount++;
4282 #ifdef CGNAPT_DEBUGGING
4283 p_nat->naptDroppedPktCount4++;
4288 #ifdef CGNAPT_DBG_PRNT
4289 if (CGNAPT_DEBUG > 2) {
4291 ("MAC found for ip 0x%x, port %d - %02x:%02x: "
4292 "%02x:%02x:%02x:%02x\n", dest_address,
4294 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
4295 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
4296 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]
4300 ("Dest MAC before - %02x:%02x:%02x:%02x "
4301 ":%02x:%02x\n", eth_dest[0], eth_dest[1],
4302 eth_dest[2], eth_dest[3], eth_dest[4],
4307 memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
4309 link_hw_laddr_valid[dest_if] = 1;
4310 memcpy(&link_hw_laddr[dest_if], &hw_addr,
4311 sizeof(struct ether_addr));
4313 #ifdef CGNAPT_DBG_PRNT
4314 if (CGNAPT_DEBUG > 2) {
4315 printf("Dest MAC after - "
4316 "%02x:%02x:%02x:%02x:%02x:%02x\n",
4317 eth_dest[0], eth_dest[1], eth_dest[2], eth_dest[3],
4318 eth_dest[4], eth_dest[5]);
4322 memcpy(eth_src, get_link_hw_addr(dest_if),
4323 sizeof(struct ether_addr));
4329 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
4330 if (protocol == IP_PROTOCOL_ICMP) {
4331 /* Query ID reverse translation done here */
4332 /* dont care sequence num */
4333 *src_port = rte_bswap16(entry->data.prv_port);
4336 #ifdef NAT_ONLY_CONFIG_REQ
4337 if (!nat_only_config_flag) {
4339 *dst_port = rte_bswap16(entry->data.prv_port);
4341 #ifdef NAT_ONLY_CONFIG_REQ
4345 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4346 rte_be_to_cpu_16(*dst_port) == 21) {
4347 pkt_mask = cgnapt_ct_process(cgnat_cnxn_tracker, pkts,
4348 pkt_mask, &ct_helper);
4354 uint16_t rtp_port = 0, rtcp_port = 0;
4355 struct cgnapt_table_entry *entry_ptr1 = NULL,
4358 /* Commented code may be required for debug
4359 * and future use, Please keep it */
4361 struct cgnapt_table_entry *entry_ptr2 = NULL,
4365 if (unlikely(protocol == IP_PROTOCOL_UDP
4366 && (rte_be_to_cpu_16(*dst_port) == 5060
4367 || rte_be_to_cpu_16(*src_port) == 5060))) {
4368 /* Commented code may be required for future usage,
4372 int ret = natSipAlgGetAudioPorts(pkt, &rtp_port,
4375 printf("%s: Wrong SIP ALG packet1\n",
4377 p_nat->invalid_packets |= pkt_mask;
4379 p_nat->naptDroppedPktCount++;
4381 #ifdef CGNAPT_DEBUGGING
4382 p_nat->naptDroppedPktCount4++;
4386 if (rtp_port != 0) {
4387 struct pipeline_cgnapt_entry_key rtp_key;
4388 rtp_key.ip = entry->data.pub_ip;
4389 rtp_key.port = rtp_port;
4390 rtp_key.pid = 0xffff;
4392 if (retrieve_cgnapt_entry_alg(&rtp_key,
4393 &entry_ptr1, &entry_ptr2) == 0) {
4394 printf("%s: Wrong SIP ALG packet2\n",
4396 p_nat->invalid_packets |= pkt_mask;
4398 p_nat->naptDroppedPktCount++;
4400 #ifdef CGNAPT_DEBUGGING
4401 p_nat->naptDroppedPktCount4++;
4407 if (rtcp_port != 0) {
4408 struct pipeline_cgnapt_entry_key rtcp_key;
4409 rtcp_key.ip = entry->data.pub_ip;
4410 rtcp_key.port = rtcp_port;
4411 rtcp_key.pid = 0xffff;
4413 if (retrieve_cgnapt_entry_alg(&rtcp_key,
4414 &entry_ptr3, &entry_ptr4) == 0) {
4415 printf("%s: Wrong SIP ALG packet3\n",
4417 p_nat->invalid_packets |= pkt_mask;
4419 p_nat->naptDroppedPktCount++;
4421 #ifdef CGNAPT_DEBUGGING
4422 p_nat->naptDroppedPktCount4++;
4430 if (sip_alg_dpi(pkt, PUBLIC, entry->data.u.prv_ip,
4431 entry->data.prv_port, entry->data.pub_ip,
4432 entry->data.pub_port, (rtp_port == 0) ? 0 :
4433 entry_ptr1->data.prv_port,
4434 (rtcp_port == 0) ? 0 :
4435 entry_ptr3->data.prv_port) == 0) {
4437 printf("%s: Wrong SIP ALG packet4\n",
4439 p_nat->invalid_packets |= pkt_mask;
4441 p_nat->naptDroppedPktCount++;
4443 #ifdef CGNAPT_DEBUGGING
4444 p_nat->naptDroppedPktCount4++;
4450 #endif /* SIP_ALG */
4453 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4454 rte_be_to_cpu_16(*dst_port) == 21) {
4455 int32_t ct_position = cgnat_cnxn_tracker->
4457 if (ct_position < 0){
4458 p_nat->invalid_packets |= pkt_mask;
4460 p_nat->naptDroppedPktCount++;
4464 rte_hexdump(stdout, "CT Entry", &cgnat_cnxn_tracker->
4465 hash_table_entries[ct_position].key, 40);
4468 /* Commented code may be required for debug
4469 * and future use, Please keep it*/
4470 //if (cgnat_cnxn_tracker->hash_table_entries
4471 // [ct_position].alg_bypass_flag != BYPASS)
4474 struct pipeline_cgnapt_entry_key
4475 data_channel_entry_key;
4477 data_channel_entry_key.ip = entry->data.pub_ip;
4478 data_channel_entry_key.port = entry->data.pub_port;
4479 data_channel_entry_key.pid = 0xffff;
4480 //printf("pkt_work_pub ftp_alg_dpi\n");
4481 ftp_alg_dpi(p_nat, &data_channel_entry_key, pkt,
4482 cgnat_cnxn_tracker, ct_position, PUBLIC);
4488 p_nat->inaptedPktCount++;
4491 p_nat->naptedPktCount++;
4493 #ifdef HW_CHECKSUM_REQ
4494 if (p_nat->hw_checksum_reqd)
4495 hw_checksum(pkt, pkt_type);
4498 sw_checksum(pkt, pkt_type);
4503 * NAPT function for IPv4 private traffic which handles 4 pkts
4506 * A pointer to array of packets mbuf
4508 * Starting pkt number of pkts
4512 * A pointer to main CGNAPT structure
4516 pkt4_work_cgnapt_ipv4_prv(
4517 struct rte_mbuf **pkts,
4518 uint32_t in_pkt_num,
4519 __rte_unused void *arg,
4520 struct pipeline_cgnapt *p_nat)
4522 uint32_t dest_if = 0xff; /* Added for Multiport */
4523 struct rte_mbuf *pkt;
4526 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4529 struct rte_CT_helper ct_helper;
4530 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4533 for (i = 0; i < 4; i++) {
4534 pkt_num = in_pkt_num + i;
4535 pkt = pkts[pkt_num];
4537 /* index into hash table entries */
4538 int hash_table_entry = p_nat->lkup_indx[pkt_num];
4539 /*bitmask representing only this packet */
4540 uint64_t pkt_mask = 1LLU << pkt_num;
4542 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
4544 uint16_t *outport_id =
4545 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
4547 struct cgnapt_table_entry *entry = NULL;
4549 if (hash_table_entry < 0) {
4551 /* try to add new entry */
4552 struct rte_pipeline_table_entry *table_entry = NULL;
4555 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
4557 &p_nat->valid_packets, pkt_num,
4561 /* ICMP Error message generation for
4562 * Destination Host unreachable
4564 if (protocol == IP_PROTOCOL_ICMP) {
4565 cgnapt_icmp_pkt = pkt;
4566 send_icmp_dest_unreachable_msg();
4569 /* Drop packet by adding to invalid pkt mask */
4571 p_nat->invalid_packets |= dropmask;
4573 #ifdef CGNAPT_DEBUGGING
4574 if (p_nat->kpc2++ < 5) {
4575 printf("in_ah Th: %d",
4576 p_nat->pipeline_num);
4577 print_key(p_nat->key_ptrs[pkt_num]);
4581 p_nat->naptDroppedPktCount++;
4583 #ifdef CGNAPT_DEBUGGING
4584 p_nat->naptDroppedPktCount3++;
4589 entry = (struct cgnapt_table_entry *)table_entry;
4591 /* entry found for this packet */
4592 entry = &napt_hash_tbl_entries[hash_table_entry];
4595 /* apply napt and mac changes */
4597 p_nat->entries[pkt_num] = &(entry->head);
4599 uint32_t *src_addr =
4600 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP4);
4601 uint32_t *dst_addr =
4602 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4603 uint16_t src_port_offset = 0;
4604 uint16_t dst_port_offset = 0;
4609 if ((protocol == IP_PROTOCOL_TCP)
4610 || (protocol == IP_PROTOCOL_UDP)) {
4611 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4612 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4613 } else if (protocol == IP_PROTOCOL_ICMP) {
4615 src_port_offset = MBUF_HDR_ROOM +
4618 /*Sequence number */
4619 dst_port_offset = MBUF_HDR_ROOM +
4626 case IP_PROTOCOL_TCP:
4627 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4628 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4629 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4631 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4635 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4636 rte_be_to_cpu_16(*dst_port) == 21) {
4638 //To process CT , pkt_mask does it need
4639 //to be complemented ??
4641 printf("cgnapt_ct_process: pkt_mask: "
4642 "% "PRIu64", pkt_num: %d\n",
4646 pkt_mask = cgnapt_ct_process(
4647 cgnat_cnxn_tracker, pkts,
4648 pkt_mask, &ct_helper);
4652 case IP_PROTOCOL_UDP:
4653 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4654 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4655 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4657 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4660 case IP_PROTOCOL_ICMP:
4662 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
4664 /*Sequence number */
4665 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
4667 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4669 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4676 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4678 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4680 if (entry->data.ttl == NAPT_ENTRY_STALE)
4681 entry->data.ttl = NAPT_ENTRY_VALID;
4683 struct ether_addr hw_addr;
4684 uint32_t dest_address = 0;
4685 /*Multiport Changes */
4692 if (unlikely(protocol == IP_PROTOCOL_UDP
4693 && rte_be_to_cpu_16(*dst_port) == 53)) {
4694 p_nat->invalid_packets |= pkt_mask;
4695 p_nat->naptDroppedPktCount++;
4697 #ifdef CGNAPT_DEBUGGING
4698 p_nat->naptDroppedPktCount6++;
4703 dest_address = rte_bswap32(*dst_addr);
4704 ret = local_get_nh_ipv4(dest_address, &dest_if, &nhip, p_nat);
4706 dest_if = get_prv_to_pub_port(&dest_address,
4708 if (dest_if == INVALID_DESTIF) {
4709 p_nat->invalid_packets |= pkt_mask;
4710 p_nat->naptDroppedPktCount++;
4711 #ifdef CGNAPT_DEBUGGING
4712 p_nat->naptDroppedPktCount6++;
4716 do_local_nh_ipv4_cache(dest_if, p_nat);
4718 *outport_id = p_nat->outport_id[dest_if];
4720 #ifdef CGNAPT_DBG_PRNT
4721 if (CGNAPT_DEBUG > 2)
4722 printf("Egress: \tphy_port:%d\t "
4723 "get_prv_to_pub():%d \tout_port:%d\n",
4724 pkt->port, dest_if, *outport_id);
4728 if (local_dest_mac_present(dest_if)) {
4730 get_local_link_hw_addr(dest_if),
4731 sizeof(struct ether_addr));
4733 get_link_hw_addr(dest_if),
4734 sizeof(struct ether_addr));
4737 ret = get_dest_mac_addr_port(dest_address, &dest_if, &hw_addr);
4739 if (unlikely(ret != ARP_FOUND)) {
4741 if (unlikely(ret == ARP_NOT_FOUND)) {
4742 printf("%s: ARP Not Found, nhip: %x, "
4743 "outport_id: %d\n", __func__, nhip,
4745 //request_arp(*outport_id, nhip, p_nat->p.p);
4749 p_nat->invalid_packets |= pkt_mask;
4750 p_nat->naptDroppedPktCount++;
4752 #ifdef CGNAPT_DEBUGGING
4753 p_nat->naptDroppedPktCount4++;
4758 #ifdef CGNAPT_DBG_PRNT
4759 if (CGNAPT_DEBUG > 2) {
4760 printf("MAC found for ip 0x%x, port %d - "
4761 "%02x:%02x:%02x:%02x:%02x:%02x\n",
4764 hw_addr.addr_bytes[0],
4765 hw_addr.addr_bytes[1],
4766 hw_addr.addr_bytes[2],
4767 hw_addr.addr_bytes[3],
4768 hw_addr.addr_bytes[4],
4769 hw_addr.addr_bytes[5]
4772 printf("Dest MAC before - "
4773 "%02x:%02x:%02x:%02x:%02x:%02x\n",
4774 eth_dest[0], eth_dest[1], eth_dest[2],
4775 eth_dest[3], eth_dest[4], eth_dest[5]);
4779 memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
4781 link_hw_laddr_valid[dest_if] = 1;
4782 memcpy(&link_hw_laddr[dest_if], &hw_addr,
4783 sizeof(struct ether_addr));
4785 #ifdef CGNAPT_DBG_PRNT
4786 if (CGNAPT_DEBUG > 2) {
4787 printf("Dest MAC after - "
4788 "%02x:%02x:%02x:%02x:%02x:%02x\n",
4789 eth_dest[0], eth_dest[1], eth_dest[2],
4790 eth_dest[3], eth_dest[4], eth_dest[5]);
4795 get_link_hw_addr(dest_if),
4796 sizeof(struct ether_addr));
4801 *src_addr = rte_bswap32(entry->data.pub_ip);
4803 #ifdef NAT_ONLY_CONFIG_REQ
4804 if (!nat_only_config_flag) {
4806 *src_port = rte_bswap16(entry->data.pub_port);
4807 #ifdef NAT_ONLY_CONFIG_REQ
4812 uint16_t rtp_port = 0, rtcp_port = 0;
4813 struct cgnapt_table_entry *entry_ptr1 = NULL,
4814 *entry_ptr2 = NULL, *entry_ptr3 = NULL,
4817 if (unlikely(protocol == IP_PROTOCOL_UDP
4818 && (rte_be_to_cpu_16(*dst_port) == 5060
4819 || rte_be_to_cpu_16(*src_port) == 5060))) {
4821 int ret = natSipAlgGetAudioPorts(pkt,
4822 &rtp_port, &rtcp_port);
4823 /* Commented code may be required for future usage,
4828 printf("%s: Wrong SIP ALG packet1\n",
4830 p_nat->invalid_packets |= pkt_mask;
4832 p_nat->naptDroppedPktCount++;
4834 #ifdef CGNAPT_DEBUGGING
4835 p_nat->naptDroppedPktCount4++;
4841 if (ret >= 0 && rtp_port != 0) {
4842 struct pipeline_cgnapt_entry_key rtp_key;
4843 rtp_key.ip = entry->data.u.prv_ip;
4844 rtp_key.port = rtp_port;
4845 rtp_key.pid = entry->data.prv_phy_port;
4847 if (add_dynamic_cgnapt_entry_alg(
4848 (struct pipeline *)p_nat, &rtp_key,
4849 &entry_ptr1, &entry_ptr2) == 0) {
4850 printf("%s: Wrong SIP ALG packet2\n",
4852 p_nat->invalid_packets |= pkt_mask;
4854 p_nat->naptDroppedPktCount++;
4856 #ifdef CGNAPT_DEBUGGING
4857 p_nat->naptDroppedPktCount4++;
4863 if (ret >= 0 && rtcp_port != 0) {
4864 struct pipeline_cgnapt_entry_key rtcp_key;
4865 rtcp_key.ip = entry->data.u.prv_ip;
4866 rtcp_key.port = rtcp_port;
4867 rtcp_key.pid = entry->data.prv_phy_port;
4869 if (add_dynamic_cgnapt_entry_alg(
4870 (struct pipeline *)p_nat, &rtcp_key,
4871 &entry_ptr3, &entry_ptr4) == 0) {
4873 printf("%s: Wrong SIP ALG packet3\n",
4875 p_nat->invalid_packets |= pkt_mask;
4877 p_nat->naptDroppedPktCount++;
4879 #ifdef CGNAPT_DEBUGGING
4880 p_nat->naptDroppedPktCount4++;
4886 //if(entry_ptr1 != NULL && entry_ptr3 != NULL)
4887 if (sip_alg_dpi(pkt, PRIVATE,
4889 entry->data.pub_port,
4890 entry->data.u.prv_ip,
4891 entry->data.prv_port,
4892 (rtp_port == 0) ? 0 :
4893 entry_ptr1->data.pub_port,
4894 (rtcp_port == 0) ? 0 :
4895 entry_ptr3->data.pub_port) == 0) {
4897 printf("%s: Wrong SIP ALG packet4\n",
4899 p_nat->invalid_packets |= pkt_mask;
4901 p_nat->naptDroppedPktCount++;
4903 #ifdef CGNAPT_DEBUGGING
4904 p_nat->naptDroppedPktCount4++;
4909 #endif /* SIP_ALG */
4912 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4913 rte_be_to_cpu_16(*dst_port) == 21) {
4915 int32_t ct_position =
4916 cgnat_cnxn_tracker->positions[pkt_num];
4918 printf("@CGNAT-pkt4work ct_position :%d, pkt_num %d "
4919 "pkt_mask = %" PRIu64 "\n", ct_position,
4923 if (ct_position < 0){
4924 p_nat->invalid_packets |= pkt_mask;
4925 p_nat->naptDroppedPktCount++;
4928 if (cgnat_cnxn_tracker->hash_table_entries[ct_position].
4929 alg_bypass_flag != BYPASS){
4931 struct pipeline_cgnapt_entry_key
4932 data_channel_entry_key;
4934 data_channel_entry_key.ip =
4936 data_channel_entry_key.port =
4937 entry->data.pub_port;
4938 data_channel_entry_key.pid = 0xffff;
4940 ftp_alg_dpi(p_nat, &data_channel_entry_key,
4941 pkt, cgnat_cnxn_tracker, ct_position,
4947 p_nat->enaptedPktCount++;
4950 p_nat->naptedPktCount++;
4952 #ifdef HW_CHECKSUM_REQ
4953 if (p_nat->hw_checksum_reqd)
4954 hw_checksum(pkt, pkt_type);
4957 sw_checksum(pkt, pkt_type);
4962 * NAPT function for IPv4 public traffic which handles 4 pkts
4965 * A pointer to array of packets mbuf
4967 * Starting pkt number of pkts
4971 * A pointer to main CGNAPT structure
4975 pkt4_work_cgnapt_ipv4_pub(
4976 struct rte_mbuf **pkts,
4977 uint32_t in_pkt_num,
4978 __rte_unused void *arg,
4979 struct pipeline_cgnapt *p_nat)
4982 struct rte_CT_helper ct_helper;
4983 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4985 struct rte_mbuf *pkt;
4988 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4990 for (i = 0; i < 4; i++) {
4991 pkt_num = in_pkt_num + i;
4992 pkt = pkts[pkt_num];
4994 /* index into hash table entries */
4995 int hash_table_entry = p_nat->lkup_indx[pkt_num];
4996 /*bitmask representing only this packet */
4997 uint64_t pkt_mask = 1LLU << pkt_num;
4999 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
5001 uint32_t dest_if = 0xff; /* Added for Multiport */
5002 uint16_t *outport_id =
5003 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
5005 struct cgnapt_table_entry *entry = NULL;
5007 if (hash_table_entry < 0) {
5009 /* try to add new entry */
5010 struct rte_pipeline_table_entry *table_entry = NULL;
5013 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
5015 &p_nat->valid_packets, pkt_num,
5019 /* ICMP Error message generation for
5020 * Destination Host unreachable
5022 if (protocol == IP_PROTOCOL_ICMP) {
5023 cgnapt_icmp_pkt = pkt;
5024 send_icmp_dest_unreachable_msg();
5027 /* Drop packet by adding to invalid pkt mask */
5029 p_nat->invalid_packets |= dropmask;
5031 #ifdef CGNAPT_DEBUGGING
5032 if (p_nat->kpc2++ < 5) {
5033 printf("in_ah Th: %d",
5034 p_nat->pipeline_num);
5035 print_key(p_nat->key_ptrs[pkt_num]);
5039 p_nat->naptDroppedPktCount++;
5041 #ifdef CGNAPT_DEBUGGING
5042 p_nat->naptDroppedPktCount3++;
5048 entry = (struct cgnapt_table_entry *)table_entry;
5050 /* entry found for this packet */
5051 entry = &napt_hash_tbl_entries[hash_table_entry];
5054 /* apply napt and mac changes */
5056 p_nat->entries[pkt_num] = &(entry->head);
5058 uint32_t *dst_addr =
5059 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
5060 uint16_t src_port_offset = 0;
5061 uint16_t dst_port_offset = 0;
5063 if ((protocol == IP_PROTOCOL_TCP)
5064 || (protocol == IP_PROTOCOL_UDP)) {
5065 src_port_offset = SRC_PRT_OFST_IP4_TCP;
5066 dst_port_offset = DST_PRT_OFST_IP4_TCP;
5067 } else if (protocol == IP_PROTOCOL_ICMP) {
5069 src_port_offset = MBUF_HDR_ROOM +
5072 /*Sequence number */
5073 dst_port_offset = MBUF_HDR_ROOM +
5078 uint16_t *src_port =
5079 RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
5080 uint16_t *dst_port =
5081 RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
5084 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
5086 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
5088 if (entry->data.ttl == NAPT_ENTRY_STALE)
5089 entry->data.ttl = NAPT_ENTRY_VALID;
5091 struct ether_addr hw_addr;
5092 uint32_t dest_address = 0;
5093 /* Multiport Changes */
5099 if (unlikely(protocol == IP_PROTOCOL_UDP
5100 && rte_be_to_cpu_16(*src_port) == 53)) {
5101 p_nat->invalid_packets |= pkt_mask;
5102 p_nat->naptDroppedPktCount++;
5103 #ifdef CGNAPT_DEBUGGING
5104 p_nat->naptDroppedPktCount6++;
5109 dest_address = entry->data.u.prv_ip;
5110 ret = local_get_nh_ipv4(dest_address, &dest_if, &nhip, p_nat);
5112 dest_if = get_prv_to_pub_port(&dest_address, IP_VERSION_4);
5114 if (dest_if == INVALID_DESTIF) {
5115 p_nat->invalid_packets |= pkt_mask;
5116 p_nat->naptDroppedPktCount++;
5117 #ifdef CGNAPT_DEBUGGING
5118 p_nat->naptDroppedPktCount6++;
5123 do_local_nh_ipv4_cache(dest_if, p_nat);
5126 *outport_id = p_nat->outport_id[dest_if];
5128 #ifdef CGNAPT_DBG_PRNT
5129 if (CGNAPT_DEBUG > 2)
5130 printf("Ingress: \tphy_port:%d\t "
5131 "get_pub_to_prv():%d \tout_port%d\n",
5137 if (local_dest_mac_present(dest_if)) {
5139 get_local_link_hw_addr(dest_if),
5140 sizeof(struct ether_addr));
5142 get_link_hw_addr(dest_if),
5143 sizeof(struct ether_addr));
5146 ret = get_dest_mac_addr_port(dest_address, &dest_if, &hw_addr);
5148 if (unlikely(ret != ARP_FOUND)) {
5150 if (unlikely(ret == ARP_NOT_FOUND)) {
5151 printf("%s: ARP Not Found, nhip: %x, "
5152 "outport_id: %d\n", __func__, nhip,
5154 //request_arp(*outport_id, nhip, p_nat->p.p);
5158 p_nat->invalid_packets |= pkt_mask;
5159 p_nat->naptDroppedPktCount++;
5161 #ifdef CGNAPT_DEBUGGING
5162 p_nat->naptDroppedPktCount4++;
5167 #ifdef CGNAPT_DBG_PRNT
5168 if (CGNAPT_DEBUG > 2) {
5169 printf("MAC found for ip 0x%x, port %d - "
5170 "%02x:%02x:%02x:%02x:%02x:%02x\n",
5171 dest_address, *outport_id,
5172 hw_addr.addr_bytes[0],
5173 hw_addr.addr_bytes[1],
5174 hw_addr.addr_bytes[2],
5175 hw_addr.addr_bytes[3],
5176 hw_addr.addr_bytes[4],
5177 hw_addr.addr_bytes[5]
5180 printf("Dest MAC before - "
5181 "%02x:%02x:%02x:%02x:%02x:%02x\n",
5182 eth_dest[0], eth_dest[1], eth_dest[2],
5183 eth_dest[3], eth_dest[4], eth_dest[5]);
5187 memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
5189 link_hw_laddr_valid[dest_if] = 1;
5190 memcpy(&link_hw_laddr[dest_if],
5191 &hw_addr, sizeof(struct ether_addr));
5193 #ifdef CGNAPT_DBG_PRNT
5194 if (CGNAPT_DEBUG > 2) {
5195 printf("Dest MAC after - %02x:%02x:%02x: "
5197 eth_dest[0], eth_dest[1], eth_dest[2],
5198 eth_dest[3], eth_dest[4], eth_dest[5]);
5203 get_link_hw_addr(dest_if),
5204 sizeof(struct ether_addr));
5210 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
5211 if (protocol == IP_PROTOCOL_ICMP) {
5212 /* Query ID reverse translation done here */
5213 *src_port = rte_bswap16(entry->data.prv_port);
5214 /* dont care sequence num */
5216 #ifdef NAT_ONLY_CONFIG_REQ
5217 if (!nat_only_config_flag) {
5220 rte_bswap16(entry->data.prv_port);
5221 #ifdef NAT_ONLY_CONFIG_REQ
5226 if ((rte_be_to_cpu_16(*src_port) == 21) ||
5227 rte_be_to_cpu_16(*dst_port) == 21) {
5228 pkt_mask = cgnapt_ct_process(
5229 cgnat_cnxn_tracker, pkts,
5230 pkt_mask, &ct_helper);
5236 uint16_t rtp_port = 0, rtcp_port = 0;
5237 struct cgnapt_table_entry *entry_ptr1 = NULL,
5239 /* Commented code may be required for future usage,
5243 struct cgnapt_table_entry *entry_ptr2 = NULL,
5247 if (unlikely(protocol == IP_PROTOCOL_UDP
5248 && (rte_be_to_cpu_16(*dst_port) == 5060
5249 || rte_be_to_cpu_16(*src_port) == 5060))) {
5250 /* Commented code may be required for future usage,
5254 int ret = natSipAlgGetAudioPorts(pkt,
5255 &rtp_port, &rtcp_port);
5257 printf("%s: Wrong SIP ALG packet1\n",
5259 p_nat->invalid_packets |= pkt_mask;
5261 p_nat->naptDroppedPktCount++;
5263 #ifdef CGNAPT_DEBUGGING
5264 p_nat->naptDroppedPktCount4++;
5269 if (rtp_port != 0) {
5270 struct pipeline_cgnapt_entry_key rtp_key;
5271 rtp_key.ip = entry->data.pub_ip;
5272 rtp_key.port = rtp_port;
5273 rtp_key.pid = 0xffff;
5275 if (retrieve_cgnapt_entry_alg(&rtp_key,
5276 &entry_ptr1, &entry_ptr2) == 0) {
5277 printf("%s: Wrong SIP ALG packet2\n",
5279 p_nat->invalid_packets |= pkt_mask;
5281 p_nat->naptDroppedPktCount++;
5283 #ifdef CGNAPT_DEBUGGING
5284 p_nat->naptDroppedPktCount4++;
5290 if (rtcp_port != 0) {
5291 struct pipeline_cgnapt_entry_key rtcp_key;
5292 rtcp_key.ip = entry->data.pub_ip;
5293 rtcp_key.port = rtcp_port;
5294 rtcp_key.pid = 0xffff;
5296 if (retrieve_cgnapt_entry_alg(&rtcp_key,
5297 &entry_ptr3, &entry_ptr4) == 0) {
5298 printf("%s: Wrong SIP ALG packet3\n",
5300 p_nat->invalid_packets |= pkt_mask;
5301 p_nat->naptDroppedPktCount++;
5303 #ifdef CGNAPT_DEBUGGING
5304 p_nat->naptDroppedPktCount4++;
5311 if (sip_alg_dpi(pkt, PUBLIC,
5312 entry->data.u.prv_ip,
5313 entry->data.prv_port,
5315 entry->data.pub_port,
5316 (rtp_port == 0) ? 0 :
5317 entry_ptr1->data.prv_port,
5318 (rtcp_port == 0) ? 0 :
5319 entry_ptr3->data.prv_port) == 0) {
5321 printf("%s: Wrong SIP ALG packet4\n",
5323 p_nat->invalid_packets |= pkt_mask;
5325 p_nat->naptDroppedPktCount++;
5327 #ifdef CGNAPT_DEBUGGING
5328 p_nat->naptDroppedPktCount4++;
5333 #endif /* SIP_ALG */
5336 if ((rte_be_to_cpu_16(*src_port) == 21) ||
5337 rte_be_to_cpu_16(*dst_port) == 21) {
5339 int32_t ct_position =
5340 cgnat_cnxn_tracker->positions[pkt_num];
5341 if (ct_position < 0){
5342 p_nat->invalid_packets |= pkt_mask;
5344 p_nat->naptDroppedPktCount++;
5347 if (cgnat_cnxn_tracker->hash_table_entries
5348 [ct_position].alg_bypass_flag != BYPASS){
5350 struct pipeline_cgnapt_entry_key
5351 data_channel_entry_key;
5354 data_channel_entry_key.ip =
5356 data_channel_entry_key.port =
5357 entry->data.pub_port;
5358 data_channel_entry_key.pid = 0xffff;
5360 ftp_alg_dpi(p_nat, &data_channel_entry_key,
5361 pkt, cgnat_cnxn_tracker,
5362 ct_position, PUBLIC);
5367 p_nat->inaptedPktCount++;
5370 p_nat->naptedPktCount++;
5372 #ifdef HW_CHECKSUM_REQ
5373 if (p_nat->hw_checksum_reqd)
5374 hw_checksum(pkt, pkt_type);
5377 sw_checksum(pkt, pkt_type);
5382 * NAPT key calculation function for IPv6 private traffic
5383 * which handles 1 pkt
5386 * A pointer to array of packets mbuf
5388 * Pkt number of pkts
5392 * A pointer to main CGNAPT structure
5396 pkt_work_cgnapt_key_ipv6_prv(
5397 struct rte_mbuf *pkt,
5399 __rte_unused void *arg,
5400 struct pipeline_cgnapt *p_nat)
5403 p_nat->receivedPktCount++;
5405 /* bitmask representing only this packet */
5406 uint64_t pkt_mask = 1LLU << pkt_num;
5408 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
5409 uint32_t *src_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
5411 uint16_t src_port = RTE_MBUF_METADATA_UINT16(pkt, SRC_PRT_OFST_IP6);
5413 uint16_t phy_port = pkt->port;
5414 struct pipeline_cgnapt_entry_key key;
5416 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
5418 #ifdef CGNAPT_DBG_PRNT
5419 if (CGNAPT_DEBUG > 4)
5424 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
5429 case IP_PROTOCOL_UDP:
5433 struct udp_hdr *udp;
5435 udp = (struct udp_hdr *)
5436 RTE_MBUF_METADATA_UINT8_PTR(pkt,
5439 if (rte_bswap16(udp->dst_port) ==
5441 handle_pcp_req(pkt, IPV6_SZ, p_nat);
5442 p_nat->invalid_packets |= pkt_mask;
5448 case IP_PROTOCOL_TCP:
5449 case IP_PROTOCOL_ICMP:
5450 /*we don't need icmp check in ipv6 */
5454 printf("wrong protocol: %d\n", protocol);
5455 /* remember invalid packets to be dropped */
5456 p_nat->invalid_packets |= pkt_mask;
5457 p_nat->naptDroppedPktCount++;
5459 #ifdef CGNAPT_DEBUGGING
5460 p_nat->naptDroppedPktCount2++;
5466 key.ip = rte_bswap32(src_addr[3]);
5467 key.port = rte_bswap16(src_port);
5469 #ifdef NAT_ONLY_CONFIG_REQ
5470 if (nat_only_config_flag)
5474 memcpy(&p_nat->keys[pkt_num], &key,
5475 sizeof(struct pipeline_cgnapt_entry_key));
5476 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5480 * NAPT key calculation function for IPv6 public traffic
5481 * which handles 1 pkt
5484 * A pointer to array of packets mbuf
5486 * Pkt number of pkts
5490 * A pointer to main CGNAPT structure
5494 pkt_work_cgnapt_key_ipv6_pub(
5495 struct rte_mbuf *pkt,
5497 __rte_unused void *arg,
5498 struct pipeline_cgnapt *p_nat)
5502 p_nat->receivedPktCount++;
5504 /* bitmask representing only this packet */
5505 uint64_t pkt_mask = 1LLU << pkt_num;
5507 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
5509 uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
5511 uint16_t dst_port = RTE_MBUF_METADATA_UINT16(pkt,
5512 DST_PRT_OFST_IP4_TCP);
5514 struct pipeline_cgnapt_entry_key key;
5516 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
5518 #ifdef CGNAPT_DBG_PRNT
5519 if (CGNAPT_DEBUG > 4)
5524 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
5530 case IP_PROTOCOL_UDP:
5531 case IP_PROTOCOL_TCP:
5532 case IP_PROTOCOL_ICMP:
5533 /*we don't need icmp check in ipv6 */
5537 /* remember invalid packets to be dropped */
5538 p_nat->invalid_packets |= pkt_mask;
5539 p_nat->naptDroppedPktCount++;
5541 #ifdef CGNAPT_DEBUGGING
5542 p_nat->naptDroppedPktCount2++;
5548 key.ip = rte_bswap32(dst_addr[0]);
5549 key.port = rte_bswap16(dst_port);
5551 #ifdef NAT_ONLY_CONFIG_REQ
5552 if (nat_only_config_flag)
5556 memcpy(&p_nat->keys[pkt_num], &key,
5557 sizeof(struct pipeline_cgnapt_entry_key));
5558 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5562 * NAPT key calculation function for IPv6 private traffic
5563 * which handles 4 pkts
5566 * A pointer to array of packets mbuf
5568 * Starting pkt number of pkts
5572 * A pointer to main CGNAPT structure
5576 pkt4_work_cgnapt_key_ipv6_prv(
5577 struct rte_mbuf **pkt,
5579 __rte_unused void *arg,
5580 struct pipeline_cgnapt *p_nat)
5582 p_nat->receivedPktCount += 4;
5584 /* bitmask representing only this packet */
5585 uint64_t pkt_mask0 = 1LLU << pkt_num;
5586 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
5587 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
5588 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
5590 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
5592 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
5594 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
5596 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
5599 uint32_t *src_addr0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0],
5601 uint32_t *src_addr1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1],
5603 uint32_t *src_addr2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2],
5605 uint32_t *src_addr3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3],
5608 uint16_t src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
5610 uint16_t src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
5612 uint16_t src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
5614 uint16_t src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
5617 uint16_t phy_port0 = pkt[0]->port;
5618 uint16_t phy_port1 = pkt[1]->port;
5619 uint16_t phy_port2 = pkt[2]->port;
5620 uint16_t phy_port3 = pkt[3]->port;
5622 struct pipeline_cgnapt_entry_key key0;
5623 struct pipeline_cgnapt_entry_key key1;
5624 struct pipeline_cgnapt_entry_key key2;
5625 struct pipeline_cgnapt_entry_key key3;
5627 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
5628 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
5629 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
5630 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
5634 #ifdef CGNAPT_DBG_PRNT
5635 if (CGNAPT_DEBUG > 4)
5640 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
5644 switch (protocol0) {
5646 case IP_PROTOCOL_UDP:
5650 struct udp_hdr *udp;
5652 udp = (struct udp_hdr *)
5653 RTE_MBUF_METADATA_UINT8_PTR(pkt[0],
5656 if (rte_bswap16(udp->dst_port) ==
5658 handle_pcp_req(pkt[0], IPV6_SZ, p_nat);
5659 p_nat->invalid_packets |= pkt_mask0;
5665 case IP_PROTOCOL_TCP:
5666 case IP_PROTOCOL_ICMP:
5667 /*we don't need icmp check in ipv6 */
5671 /* remember invalid packets to be dropped */
5672 p_nat->invalid_packets |= pkt_mask0;
5673 p_nat->naptDroppedPktCount++;
5675 #ifdef CGNAPT_DEBUGGING
5676 p_nat->naptDroppedPktCount2++;
5683 key0.pid = phy_port0;
5684 key0.ip = rte_bswap32(src_addr0[3]);
5685 key0.port = rte_bswap16(src_port0);
5687 #ifdef NAT_ONLY_CONFIG_REQ
5688 if (nat_only_config_flag)
5692 memcpy(&p_nat->keys[pkt_num], &key0,
5693 sizeof(struct pipeline_cgnapt_entry_key));
5694 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5697 #ifdef CGNAPT_DBG_PRNT
5698 if (CGNAPT_DEBUG > 4)
5703 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
5707 switch (protocol1) {
5708 case IP_PROTOCOL_UDP:
5712 struct udp_hdr *udp;
5714 udp = (struct udp_hdr *)
5715 RTE_MBUF_METADATA_UINT8_PTR(pkt[1],
5718 if (rte_bswap16(udp->dst_port) ==
5720 handle_pcp_req(pkt[1], IPV6_SZ, p_nat);
5721 p_nat->invalid_packets |= pkt_mask1;
5727 case IP_PROTOCOL_TCP:
5728 case IP_PROTOCOL_ICMP:
5729 /*we don't need icmp check in ipv6 */
5733 /* remember invalid packets to be dropped */
5734 p_nat->invalid_packets |= pkt_mask1;
5735 p_nat->naptDroppedPktCount++;
5737 #ifdef CGNAPT_DEBUGGING
5738 p_nat->naptDroppedPktCount2++;
5744 key1.pid = phy_port1;
5745 key1.ip = rte_bswap32(src_addr1[3]);
5746 key1.port = rte_bswap16(src_port1);
5748 #ifdef NAT_ONLY_CONFIG_REQ
5749 if (nat_only_config_flag)
5753 memcpy(&p_nat->keys[pkt_num + 1], &key1,
5754 sizeof(struct pipeline_cgnapt_entry_key));
5755 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
5758 #ifdef CGNAPT_DBG_PRNT
5759 if (CGNAPT_DEBUG > 4)
5764 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
5768 switch (protocol2) {
5769 case IP_PROTOCOL_UDP:
5773 struct udp_hdr *udp;
5775 udp = (struct udp_hdr *)
5776 RTE_MBUF_METADATA_UINT8_PTR(pkt[2],
5779 if (rte_bswap16(udp->dst_port) ==
5781 handle_pcp_req(pkt[2], IPV6_SZ, p_nat);
5782 p_nat->invalid_packets |= pkt_mask2;
5788 case IP_PROTOCOL_TCP:
5789 case IP_PROTOCOL_ICMP:
5790 /*we don't need icmp check in ipv6 */
5794 /* remember invalid packets to be dropped */
5795 p_nat->invalid_packets |= pkt_mask2;
5796 p_nat->naptDroppedPktCount++;
5798 #ifdef CGNAPT_DEBUGGING
5799 p_nat->naptDroppedPktCount2++;
5805 key2.pid = phy_port2;
5806 key2.ip = rte_bswap32(src_addr2[3]);
5807 key2.port = rte_bswap16(src_port2);
5809 #ifdef NAT_ONLY_CONFIG_REQ
5810 if (nat_only_config_flag)
5814 memcpy(&p_nat->keys[pkt_num + 2], &key2,
5815 sizeof(struct pipeline_cgnapt_entry_key));
5816 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
5819 #ifdef CGNAPT_DBG_PRNT
5820 if (CGNAPT_DEBUG > 4)
5825 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
5829 switch (protocol3) {
5830 case IP_PROTOCOL_UDP:
5834 struct udp_hdr *udp;
5836 udp = (struct udp_hdr *)
5837 RTE_MBUF_METADATA_UINT8_PTR(pkt[3],
5840 if (rte_bswap16(udp->dst_port) ==
5842 handle_pcp_req(pkt[3], IPV6_SZ, p_nat);
5843 p_nat->invalid_packets |= pkt_mask3;
5849 case IP_PROTOCOL_TCP:
5850 case IP_PROTOCOL_ICMP:
5851 /*we don't need icmp check in ipv6 */
5855 /* remember invalid packets to be dropped */
5856 p_nat->invalid_packets |= pkt_mask2;
5857 p_nat->naptDroppedPktCount++;
5859 #ifdef CGNAPT_DEBUGGING
5860 p_nat->naptDroppedPktCount2++;
5866 key3.pid = phy_port3;
5867 key3.ip = rte_bswap32(src_addr3[3]);
5868 key3.port = rte_bswap16(src_port3);
5870 #ifdef NAT_ONLY_CONFIG_REQ
5871 if (nat_only_config_flag)
5875 memcpy(&p_nat->keys[pkt_num + 3], &key3,
5876 sizeof(struct pipeline_cgnapt_entry_key));
5877 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
5883 * NAPT key calculation function for IPv4 public traffic
5884 * which handles 4 pkts
5887 * A pointer to array of packets mbuf
5889 * Starting pkt number of pkts
5893 * A pointer to main CGNAPT structure
5897 pkt4_work_cgnapt_key_ipv6_pub(
5898 struct rte_mbuf **pkt,
5900 __rte_unused void *arg,
5901 struct pipeline_cgnapt *p_nat)
5903 p_nat->receivedPktCount += 4;
5905 /* bitmask representing only this packet */
5906 uint64_t pkt_mask0 = 1LLU << pkt_num;
5907 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
5908 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
5909 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
5911 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
5913 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
5915 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
5917 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
5920 uint32_t *dst_addr0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0],
5922 uint32_t *dst_addr1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1],
5924 uint32_t *dst_addr2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2],
5926 uint32_t *dst_addr3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3],
5929 uint16_t dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
5930 DST_PRT_OFST_IP4_TCP);
5931 uint16_t dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
5932 DST_PRT_OFST_IP4_TCP);
5933 uint16_t dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
5934 DST_PRT_OFST_IP4_TCP);
5935 uint16_t dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
5936 DST_PRT_OFST_IP4_TCP);
5938 struct pipeline_cgnapt_entry_key key0;
5939 struct pipeline_cgnapt_entry_key key1;
5940 struct pipeline_cgnapt_entry_key key2;
5941 struct pipeline_cgnapt_entry_key key3;
5943 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
5944 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
5945 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
5946 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
5950 #ifdef CGNAPT_DBG_PRNT
5951 if (CGNAPT_DEBUG > 4)
5956 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
5960 switch (protocol0) {
5962 case IP_PROTOCOL_TCP:
5963 case IP_PROTOCOL_UDP:
5964 case IP_PROTOCOL_ICMP:
5965 /*we don't need icmp check in ipv6 */
5969 /* remember invalid packets to be dropped */
5970 p_nat->invalid_packets |= pkt_mask0;
5971 p_nat->naptDroppedPktCount++;
5973 #ifdef CGNAPT_DEBUGGING
5974 p_nat->naptDroppedPktCount2++;
5980 key0.ip = rte_bswap32(dst_addr0[0]);
5981 key0.port = rte_bswap16(dst_port0);
5983 #ifdef NAT_ONLY_CONFIG_REQ
5984 if (nat_only_config_flag)
5988 memcpy(&p_nat->keys[pkt_num], &key0,
5989 sizeof(struct pipeline_cgnapt_entry_key));
5990 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5996 #ifdef CGNAPT_DBG_PRNT
5997 if (CGNAPT_DEBUG > 4)
6002 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
6006 switch (protocol1) {
6008 case IP_PROTOCOL_TCP:
6009 case IP_PROTOCOL_UDP:
6010 case IP_PROTOCOL_ICMP:
6011 /*we don't need icmp check in ipv6 */
6015 /* remember invalid packets to be dropped */
6016 p_nat->invalid_packets |= pkt_mask1;
6017 p_nat->naptDroppedPktCount++;
6019 #ifdef CGNAPT_DEBUGGING
6020 p_nat->naptDroppedPktCount2++;
6026 key1.ip = rte_bswap32(dst_addr1[0]);
6027 key1.port = rte_bswap16(dst_port1);
6029 #ifdef NAT_ONLY_CONFIG_REQ
6030 if (nat_only_config_flag)
6034 memcpy(&p_nat->keys[pkt_num + 1], &key1,
6035 sizeof(struct pipeline_cgnapt_entry_key));
6036 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
6042 #ifdef CGNAPT_DBG_PRNT
6043 if (CGNAPT_DEBUG > 4)
6048 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
6052 switch (protocol2) {
6054 case IP_PROTOCOL_TCP:
6055 case IP_PROTOCOL_UDP:
6056 case IP_PROTOCOL_ICMP:
6057 /*we don't need icmp check in ipv6 */
6061 /* remember invalid packets to be dropped */
6062 p_nat->invalid_packets |= pkt_mask2;
6063 p_nat->naptDroppedPktCount++;
6065 #ifdef CGNAPT_DEBUGGING
6066 p_nat->naptDroppedPktCount2++;
6072 key2.ip = rte_bswap32(dst_addr2[0]);
6073 key2.port = rte_bswap16(dst_port2);
6075 #ifdef NAT_ONLY_CONFIG_REQ
6076 if (nat_only_config_flag)
6080 memcpy(&p_nat->keys[pkt_num + 2], &key2,
6081 sizeof(struct pipeline_cgnapt_entry_key));
6083 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
6089 #ifdef CGNAPT_DBG_PRNT
6090 if (CGNAPT_DEBUG > 4)
6095 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
6099 switch (protocol3) {
6101 case IP_PROTOCOL_TCP:
6102 case IP_PROTOCOL_UDP:
6103 case IP_PROTOCOL_ICMP:
6104 /*we don't need icmp check in ipv6 */
6108 /* remember invalid packets to be dropped */
6109 p_nat->invalid_packets |= pkt_mask3;
6110 p_nat->naptDroppedPktCount++;
6112 #ifdef CGNAPT_DEBUGGING
6113 p_nat->naptDroppedPktCount2++;
6119 key3.ip = rte_bswap32(dst_addr3[0]);
6120 key3.port = rte_bswap16(dst_port3);
6122 #ifdef NAT_ONLY_CONFIG_REQ
6123 if (nat_only_config_flag)
6127 memcpy(&p_nat->keys[pkt_num + 3], &key3,
6128 sizeof(struct pipeline_cgnapt_entry_key));
6130 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
6134 * NAPT function for IPv6 private traffic which handles 1 pkt
6137 * A pointer to array of packet mbuf
6143 * A pointer to main CGNAPT structure
6147 pkt_work_cgnapt_ipv6_prv(
6148 struct rte_mbuf *pkt,
6150 __rte_unused void *arg,
6151 struct pipeline_cgnapt *p_nat)
6154 /* index into hash table entries */
6155 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6157 /*bitmask representing only this packet */
6158 uint64_t pkt_mask = 1LLU << pkt_num;
6160 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
6162 /* Added for Multiport */
6163 uint32_t dest_if = INVALID_DESTIF;
6164 uint16_t *outport_id = RTE_MBUF_METADATA_UINT16_PTR(pkt,
6165 cgnapt_meta_offset);
6167 struct cgnapt_table_entry *entry = NULL;
6168 enum PKT_TYPE pkt_type = PKT_TYPE_IPV6to4;
6170 if (hash_table_entry < 0) {
6172 /* try to add new entry */
6173 struct rte_pipeline_table_entry *table_entry = NULL;
6175 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
6177 &p_nat->valid_packets, pkt_num,
6181 /* ICMP Error message generation for
6182 * Destination Host unreachable
6184 /* Do we need this check for ipv6? */
6185 if (protocol == IP_PROTOCOL_ICMP) {
6186 cgnapt_icmp_pkt = pkt;
6187 send_icmp_dest_unreachable_msg();
6190 /* Drop packet by adding to invalid pkt mask */
6192 p_nat->invalid_packets |= dropmask;
6194 #ifdef CGNAPT_DEBUGGING
6195 if (p_nat->kpc2++ < 5) {
6196 printf("in_ah Th: %d", p_nat->pipeline_num);
6197 print_key(p_nat->key_ptrs[pkt_num]);
6201 p_nat->naptDroppedPktCount++;
6203 #ifdef CGNAPT_DEBUGGING
6204 p_nat->naptDroppedPktCount3++;
6210 entry = (struct cgnapt_table_entry *)table_entry;
6212 /* entry found for this packet */
6213 entry = &napt_hash_tbl_entries[hash_table_entry];
6216 /* apply napt and mac changes */
6218 p_nat->entries[pkt_num] = &(entry->head);
6220 struct ipv6_hdr ipv6_hdr;
6222 struct ether_addr hw_addr;
6223 uint32_t dest_address = 0;
6228 convert_ipv6_to_ipv4(pkt, &ipv6_hdr);
6230 #ifdef CGNAPT_DBG_PRNT
6231 if (CGNAPT_DEBUG == 1)
6232 printf("pkt_work_cganpt: convert_ipv6_to_ipv4\n");
6235 struct cgnapt_nsp_node *ll = nsp_ll;
6238 while (ll != NULL) {
6240 (&ipv6_hdr.dst_addr[0], &ll->nsp.prefix[0],
6241 ll->nsp.depth / 8)) {
6249 && !memcmp(&ipv6_hdr.dst_addr[0], &well_known_prefix[0],
6255 p_nat->invalid_packets |= pkt_mask;
6256 p_nat->naptDroppedPktCount++;
6258 #ifdef CGNAPT_DEBUGGING
6259 p_nat->naptDroppedPktCount5++;
6267 /* As packet is already converted into IPv4 we must not
6268 * operate IPv6 offsets on packet
6269 * Only perform IPv4 operations
6272 uint32_t *src_addr =
6273 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP6t4);
6274 uint32_t *dst_addr =
6275 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP6t4);
6276 uint16_t *src_port =
6277 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP6t4);
6278 uint16_t *dst_port =
6279 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP6t4);
6281 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt,
6283 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt,
6284 ETH_OFST_IP6t4 + 6);
6286 if (entry->data.ttl == NAPT_ENTRY_STALE)
6287 entry->data.ttl = NAPT_ENTRY_VALID;
6290 if (unlikely(protocol == IP_PROTOCOL_UDP
6291 && rte_be_to_cpu_16(*dst_port) == 53)) {
6292 p_nat->invalid_packets |= pkt_mask;
6293 p_nat->naptDroppedPktCount++;
6295 #ifdef CGNAPT_DEBUGGING
6296 p_nat->naptDroppedPktCount6++;
6302 dest_address = rte_bswap32(*dst_addr);
6303 /*Multiport Changes */
6306 ret = local_get_nh_ipv4(dest_address, &dest_if, &nhip, p_nat);
6308 dest_if = get_prv_to_pub_port(&dest_address, IP_VERSION_4);
6310 if (dest_if == INVALID_DESTIF) {
6311 p_nat->invalid_packets |= pkt_mask;
6312 p_nat->naptDroppedPktCount++;
6313 #ifdef CGNAPT_DEBUGGING
6314 p_nat->naptDroppedPktCount6++;
6319 do_local_nh_ipv4_cache(dest_if, p_nat);
6321 *outport_id = p_nat->outport_id[dest_if];
6323 #ifdef CGNAPT_DBG_PRNT
6324 if (CGNAPT_DEBUG > 2)
6325 printf("Egress: \tphy_port:%d\t get_prv_to_pub():%d "
6326 "\tout_port:%d\n", pkt->port,
6327 dest_if, *outport_id);
6331 #ifdef CGNAPT_DBG_PRNT
6332 static int static_count;
6334 if (static_count++ < 10) {
6336 my_print_entry(entry);
6337 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6338 printf("dest_add:%x\n", entry->data.u.prv_ip);
6339 printf("dest_add:%x\n", *dst_addr);
6340 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6344 if (local_dest_mac_present(dest_if)) {
6346 get_local_link_hw_addr(dest_if),
6347 sizeof(struct ether_addr));
6348 memcpy(eth_src, get_link_hw_addr(dest_if),
6349 sizeof(struct ether_addr));
6352 ret = get_dest_mac_addr_port(dest_address, &dest_if, &hw_addr);
6354 if (unlikely(ret != ARP_FOUND)) {
6356 if (unlikely(ret == ARP_NOT_FOUND)) {
6357 printf("%s: ARP Not Found, nhip: %x, "
6358 "outport_id: %d\n", __func__, nhip,
6360 //request_arp(*outport_id, nhip, p_nat->p.p);
6364 p_nat->invalid_packets |= pkt_mask;
6365 p_nat->naptDroppedPktCount++;
6367 #ifdef CGNAPT_DEBUGGING
6368 p_nat->naptDroppedPktCount4++;
6373 #ifdef CGNAPT_DBG_PRNT
6374 if (CGNAPT_DEBUG > 2) {
6375 printf("MAC found for ip 0x%x, port %d - %02x:%02x: "
6376 "%02x:%02x:%02x:%02x\n", dest_address,
6378 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
6379 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
6380 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
6382 printf("Dest MAC before - %02x:%02x:%02x:%02x: "
6383 "%02x:%02x\n", eth_dest[0], eth_dest[1],
6384 eth_dest[2], eth_dest[3],
6385 eth_dest[4], eth_dest[5]);
6389 memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
6391 #ifdef CGNAPT_DBG_PRNT
6392 if (CGNAPT_DEBUG > 2) {
6393 printf("Dest MAC after - "
6394 "%02x:%02x:%02x:%02x:%02x:%02x\n",
6395 eth_dest[0], eth_dest[1], eth_dest[2], eth_dest[3],
6396 eth_dest[4], eth_dest[5]);
6400 memcpy(eth_src, get_link_hw_addr(dest_if),
6401 sizeof(struct ether_addr));
6406 *src_addr = rte_bswap32(entry->data.pub_ip);
6408 #ifdef NAT_ONLY_CONFIG_REQ
6409 if (!nat_only_config_flag) {
6411 *src_port = rte_bswap16(entry->data.pub_port);
6413 #ifdef NAT_ONLY_CONFIG_REQ
6417 p_nat->enaptedPktCount++;
6420 p_nat->naptedPktCount++;
6422 #ifdef HW_CHECKSUM_REQ
6423 if (p_nat->hw_checksum_reqd)
6424 hw_checksum(pkt, pkt_type);
6427 sw_checksum(pkt, pkt_type);
6432 * NAPT function for IPv6 public traffic which handles 1 pkt
6435 * A pointer to array of packet mbuf
6441 * A pointer to main CGNAPT structure
6445 pkt_work_cgnapt_ipv6_pub(
6446 struct rte_mbuf *pkt,
6448 __rte_unused void *arg,
6449 struct pipeline_cgnapt *p_nat)
6452 /* index into hash table entries */
6453 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6454 /*bitmask representing only this packet */
6455 uint64_t pkt_mask = 1LLU << pkt_num;
6457 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
6459 uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */
6460 uint16_t *outport_id =
6461 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6462 struct cgnapt_table_entry *entry = NULL;
6464 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4to6;
6466 if (hash_table_entry < 0) {
6468 /* Drop ingress initial traffic */
6470 p_nat->invalid_packets |= pkt_mask;
6471 p_nat->naptDroppedPktCount++;
6473 #ifdef CGNAPT_DEBUGGING
6474 p_nat->naptDroppedPktCount3++;
6475 if (p_nat->kpc2++ < 5) {
6476 printf("in_ah Th: %d", p_nat->pipeline_num);
6477 print_key(p_nat->key_ptrs[pkt_num]);
6484 /* entry found for this packet */
6485 entry = &napt_hash_tbl_entries[hash_table_entry];
6488 /* apply napt and mac changes */
6490 p_nat->entries[pkt_num] = &(entry->head);
6491 if (entry->data.type != CGNAPT_ENTRY_IPV6) {
6492 p_nat->invalid_packets |= pkt_mask;
6493 p_nat->naptDroppedPktCount++;
6497 struct ipv4_hdr ipv4_hdr;
6498 uint16_t *src_port =
6499 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP4_TCP);
6501 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
6502 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
6504 if (entry->data.ttl == NAPT_ENTRY_STALE)
6505 entry->data.ttl = NAPT_ENTRY_VALID;
6507 struct ether_addr hw_addr;
6508 uint8_t dest_addr_ipv6[16];
6509 uint8_t nh_ipv6[16];
6514 if (unlikely(protocol == IP_PROTOCOL_UDP
6515 && rte_be_to_cpu_16(*src_port) == 53)) {
6516 p_nat->invalid_packets |= pkt_mask;
6517 p_nat->naptDroppedPktCount++;
6518 #ifdef CGNAPT_DEBUGGING
6519 p_nat->naptDroppedPktCount6++;
6524 memcpy(&dest_addr_ipv6[0], &entry->data.u.prv_ipv6[0], 16);
6527 ret = local_get_nh_ipv6(&dest_addr_ipv6[0], &dest_if,
6530 dest_if = get_prv_to_pub_port((uint32_t *)
6534 if (dest_if == INVALID_DESTIF) {
6535 p_nat->invalid_packets |= pkt_mask;
6536 p_nat->naptDroppedPktCount++;
6537 #ifdef CGNAPT_DEBUGGING
6538 p_nat->naptDroppedPktCount6++;
6543 do_local_nh_ipv6_cache(dest_if, p_nat);
6545 *outport_id = p_nat->outport_id[dest_if];
6548 #ifdef CGNAPT_DEBUGGING
6549 static int static_count;
6551 if (static_count++ < 10) {
6553 my_print_entry(entry);
6554 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6555 printf("dest_add:%x\n", entry->data.u.prv_ip);
6556 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6560 memset(nh_ipv6, 0, 16);
6561 if (get_dest_mac_address_ipv6_port(
6567 #ifdef CGNAPT_DBG_PRNT
6568 if (CGNAPT_DEBUG > 2) {
6569 printf("MAC found for ip 0x%x, port %d - "
6570 "%02x:%02x:%02x:%02x:%02x:%02x\n",
6571 *((uint32_t *)dest_addr_ipv6 + 12),
6573 hw_addr.addr_bytes[0],
6574 hw_addr.addr_bytes[1], hw_addr.addr_bytes[2],
6575 hw_addr.addr_bytes[3], hw_addr.addr_bytes[4],
6576 hw_addr.addr_bytes[5]);
6578 printf("Dest MAC before - "
6579 "%02x:%02x:%02x:%02x:%02x:%02x\n",
6580 eth_dest[0], eth_dest[1], eth_dest[2],
6581 eth_dest[3], eth_dest[4], eth_dest[5]);
6585 memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
6587 #ifdef CGNAPT_DBG_PRNT
6588 if (CGNAPT_DEBUG > 2) {
6589 printf("Dest MAC after - "
6590 "%02x:%02x:%02x:%02x:%02x:%02x\n",
6591 eth_dest[0], eth_dest[1], eth_dest[2], eth_dest[3],
6592 eth_dest[4], eth_dest[5]);
6596 memcpy(eth_src, get_link_hw_addr(dest_if),
6597 sizeof(struct ether_addr));
6599 p_nat->invalid_packets |= pkt_mask;
6600 p_nat->naptDroppedPktCount++;
6602 #ifdef CGNAPT_DEBUGGING
6603 p_nat->naptDroppedPktCount4++;
6611 convert_ipv4_to_ipv6(pkt, &ipv4_hdr);
6613 /* Ethernet MTU check */
6614 if ((rte_pktmbuf_data_len(pkt) - 14) > 1500) {
6615 p_nat->invalid_packets |= pkt_mask;
6616 p_nat->naptDroppedPktCount++;
6619 uint32_t *dst_addr =
6620 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4t6);
6621 uint16_t *dst_port =
6622 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP4t6);
6624 memcpy((uint8_t *) &dst_addr[0], &entry->data.u.prv_ipv6[0],
6627 #ifdef NAT_ONLY_CONFIG_REQ
6628 if (!nat_only_config_flag) {
6630 *dst_port = rte_bswap16(entry->data.prv_port);
6632 #ifdef NAT_ONLY_CONFIG_REQ
6636 p_nat->inaptedPktCount++;
6639 p_nat->naptedPktCount++;
6641 #ifdef HW_CHECKSUM_REQ
6642 if (p_nat->hw_checksum_reqd)
6643 hw_checksum(pkt, pkt_type);
6646 sw_checksum(pkt, pkt_type);
6651 * NAPT function for IPv6 private traffic which handles 4 pkts
6654 * A pointer to array of packets mbuf
6656 * Starting pkt number of pkts
6660 * A pointer to main CGNAPT structure
6664 pkt4_work_cgnapt_ipv6_prv(
6665 struct rte_mbuf **pkts,
6666 uint32_t in_pkt_num,
6667 __rte_unused void *arg,
6668 struct pipeline_cgnapt *p_nat)
6670 struct rte_mbuf *pkt;
6674 enum PKT_TYPE pkt_type = PKT_TYPE_IPV6to4;
6676 for (i = 0; i < 4; i++) {
6677 pkt_num = in_pkt_num + i;
6680 /* index into hash table entries */
6681 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6682 /*bitmask representing only this packet */
6683 uint64_t pkt_mask = 1LLU << pkt_num;
6685 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
6686 uint32_t dest_if = INVALID_DESTIF;
6687 uint16_t *outport_id =
6688 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6689 struct cgnapt_table_entry *entry = NULL;
6691 if (hash_table_entry < 0) {
6693 /* try to add new entry */
6694 struct rte_pipeline_table_entry *table_entry = NULL;
6697 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
6699 &p_nat->valid_packets, pkt_num,
6703 /* ICMP Error message generation for
6704 * Destination Host unreachable
6706 /* Do we need this check for ipv6? */
6707 if (protocol == IP_PROTOCOL_ICMP) {
6708 cgnapt_icmp_pkt = pkt;
6709 send_icmp_dest_unreachable_msg();
6712 /* Drop packet by adding to invalid pkt mask */
6714 p_nat->invalid_packets |= dropmask;
6716 #ifdef CGNAPT_DEBUGGING
6717 if (p_nat->kpc2++ < 5) {
6718 printf("in_ah Th: %d",
6719 p_nat->pipeline_num);
6720 print_key(p_nat->key_ptrs[pkt_num]);
6724 p_nat->naptDroppedPktCount++;
6726 #ifdef CGNAPT_DEBUGGING
6727 p_nat->naptDroppedPktCount3++;
6733 entry = (struct cgnapt_table_entry *)table_entry;
6735 /* entry found for this packet */
6736 entry = &napt_hash_tbl_entries[hash_table_entry];
6739 /* apply napt and mac changes */
6741 p_nat->entries[pkt_num] = &(entry->head);
6743 struct ipv6_hdr ipv6_hdr;
6744 struct ether_addr hw_addr;
6745 uint32_t dest_address = 0;
6746 uint8_t nh_ipv6[16];
6751 convert_ipv6_to_ipv4(pkt, &ipv6_hdr);
6753 #ifdef CGNAPT_DBG_PRNT
6754 if (CGNAPT_DEBUG >= 1)
6755 printf("pkt_work_cganpt: "
6756 "convert_ipv6_to_ipv4\n");
6759 struct cgnapt_nsp_node *ll = nsp_ll;
6762 while (ll != NULL) {
6763 if (!memcmp(&ipv6_hdr.dst_addr[0],
6765 ll->nsp.depth / 8)) {
6773 && !memcmp(&ipv6_hdr.dst_addr[0],
6774 &well_known_prefix[0], 12)) {
6779 p_nat->invalid_packets |= pkt_mask;
6780 p_nat->naptDroppedPktCount++;
6782 #ifdef CGNAPT_DEBUGGING
6783 p_nat->naptDroppedPktCount5++;
6790 /* As packet is already converted into IPv4 we must not
6791 * operate IPv6 offsets on packet only perform IPv4 operations
6794 uint32_t *src_addr =
6795 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP6t4);
6796 uint32_t *dst_addr =
6797 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP6t4);
6798 uint16_t *src_port =
6799 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP6t4);
6800 uint16_t *dst_port =
6801 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP6t4);
6804 RTE_MBUF_METADATA_UINT8_PTR(pkt, ETH_OFST_IP6t4);
6806 RTE_MBUF_METADATA_UINT8_PTR(pkt, ETH_OFST_IP6t4 + 6);
6808 if (entry->data.ttl == NAPT_ENTRY_STALE)
6809 entry->data.ttl = NAPT_ENTRY_VALID;
6814 if (unlikely(protocol == IP_PROTOCOL_UDP
6815 && rte_be_to_cpu_16(*dst_port) == 53)) {
6816 p_nat->invalid_packets |= pkt_mask;
6817 p_nat->naptDroppedPktCount++;
6819 #ifdef CGNAPT_DEBUGGING
6820 p_nat->naptDroppedPktCount6++;
6825 dest_address = rte_bswap32(*dst_addr);
6828 ret = local_get_nh_ipv4(dest_address, &dest_if, &nhip, p_nat);
6830 dest_if = get_prv_to_pub_port(&dest_address, IP_VERSION_4);
6832 if (dest_if == INVALID_DESTIF) {
6833 p_nat->invalid_packets |= pkt_mask;
6834 p_nat->naptDroppedPktCount++;
6835 #ifdef CGNAPT_DEBUGGING
6836 p_nat->naptDroppedPktCount6++;
6841 do_local_nh_ipv4_cache(dest_if, p_nat);
6843 *outport_id = p_nat->outport_id[dest_if];
6845 #ifdef CGNAPT_DBG_PRNT
6846 if (CGNAPT_DEBUG > 2)
6847 printf("Egress: \tphy_port:%d\t"
6848 "get_prv_to_pub():%d \tout_port:%d\n",
6849 pkt->port, dest_if, *outport_id);
6853 #ifdef CGNAPT_DEBUGGING
6854 static int static_count;
6856 if (static_count++ < 10) {
6858 my_print_entry(entry);
6859 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6860 printf("dest_add:%x\n", entry->data.u.prv_ip);
6861 printf("dest_add:%x\n", *dst_addr);
6862 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6866 memset(nh_ipv6, 0, 16);
6870 ret = get_dest_mac_addr_port(dest_address, &dest_if, &hw_addr);
6872 if (unlikely(ret != ARP_FOUND)) {
6874 if (unlikely(ret == ARP_NOT_FOUND)) {
6875 /* Commented code may be required for debug
6876 * and future use, Please keep it */
6877 //request_arp(*outport_id, nhip, p_nat->p.p);
6878 printf("%s: ARP Not Found, nhip: %x, "
6879 "outport_id: %d\n", __func__, nhip,
6884 p_nat->invalid_packets |= pkt_mask;
6885 p_nat->naptDroppedPktCount++;
6887 #ifdef CGNAPT_DEBUGGING
6888 p_nat->naptDroppedPktCount4++;
6894 #ifdef CGNAPT_DBG_PRNT
6895 if (CGNAPT_DEBUG > 2) {
6896 printf("MAC found for ip 0x%x, port %d - "
6897 "%02x:%02x:%02x:%02x:%02x:%02x\n",
6898 dest_address, *outport_id,
6899 hw_addr.addr_bytes[0],
6900 hw_addr.addr_bytes[1],
6901 hw_addr.addr_bytes[2],
6902 hw_addr.addr_bytes[3],
6903 hw_addr.addr_bytes[4],
6904 hw_addr.addr_bytes[5]
6907 printf("Dest MAC before - "
6908 "%02x:%02x:%02x:%02x:%02x:%02x\n",
6909 eth_dest[0], eth_dest[1], eth_dest[2],
6910 eth_dest[3], eth_dest[4], eth_dest[5]);
6914 memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
6916 #ifdef CGNAPT_DBG_PRNT
6917 if (CGNAPT_DEBUG > 2) {
6918 printf("Dest MAC after - "
6919 "%02x:%02x:%02x:%02x:%02x:%02x\n",
6920 eth_dest[0], eth_dest[1], eth_dest[2],
6921 eth_dest[3], eth_dest[4], eth_dest[5]);
6926 get_link_hw_addr(dest_if),
6927 sizeof(struct ether_addr));
6932 *src_addr = rte_bswap32(entry->data.pub_ip);
6934 #ifdef NAT_ONLY_CONFIG_REQ
6935 if (!nat_only_config_flag) {
6937 *src_port = rte_bswap16(entry->data.pub_port);
6939 #ifdef NAT_ONLY_CONFIG_REQ
6943 p_nat->enaptedPktCount++;
6946 p_nat->naptedPktCount++;
6948 #ifdef HW_CHECKSUM_REQ
6949 if (p_nat->hw_checksum_reqd)
6950 hw_checksum(pkt, pkt_type);
6953 sw_checksum(pkt, pkt_type);
6958 * NAPT function for IPv6 public traffic which handles 4 pkts
6961 * A pointer to array of packets mbuf
6963 * Starting pkt number of pkts
6967 * A pointer to main CGNAPT structure
6971 pkt4_work_cgnapt_ipv6_pub(
6972 struct rte_mbuf **pkts,
6973 uint32_t in_pkt_num,
6974 __rte_unused void *arg,
6975 struct pipeline_cgnapt *p_nat)
6977 struct rte_mbuf *pkt;
6981 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4to6;
6983 for (i = 0; i < 4; i++) {
6984 pkt_num = in_pkt_num + i;
6987 /* index into hash table entries */
6988 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6989 /*bitmask representing only this packet */
6990 uint64_t pkt_mask = 1LLU << pkt_num;
6992 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
6993 uint16_t *outport_id =
6994 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6995 struct cgnapt_table_entry *entry = NULL;
6997 if (hash_table_entry < 0) {
6999 /* Drop ingress initial traffic */
7001 p_nat->invalid_packets |= pkt_mask;
7002 p_nat->naptDroppedPktCount++;
7003 #ifdef CGNAPT_DEBUGGING
7004 p_nat->naptDroppedPktCount3++;
7005 if (p_nat->kpc2++ < 5) {
7006 printf("in_ah Th: %d", p_nat->pipeline_num);
7007 print_key(p_nat->key_ptrs[pkt_num]);
7014 /* entry found for this packet */
7015 entry = &napt_hash_tbl_entries[hash_table_entry];
7018 /* apply napt and mac changes */
7020 p_nat->entries[pkt_num] = &(entry->head);
7021 if (entry->data.type != CGNAPT_ENTRY_IPV6) {
7022 p_nat->invalid_packets |= pkt_mask;
7023 p_nat->naptDroppedPktCount++;
7027 struct ipv4_hdr ipv4_hdr;
7029 uint16_t *src_port =
7030 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP4_TCP);
7033 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
7035 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
7037 if (entry->data.ttl == NAPT_ENTRY_STALE)
7038 entry->data.ttl = NAPT_ENTRY_VALID;
7040 struct ether_addr hw_addr;
7041 uint8_t dest_addr_ipv6[16];
7042 uint8_t nh_ipv6[16];
7043 uint32_t dest_if = INVALID_DESTIF;
7047 if (unlikely(protocol == IP_PROTOCOL_UDP
7048 && rte_be_to_cpu_16(*src_port) == 53)) {
7049 p_nat->invalid_packets |= pkt_mask;
7050 p_nat->naptDroppedPktCount++;
7051 #ifdef CGNAPT_DEBUGGING
7052 p_nat->naptDroppedPktCount6++;
7057 memcpy(&dest_addr_ipv6[0], &entry->data.u.prv_ipv6[0],
7061 ret = local_get_nh_ipv6(&dest_addr_ipv6[0], &dest_if,
7064 dest_if = get_prv_to_pub_port((uint32_t *)
7065 &dest_addr_ipv6[0], IP_VERSION_6);
7067 if (dest_if == INVALID_DESTIF) {
7068 p_nat->invalid_packets |= pkt_mask;
7069 p_nat->naptDroppedPktCount++;
7070 #ifdef CGNAPT_DEBUGGING
7071 p_nat->naptDroppedPktCount6++;
7076 do_local_nh_ipv6_cache(dest_if, p_nat);
7079 *outport_id = p_nat->outport_id[dest_if];
7082 #ifdef CGNAPT_DEBUGGING
7083 static int static_count;
7085 if (static_count++ < 10) {
7087 my_print_entry(entry);
7088 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
7089 printf("dest_add:%x\n", entry->data.u.prv_ip);
7090 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
7094 memset(nh_ipv6, 0, 16);
7095 if (get_dest_mac_address_ipv6
7096 (&dest_addr_ipv6[0], &dest_if,
7097 &hw_addr, &nh_ipv6[0])) {
7098 #ifdef CGNAPT_DBG_PRNT
7099 if (CGNAPT_DEBUG > 2) {
7100 printf("MAC found for ip 0x%x, port %d - "
7101 "%02x:%02x:%02x:%02x:%02x:%02x\n",
7102 *((uint32_t *)dest_addr_ipv6 + 12),
7104 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
7105 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
7106 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
7108 printf("Dest MAC before - "
7109 "%02x:%02x:%02x:%02x:%02x:%02x\n",
7110 eth_dest[0], eth_dest[1], eth_dest[2],
7111 eth_dest[3], eth_dest[4], eth_dest[5]);
7115 memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
7117 #ifdef CGNAPT_DBG_PRNT
7118 if (CGNAPT_DEBUG > 2) {
7119 printf("Dest MAC after - "
7120 "%02x:%02x:%02x:%02x:%02x:%02x\n",
7121 eth_dest[0], eth_dest[1], eth_dest[2],
7122 eth_dest[3], eth_dest[4], eth_dest[5]);
7127 get_link_hw_addr(dest_if),
7128 sizeof(struct ether_addr));
7130 p_nat->invalid_packets |= pkt_mask;
7131 p_nat->naptDroppedPktCount++;
7133 #ifdef CGNAPT_DEBUGGING
7134 p_nat->naptDroppedPktCount4++;
7143 convert_ipv4_to_ipv6(pkt, &ipv4_hdr);
7145 /* Ethernet MTU check */
7146 if ((rte_pktmbuf_data_len(pkt) - 14) > 1500) {
7147 p_nat->invalid_packets |= pkt_mask;
7148 p_nat->naptDroppedPktCount++;
7151 uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
7152 DST_ADR_OFST_IP4t6);
7153 uint16_t *dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
7154 DST_PRT_OFST_IP4t6);
7156 memcpy((uint8_t *) &dst_addr[0],
7157 &entry->data.u.prv_ipv6[0], 16);
7159 #ifdef NAT_ONLY_CONFIG_REQ
7160 if (!nat_only_config_flag) {
7162 *dst_port = rte_bswap16(entry->data.prv_port);
7164 #ifdef NAT_ONLY_CONFIG_REQ
7168 p_nat->inaptedPktCount++;
7171 p_nat->naptedPktCount++;
7173 #ifdef HW_CHECKSUM_REQ
7174 if (p_nat->hw_checksum_reqd)
7175 hw_checksum(pkt, pkt_type);
7178 sw_checksum(pkt, pkt_type);
7183 * Input port handler for IPv6 private traffic
7184 * Starting from the packet burst it filters unwanted packets,
7185 * calculates keys, does lookup and then based on the lookup
7186 * updates NAPT table and does packet NAPT translation.
7189 * A pointer to struct rte_pipeline
7191 * A pointer to array of packets mbuf
7193 * Number of packets in the burst
7198 * int that is not checked by caller
7200 static int cgnapt_in_port_ah_ipv6_prv(struct rte_pipeline *rte_p,
7201 struct rte_mbuf **pkts,
7202 uint32_t n_pkts, void *arg)
7205 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
7206 struct pipeline_cgnapt *p_nat = ap->p;
7208 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
7209 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
7210 p_nat->invalid_packets = 0;
7212 #ifdef CGNAPT_DBG_PRNT
7213 if (CGNAPT_DEBUG > 1)
7214 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
7217 /* prefetching for mbufs should be done here */
7218 for (j = 0; j < n_pkts; j++)
7219 rte_prefetch0(pkts[j]);
7221 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7222 pkt4_work_cgnapt_key_ipv6_prv(&pkts[i], i, arg, p_nat);
7224 for (; i < n_pkts; i++)
7225 pkt_work_cgnapt_key_ipv6_prv(pkts[i], i, arg, p_nat);
7227 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7229 if (unlikely(p_nat->valid_packets == 0)) {
7230 /* no suitable packet for lookup */
7231 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7232 return p_nat->valid_packets;
7235 /* lookup entries in the common napt table */
7237 int lookup_result = rte_hash_lookup_bulk(
7239 (const void **) &p_nat->key_ptrs,
7240 /* should be minus num invalid pkts */
7242 /*new pipeline data member */
7243 &p_nat->lkup_indx[0]);
7245 if (unlikely(lookup_result < 0)) {
7246 /* unknown error, just discard all packets */
7247 printf("Unexpected hash lookup error %d, "
7248 "discarding all packets",
7250 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
7254 /* Now call second stage of pipeline to one by one
7255 * check the result of our bulk lookup
7258 /* prefetching for table entries should be done here */
7259 for (j = 0; j < n_pkts; j++) {
7260 if (p_nat->lkup_indx[j] >= 0)
7261 rte_prefetch0(&napt_hash_tbl_entries
7262 [p_nat->lkup_indx[j]]);
7265 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7266 pkt4_work_cgnapt_ipv6_prv(&pkts[i], i, arg, p_nat);
7268 for (; i < n_pkts; i++)
7269 pkt_work_cgnapt_ipv6_prv(pkts[i], i, arg, p_nat);
7271 if (p_nat->invalid_packets) {
7272 /* get rid of invalid packets */
7273 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7275 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7277 #ifdef CGNAPT_DBG_PRNT
7278 if (CGNAPT_DEBUG > 1) {
7279 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
7280 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
7281 printf("invalid_packets:0x%jx\n",
7282 p_nat->invalid_packets);
7283 printf("rte_invalid_packets :0x%jx\n",
7284 rte_p->pkts_drop_mask);
7285 printf("Total pkts dropped :0x%jx\n",
7286 rte_p->n_pkts_ah_drop);
7291 return p_nat->valid_packets;
7296 * Input port handler for IPv6 public traffic
7297 * Starting from the packet burst it filters unwanted packets,
7298 * calculates keys, does lookup and then based on the lookup
7299 * updates NAPT table and does packet NAPT translation.
7302 * A pointer to struct rte_pipeline
7304 * A pointer to array of packets mbuf
7306 * Number of packets in the burst
7311 * int that is not checked by caller
7313 static int cgnapt_in_port_ah_ipv6_pub(struct rte_pipeline *rte_p,
7314 struct rte_mbuf **pkts,
7315 uint32_t n_pkts, void *arg)
7318 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
7319 struct pipeline_cgnapt *p_nat = ap->p;
7321 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
7322 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
7323 p_nat->invalid_packets = 0;
7325 #ifdef CGNAPT_DBG_PRNT
7326 if (CGNAPT_DEBUG > 1)
7327 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
7330 /* prefetching for mbufs should be done here */
7331 for (j = 0; j < n_pkts; j++)
7332 rte_prefetch0(pkts[j]);
7334 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7335 pkt4_work_cgnapt_key_ipv6_pub(&pkts[i], i, arg, p_nat);
7337 for (; i < n_pkts; i++)
7338 pkt_work_cgnapt_key_ipv6_pub(pkts[i], i, arg, p_nat);
7340 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7342 if (unlikely(p_nat->valid_packets == 0)) {
7343 /* no suitable packet for lookup */
7344 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7345 return p_nat->valid_packets;
7348 /* lookup entries in the common napt table */
7350 int lookup_result = rte_hash_lookup_bulk(
7352 (const void **) &p_nat->key_ptrs,
7353 /* should be minus num invalid pkts */
7355 /*new pipeline data member */
7356 &p_nat->lkup_indx[0]);
7358 if (unlikely(lookup_result < 0)) {
7359 /* unknown error, just discard all packets */
7360 printf("Unexpected hash lookup error %d, "
7361 "discarding all packets",
7363 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
7367 /* Now call second stage of pipeline to one by one
7368 * check the result of our bulk lookup
7371 /* prefetching for table entries should be done here */
7372 for (j = 0; j < n_pkts; j++) {
7373 if (p_nat->lkup_indx[j] >= 0)
7374 rte_prefetch0(&napt_hash_tbl_entries
7375 [p_nat->lkup_indx[j]]);
7378 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7379 pkt4_work_cgnapt_ipv6_pub(&pkts[i], i, arg, p_nat);
7381 for (; i < n_pkts; i++)
7382 pkt_work_cgnapt_ipv6_pub(pkts[i], i, arg, p_nat);
7384 if (p_nat->invalid_packets) {
7385 /* get rid of invalid packets */
7386 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7388 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7390 #ifdef CGNAPT_DBG_PRNT
7391 if (CGNAPT_DEBUG > 1) {
7392 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
7393 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
7394 printf("invalid_packets:0x%jx\n",
7395 p_nat->invalid_packets);
7396 printf("rte_invalid_packets :0x%jx\n",
7397 rte_p->pkts_drop_mask);
7398 printf("Total pkts dropped :0x%jx\n",
7399 rte_p->n_pkts_ah_drop);
7404 return p_nat->valid_packets;
7408 * Function to send ICMP dest unreachable msg
7411 void send_icmp_dest_unreachable_msg(void)
7414 struct ether_hdr *eth_h;
7415 struct ipv4_hdr *ip_h;
7416 struct icmp_hdr *icmp_h;
7417 struct rte_mbuf *icmp_pkt = cgnapt_icmp_pkt;
7419 if (icmp_pkt == NULL) {
7421 printf("Error allocating icmp_pkt rte_mbuf\n");
7425 port_id = icmp_pkt->port;
7427 struct app_link_params *link;
7428 link = &mylink[port_id];
7429 eth_h = rte_pktmbuf_mtod(icmp_pkt, struct ether_hdr *);
7430 ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
7431 icmp_h = (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
7433 struct ether_addr gw_addr;
7434 struct ether_addr dst_addr;
7435 ether_addr_copy(ð_h->s_addr, &dst_addr);
7436 rte_eth_macaddr_get(port_id, &gw_addr);
7437 ether_addr_copy(&gw_addr, ð_h->s_addr);
7438 ether_addr_copy(&dst_addr, ð_h->d_addr);
7440 eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
7441 ip_h->version_ihl = IP_VHL_DEF;
7442 ip_h->type_of_service = 0;
7443 ip_h->total_length = rte_cpu_to_be_16(sizeof(struct ipv4_hdr) +
7444 sizeof(struct icmp_hdr));
7445 ip_h->packet_id = 0xaabb;
7446 ip_h->fragment_offset = 0x0000;
7447 ip_h->time_to_live = 64;
7448 ip_h->next_proto_id = 1;
7451 uint32_t src_addr_offset =
7452 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_SRC_ADR_OFST;
7454 RTE_MBUF_METADATA_UINT32_PTR(cgnapt_icmp_pkt, src_addr_offset);
7456 ip_h->dst_addr = *src_addr;
7457 ip_h->src_addr = rte_bswap32(link->ip);
7459 ip_h->dst_addr = *src_addr;
7460 ip_h->src_addr = rte_bswap32(link->ip);
7462 ip_h->hdr_checksum = 0;
7463 ip_h->hdr_checksum = rte_ipv4_cksum(ip_h);
7464 icmp_h->icmp_type = 3; /* Destination Unreachable */
7465 icmp_h->icmp_code = 13; /* Communication administratively prohibited */
7467 icmp_h->icmp_cksum = ~rte_raw_cksum(icmp_h, sizeof(struct icmp_hdr));
7469 icmp_pkt->pkt_len = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
7470 sizeof(struct icmp_hdr);
7471 icmp_pkt->data_len = icmp_pkt->pkt_len;
7472 if (ARPICMP_DEBUG) {
7473 printf("Sending ICMP error message - "
7474 "Destination Unreachable\n");
7476 rte_pipeline_port_out_packet_insert(myP, port_id, icmp_pkt);
7480 * Function to add a dynamic NAPT entry pair
7483 * A pointer to struct pipeline
7485 * A pointer to struct pipeline_cgnapt_entry_key
7487 * expairy time of an dynamic or PCP req entry
7489 * uint8_t pointer of source address
7492 * A pointer to struct cgnapt_table_entry for added entry
7495 struct cgnapt_table_entry *add_dynamic_cgnapt_entry(
7497 struct pipeline_cgnapt_entry_key *key,
7504 void *entry_ptr, *ret_ptr;
7507 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
7509 #ifdef CGNAPT_DBG_PRNT
7510 if (CGNAPT_DEBUG >= 1) {
7511 printf("Th%d add_dynamic_cgnapt_entry key detail Entry:"
7512 "0x%x, %d, %d\n", p_nat->pipeline_num, key->ip, key->port,
7517 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX && i < p_nat->pkt_burst_cnt;
7519 if (p_nat->cgnapt_dyn_ent_table[i].ip == key->ip
7520 && p_nat->cgnapt_dyn_ent_table[i].port == key->port
7521 && p_nat->cgnapt_dyn_ent_table[i].pid == key->pid) {
7523 #ifdef CGNAPT_DBG_PRNT
7524 if (CGNAPT_DEBUG > 1)
7525 printf("add_dynamic_cgnapt_entry:pkt_burst "
7526 "array key matched!!!\n");
7529 return &napt_hash_tbl_entries
7530 [p_nat->cgnapt_dyn_ent_index[i]];
7534 #ifdef NAT_ONLY_CONFIG_REQ
7535 if (!nat_only_config_flag) {
7538 ret = increment_max_port_counter(key->ip, key->pid, p_nat);
7539 if (ret == MAX_PORT_INC_ERROR) {
7541 #ifdef CGNAPT_DEBUGGING
7542 p_nat->missedpktcount5++;
7545 #ifdef CGNAPT_DBG_PRNT
7546 if (CGNAPT_DEBUG > 1)
7547 printf("add_dynamic_cgnapt_entry:"
7548 "increment_max_port_counter-1 failed\n");
7555 if (ret == MAX_PORT_INC_REACHED) {
7557 #ifdef CGNAPT_DEBUGGING
7558 p_nat->missedpktcount6++;
7561 #ifdef CGNAPT_DBG_PRNT
7562 if (CGNAPT_DEBUG > 1)
7563 printf("add_dynamic_cgnapt_entry:"
7564 "increment_max_port_counter-2 failed\n");
7571 #ifdef NAT_ONLY_CONFIG_REQ
7576 port_num = get_free_iport(p_nat, &public_ip);
7578 if (port_num == -1) {
7580 #ifdef CGNAPT_DBG_PRNT
7581 if (CGNAPT_DEBUG > 2) {
7582 printf("add_dynamic_cgnapt_entry: %d\n", port_num);
7583 printf("add_dynamic_cgnapt_entry key detail:0x%x, "
7584 "%d, %d\n", key->ip, key->port, key->pid);
7588 #ifdef CGNAPT_DEBUGGING
7589 p_nat->missedpktcount7++;
7596 #ifdef NAT_ONLY_CONFIG_REQ
7597 if (!nat_only_config_flag) {
7600 if (ret == 2) { //MPPC_NEW_ENTRY
7602 /* check for max_clients_per_ip */
7603 if (rte_atomic16_read
7605 [rte_jhash(&public_ip, 4, 0) %
7606 CGNAPT_MAX_PUB_IP].count) ==
7607 p_nat->max_clients_per_ip) {
7609 /* For now just bail out
7610 * In future we can think about
7611 * retrying getting a new iport
7614 release_iport(port_num, public_ip, p_nat);
7616 #ifdef CGNAPT_DEBUGGING
7617 p_nat->missedpktcount10++;
7623 rte_atomic16_inc(&all_public_ip
7624 [rte_jhash(&public_ip, 4, 0) %
7625 CGNAPT_MAX_PUB_IP].count);
7627 #ifdef CGNAPT_DBG_PRNT
7628 if ((rte_jhash(&public_ip, 4, 0) %
7629 CGNAPT_MAX_PUB_IP) == 8)
7630 printf("pub ip:%x coutn:%d\n", public_ip,
7631 rte_atomic16_read(&all_public_ip
7632 [rte_jhash(&public_ip, 4, 0) %
7633 CGNAPT_MAX_PUB_IP].count));
7637 #ifdef NAT_ONLY_CONFIG_REQ
7641 #ifdef CGNAPT_DBG_PRNT
7642 if (CGNAPT_DEBUG > 0) {
7643 printf("add_dynamic_cgnapt_entry: %d\n",
7645 printf("add_dynamic_cgnapt_entry key detail: "
7646 "0x%x, %d, %d\n", key->ip, key->port, key->pid);
7650 struct cgnapt_table_entry entry = {
7652 .action = RTE_PIPELINE_ACTION_PORT,
7653 /* made it configurable below */
7654 {.port_id = p->port_out_id[0]},
7658 .prv_port = key->port,
7659 .pub_ip = public_ip,
7660 .pub_port = port_num,
7661 .prv_phy_port = key->pid,
7662 .pub_phy_port = get_pub_to_prv_port(
7666 /* if(timeout == -1) : static entry
7667 * if(timeout == 0 ) : dynamic entry
7668 * if(timeout > 0 ) : PCP requested entry
7670 .timeout = timeout > 0 ? timeout : 0,
7677 #ifdef NAT_ONLY_CONFIG_REQ
7678 if (nat_only_config_flag) {
7679 entry.data.prv_port = 0xffff;
7680 entry.data.pub_port = 0xffff;
7684 if (pkt_type == CGNAPT_ENTRY_IPV6) {
7685 entry.data.type = CGNAPT_ENTRY_IPV6;
7686 memcpy(&entry.data.u.prv_ipv6[0], src_addr, 16);
7688 entry.data.u.prv_ip = key->ip;
7689 entry.data.type = CGNAPT_ENTRY_IPV4;
7692 //entry.head.port_id = CGNAPT_PUB_PORT_ID; /* outgoing port info */
7693 entry.head.port_id = entry.data.pub_phy_port; /* outgoing port info */
7695 struct pipeline_cgnapt_entry_key second_key;
7696 /* Need to add a second ingress entry */
7697 second_key.ip = public_ip;
7698 second_key.port = port_num;
7699 second_key.pid = 0xffff;
7701 #ifdef NAT_ONLY_CONFIG_REQ
7702 if (nat_only_config_flag)
7703 second_key.port = 0xffff;
7706 #ifdef CGNAPT_DBG_PRNT
7707 if (CGNAPT_DEBUG > 2)
7708 printf("add_dynamic_cgnapt_entry second key detail:"
7709 "0x%x, %d, %d\n", second_key.ip, second_key.port,
7713 int32_t position = rte_hash_add_key(napt_common_table, (void *)key);
7716 #ifdef CGNAPT_DEBUGGING
7717 p_nat->missedpktcount8++;
7720 printf("CG-NAPT entry add failed ...returning "
7721 "without adding ... %d\n", position);
7726 #ifdef CGNAPT_DBG_PRNT
7728 printf("add_dynamic_cgnapt_entry\n");
7730 print_cgnapt_entry(&entry);
7734 memcpy(&napt_hash_tbl_entries[position], &entry,
7735 sizeof(struct cgnapt_table_entry));
7737 /* this pointer is returned to pkt miss function */
7738 ret_ptr = &napt_hash_tbl_entries[position];
7740 p_nat->n_cgnapt_entry_added++;
7741 p_nat->dynCgnaptCount++;
7743 /* Now modify the forward port for reverse entry */
7745 /* outgoing port info */
7746 //entry.head.port_id = CGNAPT_PRV_PORT_ID;
7747 /* outgoing port info */
7748 entry.head.port_id = entry.data.prv_phy_port;
7750 int32_t position2 = rte_hash_add_key(napt_common_table, &second_key);
7752 if (position2 < 0) {
7753 #ifdef CGNAPT_DEBUGGING
7754 p_nat->missedpktcount9++;
7756 printf("CG-NAPT entry reverse bulk add failed ..."
7757 "returning with fwd add ...%d\n",
7763 memcpy(&napt_hash_tbl_entries[position2], &entry,
7764 sizeof(struct cgnapt_table_entry));
7766 entry_ptr = &napt_hash_tbl_entries[position2];
7768 timer_thread_enqueue(key, &second_key, ret_ptr,
7769 entry_ptr, (struct pipeline *)p_nat);
7771 p_nat->n_cgnapt_entry_added++;
7772 p_nat->dynCgnaptCount++;
7774 if (p_nat->pkt_burst_cnt < RTE_PORT_IN_BURST_SIZE_MAX) {
7775 memcpy(&p_nat->cgnapt_dyn_ent_table[p_nat->pkt_burst_cnt], key,
7776 sizeof(struct pipeline_cgnapt_entry_key));
7777 p_nat->cgnapt_dyn_ent_index[p_nat->pkt_burst_cnt] = position;
7778 p_nat->pkt_burst_cnt++;
7783 int pkt_miss_cgnapt_count;
7785 * Function handle a missed NAPT entry lookup
7786 * Will attempt to add a dynamic entry pair.
7789 * A pointer to struct pipeline
7791 * A pointer to struct pipeline_cgnapt_entry_key
7793 * A pointer to pkt struct rte_mbuf
7795 * uint64_t pointer to pkt mask
7796 * @param table_entry
7797 * A pointer to struct rte_pipeline_table_entry to be created and returned
7799 * number of this pkt in current burst
7802 * A uint64_t mask for drop packets
7805 pkt_miss_cgnapt(struct pipeline_cgnapt_entry_key *key,
7806 struct rte_mbuf *pkt,
7807 struct rte_pipeline_table_entry **table_entry,
7808 __rte_unused uint64_t *pkts_mask,
7809 uint32_t pkt_num, void *arg)
7812 #ifdef CGNAPT_DBG_PRNT
7813 if (CGNAPT_DEBUG > 0)
7814 printf("\n pkt_miss_cgnapt\n");
7818 * see if get_port passes for this src address
7819 * if passed add a new egress entry and a
7820 * corresponding new ingress entry
7821 * return the fwd entry to calling function using input pointer
7822 * else if get_port fails drop packet
7825 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)arg;
7827 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
7828 uint32_t src_addr_offset_ipv6 =
7829 MBUF_HDR_ROOM + ETH_HDR_SIZE + IPV6_HDR_SRC_ADR_OFST;
7830 uint16_t phy_port = pkt->port;
7832 uint16_t *eth_proto =
7833 RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
7835 uint8_t *src_addr = NULL;
7836 uint8_t src_addr_ipv6[16];
7837 uint8_t pkt_type = CGNAPT_ENTRY_IPV4;
7838 /* To drop the packet */
7839 uint64_t drop_mask = 0;
7841 if (p_nat->is_static_cgnapt) {
7842 drop_mask |= 1LLU << pkt_num;
7843 p_nat->missedPktCount++;
7845 #ifdef CGNAPT_DEBUGGING
7846 p_nat->missedpktcount1++;
7851 if (rte_be_to_cpu_16(*eth_proto) == ETHER_TYPE_IPv6) {
7853 RTE_MBUF_METADATA_UINT8_PTR(pkt, src_addr_offset_ipv6);
7854 pkt_type = CGNAPT_ENTRY_IPV6;
7855 memcpy(src_addr_ipv6, src_addr, 16);
7860 /* some validation first */
7861 if (is_phy_port_privte(phy_port)) {
7862 /* dynamic NAPT entry creation */
7863 *table_entry = (struct rte_pipeline_table_entry *)
7864 add_dynamic_cgnapt_entry(
7865 (struct pipeline *)&p_nat->p,
7867 DYNAMIC_CGNAPT_TIMEOUT,
7869 src_addr_ipv6, &err);
7871 if (!(*table_entry)) {
7873 drop_mask |= 1LLU << pkt_num;
7874 p_nat->missedPktCount++;
7876 #ifdef CGNAPT_DEBUGGING
7877 p_nat->missedpktcount2++;
7880 #ifdef CGNAPT_DBG_PRNT
7881 if (CGNAPT_DEBUG > 1)
7882 printf("Add Dynamic NAT entry failed "
7886 #ifdef CGNAPT_DEBUGGING
7887 p_nat->missedpktcount11++;
7893 } else if (!is_phy_port_privte(phy_port)) {
7895 #ifdef CGNAPT_DBG_PRNT
7896 if (CGNAPT_DEBUG >= 2) {
7897 printf("Initial Ingress entry creation NOT ALLOWED "
7902 drop_mask |= 1LLU << pkt_num;
7903 p_nat->missedPktCount++;
7905 #ifdef CGNAPT_DEBUGGING
7906 p_nat->missedpktcount3++;
7910 #ifdef CGNAPT_DBG_PRNT
7911 if (CGNAPT_DEBUG > 1)
7912 printf("NOT a PRIVATE or PUBLIC port!!!!!\n");
7915 drop_mask |= 1LLU << pkt_num;
7916 p_nat->missedPktCount++;
7918 #ifdef CGNAPT_DEBUGGING
7919 p_nat->missedpktcount4++;
7923 #ifdef CGNAPT_DBG_PRNT
7924 if (CGNAPT_DEBUG > 5)
7934 * Function to print the contents of a packet
7937 * A pointer to pkt struct rte_mbuf
7939 void print_pkt(struct rte_mbuf *pkt)
7943 printf("\nPacket Contents:\n");
7945 uint8_t *rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
7947 for (i = 0; i < 20; i++) {
7948 for (j = 0; j < 20; j++)
7949 printf("%02x ", rd[(20 * i) + j]);
7955 rte_table_hash_op_hash cgnapt_hash_func[] = {
7967 * Function to parse incoming pipeline arguments
7968 * Called during pipeline initialization
7971 * A pointer to struct pipeline_cgnapt
7973 * A pointer to struct pipeline_params
7976 * 0 if success, negative if failure
7979 pipeline_cgnapt_parse_args(struct pipeline_cgnapt *p,
7980 struct pipeline_params *params)
7982 uint32_t n_flows_present = 0;
7983 uint32_t key_offset_present = 0;
7984 uint32_t key_size_present = 0;
7985 uint32_t hash_offset_present = 0;
7986 uint32_t n_entries_present = 0;
7987 uint32_t max_port_present = 0;
7988 uint32_t max_client_present = 0;
7989 uint32_t public_ip_range_present = 0;
7990 uint32_t public_ip_port_range_present = 0;
7992 uint8_t public_ip_count = 0;
7993 uint8_t public_ip_range_count = 0;
7994 uint8_t dest_if_offset_present = 0;
7995 uint8_t cgnapt_meta_offset_present = 0;
7996 uint8_t prv_que_handler_present = 0;
7997 uint8_t n_prv_in_port = 0;
7999 if (CGNAPT_DEBUG > 2) {
8000 printf("CGNAPT pipeline_cgnapt_parse_args params->n_args: %d\n",
8003 for (i = 0; i < params->n_args; i++) {
8004 char *arg_name = params->args_name[i];
8005 char *arg_value = params->args_value[i];
8007 if (CGNAPT_DEBUG > 2) {
8008 printf("CGNAPT args[%d]: %s %d, %s\n", i, arg_name,
8009 atoi(arg_value), arg_value);
8011 if (strcmp(arg_name, "prv_que_handler") == 0) {
8013 if (prv_que_handler_present) {
8014 printf("Duplicate pktq_in_prv ..\n\n");
8017 prv_que_handler_present = 1;
8022 /* get the first token */
8023 token = strtok(arg_value, "(");
8024 token = strtok(token, ")");
8025 token = strtok(token, ",");
8026 printf("***** prv_que_handler *****\n");
8028 if (token == NULL) {
8029 printf("string is null\n");
8030 printf("invalid prv_que_handler value/n");
8033 printf("string is :%s\n", token);
8035 /* walk through other tokens */
8036 while (token != NULL) {
8037 printf(" %s\n", token);
8038 rxport = atoi(token);
8039 cgnapt_prv_que_port_index[n_prv_in_port++] =
8041 if (rxport < PIPELINE_MAX_PORT_IN)
8042 cgnapt_in_port_egress_prv[rxport] = 1;
8043 token = strtok(NULL, ",");
8046 if (n_prv_in_port == 0) {
8047 printf("VNF common parse err - "
8048 "no prv RX phy port\n");
8054 if (strcmp(arg_name, "cgnapt_meta_offset") == 0) {
8055 if (cgnapt_meta_offset_present) {
8056 printf("CG-NAPT parse error:");
8057 printf("cgnapt_meta_offset initizlized "
8058 "mulitple times\n");
8061 cgnapt_meta_offset_present = 1;
8063 temp = atoi(arg_value);
8066 printf("cgnapt_meta_offset is invalid :");
8067 printf("Not be more than metadata size\n");
8070 cgnapt_meta_offset = (uint16_t) temp;
8072 if (strcmp(arg_name, "vnf_set") == 0)
8075 if (strcmp(arg_name, "public_ip_range") == 0) {
8076 public_ip_range_present = 1;
8077 if (public_ip_port_range_present) {
8078 printf("CG-NAPT parse error:");
8079 printf("public_ip_range with "
8080 "public_ip_port_range_present\n");
8084 p->pub_ip_range = rte_realloc(p->pub_ip_range,
8087 RTE_CACHE_LINE_SIZE);
8089 if (!p->pub_ip_range) {
8090 printf("Memory allocation failed for "
8095 uint32_t sip = 0, eip = 0;
8097 if (sscanf(arg_value, "(%x,%x)", &sip, &eip) != 2) {
8098 printf("public_ip_range is invalid\n");
8102 if (sip <= 0 || eip <= 0 || sip >= eip) {
8103 printf("public_ip_range is invalid %x-%x\n",
8108 printf("public_ip_range: %d-%d\n",
8109 p->pub_ip_range[public_ip_range_count].
8111 p->pub_ip_range[public_ip_range_count].
8114 p->pub_ip_range_count = ++public_ip_range_count;
8118 if (strcmp(arg_name, "public_ip_port_range") == 0) {
8119 public_ip_port_range_present = 1;
8120 if (nat_only_config_flag || public_ip_range_present) {
8122 printf("CG-NAPT parse error:");
8123 printf("nat_only_config_flag OR ");
8124 printf("public_ip_range_present with "
8125 "public_ip_port_range_present\n");
8129 p->pub_ip_port_set = rte_realloc(
8131 sizeof(struct pub_ip_port_set),
8132 RTE_CACHE_LINE_SIZE);
8134 if (!p->pub_ip_port_set) {
8135 printf("Memory allocation failed for "
8143 if (sscanf(arg_value, "%x:(%d,%d)",
8144 &ip, &sp, &ep) != 3) {
8145 printf("Public IP or Port-range is invalid\n");
8149 if (ip <= 0 || sp <= 0 || ep <= 0 || sp > ep) {
8150 printf("Public IP or Port-range is invalid "
8151 "%x:%d-%d\n", ip, sp, ep);
8155 printf("public_ip: 0x%x Range:%d-%d\n",
8156 p->pub_ip_port_set[public_ip_count].ip = ip,
8157 p->pub_ip_port_set[public_ip_count].start_port = sp,
8158 p->pub_ip_port_set[public_ip_count].end_port = ep);
8160 napt_port_alloc_elem_count += (ep - sp + 1);
8161 printf("parse - napt_port_alloc_elem_count :%d\n",
8162 napt_port_alloc_elem_count);
8164 /* Store all public IPs of all CGNAPT threads
8165 * in the global variable
8167 /* to revisit indexing */
8168 all_public_ip[rte_jhash(&ip, 4, 0) %
8169 CGNAPT_MAX_PUB_IP].ip = ip;
8170 p->pub_ip_count = ++public_ip_count;
8171 printf("public_ip_count:%d hash:%d\n", public_ip_count,
8172 rte_jhash(&ip, 4, 0) % CGNAPT_MAX_PUB_IP);
8176 /* hw_checksum_reqd */
8177 if (strcmp(arg_name, "hw_checksum_reqd") == 0) {
8179 temp = atoi(arg_value);
8180 if ((temp != 0) && (temp != 1)) {
8181 printf("hw_checksum_reqd is invalid\n");
8184 p->hw_checksum_reqd = temp;
8188 /* nat_only_config_flag */
8189 if (strcmp(arg_name, "nat_only_config_flag") == 0) {
8190 nat_only_config_flag = 1;
8191 if (public_ip_port_range_present) {
8193 printf("CG-NAPT parse error:");
8194 printf("nat_only_config_flag with "
8195 "public_ip_port_range_present\n");
8201 /* max_port_per_client */
8202 if (strcmp(arg_name, "max_port_per_client") == 0) {
8203 if (max_port_present) {
8204 printf("CG-NAPT Parse Error: "
8205 "duplicate max_port_per_client\n");
8208 max_port_present = 1;
8211 max = atoi(arg_value);
8213 printf("max_port_per_client is invalid !!!\n");
8217 p->max_port_per_client = (uint16_t) max;
8219 if (p->max_port_per_client <= 0) {
8220 printf("max port per client is invalid\n");
8224 printf("max_port_per_client comp: %d\n",
8225 p->max_port_per_client);
8229 /* max_clients_per_ip */
8230 if (strcmp(arg_name, "max_clients_per_ip") == 0) {
8231 if (max_client_present) {
8232 printf("CG-NAPT parse Error: duplicate "
8233 "max_clients_per_ip\n");
8236 max_client_present = 1;
8238 if (nat_only_config_flag) {
8239 printf("CG-NAPT parse error:");
8240 printf("nat_only_config_flag with "
8241 "max_clients_per_ip\n");
8246 max = atoi(arg_value);
8248 printf("max_clients_per_ip is invalid !!!\n");
8252 p->max_clients_per_ip = (uint16_t) max;
8254 if (p->max_clients_per_ip <= 0) {
8255 printf("max_clients_per_ip is invalid\n");
8259 printf("max_clients_per_ip: %d\n",
8260 p->max_clients_per_ip);
8265 if (strcmp(arg_name, "n_entries") == 0) {
8266 if (n_entries_present)
8268 n_entries_present = 1;
8270 p->n_entries = atoi(arg_value);
8271 if (p->n_entries == 0)
8278 if (strcmp(arg_name, "n_flows") == 0) {
8279 if (n_flows_present)
8281 n_flows_present = 1;
8283 p->n_flows = atoi(arg_value);
8284 if (p->n_flows == 0)
8287 napt_common_table_hash_params.entries = p->n_flows;
8290 /* dest_if_offset Multiport Changes */
8291 if (strcmp(arg_name, "dest_if_offset") == 0) {
8292 if (dest_if_offset_present)
8294 //dest_if_offset_present = 1;
8296 dest_if_offset = atoi(arg_value);
8302 if (strcmp(arg_name, "key_offset") == 0) {
8303 if (key_offset_present)
8305 key_offset_present = 1;
8307 p->key_offset = atoi(arg_value);
8313 if (strcmp(arg_name, "key_size") == 0) {
8314 if (key_size_present)
8316 key_size_present = 1;
8318 p->key_size = atoi(arg_value);
8319 if ((p->key_size == 0) ||
8320 (p->key_size > PIPELINE_CGNAPT_KEY_MAX_SIZE) ||
8328 if (strcmp(arg_name, "hash_offset") == 0) {
8329 if (hash_offset_present)
8331 hash_offset_present = 1;
8333 p->hash_offset = atoi(arg_value);
8339 if (strcmp(arg_name, "pkt_type") == 0) {
8340 if (strcmp(arg_value, "ipv4") == 0) {
8341 p->traffic_type = TRAFFIC_TYPE_IPV4;
8342 printf("Traffic is set to IPv4\n");
8343 } else if (strcmp(arg_value, "ipv6") == 0) {
8344 p->traffic_type = TRAFFIC_TYPE_IPV6;
8345 printf("Traffic is set to IPv6\n");
8351 if (strcmp(arg_name, "cgnapt_debug") == 0) {
8352 CGNAPT_DEBUG = atoi(arg_value);
8357 /* any other Unknown argument return -1 */
8360 #ifdef NAT_ONLY_CONFIG_REQ
8361 if (nat_only_config_flag) {
8362 if (!public_ip_range_count) {
8363 printf("No public_ip_range %d for NAT only config.\n",
8364 public_ip_range_count);
8365 printf("Running static NAT only configuration\n");
8366 p->is_static_cgnapt = 1;
8371 if (!p->max_port_per_client)
8372 p->is_static_cgnapt = 1;
8375 /* Check that mandatory arguments are present */
8376 if ((n_flows_present == 0) ||
8377 (cgnapt_meta_offset_present == 0))
8385 * Function to initialize the pipeline
8388 * A pointer to struct pipeline_params
8390 * Void pointer - points to app params
8393 * void pointer to the pipeline, NULL 0 if failure
8395 static void *pipeline_cgnapt_init(struct pipeline_params *params, void *arg)
8396 /* (struct app_params *app) save it for use in port in handler */
8399 struct pipeline_cgnapt *p_nat;
8400 uint32_t size, i, in_ports_arg_size;
8402 /* Check input arguments */
8403 if ((params == NULL) ||
8404 (params->n_ports_in == 0) || (params->n_ports_out == 0))
8407 /* Memory allocation */
8408 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_cgnapt));
8409 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8410 p_nat = (struct pipeline_cgnapt *)p;
8414 all_pipeline_cgnapt[n_cgnapt_pipeline++] = p_nat;
8416 strcpy(p->name, params->name);
8417 p->log_level = params->log_level;
8419 PLOG(p, HIGH, "CG-NAPT");
8420 /* Initialize all counters and arrays */
8422 p_nat->n_cgnapt_entry_deleted = 0;
8423 p_nat->n_cgnapt_entry_added = 0;
8424 p_nat->naptedPktCount = 0;
8425 p_nat->naptDroppedPktCount = 0;
8426 p_nat->inaptedPktCount = 0;
8427 p_nat->enaptedPktCount = 0;
8428 p_nat->receivedPktCount = 0;
8429 p_nat->missedPktCount = 0;
8430 p_nat->dynCgnaptCount = 0;
8431 p_nat->arpicmpPktCount = 0;
8433 p_nat->app_params_addr = (uint64_t) arg;
8434 for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
8435 p_nat->links_map[i] = 0xff;
8436 p_nat->outport_id[i] = 0xff;
8437 cgnapt_in_port_egress_prv[i] = 0;
8438 cgnapt_prv_que_port_index[i] = 0;
8440 p_nat->pipeline_num = 0xff;
8441 p_nat->hw_checksum_reqd = 0;
8442 p_nat->pub_ip_port_set = NULL;
8443 p_nat->pub_ip_count = 0;
8444 p_nat->traffic_type = TRAFFIC_TYPE_MIX;
8445 p_nat->vnf_set = 0xff;
8447 /* For every init it should be reset */
8448 napt_port_alloc_elem_count = 0;
8450 #ifdef CGNAPT_TIMING_INST
8451 p_nat->in_port_exit_timestamp = 0;
8452 p_nat->external_time_sum = 0;
8453 p_nat->internal_time_sum = 0;
8454 p_nat->time_measurements = 0;
8455 p_nat->max_time_mesurements = 10000;
8456 p_nat->time_measurements_on = 0;
8459 #ifdef CGNAPT_DEBUGGING
8461 p_nat->naptDebugCount = 0;
8463 p_nat->naptDroppedPktCount1 = 0;
8464 p_nat->naptDroppedPktCount2 = 0;
8465 p_nat->naptDroppedPktCount3 = 0;
8466 p_nat->naptDroppedPktCount4 = 0;
8467 p_nat->naptDroppedPktCount5 = 0;
8468 p_nat->naptDroppedPktCount6 = 0;
8470 p_nat->missedpktcount1 = 0;
8471 p_nat->missedpktcount2 = 0;
8472 p_nat->missedpktcount3 = 0;
8473 p_nat->missedpktcount4 = 0;
8474 p_nat->missedpktcount5 = 0;
8475 p_nat->missedpktcount6 = 0;
8476 p_nat->missedpktcount7 = 0;
8477 p_nat->missedpktcount8 = 0;
8478 p_nat->missedpktcount9 = 0;
8479 p_nat->missedpktcount10 = 0;
8480 p_nat->missedpktcount11 = 0;
8481 p_nat->missedpktcount12 = 0;
8483 p_nat->max_port_dec_err1 = 0;
8484 p_nat->max_port_dec_err2 = 0;
8485 p_nat->max_port_dec_err3 = 0;
8486 p_nat->max_port_dec_success = 0;
8502 static int sip_enabled;
8506 #endif /* SIP_ALG */
8508 /*struct rte_pipeline_table_entry *entries[RTE_HASH_LOOKUP_BULK_MAX];*/
8509 /* bitmap of valid packets */
8510 p_nat->valid_packets = 0;
8511 /* bitmap of invalid packets to be dropped */
8512 p_nat->invalid_packets = 0;
8514 for (i = 0; i < RTE_HASH_LOOKUP_BULK_MAX; i++)
8515 p_nat->key_ptrs[i] = &(p_nat->keys[i]);
8517 p_nat->port_alloc_ring = NULL;
8519 /* Parse arguments */
8520 if (pipeline_cgnapt_parse_args(p_nat, params))
8523 p_nat->vnf_set = vnf_set_count;
8527 struct rte_pipeline_params pipeline_params = {
8528 .name = params->name,
8529 .socket_id = params->socket_id,
8530 .offset_port_id = cgnapt_meta_offset,
8533 p->p = rte_pipeline_create(&pipeline_params);
8541 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8543 uint32_t instr_size =
8544 RTE_CACHE_LINE_ROUNDUP((sizeof(uint64_t)) *
8547 (uint64_t *) rte_zmalloc(NULL, instr_size,
8548 RTE_CACHE_LINE_SIZE);
8550 (uint64_t *) rte_zmalloc(NULL, instr_size,
8551 RTE_CACHE_LINE_SIZE);
8553 (uint32_t *) rte_zmalloc(NULL, instr_size / 2,
8554 RTE_CACHE_LINE_SIZE);
8555 if ((inst_start_time == NULL) || (inst_end_time == NULL)
8556 || (inst_diff_time == NULL)) {
8557 printf("Inst array alloc failed .... ");
8562 /* Memory allocation for in_port_h_arg */
8563 in_ports_arg_size = RTE_CACHE_LINE_ROUNDUP(
8564 (sizeof(struct pipeline_cgnapt_in_port_h_arg)) *
8565 (params->n_ports_in));
8566 struct pipeline_cgnapt_in_port_h_arg *ap =
8567 (struct pipeline_cgnapt_in_port_h_arg *)
8570 RTE_CACHE_LINE_SIZE);
8574 myApp = (struct app_params *) arg;
8577 p->n_ports_in = params->n_ports_in;
8578 for (i = 0; i < p->n_ports_in; i++) {
8579 /* passing our cgnapt pipeline in call back arg */
8581 (ap[i]).in_port_id = i;
8583 struct rte_pipeline_port_in_params port_params = {
8585 pipeline_port_in_params_get_ops(¶ms->port_in
8588 pipeline_port_in_params_convert(¶ms->port_in
8590 .f_action = cgnapt_in_port_ah_mix,
8592 .burst_size = params->port_in[i].burst_size,
8595 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8597 instrumentation_port_in_arg = &(ap[i]);
8600 if (p_nat->traffic_type == TRAFFIC_TYPE_IPV4) {
8601 /* Private in-port handler */
8602 /* Multiport changes */
8603 if (cgnapt_in_port_egress_prv[i]) {
8604 port_params.f_action =
8605 cgnapt_in_port_ah_ipv4_prv;
8606 printf("CGNAPT port %d is IPv4 Prv\n", i);
8608 port_params.f_action =
8609 cgnapt_in_port_ah_ipv4_pub;
8610 printf("CGNAPT port %d is IPv4 Pub\n", i);
8614 if (p_nat->traffic_type == TRAFFIC_TYPE_IPV6) {
8615 if (cgnapt_in_port_egress_prv[i]) {
8616 port_params.f_action =
8617 cgnapt_in_port_ah_ipv6_prv;
8618 printf("CGNAPT port %d is IPv6 Prv\n", i);
8620 port_params.f_action =
8621 cgnapt_in_port_ah_ipv6_pub;
8622 printf("CGNAPT port %d is IPv6 Pub\n", i);
8626 int status = rte_pipeline_port_in_create(p->p,
8631 rte_pipeline_free(p->p);
8639 p->n_ports_out = params->n_ports_out;
8640 for (i = 0; i < p->n_ports_out; i++) {
8641 struct rte_pipeline_port_out_params port_params = {
8642 .ops = pipeline_port_out_params_get_ops(
8643 ¶ms->port_out[i]),
8644 .arg_create = pipeline_port_out_params_convert(
8645 ¶ms->port_out[i]),
8646 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8647 .f_action = port_out_ah_cgnapt,
8654 int status = rte_pipeline_port_out_create(p->p,
8656 &p->port_out_id[i]);
8659 rte_pipeline_free(p->p);
8665 int pipeline_num = 0;
8667 ignore = sscanf(params->name, "PIPELINE%d", &pipeline_num);
8669 printf("Not able to read pipeline number\n");
8672 p_nat->pipeline_num = (uint8_t) pipeline_num;
8673 register_pipeline_Qs(p_nat->pipeline_num, p);
8674 set_link_map(p_nat->pipeline_num, p, p_nat->links_map);
8675 set_outport_id(p_nat->pipeline_num, p, p_nat->outport_id);
8681 if (napt_common_table == NULL) {
8682 if (create_napt_common_table(p_nat->n_flows)) {
8684 "CG-NAPT create_napt_common_table failed.");
8689 struct rte_pipeline_table_params table_params = {
8690 .ops = &rte_table_stub_ops,
8692 .f_action_hit = NULL,
8693 .f_action_miss = NULL,
8695 .action_data_size = 0,
8698 int status = rte_pipeline_table_create(p->p,
8703 rte_pipeline_free(p->p);
8707 struct rte_pipeline_table_entry default_entry = {
8708 .action = RTE_PIPELINE_ACTION_PORT_META
8710 struct rte_pipeline_table_entry *default_entry_ptr;
8711 status = rte_pipeline_table_default_entry_add(
8715 &default_entry_ptr);
8717 rte_pipeline_free(p->p);
8723 /* Connecting input ports to tables */
8724 for (i = 0; i < p->n_ports_in; i++) {
8725 int status = rte_pipeline_port_in_connect_to_table(p->p,
8732 rte_pipeline_free(p->p);
8738 /* Enable input ports */
8739 for (i = 0; i < p->n_ports_in; i++) {
8740 int status = rte_pipeline_port_in_enable(p->p,
8744 rte_pipeline_free(p->p);
8750 /* Check pipeline consistency */
8751 if (rte_pipeline_check(p->p) < 0) {
8752 rte_pipeline_free(p->p);
8757 /* Message queues */
8758 p->n_msgq = params->n_msgq;
8759 for (i = 0; i < p->n_msgq; i++)
8760 p->msgq_in[i] = params->msgq_in[i];
8761 for (i = 0; i < p->n_msgq; i++)
8762 p->msgq_out[i] = params->msgq_out[i];
8764 /* Message handlers */
8765 memcpy(p->handlers, handlers, sizeof(p->handlers));
8766 memcpy(p_nat->custom_handlers,
8767 custom_handlers, sizeof(p_nat->custom_handlers));
8769 if (!p_nat->is_static_cgnapt) {
8770 printf("Initializing dyn napt components ... %d\n",
8771 p_nat->pipeline_num);
8772 if (napt_port_alloc_init(p_nat) == -1) {
8773 printf("Error - napt_port_alloc_init failed - %d\n",
8774 p_nat->pipeline_num);
8779 if (max_port_per_client_hash == NULL) {
8780 rc = init_max_port_per_client(p_nat);
8782 printf("CGNAPT Error - "
8783 "init_max_port_per_client failed %d", rc);
8790 if (!icmp_pool_init) {
8792 /* create the arp_icmp mbuf rx pool */
8793 cgnapt_icmp_pktmbuf_tx_pool =
8794 rte_pktmbuf_pool_create("icmp_mbuf_tx_pool", 63, 32, 0,
8795 RTE_MBUF_DEFAULT_BUF_SIZE,
8797 if (cgnapt_icmp_pktmbuf_tx_pool == NULL) {
8798 PLOG(p, HIGH, "ICMP mbuf pool create failed.");
8803 rte_pktmbuf_alloc(cgnapt_icmp_pktmbuf_tx_pool);
8805 if (cgnapt_icmp_pkt == NULL) {
8806 printf("Failed to allocate cgnapt_icmp_pkt\n");
8813 cgnat_cnxn_tracker = rte_zmalloc(NULL, rte_ct_get_cnxn_tracker_size(),
8814 RTE_CACHE_LINE_SIZE);
8816 if (cgnat_cnxn_tracker == NULL) {
8817 printf("CGNAPT CT memory not allocated\n");
8820 rte_ct_initialize_default_timeouts(cgnat_cnxn_tracker);
8822 printf("CGNAPT CT Flows %d\n", p_nat->n_flows);
8824 ret = rte_ct_initialize_cnxn_tracker(cgnat_cnxn_tracker,
8826 "CGNAT_CT_COMMON_TABLE");
8836 if (pcp_init() == PCP_INIT_SUCCESS)
8837 printf("PCP contents are initialized successfully\n");
8839 printf("Error in initializing PCP contents\n");
8846 * Function for pipeline cleanup
8849 * A void pointer to pipeline
8854 static int pipeline_cgnapt_free(void *pipeline)
8856 struct pipeline *p = (struct pipeline *)pipeline;
8858 /* Check input arguments */
8862 /* Free resources */
8863 rte_pipeline_free(p->p);
8869 pipeline_cgnapt_track(void *pipeline, __rte_unused uint32_t port_in,
8872 struct pipeline *p = (struct pipeline *)pipeline;
8874 /* Check input arguments */
8875 if ((p == NULL) || (port_in >= p->n_ports_in) || (port_out == NULL))
8878 if (p->n_ports_in == 1) {
8887 * Function for pipeline timers
8890 * A void pointer to pipeline
8895 static int pipeline_cgnapt_timer(void *pipeline)
8897 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)pipeline;
8899 pipeline_msg_req_handle(&p_nat->p);
8901 rte_pipeline_flush(((struct pipeline *)p_nat)->p);
8907 * Function for pipeline custom handlers
8910 * A void pointer to pipeline
8912 * void pointer for incoming data
8915 * void pointer of response
8917 void *pipeline_cgnapt_msg_req_custom_handler(struct pipeline *p, void *msg)
8919 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
8920 struct pipeline_custom_msg_req *req = msg;
8921 pipeline_msg_req_handler f_handle;
8923 f_handle = (req->subtype < PIPELINE_CGNAPT_MSG_REQS) ?
8924 p_nat->custom_handlers[req->subtype] :
8925 pipeline_msg_req_invalid_handler;
8927 if (f_handle == NULL)
8928 f_handle = pipeline_msg_req_invalid_handler;
8930 return f_handle(p, req);
8934 * Function for adding NSP data
8937 * A void pointer to pipeline
8939 * void pointer for incoming data
8942 * void pointer of response
8944 void *pipeline_cgnapt_msg_req_nsp_add_handler(
8945 __rte_unused struct pipeline *p,
8948 struct pipeline_cgnapt_nsp_add_msg_req *req = msg;
8949 struct pipeline_cgnapt_nsp_add_msg_rsp *rsp = msg;
8951 struct cgnapt_nsp_node *node = NULL, *ll = nsp_ll;
8954 (req->nsp.depth == 32 || req->nsp.depth == 40
8955 || req->nsp.depth == 48 || req->nsp.depth == 56
8956 || req->nsp.depth == 64 || req->nsp.depth == 96)) {
8962 printf("be initial cond\n");
8963 if (nsp_ll == NULL) {
8964 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_nsp_node));
8965 node = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8967 printf("be 1st cond\n");
8973 memcpy(&node->nsp, &req->nsp,
8974 sizeof(struct pipeline_cgnapt_nsp_t));
8978 while (ll != NULL) {
8979 if (!memcmp(ll->nsp.prefix, req->nsp.prefix, 16)
8980 && ll->nsp.depth == req->nsp.depth) {
8981 printf("be 2st cond\n");
8989 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_nsp_node));
8990 node = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8992 printf("be 3st cond\n");
8998 memcpy(&node->nsp, &req->nsp,
8999 sizeof(struct pipeline_cgnapt_nsp_t));
9000 node->next = nsp_ll;
9007 printf("be 4st cond\n");
9012 * Function for deleting NSP data
9015 * A void pointer to pipeline
9017 * void pointer for incoming data
9020 * void pointer of response
9022 void *pipeline_cgnapt_msg_req_nsp_del_handler(
9023 __rte_unused struct pipeline *p,
9026 struct pipeline_cgnapt_nsp_del_msg_req *req = msg;
9027 struct pipeline_cgnapt_nsp_del_msg_rsp *rsp = msg;
9028 struct cgnapt_nsp_node *prev = NULL, *ll = nsp_ll;
9030 while (ll != NULL) {
9031 if (!memcmp(ll->nsp.prefix, req->nsp.prefix, 16)
9032 && ll->nsp.depth == req->nsp.depth) {
9034 prev->next = ll->next;
9057 * Function for adding NAPT entry
9060 * A void pointer to pipeline
9062 * void pointer for incoming data
9065 * void pointer of response
9067 void *pipeline_cgnapt_msg_req_entry_add_handler(struct pipeline *p, void *msg)
9069 struct pipeline_cgnapt_entry_add_msg_req *req = msg;
9070 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9071 uint8_t type = req->data.type;
9072 uint32_t src_ip = (type == CGNAPT_ENTRY_IPV4) ?
9073 req->data.u.prv_ip :
9074 rte_bswap32(req->data.u.u32_prv_ipv6[3]);
9076 uint8_t src_ipv6[16];
9078 uint32_t dest_ip = req->data.pub_ip;
9079 uint16_t src_port = req->data.prv_port;
9080 uint16_t dest_port = req->data.pub_port;
9081 uint16_t rx_port = req->data.prv_phy_port;
9082 uint32_t ttl = req->data.ttl;
9084 if (type == CGNAPT_ENTRY_IPV6)
9085 memcpy(src_ipv6, req->data.u.prv_ipv6, 16);
9087 printf("CG-NAPT addm - PrvIP %x, PrvPort %d,", src_ip, src_port);
9088 printf("PubIP %x, PubPort %d,", dest_ip, dest_port);
9090 printf("PhyPort %d, ttl %u,", rx_port, ttl);
9091 printf("entry_type %d\n", type);
9093 #ifdef NAT_ONLY_CONFIG_REQ
9094 if (nat_only_config_flag) {
9095 if (!p_nat->is_static_cgnapt) {
9098 for (i = 0; i < p_nat->pub_ip_range_count; i++) {
9099 if (((dest_ip >= p_nat->pub_ip_range[i].start_ip)
9100 && (dest_ip <= p_nat->pub_ip_range[i].end_ip))) {
9101 printf("Error - static port cannot be in Dynamic "
9103 printf("%x-%x\n", p_nat->pub_ip_range[i].start_ip,
9104 p_nat->pub_ip_range[i].end_ip);
9110 if (pipeline_cgnapt_msg_req_entry_addm_pair(p, msg,
9116 printf("pipeline_cgnapt_msg_req_entry_addm_handler\n");
9120 printf("Success - pipeline_cgnapt_msg_req_entry_addm_handler");
9121 printf("added %d rule pairs.\n", count);
9127 if (!p_nat->is_static_cgnapt) {
9130 for (i = 0; i < p_nat->pub_ip_count; i++) {
9131 /* Check port range if same Public-IP */
9132 if (dest_ip != p_nat->pub_ip_port_set[i].ip)
9134 if (((dest_port >= p_nat->pub_ip_port_set[i].start_port) &&
9135 (dest_port <= p_nat->pub_ip_port_set[i].end_port))) {
9136 printf("Error - port cannot be in Dynamic "
9137 "port range %d-%d\n",
9138 p_nat->pub_ip_port_set[i].start_port,
9139 p_nat->pub_ip_port_set[i].end_port);
9145 if (pipeline_cgnapt_msg_req_entry_addm_pair
9146 (p, msg, src_ip, src_port, dest_ip, dest_port, rx_port,
9147 ttl, type, src_ipv6)) {
9148 printf("Error - pipeline_cgnapt_msg_req_entry_add_handler\n");
9153 printf("\nSuccess - pipeline_cgnapt_msg_req_entry_add_handler "
9160 * Function for adding a NAPT entry pair
9163 * A void pointer to pipeline
9165 * void pointer for incoming data
9171 * destination ip address
9175 * Physical receive port
9177 * time to live value
9179 * type of entry IPv4 vs IPv6
9181 * uint8_t array of IPv6 address
9184 * 0 if success, negative if fails
9187 pipeline_cgnapt_msg_req_entry_addm_pair(
9188 struct pipeline *p, __rte_unused void *msg,
9189 uint32_t src_ip, uint16_t src_port,
9190 uint32_t dest_ip, uint16_t dest_port,
9191 uint16_t rx_port, uint32_t ttl,
9192 uint8_t type, uint8_t src_ipv6[16])
9195 struct pipeline_cgnapt_entry_key key;
9196 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9199 key.port = src_port;
9202 struct cgnapt_table_entry entry = {
9204 .action = RTE_PIPELINE_ACTION_PORT,
9205 .port_id = CGNAPT_PUB_PORT_ID,
9209 /*.prv_ip = src_ip, */
9210 .prv_port = src_port,
9212 .pub_port = dest_port,
9213 .prv_phy_port = rx_port,
9214 .pub_phy_port = get_prv_to_pub_port(&dest_ip,
9217 .timeout = STATIC_CGNAPT_TIMEOUT,
9224 if (type == CGNAPT_ENTRY_IPV4) {
9225 entry.data.type = CGNAPT_ENTRY_IPV4;
9226 entry.data.u.prv_ip = src_ip;
9228 entry.data.type = CGNAPT_ENTRY_IPV6;
9229 memcpy(entry.data.u.prv_ipv6, src_ipv6, 16);
9232 /* Also need to add a paired entry on our own */
9234 * Need to change key
9235 * Need to change entry header
9236 * Will keep the same entry and take care
9237 * of translation in table hit handler
9239 struct pipeline_cgnapt_entry_key second_key;
9241 /* Need to add a second ingress entry */
9242 second_key.ip = dest_ip;
9243 second_key.port = dest_port;
9244 second_key.pid = 0xffff;
9246 #ifdef NAT_ONLY_CONFIG_REQ
9247 if (nat_only_config_flag) {
9249 entry.data.pub_port = 0xffff;
9250 second_key.port = 0xffff;
9254 if (CGNAPT_DEBUG > 2)
9255 printf("key.ip %x, key.port %d", key.ip, key.port);
9256 printf("key.pid %d, in_type %d,", key.pid, type);
9257 printf("entry_type %d\n", entry.data.type);
9259 int32_t position = rte_hash_add_key(napt_common_table, &key);
9262 printf("CG-NAPT entry bulk add failed");
9263 printf(" ... returning without adding ...\n");
9267 memcpy(&napt_hash_tbl_entries[position], &entry,
9268 sizeof(struct cgnapt_table_entry));
9270 #ifdef CGNAPT_DEBUGGING
9271 if (p_nat->kpc1++ < 5)
9275 p_nat->n_cgnapt_entry_added++;
9277 /* Now modify the forward port for reverse entry */
9278 entry.head.port_id = CGNAPT_PRV_PORT_ID;
9280 position = rte_hash_add_key(napt_common_table, &second_key);
9283 printf("CG-NAPT entry reverse bulk add failed");
9284 printf(" ... returning with fwd add ...%d\n", position);
9288 memcpy(&napt_hash_tbl_entries[position], &entry,
9289 sizeof(struct cgnapt_table_entry));
9291 #ifdef CGNAPT_DEBUGGING
9292 if (p_nat->kpc1 < 5)
9293 print_key(&second_key);
9296 p_nat->n_cgnapt_entry_added++;
9301 * Function for adding multiple NAPT entries
9304 * A void pointer to pipeline
9306 * void pointer for incoming data
9309 * void pointer of response
9311 void *pipeline_cgnapt_msg_req_entry_addm_handler(struct pipeline *p, void *msg)
9313 struct pipeline_cgnapt_entry_addm_msg_req *req = msg;
9314 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9316 uint32_t max_ue = req->data.num_ue;
9317 uint8_t type = req->data.type;
9318 uint32_t src_ip = (type == CGNAPT_ENTRY_IPV4) ?
9319 req->data.u.prv_ip :
9320 rte_bswap32(req->data.u.u32_prv_ipv6[3]);
9322 uint8_t src_ipv6[16];
9324 uint32_t dest_ip = req->data.pub_ip;
9325 uint16_t src_port = req->data.prv_port;
9326 uint16_t dest_port = req->data.pub_port;
9327 uint16_t rx_port = req->data.prv_phy_port;
9328 uint32_t ttl = req->data.ttl;
9329 uint16_t max_src_port = req->data.prv_port_max;
9330 uint16_t max_dest_port = req->data.pub_port_max;
9332 uint16_t src_port_start = src_port;
9333 uint16_t dest_port_start = dest_port;
9334 uint32_t src_ip_temp;
9336 if (type == CGNAPT_ENTRY_IPV6)
9337 memcpy(src_ipv6, req->data.u.prv_ipv6, 16);
9339 printf("CG-NAPT addm - PrvIP %x, PrvPort %d,", src_ip, src_port);
9340 printf("PubIP %x, PubPort %d,", dest_ip, dest_port);
9341 printf("PhyPort %d, ttl %u, NumUe %d,", rx_port, ttl, max_ue);
9342 printf("mPrvPort %d, mPubPort %d,", max_src_port, max_dest_port);
9343 printf("entry_type %d\n", type);
9345 #ifdef NAT_ONLY_CONFIG_REQ
9346 if (nat_only_config_flag) {
9347 if (!p_nat->is_static_cgnapt) {
9350 for (i = 0; i < p_nat->pub_ip_range_count; i++) {
9351 if (((dest_ip >= p_nat->pub_ip_range[i].start_ip)
9352 && (dest_ip <= p_nat->pub_ip_range[i].end_ip)) ||
9353 (((dest_ip + max_ue) >=
9354 p_nat->pub_ip_range[i].start_ip) &&
9355 ((dest_ip + max_ue) <=
9356 p_nat->pub_ip_range[i].end_ip))) {
9357 printf("Error - static port cannot be in Dynamic "
9359 printf("%x-%x\n", p_nat->pub_ip_range[i].start_ip,
9360 p_nat->pub_ip_range[i].end_ip);
9367 for (uenum = 0; uenum < max_ue; uenum++) {
9369 if (pipeline_cgnapt_msg_req_entry_addm_pair(p, msg,
9375 printf("pipeline_cgnapt_msg_req_entry_addm_handler\n");
9385 printf("Success - pipeline_cgnapt_msg_req_entry_addm_handler");
9386 printf("added %d rule pairs.\n", count);
9392 if (!p_nat->is_static_cgnapt) {
9395 for (i = 0; i < p_nat->pub_ip_count; i++) {
9396 /* Check port range if same Public-IP */
9397 if (dest_ip != p_nat->pub_ip_port_set[i].ip)
9399 if (((dest_port >= p_nat->pub_ip_port_set[i].start_port) &&
9400 (dest_port <= p_nat->pub_ip_port_set[i].end_port)) ||
9401 ((max_dest_port >= p_nat->pub_ip_port_set[i].start_port)
9402 && max_dest_port <= p_nat->pub_ip_port_set[i].end_port)) {
9403 printf("Error - port cannot be in Dynamic port range %d-%d\n",
9404 p_nat->pub_ip_port_set[i].start_port,
9405 p_nat->pub_ip_port_set[i].end_port);
9411 for (uenum = 0; uenum < max_ue; uenum++) {
9412 if (pipeline_cgnapt_msg_req_entry_addm_pair
9413 (p, msg, src_ip, src_port, dest_ip, dest_port, rx_port,
9414 ttl, type, src_ipv6)) {
9415 printf("Error - pipeline_cgnapt_msg_req_entry_addm_handler\n");
9422 if (src_port > max_src_port) {
9423 src_port = src_port_start;
9425 if (req->data.type == CGNAPT_ENTRY_IPV6) {
9426 src_ip_temp = rte_bswap32(src_ip);
9427 memcpy(&src_ipv6[12], &src_ip_temp, 4);
9431 if (dest_port > max_dest_port) {
9432 dest_port = dest_port_start;
9437 printf("\nSuccess - pipeline_cgnapt_msg_req_entry_addm_handler added");
9438 printf("%d rule pairs.\n", count);
9444 * Function for deleting NAPT entry
9447 * A void pointer to pipeline
9449 * void pointer for incoming data
9452 * void pointer of response
9454 void *pipeline_cgnapt_msg_req_entry_del_handler(struct pipeline *p, void *msg)
9456 struct pipeline_cgnapt_entry_delete_msg_req *req = msg;
9457 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9458 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9461 uint8_t *KeyP = (void *)(&req->key);
9464 printf("pipeline_cgnapt_msg_req_entry_del_handler - Key: ");
9465 for (i = 0; i < (int)sizeof(struct pipeline_cgnapt_entry_key);
9467 printf(" %02x", KeyP[i]);
9468 printf(" ,KeySize %u\n",
9469 (int)sizeof(struct pipeline_cgnapt_entry_key));
9472 struct cgnapt_table_entry entry;
9474 /* If ingress key */
9475 if (!is_phy_port_privte(req->key.pid))
9476 req->key.pid = 0xffff;
9478 #ifdef NAT_ONLY_CONFIG_REQ
9479 if (nat_only_config_flag)
9480 req->key.port = 0xffff;
9484 position = rte_hash_lookup(napt_common_table, &req->key);
9485 if (position == -ENOENT) {
9486 printf("Entry not found\n");
9489 memcpy(&entry, &napt_hash_tbl_entries[position],
9490 sizeof(struct cgnapt_table_entry));
9491 position = rte_hash_del_key(napt_common_table, &req->key);
9492 p_nat->n_cgnapt_entry_deleted++;
9494 struct pipeline_cgnapt_entry_key second_key;
9496 if (is_phy_port_privte(req->key.pid)) {
9497 /* key is for egress - make second key for ingress */
9498 second_key.ip = entry.data.pub_ip;
9499 second_key.port = entry.data.pub_port;
9500 second_key.pid = 0xffff;
9503 /* key is for ingress - make second key for egress */
9504 second_key.ip = entry.data.u.prv_ip;
9505 second_key.port = entry.data.prv_port;
9506 second_key.pid = entry.data.prv_phy_port;
9509 #ifdef NAT_ONLY_CONFIG_REQ
9510 if (nat_only_config_flag)
9511 second_key.port = 0xffff;
9514 position = rte_hash_del_key(napt_common_table, &second_key);
9515 p_nat->n_cgnapt_entry_deleted++;
9520 void *pipeline_cgnapt_msg_req_entry_sync_handler(struct pipeline *p, void *msg)
9522 struct pipeline_cgnapt_entry_delete_msg_req *req = msg;
9523 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9525 rsp->status = rte_pipeline_table_entry_delete(
9529 &rsp->key_found, NULL);
9535 * Function to print the NAPT key
9538 * A pointer to struct pipeline_cgnapt_entry_key
9540 void print_key(struct pipeline_cgnapt_entry_key *key)
9542 uint8_t *KeyP = (void *)(key);
9546 for (i = 0; i < (int)sizeof(struct pipeline_cgnapt_entry_key); i++)
9547 printf(" %02x", KeyP[i]);
9551 * Function to print the table entry
9554 * A pointer to struct rte_pipeline_table_entry
9556 void print_entry1(struct rte_pipeline_table_entry *entry)
9558 uint8_t *entryP = (void *)(entry);
9562 for (i = 0; i < (int)sizeof(struct rte_pipeline_table_entry); i++)
9563 printf(" %02x", entryP[i]);
9567 * Function to print the NAPT table entry
9570 * A pointer to struct cgnapt_table_entry
9572 void print_cgnapt_entry(struct cgnapt_table_entry *entry)
9574 uint8_t *entryP = (void *)(entry);
9577 printf("CGNAPT Entry: ");
9578 for (i = 0; i < (int)sizeof(struct cgnapt_table_entry); i++)
9579 printf(" %02x", entryP[i]);
9580 printf(" size:%d\n", (int)sizeof(struct cgnapt_table_entry));
9584 * Function to get a free port
9587 * A pointer to struct pipeline_cgnapt
9589 * A uint32_t pointer to return corresponding ip address
9592 * free port number, 0 if error
9594 int get_free_iport(struct pipeline_cgnapt *p_nat, uint32_t *public_ip)
9597 /* If we don't have a valid napt_port_alloc_elem get one from
9600 if (p_nat->allocated_ports == NULL) {
9604 ret = rte_ring_dequeue(p_nat->port_alloc_ring, &ports);
9606 p_nat->allocated_ports =
9607 (struct napt_port_alloc_elem *)ports;
9609 #ifdef CGNAPT_DEBUGGING
9613 #ifdef CGNAPT_DBG_PRNT
9614 if (CGNAPT_DEBUG > 3)
9615 printf("p_nat->allocated_ports %p\n",
9616 p_nat->allocated_ports);
9619 printf("CGNAPT Err - get_free_iport rte_ring_dequeue "
9621 printf("%d, %d, %d\n", rte_ring_count(
9622 p_nat->port_alloc_ring), rte_ring_free_count(
9623 p_nat->port_alloc_ring), ret);
9625 #ifdef CGNAPT_DEBUGGING
9626 #ifdef CGNAPT_DBG_PRNT
9627 printf("Th%d GFP:: %" PRIu64 ", %" PRIu64 ", "
9628 "%" PRIu64", %" PRIu64 ",\n", p_nat->pipeline_num,
9629 p_nat->gfp_get, p_nat->gfp_ret, p_nat->gfp_suc,
9639 /* get the port from index count-1 and decrease count */
9640 port = p_nat->allocated_ports->ports
9641 [p_nat->allocated_ports->count - 1];
9642 *public_ip = p_nat->allocated_ports->ip_addr
9643 [p_nat->allocated_ports->count - 1];
9645 p_nat->allocated_ports->count -= 1;
9647 /* if count is zero, return buffer to mem pool */
9648 if (p_nat->allocated_ports->count == 0) {
9649 rte_mempool_put(napt_port_pool, p_nat->allocated_ports);
9651 #ifdef CGNAPT_DEBUGGING
9653 #ifdef CGNAPT_DBG_PRNT
9654 printf("Th%d Returned to pool p_nat->allocated_ports %p,",
9655 p_nat->pipeline_num, p_nat->allocated_ports);
9656 printf("%" PRIu64 ", %" PRIu64 ",",
9657 p_nat->gfp_get, p_nat->gfp_ret);
9658 printf("%" PRIu64 ", %" PRIu64 ",\n",
9659 p_nat->gfp_suc, p_nat->gfp_err);
9663 p_nat->allocated_ports = NULL;
9666 #ifdef CGNAPT_DEBUGGING
9674 * Function to free a port
9677 * Port number to free
9679 * Corresponding ip address
9681 * A pointer to struct pipeline_cgnapt
9684 void release_iport(uint16_t port_num, uint32_t public_ip,
9685 struct pipeline_cgnapt *p_nat)
9687 /* If we don't have a valid napt_port_alloc_elem get one
9690 if (p_nat->free_ports == NULL) {
9693 #ifdef CGNAPT_DEBUGGING
9697 if (rte_mempool_get(napt_port_pool, &ports) < 0) {
9698 #ifdef CGNAPT_DEBUGGING
9701 printf("CGNAPT release_iport error in getting "
9702 "port alloc buffer\n");
9706 p_nat->free_ports = (struct napt_port_alloc_elem *)ports;
9707 p_nat->free_ports->count = 0;
9710 /* put the port at index count and increase count */
9711 p_nat->free_ports->ip_addr[p_nat->free_ports->count] = public_ip;
9712 p_nat->free_ports->ports[p_nat->free_ports->count] = port_num;
9713 p_nat->free_ports->count += 1;
9715 /* if napt_port_alloc_elem is full add it to ring */
9718 #ifdef CGNAPT_DEBUGGING
9722 #ifdef CGNAPT_DBG_PRNT
9723 if (CGNAPT_DEBUG >= 2) {
9724 printf("CGNAPT port_alloc_ring before EnQ Cnt %d, Free %d\n",
9725 rte_ring_count(p_nat->port_alloc_ring),
9726 rte_ring_free_count(p_nat->port_alloc_ring));
9730 if (rte_ring_enqueue(p_nat->port_alloc_ring,
9731 (void *)p_nat->free_ports) != 0) {
9732 printf("CGNAPT release_iport Enqueue error %p\n",
9735 #ifdef CGNAPT_DEBUGGING
9740 #ifdef CGNAPT_DBG_PRNT
9741 if (CGNAPT_DEBUG >= 2) {
9742 printf("CGNAPT port_alloc_ring after EnQ Cnt %d",
9743 rte_ring_count(p_nat->port_alloc_ring));
9745 rte_ring_free_count(p_nat->port_alloc_ring));
9749 p_nat->free_ports = NULL;
9752 #ifdef CGNAPT_DEBUGGING
9758 * Function to initialize max ports per client data structures
9759 * Called during dynamic NAPT initialization.
9762 * A pointer to struct pipeline_cgnapt
9765 * 0 if success, negative if error
9767 int init_max_port_per_client(
9768 __rte_unused struct pipeline_cgnapt *p_nat)
9770 if (max_port_per_client_hash)
9773 /*MPPC_ALREADY_EXISTS */
9777 max_port_per_client_hash =
9778 rte_hash_create(&max_port_per_client_hash_params);
9779 if (!max_port_per_client_hash)
9782 /*MPPC_HASH_CREATE_ERROR */
9784 max_port_per_client_array =
9786 sizeof(struct max_port_per_client) * MAX_DYN_ENTRY,
9787 RTE_CACHE_LINE_SIZE);
9788 if (!max_port_per_client_array)
9791 /*MPPC_ARRAY_CREATE_ERROR */
9793 for (i = 0; i < MAX_DYN_ENTRY; i++) {
9794 max_port_per_client_array[i].prv_ip = 0;
9795 max_port_per_client_array[i].prv_phy_port = 0;
9796 max_port_per_client_array[i].max_port_cnt = 0;
9804 * Function to check if max ports for a client is reached
9806 * @param prv_ip_param
9807 * A uint32_t ip address of client
9808 * @param prv_phy_port_param
9809 * A uint32_t physical port id of the client
9811 * A pointer to struct pipeline_cgnapt
9814 * 0 if max port not reached, 1 if reached, -1 if error
9816 int is_max_port_per_client_reached(uint32_t prv_ip_param,
9817 uint32_t prv_phy_port_param,
9818 struct pipeline_cgnapt *p_nat)
9820 int index = MAX_PORT_INVALID_KEY;
9822 struct max_port_per_client_key key = {
9823 .prv_ip = prv_ip_param,
9824 .prv_phy_port = prv_phy_port_param,
9827 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9830 return MAX_PORT_INVALID_KEY;
9832 if (max_port_per_client_array[index].max_port_cnt >=
9833 p_nat->max_port_per_client)
9834 return MAX_PORT_REACHED;
9836 return MAX_PORT_NOT_REACHED;
9840 * Function to increase max ports for a client
9842 * @param prv_ip_param
9843 * A uint32_t ip address of client
9844 * @param prv_phy_port_param
9845 * A uint32_t physical port id of the client
9847 * A pointer to struct pipeline_cgnapt
9850 * 0 if max port reached, 1 if success, 2 if new entry, -1 if error
9852 int increment_max_port_counter(uint32_t prv_ip_param,
9853 uint32_t prv_phy_port_param,
9854 struct pipeline_cgnapt *p_nat)
9856 int index = MAX_PORT_INC_ERROR;
9858 struct max_port_per_client_key key = {
9859 .prv_ip = prv_ip_param,
9860 .prv_phy_port = prv_phy_port_param,
9863 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9865 if (index == -EINVAL)
9866 return MAX_PORT_INC_ERROR;
9868 if (index == -ENOENT) {
9869 if (max_port_per_client_add_entry(prv_ip_param,
9872 return MAX_PORT_INC_ERROR;
9874 return 2; /*return MAX_PORT_NEW_ENTRY; */
9877 if (CGNAPT_DEBUG > 2)
9878 printf("%s: max_port_cnt(%d), p_nat_max(%d)\n", __func__,
9879 max_port_per_client_array[index].max_port_cnt,
9880 p_nat->max_port_per_client);
9882 if (max_port_per_client_array[index].max_port_cnt <
9883 p_nat->max_port_per_client) {
9884 max_port_per_client_array[index].max_port_cnt++;
9885 return MAX_PORT_INC_SUCCESS;
9888 return MAX_PORT_INC_REACHED;
9892 * Function to decrease max ports for a client
9894 * @param prv_ip_param
9895 * A uint32_t ip address of client
9896 * @param prv_phy_port_param
9897 * A uint32_t physical port id of the client
9899 * A pointer to struct pipeline_cgnapt
9902 * 0 if count already 0, 1 if success, -1 if error
9904 int decrement_max_port_counter(uint32_t prv_ip_param,
9905 uint32_t prv_phy_port_param,
9906 struct pipeline_cgnapt *p_nat)
9908 int index = MAX_PORT_DEC_ERROR;
9910 struct max_port_per_client_key key = {
9911 .prv_ip = prv_ip_param,
9912 .prv_phy_port = prv_phy_port_param,
9915 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9918 #ifdef CGNAPT_DEBUGGING
9919 p_nat->max_port_dec_err1++;
9921 return MAX_PORT_DEC_ERROR;
9925 if (max_port_per_client_array[index].max_port_cnt > 0) {
9926 /* If it is the last port,ret this info which is used for
9927 * max_cli_per_pub_ip
9930 max_port_per_client_array[index].max_port_cnt--;
9931 /* Count should be atomic but we are good as we have only
9932 * one task handling this counter at a time (core affinity)
9936 if (max_port_per_client_array[index].max_port_cnt <= 0) {
9937 if (max_port_per_client_del_entry
9938 (prv_ip_param, prv_phy_port_param, p_nat) <= 0) {
9940 #ifdef CGNAPT_DEBUGGING
9941 p_nat->max_port_dec_err2++;
9943 return MAX_PORT_DEC_ERROR;
9946 #ifdef CGNAPT_DEBUGGING
9947 p_nat->max_port_dec_err3++;
9950 return MAX_PORT_DEC_REACHED;
9953 #ifdef CGNAPT_DEBUGGING
9954 p_nat->max_port_dec_success++;
9957 return MAX_PORT_DEC_SUCCESS;
9961 * Function to add a max ports per client entry
9963 * @param prv_ip_param
9964 * A uint32_t ip address of client
9965 * @param prv_phy_port_param
9966 * A uint32_t physical port id of the client
9968 * A pointer to struct pipeline_cgnapt
9971 * 0 no success, 1 if success, -1 if error
9973 int max_port_per_client_add_entry(
9974 uint32_t prv_ip_param,
9975 uint32_t prv_phy_port_param,
9976 __rte_unused struct pipeline_cgnapt *p_nat)
9978 int index = MAX_PORT_ADD_ERROR;
9980 struct max_port_per_client_key key = {
9981 .prv_ip = prv_ip_param,
9982 .prv_phy_port = prv_phy_port_param,
9985 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9986 if (index == -EINVAL)
9987 return MAX_PORT_ADD_ERROR;
9990 return MAX_PORT_ADD_UNSUCCESS;
9992 if (index == -ENOENT) {
9994 #ifdef CGNAPT_DBG_PRNT
9995 if (CGNAPT_DEBUG > 2)
9996 printf("max_port_per_client_add_entry fn: "
9997 "Entry does not exist\n");
10001 rte_hash_add_key(max_port_per_client_hash,
10002 (const void *)&key);
10003 if (index == -ENOSPC)
10004 return MAX_PORT_ADD_UNSUCCESS;
10006 #ifdef CGNAPT_DBG_PRNT
10007 if (CGNAPT_DEBUG > 2)
10008 printf("max_port_per_client_add_entry fn:"
10009 "Add entry index(%d)\n", index);
10012 max_port_per_client_array[index].prv_ip = prv_ip_param;
10013 max_port_per_client_array[index].prv_phy_port =
10014 prv_phy_port_param;
10017 max_port_per_client_array[index].max_port_cnt++;
10018 return MAX_PORT_ADD_SUCCESS;
10022 * Function to delete a max ports per client entry
10024 * @param prv_ip_param
10025 * A uint32_t ip address of client
10026 * @param prv_phy_port_param
10027 * A uint32_t physical port id of the client
10029 * A pointer to struct pipeline_cgnapt
10032 * 0 no success, 1 if success, -1 if error
10034 int max_port_per_client_del_entry(
10035 uint32_t prv_ip_param,
10036 uint32_t prv_phy_port_param,
10037 __rte_unused struct pipeline_cgnapt *p_nat)
10039 int index = MAX_PORT_DEL_ERROR;
10041 struct max_port_per_client_key key = {
10042 .prv_ip = prv_ip_param,
10043 .prv_phy_port = prv_phy_port_param,
10046 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
10048 if (index == -EINVAL)
10049 return MAX_PORT_DEL_ERROR;
10051 if (index == -ENOENT)
10052 return MAX_PORT_DEL_UNSUCCESS;
10054 index = rte_hash_del_key(max_port_per_client_hash, (const void *)&key);
10055 max_port_per_client_array[index].prv_ip = 0;
10056 max_port_per_client_array[index].prv_phy_port = 0;
10057 max_port_per_client_array[index].max_port_cnt = 0;
10059 return MAX_PORT_DEL_SUCCESS;
10063 * Function to execute debug commands
10066 * A pointer to struct pipeline
10068 * void pointer to incoming arguments
10070 void *pipeline_cgnapt_msg_req_entry_dbg_handler(struct pipeline *p, void *msg)
10072 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
10073 uint8_t *Msg = msg;
10074 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
10078 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_STATS_SHOW) {
10079 printf("\nCG-NAPT Packet Stats:\n");
10080 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10081 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10082 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10083 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10084 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10085 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10086 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10088 #ifdef CGNAPT_DEBUGGING
10089 printf("\n Drop detail 1:%" PRIu64 ",",
10090 p_nat->naptDroppedPktCount1);
10091 printf("\n Drop detail 2:%" PRIu64 ",",
10092 p_nat->naptDroppedPktCount2);
10093 printf("\n Drop detail 3:%" PRIu64 ",",
10094 p_nat->naptDroppedPktCount3);
10095 printf("\n Drop detail 4:%" PRIu64 ",",
10096 p_nat->naptDroppedPktCount4);
10097 printf("\n Drop detail 5:%" PRIu64 ",",
10098 p_nat->naptDroppedPktCount5);
10099 printf("\n Drop detail 6:%" PRIu64 "",
10100 p_nat->naptDroppedPktCount6);
10102 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10103 p_nat->missedpktcount1,
10104 p_nat->missedpktcount2);
10105 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10106 p_nat->missedpktcount3,
10107 p_nat->missedpktcount4);
10108 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10109 p_nat->missedpktcount5,
10110 p_nat->missedpktcount6);
10111 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10112 p_nat->missedpktcount7,
10113 p_nat->missedpktcount8);
10114 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10115 p_nat->missedpktcount9,
10116 p_nat->missedpktcount10);
10123 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_STATS_CLEAR) {
10124 printf("\nCG-NAPT Packet Stats:\n");
10125 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10126 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10127 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10128 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10129 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10130 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10131 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10133 p_nat->naptedPktCount = 0;
10134 p_nat->naptDroppedPktCount = 0;
10135 p_nat->inaptedPktCount = 0;
10136 p_nat->enaptedPktCount = 0;
10137 p_nat->receivedPktCount = 0;
10138 p_nat->missedPktCount = 0;
10139 p_nat->arpicmpPktCount = 0;
10140 printf("CG-NAPT Packet Stats cleared\n");
10144 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DBG_LEVEL) {
10145 CGNAPT_DEBUG = Msg[CGNAPT_DBG_CMD_OFST + 1];
10146 printf("CG-NAPT debug level set to %d\n", CGNAPT_DEBUG);
10150 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DBG_SHOW) {
10152 printf("\nNAPT entries - added %" PRIu64 ",",
10153 p_nat->n_cgnapt_entry_added);
10154 printf("deleted %" PRIu64 ",", p_nat->n_cgnapt_entry_deleted);
10155 printf("current %" PRIu64 "", p_nat->n_cgnapt_entry_added -
10156 p_nat->n_cgnapt_entry_deleted);
10158 printf("\nCG-NAPT Packet Stats:\n");
10159 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10160 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10161 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10162 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10163 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10164 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10165 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10169 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
10170 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_INSTRUMENTATION) {
10171 if (Msg[CGNAPT_DBG_CMD_OFST1] ==
10172 CGNAPT_CMD_INSTRUMENTATION_SUB0) {
10175 uint32_t diff_sum = 0;
10177 printf("CG-NAPT Instrumentation ...\n");
10178 printf("Instrumentation data collected for fn# %d\n",
10179 cgnapt_num_func_to_inst);
10180 printf("Current collection index %d\n",
10181 cgnapt_inst_index);
10183 if (Msg[CGNAPT_DBG_CMD_OFST + 2] == 2) {
10184 printf("Timer Start:\n");
10186 for (index = 0; index < INST_ARRAY_SIZE; index++) {
10187 if ((index % 5) == 0)
10189 printf(" 0x%jx", inst_start_time[index]);
10191 printf("\n\nTimer End:\n");
10193 for (index = 0; index < INST_ARRAY_SIZE; index++) {
10194 if ((index % 5) == 0)
10196 printf(" 0x%jx", inst_end_time[index]);
10200 for (index = 0; index < INST_ARRAY_SIZE; index++) {
10201 inst_diff_time[index] = (uint32_t) (inst_end_time[index] -
10202 inst_start_time[index]);
10205 if (Msg[CGNAPT_DBG_CMD_OFST + 2] ==
10206 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
10207 printf("\n\nTimer Diff:\n");
10209 for (index = 0; index < INST_ARRAY_SIZE; index++) {
10210 if (Msg[CGNAPT_DBG_CMD_OFST + 2] ==
10211 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
10212 if ((index % 5) == 0)
10214 printf(" 0x%08x", inst_diff_time[index]);
10217 diff_sum += inst_diff_time[index];
10220 printf("\ndiff_sum %u, INST_ARRAY_SIZE %d, Ave Time %u\n",
10221 diff_sum, INST_ARRAY_SIZE, (diff_sum / INST_ARRAY_SIZE));
10222 } else if (Msg[CGNAPT_DBG_CMD_OFST + 1] ==
10223 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
10224 /* p plid entry dbg 7 1 0
10225 * p plid entry dbg 7 1 1 <--- pkt_work_cgnapt
10226 * p plid entry dbg 7 1 2 <--- pkt4_work_cgnapt
10227 * p plid entry dbg 7 1 3 <--- pkt_work_cgnapt_key
10228 * p plid entry dbg 7 1 4 <--- pkt4_work_cgnapt_key
10229 * p plid entry dbg 7 1 5 <--- in port ah to out port ah
10230 * - pkt life in the system
10231 * p plid entry dbg 7 1 6 <--- how long this instrumentation
10234 cgnapt_inst_index = 0;
10235 cgnapt_num_func_to_inst = Msg[CGNAPT_DBG_CMD_OFST + 2];
10236 printf("Instrumentation data collection started for fn# %d\n",
10237 cgnapt_num_func_to_inst);
10238 } else if (Msg[CGNAPT_DBG_CMD_OFST + 1] ==
10239 CGNAPT_CMD_INSTRUMENTATION_SUB2) {
10240 /* p plid entry dbg 7 2 0
10241 * Test all major functions by calling them multiple times
10242 * pkt_work_cgnapt, pkt4_work_cgnapt, pkt_work_cgnapt_key,
10243 * pkt4_work_cgnapt_key
10245 if (cgnapt_test_pktmbuf_pool == NULL) {
10246 cgnapt_test_pktmbuf_pool = rte_pktmbuf_pool_create(
10247 "cgnapt_test_pktmbuf_pool", 63, 32, 0,
10248 RTE_MBUF_DEFAULT_BUF_SIZE,
10252 if (cgnapt_test_pktmbuf_pool == NULL)
10253 printf("CGNAPT test mbuf pool create failed.\n");
10255 struct rte_mbuf *cgnapt_test_pkt0 =
10256 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
10257 if (cgnapt_test_pkt0 == NULL)
10258 printf("CGNAPT test pkt 0 alloc failed.");
10259 struct rte_mbuf *cgnapt_test_pkt1 =
10260 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
10261 if (cgnapt_test_pkt1 == NULL)
10262 printf("CGNAPT test pkt 1 alloc failed.");
10263 struct rte_mbuf *cgnapt_test_pkt2 =
10264 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
10265 if (cgnapt_test_pkt2 == NULL)
10266 printf("CGNAPT test pkt 2 alloc failed.");
10267 struct rte_mbuf *cgnapt_test_pkt3 =
10268 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
10269 if (cgnapt_test_pkt3 == NULL)
10270 printf("CGNAPT test pkt 3 alloc failed.");
10272 struct rte_mbuf *cgnapt_test_pkts[4];
10274 cgnapt_test_pkts[0] = cgnapt_test_pkt0;
10275 cgnapt_test_pkts[1] = cgnapt_test_pkt1;
10276 cgnapt_test_pkts[2] = cgnapt_test_pkt2;
10277 cgnapt_test_pkts[3] = cgnapt_test_pkt3;
10279 uint32_t src_addr_offset =
10280 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_SRC_ADR_OFST;
10281 /* header room + eth hdr size +
10282 * src_aadr offset in ip header
10284 uint32_t dst_addr_offset =
10285 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
10286 /* header room + eth hdr size +
10287 * dst_aadr offset in ip header
10289 uint32_t prot_offset =
10290 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_PROTOCOL_OFST;
10291 /* header room + eth hdr size +
10292 * srprotocol char offset in ip header
10294 int pktCnt = 0, entCnt = 0, exCnt = 0;
10296 for (pktCnt = 0; pktCnt < 4; pktCnt++) {
10297 uint32_t *src_addr =
10298 RTE_MBUF_METADATA_UINT32_PTR
10299 (cgnapt_test_pkts[pktCnt], src_addr_offset);
10300 uint32_t *dst_addr =
10301 RTE_MBUF_METADATA_UINT32_PTR
10302 (cgnapt_test_pkts[pktCnt], dst_addr_offset);
10303 uint8_t *protocol =
10304 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10307 uint8_t *phy_port =
10308 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10310 uint8_t *eth_dest =
10311 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10315 RTE_MBUF_METADATA_UINT8_PTR(
10316 cgnapt_test_pkts[pktCnt],
10319 uint16_t *src_port =
10320 RTE_MBUF_METADATA_UINT16_PTR
10321 (cgnapt_test_pkts[pktCnt],
10322 MBUF_HDR_ROOM + ETH_HDR_SIZE +
10324 uint16_t *dst_port =
10325 RTE_MBUF_METADATA_UINT16_PTR
10326 (cgnapt_test_pkts[pktCnt],
10327 MBUF_HDR_ROOM + ETH_HDR_SIZE +
10329 *src_addr = 0xc0a80001;
10330 *dst_addr = 0x90418634;
10341 eth_dest[0] = 0x90;
10342 eth_dest[1] = 0xE2;
10343 eth_dest[2] = 0xba;
10344 eth_dest[3] = 0x54;
10345 eth_dest[4] = 0x67;
10346 eth_dest[5] = 0xc8;
10348 struct rte_pipeline_table_entry *table_entries[4];
10349 struct cgnapt_table_entry ctable_entries[4];
10350 table_entries[0] = (struct rte_pipeline_table_entry *)
10351 &ctable_entries[0];
10352 table_entries[1] = (struct rte_pipeline_table_entry *)
10353 &ctable_entries[1];
10354 table_entries[2] = (struct rte_pipeline_table_entry *)
10355 &ctable_entries[2];
10356 table_entries[3] = (struct rte_pipeline_table_entry *)
10357 &ctable_entries[3];
10358 for (entCnt = 0; entCnt < 4; entCnt++) {
10359 ctable_entries[entCnt].head.action =
10360 RTE_PIPELINE_ACTION_PORT;
10361 ctable_entries[entCnt].head.port_id = 0;
10363 ctable_entries[entCnt].data.prv_ip = 0x01020304;
10364 ctable_entries[entCnt].data.prv_port = 1234;
10365 ctable_entries[entCnt].data.pub_ip = 0x0a0b0c0d;
10366 ctable_entries[entCnt].data.pub_port = 4000;
10367 ctable_entries[entCnt].data.prv_phy_port = 0;
10368 ctable_entries[entCnt].data.pub_phy_port = 1;
10369 ctable_entries[entCnt].data.ttl = 500;
10372 uint64_t time1 = rte_get_tsc_cycles();
10374 for (exCnt = 0; exCnt < 1000; exCnt++) {
10375 pkt_work_cgnapt_key(cgnapt_test_pkts[0],
10376 instrumentation_port_in_arg);
10378 uint64_t time2 = rte_get_tsc_cycles();
10380 printf("times for %d times execution of "
10381 "pkt_work_cgnapt_key 0x%jx",
10383 printf(", 0x%jx, diff %" PRIu64 "\n", time2,
10386 time1 = rte_get_tsc_cycles();
10387 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10388 pkt_work_cgnapt_key(cgnapt_test_pkts[0],
10389 instrumentation_port_in_arg);
10391 time2 = rte_get_tsc_cycles();
10392 printf("times for %d times execution of "
10393 "pkt_work_cgnapt_key 0x%jx", exCnt, time1);
10394 printf("0x%jx, diff %" PRIu64 "\n", time2,
10397 time1 = rte_get_tsc_cycles();
10398 for (exCnt = 0; exCnt < 1000; exCnt++) {
10399 pkt4_work_cgnapt_key(cgnapt_test_pkts,
10400 instrumentation_port_in_arg);
10402 time2 = rte_get_tsc_cycles();
10403 printf("times for %d times execution of "
10404 "pkt4_work_cgnapt_key 0x%jx",
10406 printf(" 0x%jx, diff %" PRIu64 "\n", time2,
10409 time1 = rte_get_tsc_cycles();
10410 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10411 pkt4_work_cgnapt_key(cgnapt_test_pkts,
10412 instrumentation_port_in_arg);
10414 time2 = rte_get_tsc_cycles();
10415 printf("times for %d times execution of "
10416 "pkt4_work_cgnapt_key 0x%jx",
10418 printf("0x%jx, diff %" PRIu64 "\n", time2,
10421 uint64_t mask = 0xff;
10423 time1 = rte_get_tsc_cycles();
10424 for (exCnt = 0; exCnt < 1000; exCnt++) {
10425 pkt_work_cgnapt(cgnapt_test_pkts[0],
10426 table_entries[0], 3, &mask,
10429 time2 = rte_get_tsc_cycles();
10430 printf("times for %d times execution of "
10431 "pkt_work_cgnapt 0x%jx",
10433 printf("0x%jx, diff %" PRIu64 "\n", time2,
10436 time1 = rte_get_tsc_cycles();
10437 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10438 pkt_work_cgnapt(cgnapt_test_pkts[0],
10439 table_entries[0], 3, &mask,
10442 time2 = rte_get_tsc_cycles();
10443 printf("times for %d times execution of "
10444 "pkt_work_cgnapt 0x%jx",
10446 printf("0x%jx, diff %" PRIu64 "\n", time2,
10449 time1 = rte_get_tsc_cycles();
10450 for (exCnt = 0; exCnt < 1000; exCnt++) {
10451 pkt4_work_cgnapt(cgnapt_test_pkts,
10452 table_entries, 0, &mask, NULL);
10454 time2 = rte_get_tsc_cycles();
10455 printf("times for %d times execution of "
10456 "pkt4_work_cgnapt 0x%jx",
10458 printf("0x%jx, diff % " PRIu64 "\n", time2,
10461 int idummy = ctable_entries[0].data.prv_port;
10471 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_LS_ENTRY) {
10472 printf("CG-NAPT be entries are:\n");
10473 printf("Pipeline pointer %p\n", p);
10477 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DYN) {
10478 printf("Total Number of dynamic napt entries: %" PRIu64 "\n",
10479 p_nat->dynCgnaptCount);
10481 #ifdef CGNAPT_DEBUGGING
10482 printf("MAX PORT PER CLIENT:");
10483 printf("%" PRIu64 ",%" PRIu64 ",%" PRIu64 "\n",
10484 p_nat->max_port_dec_err1, p_nat->max_port_dec_err2,
10485 p_nat->max_port_dec_err3);
10486 printf("MPPC success : %" PRIu64 "\n",
10487 p_nat->max_port_dec_success);
10489 printf("Release port:err:%" PRIu64 ",ret::%" PRIu64 ",get::%"
10490 PRIu64 ",suc::%" PRIu64 "\n", p_nat->pfb_err,
10491 p_nat->pfb_ret, p_nat->pfb_get, p_nat->pfb_suc);
10492 printf("Get port::err:%" PRIu64 ",ret::%" PRIu64 ",get::%"
10493 PRIu64 ",suc::%" PRIu64 "\n", p_nat->gfp_err,
10494 p_nat->gfp_ret, p_nat->gfp_get, p_nat->gfp_suc);
10495 printf("Ring Info:\n");
10496 rte_ring_dump(stdout, p_nat->port_alloc_ring);
10500 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_IPV6) {
10501 dual_stack_enable = Msg[CGNAPT_DBG_CMD_OFST + 1];
10502 printf("Dual Stack option set: %x\n", dual_stack_enable);
10506 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_MAPS_INFO) {
10507 pipelines_port_info();
10508 pipelines_map_info();
10512 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_ITER_COM_TBL) {
10513 uint32_t count = 0;
10521 rte_hash_iterate(napt_common_table, &key, &data,
10524 if ((index != -EINVAL) && (index != -ENOENT)) {
10525 printf("\n%04d ", count);
10526 rte_hexdump(stdout, "KEY", key,
10528 pipeline_cgnapt_entry_key));
10530 //print_key((struct pipeline_cgnapt_entry_key *)
10533 rte_hash_lookup(napt_common_table,
10535 print_cgnapt_entry(&napt_hash_tbl_entries
10540 } while (index != -ENOENT);
10544 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_IF_STATS) {
10546 struct app_params *app =
10547 (struct app_params *)p_nat->app_params_addr;
10550 cmd[0] = Msg[CGNAPT_DBG_CMD_OFST + 1];
10551 cmd[1] = Msg[CGNAPT_DBG_CMD_OFST + 2];
10553 case CGNAPT_IF_STATS_HWQ:
10554 printf("n_pktq_hwq_int :%d\n", app->n_pktq_hwq_in);
10555 printf("n_pktq_hwq_out :%d\n", app->n_pktq_hwq_out);
10559 for (i = 0; i < app->n_pktq_hwq_in; i++) {
10560 struct rte_eth_stats stats;
10562 rte_eth_stats_get(p_nat->links_map[i], &stats);
10564 if (is_phy_port_privte(i))
10565 printf("Private Port Stats %d\n", i);
10567 printf("Public Port Stats %d\n", i);
10569 printf("\n\tipackets : %" PRIu64 "",
10571 printf("\n\topackets : %" PRIu64 "",
10573 printf("\n\tierrors : %" PRIu64 "",
10575 printf("\n\toerrors : %" PRIu64 "",
10577 printf("\n\trx_nombuf: %" PRIu64 "",
10580 if (is_phy_port_privte(i))
10581 printf("Private Q:");
10583 printf("Public Q:");
10584 for (j = 0; j < RTE_ETHDEV_QUEUE_STAT_CNTRS;
10586 printf(" %" PRIu64 ", %" PRIu64 "|",
10587 stats.q_ipackets[j],
10588 stats.q_opackets[j]);
10596 case CGNAPT_IF_STATS_SWQ:
10598 printf("n_pktq_swq :%d\n", app->n_pktq_swq);
10600 if (cmd[1] < app->n_pktq_swq) {
10601 rte_ring_dump(stdout, app->swq[cmd[1]]);
10604 printf("SWQ number is invalid\n");
10607 case CGNAPT_IF_STATS_OTH:
10609 printf("config_file:%s\n", app->config_file);
10610 printf("script_file:%s\n", app->script_file);
10611 printf("parser_file:%s\n", app->parser_file);
10612 printf("output_file:%s\n", app->output_file);
10613 printf("n_msgq :%d\n", app->n_msgq);
10614 printf("n_pktq_tm :%d\n", app->n_pktq_tm);
10615 printf("n_pktq_source :%d\n", app->n_pktq_source);
10616 printf("n_pktq_sink :%d\n", app->n_pktq_sink);
10617 printf("n_pipelines :%d\n", app->n_pipelines);
10621 printf("Command does not match\n\n");
10629 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_MAX_CLI_PER_PUB_IP) {
10630 if (nat_only_config_flag) {
10631 printf("Command not supported for NAT only config.\n");
10636 printf("\tPublic IP: Num Clients\n");
10637 for (ii = 0; ii < CGNAPT_MAX_PUB_IP; ii++)
10638 printf("\t%x : %7d\n", all_public_ip[ii].ip,
10639 rte_atomic16_read(&all_public_ip[ii].count));
10643 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_PUB_IP_LIST) {
10646 for (i = 0; i < p_nat->pub_ip_count; i++)
10647 printf("%x : (%d,%d)\n", p_nat->pub_ip_port_set[i].ip,
10648 p_nat->pub_ip_port_set[i].start_port,
10649 p_nat->pub_ip_port_set[i].end_port);
10653 #ifdef CGNAPT_TIMING_INST
10654 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_TIMING_INST) {
10655 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 0) {
10656 p_nat->time_measurements_on = 1;
10657 p_nat->time_measurements = 0;
10658 printf("CGNAPT timing instrumentation turned on.\n");
10659 printf("Max samples %d\n", p_nat->max_time_mesurements);
10661 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 1) {
10662 p_nat->time_measurements_on = 0;
10663 printf("CGNAPT timing instrumentation turned off.\n");
10664 printf("Cur Samples %d\n", p_nat->time_measurements);
10666 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 2) {
10667 uint64_t sum = p_nat->external_time_sum +
10668 p_nat->internal_time_sum;
10669 uint64_t isump = (p_nat->internal_time_sum * 100) / sum;
10670 uint64_t esump = (p_nat->external_time_sum * 100) / sum;
10671 printf("CGNAPT timing instrumentation status ...\n");
10672 printf("Max Count %d, Cur Count %d, Status %d (1=ON)\n",
10673 p_nat->max_time_mesurements,
10674 p_nat->time_measurements,
10675 p_nat->time_measurements_on);
10676 printf("Internal Time Sum %" PRIu64 " , Ave %" PRIu64
10677 ", percent %" PRIu64 "\n",
10678 p_nat->internal_time_sum,
10679 (p_nat->internal_time_sum /
10680 p_nat->time_measurements), isump);
10681 printf("External Time Sum %" PRIu64 " , Ave %" PRIu64
10682 ", percent %" PRIu64 "\n",
10683 p_nat->external_time_sum,
10684 (p_nat->external_time_sum /
10685 p_nat->time_measurements), esump);
10692 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_PRINT_NSP) {
10693 struct cgnapt_nsp_node *ll = nsp_ll;
10695 while (ll != NULL) {
10696 fprintf(stderr, "NSP Prefix/Depth=>%x%x:%x%x:%x%x: "
10697 "%x%x:%x%x:%x%x:%x%x:%x%x/%d",
10698 ll->nsp.prefix[0], ll->nsp.prefix[1],
10699 ll->nsp.prefix[2], ll->nsp.prefix[3],
10700 ll->nsp.prefix[4], ll->nsp.prefix[5],
10701 ll->nsp.prefix[6], ll->nsp.prefix[7],
10702 ll->nsp.prefix[8], ll->nsp.prefix[9],
10703 ll->nsp.prefix[10], ll->nsp.prefix[11],
10704 ll->nsp.prefix[12], ll->nsp.prefix[13],
10705 ll->nsp.prefix[14], ll->nsp.prefix[15],
10714 printf("CG-NAPT debug handler called with wrong args %x %x\n", Msg[0],
10718 for (i = 0; i < 20; i++)
10719 printf("%02x ", Msg[i]);
10725 * Function to print num of clients per IP address
10728 void print_num_ip_clients(void)
10730 if (nat_only_config_flag) {
10731 printf("Command not supported for NAT only config.\n");
10736 printf("\tPublic IP: Num Clients\n");
10737 for (ii = 0; ii < CGNAPT_MAX_PUB_IP; ii++)
10738 printf("\t%08x : %7d\n", all_public_ip[ii].ip,
10739 rte_atomic16_read(&all_public_ip[ii].count));
10743 * Function to print CGNAPT version info
10746 * An unused pointer to struct pipeline
10748 * void pointer to incoming arguments
10750 void *pipeline_cgnapt_msg_req_ver_handler(__rte_unused struct pipeline *p,
10753 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
10754 uint8_t *Msg = msg;
10758 printf("CG-NAPT debug handler called with args %x %x, offset %d\n",
10759 Msg[CGNAPT_VER_CMD_OFST], Msg[CGNAPT_VER_CMD_OFST + 1],
10760 CGNAPT_VER_CMD_OFST);
10762 if (Msg[CGNAPT_VER_CMD_OFST] == CGNAPT_VER_CMD_VER) {
10763 printf("CGNAPT Version %s\n", CGNAPT_VERSION);
10766 printf("CG-NAPT Version handler called with wrong args %x %x\n",
10770 for (i = 0; i < 20; i++)
10771 printf("%02x ", Msg[i]);
10777 * Function to show CGNAPT stats
10780 void all_cgnapt_stats(void)
10783 struct pipeline_cgnapt *p_nat;
10784 uint64_t receivedPktCount = 0;
10785 uint64_t missedPktCount = 0;
10786 uint64_t naptDroppedPktCount = 0;
10787 uint64_t naptedPktCount = 0;
10788 uint64_t inaptedPktCount = 0;
10789 uint64_t enaptedPktCount = 0;
10790 uint64_t arpicmpPktCount = 0;
10792 printf("\nCG-NAPT Packet Stats:\n");
10793 for (i = 0; i < n_cgnapt_pipeline; i++) {
10794 p_nat = all_pipeline_cgnapt[i];
10796 receivedPktCount += p_nat->receivedPktCount;
10797 missedPktCount += p_nat->missedPktCount;
10798 naptDroppedPktCount += p_nat->naptDroppedPktCount;
10799 naptedPktCount += p_nat->naptedPktCount;
10800 inaptedPktCount += p_nat->inaptedPktCount;
10801 enaptedPktCount += p_nat->enaptedPktCount;
10802 arpicmpPktCount += p_nat->arpicmpPktCount;
10804 printf("pipeline %d stats:\n", p_nat->pipeline_num);
10805 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10806 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10807 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10808 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10809 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10810 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10811 printf("arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10814 #ifdef CGNAPT_DEBUGGING
10815 printf("\n Drop detail 1:%" PRIu64 ",",
10816 p_nat->naptDroppedPktCount1);
10817 printf("\n Drop detail 2:%" PRIu64 ",",
10818 p_nat->naptDroppedPktCount2);
10819 printf("\n Drop detail 3:%" PRIu64 ",",
10820 p_nat->naptDroppedPktCount3);
10821 printf("\n Drop detail 4:%" PRIu64 ",",
10822 p_nat->naptDroppedPktCount4);
10823 printf("\n Drop detail 5:%" PRIu64 ",",
10824 p_nat->naptDroppedPktCount5);
10825 printf("\n Drop detail 6:%" PRIu64 "",
10826 p_nat->naptDroppedPktCount6);
10828 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10829 p_nat->missedpktcount1,
10830 p_nat->missedpktcount2);
10831 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10832 p_nat->missedpktcount3,
10833 p_nat->missedpktcount4);
10834 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10835 p_nat->missedpktcount5,
10836 p_nat->missedpktcount6);
10837 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10838 p_nat->missedpktcount7,
10839 p_nat->missedpktcount8);
10840 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10841 p_nat->missedpktcount9,
10842 p_nat->missedpktcount10);
10848 printf("\nTotal pipeline stats:\n");
10849 printf("Received %" PRIu64 ",", receivedPktCount);
10850 printf("Missed %" PRIu64 ",", missedPktCount);
10851 printf("Dropped %" PRIu64 ",", naptDroppedPktCount);
10852 printf("Translated %" PRIu64 ",", naptedPktCount);
10853 printf("ingress %" PRIu64 ",", inaptedPktCount);
10854 printf("egress %" PRIu64 "\n", enaptedPktCount);
10855 printf("arpicmp pkts %" PRIu64 "\n", arpicmpPktCount);
10858 void all_cgnapt_clear_stats(void)
10861 struct pipeline_cgnapt *p_nat;
10862 printf("\nCG-NAPT Packet Stats:\n");
10863 for (i = 0; i < n_cgnapt_pipeline; i++) {
10864 p_nat = all_pipeline_cgnapt[i];
10866 printf("pipeline %d stats:\n", p_nat->pipeline_num);
10867 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10868 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10869 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10870 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10871 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10872 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10873 printf("arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10875 p_nat->receivedPktCount = 0;
10876 p_nat->missedPktCount = 0;
10877 p_nat->naptDroppedPktCount = 0;
10878 p_nat->naptedPktCount = 0;
10879 p_nat->inaptedPktCount = 0;
10880 p_nat->enaptedPktCount = 0;
10881 p_nat->arpicmpPktCount = 0;
10883 #ifdef CGNAPT_DEBUGGING
10884 printf("\n Drop detail 1:%" PRIu64 ",",
10885 p_nat->naptDroppedPktCount1);
10886 printf("\n Drop detail 2:%" PRIu64 ",",
10887 p_nat->naptDroppedPktCount2);
10888 printf("\n Drop detail 3:%" PRIu64 ",",
10889 p_nat->naptDroppedPktCount3);
10890 printf("\n Drop detail 4:%" PRIu64 ",",
10891 p_nat->naptDroppedPktCount4);
10892 printf("\n Drop detail 5:%" PRIu64 ",",
10893 p_nat->naptDroppedPktCount5);
10894 printf("\n Drop detail 6:%" PRIu64 "",
10895 p_nat->naptDroppedPktCount6);
10897 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10898 p_nat->missedpktcount1,
10899 p_nat->missedpktcount2);
10900 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10901 p_nat->missedpktcount3,
10902 p_nat->missedpktcount4);
10903 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10904 p_nat->missedpktcount5,
10905 p_nat->missedpktcount6);
10906 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10907 p_nat->missedpktcount7,
10908 p_nat->missedpktcount8);
10909 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10910 p_nat->missedpktcount9,
10911 p_nat->missedpktcount10);
10919 * Function to print common CGNAPT table entries
10922 void print_static_cgnapt_entries(void)
10924 uint32_t count = 0;
10929 struct cgnapt_table_entry *entry;
10931 index = rte_hash_iterate(napt_common_table,
10932 &key, &data, &next);
10934 if ((index != -EINVAL) && (index != -ENOENT)) {
10935 printf("\n%04d ", count);
10936 rte_hexdump(stdout, "KEY", key,
10937 sizeof(struct pipeline_cgnapt_entry_key));
10938 int32_t position = rte_hash_lookup(
10939 napt_common_table, key);
10940 entry = &napt_hash_tbl_entries[position];
10942 if (entry->data.timeout == STATIC_CGNAPT_TIMEOUT)
10943 rte_hexdump(stdout, "Entry",
10944 (const void *)entry,
10945 sizeof(struct cgnapt_table_entry));
10949 } while (index != -ENOENT);
10953 * Function to show CGNAPT stats
10957 struct pipeline_be_ops pipeline_cgnapt_be_ops = {
10958 .f_init = pipeline_cgnapt_init,
10959 .f_free = pipeline_cgnapt_free,
10961 .f_timer = pipeline_cgnapt_timer,
10962 .f_track = pipeline_cgnapt_track,