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"
69 #include "pipeline_common_fe.h"
71 #include "rte_ct_tcp.h"
72 #include "rte_cnxn_tracking.h"
75 #include "lib_ftp_alg.h"
78 #include "cgnapt_pcp_be.h"
81 /* To maintain all cgnapt pipeline pointers used for all stats */
82 struct pipeline_cgnapt *all_pipeline_cgnapt[128];
83 uint8_t n_cgnapt_pipeline;
84 struct pipeline_cgnapt *global_pnat;
86 uint64_t arp_pkts_mask;
88 /* To know egress or ingress port */
89 static uint8_t cgnapt_in_port_egress_prv[PIPELINE_MAX_PORT_IN];
90 static uint8_t cgnapt_prv_que_port_index[PIPELINE_MAX_PORT_IN];
92 /* Max port per client declarations */
94 struct rte_hash_parameters max_port_per_client_hash_params = {
95 .name = "MAX_PORT_PER_CLIENT",
96 .entries = MAX_DYN_ENTRY,
97 .key_len = sizeof(struct max_port_per_client_key),
98 .hash_func = rte_jhash,
99 .hash_func_init_val = 0,
102 struct rte_ct_cnxn_tracker *cgnat_cnxn_tracker;
105 /***** Common Port Allocation declarations *****/
107 struct rte_ring *port_alloc_ring[MAX_CGNAPT_SETS] = { NULL, NULL, NULL, NULL,
108 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
109 NULL, NULL, NULL, NULL};
110 const char *napt_port_alloc_ring_name[MAX_CGNAPT_SETS] = {
111 "NAPT_PORT_ALLOC_0 ",
112 "NAPT_PORT_ALLOC_1 ",
113 "NAPT_PORT_ALLOC_2 ",
114 "NAPT_PORT_ALLOC_3 ",
115 "NAPT_PORT_ALLOC_4 ",
116 "NAPT_PORT_ALLOC_5 ",
117 "NAPT_PORT_ALLOC_6 ",
118 "NAPT_PORT_ALLOC_7 ",
119 "NAPT_PORT_ALLOC_8 ",
120 "NAPT_PORT_ALLOC_9 ",
121 "NAPT_PORT_ALLOC_10 ",
122 "NAPT_PORT_ALLOC_11 ",
123 "NAPT_PORT_ALLOC_12 ",
124 "NAPT_PORT_ALLOC_13 ",
125 "NAPT_PORT_ALLOC_14 ",
126 "NAPT_PORT_ALLOC_16 "
129 int vnf_set_count = -1;
131 struct app_params *myApp;
133 /***** Common Port Allocation declarations *****/
134 int napt_port_alloc_elem_count;
136 /***** Common Table declarations *****/
137 struct rte_hash_parameters napt_common_table_hash_params = {
138 .name = "NAPT_COM_TBL",
139 .entries = MAX_NAPT_ENTRIES,
140 .key_len = sizeof(struct pipeline_cgnapt_entry_key),
141 .hash_func = rte_jhash,
142 .hash_func_init_val = 0,
146 /***** ARP local cache *****/
148 uint8_t link_hw_laddr_valid[MAX_NUM_LOCAL_MAC_ADDRESS] = {
149 0, 0, 0, 0, 0, 0, 0, 0,
150 0, 0, 0, 0, 0, 0, 0, 0
153 struct ether_addr link_hw_laddr[MAX_NUM_LOCAL_MAC_ADDRESS] = {
154 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
155 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
156 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
157 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
158 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
159 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
160 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
161 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
162 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
163 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
164 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
165 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
166 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
167 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
168 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
169 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }
172 /****** NAT64 declarations *****/
174 uint8_t well_known_prefix[16] = {
175 0x00, 0x64, 0xff, 0x9b,
176 0x00, 0x00, 0x00, 0x00,
177 0x00, 0x00, 0x00, 0x00,
178 0x00, 0x00, 0x00, 0x00
181 static uint8_t check_arp_icmp(
182 struct rte_mbuf *pkt,
184 struct pipeline_cgnapt *p_nat);
186 /* Finds next power of two for n. If n itself
187 * is a power of two then returns n
190 * Value usually 32-bit value
193 * Value after roundup to power of 2
195 uint64_t nextPowerOf2(uint64_t n)
209 /* Commented code may be required for future usage, Please keep it*/
211 static int retrieve_cgnapt_entry_alg(
212 struct pipeline_cgnapt_entry_key *key,
213 struct cgnapt_table_entry **entry_ptr1,
214 struct cgnapt_table_entry **entry_ptr2)
216 #ifdef CGNAPT_DBG_PRNT
217 printf("retrieve_cgnapt_entry key detail Entry:"
218 "0x%x, %d, %d\n", key->ip, key->port,
222 int position = rte_hash_lookup(napt_common_table, key);
224 printf("Invalid cgnapt entry position(first_key): %d\n",
229 *entry_ptr1 = &napt_hash_tbl_entries[position];
231 uint32_t prv_ip = (*entry_ptr1)->data.prv_ip;
232 uint32_t prv_port = (*entry_ptr1)->data.prv_port;
233 uint32_t prv_phy_port = (*entry_ptr1)->data.prv_phy_port;
235 struct pipeline_cgnapt_entry_key second_key;
236 second_key.ip = prv_ip;
237 second_key.port = prv_port;
238 second_key.pid = prv_phy_port;
240 position = rte_hash_lookup(napt_common_table, &second_key);
242 printf("Invalid cgnapt entry position(second_key): %d\n",
247 *entry_ptr2 = &napt_hash_tbl_entries[position];
253 int add_dynamic_cgnapt_entry_alg(
255 struct pipeline_cgnapt_entry_key *key,
256 struct cgnapt_table_entry **entry_ptr1,
257 struct cgnapt_table_entry **entry_ptr2)
259 int port_num = 0, ret;
261 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
263 #ifdef CGNAPT_DBG_PRNT
264 if (CGNAPT_DEBUG >= 1) {
265 printf("Th%d add_dynamic_cgnapt_entry key detail Entry:"
266 "0x%x, %d, %d\n", p_nat->pipeline_num, key->ip, key->port,
271 int32_t position = rte_hash_lookup(napt_common_table, key);
273 #ifdef CGNAPT_DBG_PRNT
274 if (CGNAPT_DEBUG >= 1) {
275 printf("%s: cgnapt entry exists in "
276 "position(first_key): %d\n", __func__, position);
279 *entry_ptr1 = &napt_hash_tbl_entries[position];
280 /* not required, as it is not used in the caller */
286 ret = increment_max_port_counter(key->ip, key->pid, p_nat);
287 if (ret == MAX_PORT_INC_ERROR) {
289 #ifdef CGNAPT_DBG_PRNT
290 if (CGNAPT_DEBUG > 1)
291 printf("add_dynamic_cgnapt_entry:"
292 "increment_max_port_counter-1 failed\n");
298 if (ret == MAX_PORT_INC_REACHED) {
300 #ifdef CGNAPT_DBG_PRNT
301 if (CGNAPT_DEBUG > 1)
302 printf("add_dynamic_cgnapt_entry:"
303 "increment_max_port_counter-2 failed\n");
310 port_num = get_free_iport(p_nat, &public_ip);
312 if (port_num == -1) {
314 #ifdef CGNAPT_DBG_PRNT
315 if (CGNAPT_DEBUG > 2) {
316 printf("add_dynamic_cgnapt_entry: %d\n", port_num);
317 printf("add_dynamic_cgnapt_entry key detail:0x%x, "
318 "%d, %d\n", key->ip, key->port, key->pid);
325 /* check for max_clients_per_ip */
326 if (rte_atomic16_read
328 [rte_jhash(&public_ip, 4, 0) % 16].count) ==
329 p_nat->max_clients_per_ip) {
330 /* For now just bail out
331 * In future we can think about
332 * retrying getting a new iport
334 release_iport(port_num, public_ip, p_nat);
339 rte_atomic16_inc(&all_public_ip
340 [rte_jhash(&public_ip, 4, 0) %
343 #ifdef CGNAPT_DBG_PRNT
344 if ((rte_jhash(&public_ip, 4, 0) % 16) == 8)
345 printf("pub ip:%x coutn:%d\n", public_ip,
346 rte_atomic16_read(&all_public_ip
347 [rte_jhash(&public_ip, 4, 0) % 16].count));
350 #ifdef CGNAPT_DBG_PRNT
351 if (CGNAPT_DEBUG > 0) {
352 printf("add_dynamic_cgnapt_entry: %d\n",
354 printf("add_dynamic_cgnapt_entry key detail: "
355 "0x%x, %d, %d\n", key->ip, key->port, key->pid);
359 struct cgnapt_table_entry entry = {
361 .action = RTE_PIPELINE_ACTION_PORT,
362 /* made it configurable below */
363 {.port_id = p->port_out_id[0]},
367 .prv_port = key->port,
369 .pub_port = port_num,
370 .prv_phy_port = key->pid,
371 .pub_phy_port = get_pub_to_prv_port(
375 /* if(timeout == -1) : static entry
376 * if(timeout == 0 ) : dynamic entry
377 * if(timeout > 0 ) : PCP requested entry
386 entry.data.u.prv_ip = key->ip;
387 entry.data.type = CGNAPT_ENTRY_IPV4;
389 entry.head.port_id = entry.data.pub_phy_port; /* outgoing port info */
391 struct pipeline_cgnapt_entry_key second_key;
392 /* Need to add a second ingress entry */
393 second_key.ip = public_ip;
394 second_key.port = port_num;
395 second_key.pid = 0xffff;
397 #ifdef CGNAPT_DBG_PRNT
398 if (CGNAPT_DEBUG > 2)
399 printf("add_dynamic_cgnapt_entry second key detail:"
400 "0x%x, %d, %d\n", second_key.ip, second_key.port,
404 int32_t position1 = rte_hash_add_key(napt_common_table, (void *)key);
407 printf("CG-NAPT entry add failed ...returning "
408 "without adding ... %d\n", position1);
413 #ifdef CGNAPT_DBG_PRNT
415 printf("add_dynamic_cgnapt_entry:");
417 print_cgnapt_entry(&entry);
421 memcpy(&napt_hash_tbl_entries[position1], &entry,
422 sizeof(struct cgnapt_table_entry));
424 /* this pointer is returned to pkt miss function */
425 *entry_ptr1 = &napt_hash_tbl_entries[position1];
427 p_nat->n_cgnapt_entry_added++;
428 p_nat->dynCgnaptCount++;
430 /* Now modify the forward port for reverse entry */
432 /* outgoing port info */
433 entry.head.port_id = entry.data.prv_phy_port;
435 int32_t position2 = rte_hash_add_key(napt_common_table, &second_key);
438 printf("CG-NAPT entry reverse bulk add failed ..."
439 "returning with fwd add ...%d\n",
444 memcpy(&napt_hash_tbl_entries[position2], &entry,
445 sizeof(struct cgnapt_table_entry));
447 *entry_ptr2 = &napt_hash_tbl_entries[position2];
449 #ifdef CGNAPT_DBG_PRNT
450 if (CGNAPT_DEBUG >= 1) {
451 printf("add_dynamic_cgnapt_entry position: %d, %d\n",
452 position1, position2);
453 printf("add_dynamic_cgnapt_entry: entry_ptr1: %p, "
454 "entry_ptr2: %p\n", *entry_ptr1, *entry_ptr2);
458 timer_thread_enqueue(key, &second_key, *entry_ptr1,
459 *entry_ptr2, (struct pipeline *)p_nat);
461 p_nat->n_cgnapt_entry_added++;
462 p_nat->dynCgnaptCount++;
469 void hw_checksum(struct rte_mbuf *pkt, enum PKT_TYPE ver)
471 struct tcp_hdr *tcp = NULL;
472 struct udp_hdr *udp = NULL;
473 struct icmp_hdr *icmp = NULL;
475 void *ip_header = NULL;
476 uint16_t prot_offset = 0;
477 uint32_t pkt_type_is_ipv4 = 1;
479 pkt->ol_flags |= PKT_TX_IP_CKSUM;
480 pkt->l2_len = ETH_HDR_SIZE;
485 case PKT_TYPE_IPV4to6:
489 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
490 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
492 pkt_type_is_ipv4 = 0;
493 pkt->ol_flags |= PKT_TX_IPV6;
495 sizeof(struct ipv6_hdr);
496 tcp = (struct tcp_hdr *)
497 ((unsigned char *)ip_header +
498 sizeof(struct ipv6_hdr));
499 udp = (struct udp_hdr *)
500 ((unsigned char *)ip_header +
501 sizeof(struct ipv6_hdr));
502 icmp = (struct icmp_hdr *)
503 ((unsigned char *)ip_header +
504 sizeof(struct ipv6_hdr));
506 prot_offset = PROT_OFST_IP6 + temp;
508 case PKT_TYPE_IPV6to4:
512 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
513 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
515 pkt->ol_flags |= PKT_TX_IPV4;
517 sizeof(struct ipv4_hdr);
518 tcp = (struct tcp_hdr *)
519 ((unsigned char *)ip_header +
520 sizeof(struct ipv4_hdr));
521 udp = (struct udp_hdr *)
522 ((unsigned char *)ip_header +
523 sizeof(struct ipv4_hdr));
524 icmp = (struct icmp_hdr *)
525 ((unsigned char *)ip_header +
526 sizeof(struct ipv4_hdr));
527 struct ipv4_hdr *ip_hdr =
528 (struct ipv4_hdr *)ip_header;
529 ip_hdr->hdr_checksum = 0;
531 prot_offset = PROT_OFST_IP4 + temp;
534 printf("hw_checksum: pkt version is invalid\n");
536 protocol = (uint8_t *) RTE_MBUF_METADATA_UINT8_PTR(pkt,
540 case IP_PROTOCOL_TCP: /* 6 */
542 pkt->ol_flags |= PKT_TX_TCP_CKSUM;
543 if (pkt_type_is_ipv4) {
544 tcp->cksum = rte_ipv4_phdr_cksum(
545 (struct ipv4_hdr *)ip_header,
548 tcp->cksum = rte_ipv6_phdr_cksum(
549 (struct ipv6_hdr *)ip_header,
553 case IP_PROTOCOL_UDP: /* 17 */
554 udp->dgram_cksum = 0;
555 pkt->ol_flags |= PKT_TX_UDP_CKSUM;
556 if (pkt_type_is_ipv4) {
559 (struct ipv4_hdr *)ip_header,
564 (struct ipv6_hdr *)ip_header,
568 case IP_PROTOCOL_ICMP: /* 1 */
569 if (pkt_type_is_ipv4) {
570 /* ICMP checksum code */
571 struct ipv4_hdr *ip_hdr =
572 (struct ipv4_hdr *)ip_header;
573 int size = rte_bswap16(ip_hdr->total_length) - 20;
574 icmp->icmp_cksum = 0;
582 #ifdef CGNAPT_DEBUGGING
583 printf("hw_checksum() : Neither TCP or UDP pkt\n");
590 void sw_checksum(struct rte_mbuf *pkt, enum PKT_TYPE ver)
592 struct tcp_hdr *tcp = NULL;
593 struct udp_hdr *udp = NULL;
594 struct icmp_hdr *icmp = NULL;
596 void *ip_header = NULL;
597 uint16_t prot_offset = 0;
598 uint32_t pkt_type_is_ipv4 = 1;
602 case PKT_TYPE_IPV4to6:
606 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
607 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
609 pkt_type_is_ipv4 = 0;
610 tcp = (struct tcp_hdr *)
611 ((unsigned char *)ip_header +
612 sizeof(struct ipv6_hdr));
613 udp = (struct udp_hdr *)
614 ((unsigned char *)ip_header +
615 sizeof(struct ipv6_hdr));
616 icmp = (struct icmp_hdr *)
617 ((unsigned char *)ip_header +
618 sizeof(struct ipv6_hdr));
620 prot_offset = PROT_OFST_IP6 + temp;
622 case PKT_TYPE_IPV6to4:
626 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
627 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
629 tcp = (struct tcp_hdr *)
630 ((unsigned char *)ip_header +
631 sizeof(struct ipv4_hdr));
632 udp = (struct udp_hdr *)
633 ((unsigned char *)ip_header +
634 sizeof(struct ipv4_hdr));
635 icmp = (struct icmp_hdr *)
636 ((unsigned char *)ip_header +
637 sizeof(struct ipv4_hdr));
639 prot_offset = PROT_OFST_IP4 + temp;
642 printf("sw_checksum: pkt version is invalid\n");
644 protocol = (uint8_t *) RTE_MBUF_METADATA_UINT8_PTR(pkt,
648 case IP_PROTOCOL_TCP: /* 6 */
650 if (pkt_type_is_ipv4) {
651 struct ipv4_hdr *ip_hdr =
652 (struct ipv4_hdr *)ip_header;
653 tcp->cksum = rte_ipv4_udptcp_cksum(ip_hdr,
655 ip_hdr->hdr_checksum = 0;
656 ip_hdr->hdr_checksum = rte_ipv4_cksum(
657 (struct ipv4_hdr *)ip_hdr);
659 tcp->cksum = rte_ipv6_udptcp_cksum(
661 ip_header, (void *)tcp);
664 case IP_PROTOCOL_UDP: /* 17 */
665 udp->dgram_cksum = 0;
666 if (pkt_type_is_ipv4) {
667 struct ipv4_hdr *ip_hdr =
668 (struct ipv4_hdr *)ip_header;
669 udp->dgram_cksum = rte_ipv4_udptcp_cksum(
670 ip_hdr, (void *)udp);
671 ip_hdr->hdr_checksum = 0;
672 ip_hdr->hdr_checksum = rte_ipv4_cksum(ip_hdr);
674 udp->dgram_cksum = rte_ipv6_udptcp_cksum(
676 ip_header, (void *)udp);
679 case IP_PROTOCOL_ICMP: /* 1 */
680 if (pkt_type_is_ipv4) {
681 /* ICMP checksum code */
682 struct ipv4_hdr *ip_hdr =
683 (struct ipv4_hdr *)ip_header;
684 int size = rte_bswap16(ip_hdr->total_length) - 20;
685 icmp->icmp_cksum = 0;
689 ip_hdr->hdr_checksum = 0;
690 ip_hdr->hdr_checksum = rte_ipv4_cksum(ip_hdr);
695 #ifdef CGNAPT_DEBUGGING
696 printf("sw_checksum() : Neither TCP or UDP pkt\n");
702 void print_pkt_info(uint8_t *eth_dest, struct ether_addr *hw_addr,
703 uint32_t dest_address, uint32_t port_id, struct rte_mbuf *pkt)
706 if (CGNAPT_DEBUG > 2) {
707 printf("MAC Found ip 0x%x, port %d - %02x:%02x:%02x:%02x:%02x:%02x \n",
708 dest_address, port_id, hw_addr->addr_bytes[0], hw_addr->addr_bytes[1],
709 hw_addr->addr_bytes[2], hw_addr->addr_bytes[3], hw_addr->addr_bytes[4],
710 hw_addr->addr_bytes[5]);
712 printf("Dest MAC before - %02x:%02x:%02x:%02x:%02x:%02x \n",
713 eth_dest[0], eth_dest[1], eth_dest[2], eth_dest[3], eth_dest[4],
717 if (CGNAPT_DEBUG > 2) {
718 printf("Dest MAC after - "
719 "%02x:%02x:%02x:%02x:%02x:%02x \n",
720 eth_dest[0], eth_dest[1],
721 eth_dest[2], eth_dest[3],
722 eth_dest[4], eth_dest[5]);
725 if (CGNAPT_DEBUG > 4)
729 static uint8_t check_arp_icmp(
730 struct rte_mbuf *pkt,
732 struct pipeline_cgnapt *p_nat)
734 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
735 uint16_t *eth_proto = RTE_MBUF_METADATA_UINT16_PTR(
736 pkt, eth_proto_offset);
737 struct app_link_params *link;
738 uint8_t solicited_node_multicast_addr[16] = {
739 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
740 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00};
742 /* ARP outport number */
743 uint16_t out_port = p_nat->p.n_ports_out - 1;
745 uint32_t prot_offset;
747 link = &myApp->link_params[pkt->port];
750 switch (rte_be_to_cpu_16(*eth_proto)) {
754 rte_pipeline_port_out_packet_insert(
760 * Pkt mask should be changed, and not changing the
763 p_nat->invalid_packets |= pkt_mask;
764 p_nat->arpicmpPktCount++;
768 case ETH_TYPE_IPV4: {
769 /* header room + eth hdr size +
770 * src_aadr offset in ip header
772 uint32_t dst_addr_offset = MBUF_HDR_ROOM +
773 ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
775 RTE_MBUF_METADATA_UINT32_PTR(pkt,
777 prot_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
778 IP_HDR_PROTOCOL_OFST;
779 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt,
781 if ((*protocol == IP_PROTOCOL_ICMP) &&
782 link->ip == rte_be_to_cpu_32(*dst_addr)) {
784 if (is_phy_port_privte(pkt->port)) {
786 rte_pipeline_port_out_packet_insert(
787 p_nat->p.p, out_port, pkt);
790 * Pkt mask should be changed,
791 * and not changing the drop mask
794 p_nat->invalid_packets |= pkt_mask;
795 p_nat->arpicmpPktCount++;
806 if (dual_stack_enable) {
808 /* Commented code may be required for future usage,
811 //uint32_t dst_addr_offset = MBUF_HDR_ROOM +
812 // ETH_HDR_SIZE + IPV6_HDR_DST_ADR_OFST;
813 //uint32_t *dst_addr =
814 // RTE_MBUF_METADATA_UINT32_PTR(pkt,
816 uint32_t prot_offset_ipv6 = MBUF_HDR_ROOM +
817 ETH_HDR_SIZE + IPV6_HDR_PROTOCOL_OFST;
818 struct ipv6_hdr *ipv6_h;
820 ipv6_h = (struct ipv6_hdr *) MBUF_HDR_ROOM +
822 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt,
825 if (ipv6_h->proto == ICMPV6_PROTOCOL_ID) {
826 if (!memcmp(ipv6_h->dst_addr, link->ipv6, 16)
827 || !memcmp(ipv6_h->dst_addr,
828 solicited_node_multicast_addr, 13)) {
829 rte_pipeline_port_out_packet_insert(
830 p_nat->p.p, out_port, pkt);
832 * Pkt mask should be changed,
833 * and not changing the drop mask
835 p_nat->invalid_packets |= pkt_mask;
836 p_nat->arpicmpPktCount++;
838 p_nat->invalid_packets |= pkt_mask;
839 p_nat->naptDroppedPktCount++;
841 #ifdef CGNAPT_DEBUGGING
842 p_nat->naptDroppedPktCount1++;
857 * Function to create common NAPT table
858 * Called during pipeline initialization
859 * Creates the common NAPT table
860 * If it is not already created and stores its pointer
861 * in global napt_common_table pointer.
864 * Max number of NAPT flows. This parameter is configurable via config file.
867 * 0 on success, negative on error.
869 int create_napt_common_table(uint32_t nFlows)
871 if (napt_common_table != NULL) {
872 printf("napt_common_table already exists.\n");
876 napt_common_table = rte_hash_create(&napt_common_table_hash_params);
878 if (napt_common_table == NULL) {
879 printf("napt_common_table creation failed.\n");
883 uint32_t number_of_entries = nFlows;
886 RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_table_entry) *
888 napt_hash_tbl_entries = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
890 if (napt_hash_tbl_entries == NULL) {
891 printf("napt_hash_tbl_entries creation failed. %d, %d\n",
892 nFlows, (int)sizeof(struct cgnapt_table_entry));
900 * Function to initialize bulk port allocation data structures
901 * Called during pipeline initialization.
903 * Creates the port alloc ring for the VNF_set this pipeline belongs
905 * Creates global port allocation buffer pool
907 * Initializes the port alloc ring according to config data
910 * A pointer to struct pipeline_cgnapt
913 * 0 on success, negative on error.
915 int napt_port_alloc_init(struct pipeline_cgnapt *p_nat)
917 p_nat->allocated_ports = NULL;
918 p_nat->free_ports = NULL;
920 uint32_t vnf_set_num = p_nat->vnf_set;
921 /*uint32_t vnf_set_num = get_vnf_set_num(p_nat->pipeline_num); */
923 #ifdef CGNAPT_DBG_PRNT
924 printf("VNF set number for CGNAPT %d is %d.\n", p_nat->pipeline_num,
927 if (vnf_set_num == 0xFF) {
928 printf("VNF set number for CGNAPT %d is invalid %d.\n",
929 p_nat->pipeline_num, vnf_set_num);
933 p_nat->port_alloc_ring = port_alloc_ring[vnf_set_num];
934 if (p_nat->port_alloc_ring != NULL) {
935 printf("CGNAPT%d port_alloc_ring already exists.\n",
936 p_nat->pipeline_num);
940 printf("napt_port_alloc_elem_count :%d\n",
941 napt_port_alloc_elem_count);
942 napt_port_alloc_elem_count += 1;
943 napt_port_alloc_elem_count =
944 nextPowerOf2(napt_port_alloc_elem_count);
945 printf("Next power of napt_port_alloc_elem_count: %d\n",
946 napt_port_alloc_elem_count);
948 port_alloc_ring[vnf_set_num] =
949 rte_ring_create(napt_port_alloc_ring_name[vnf_set_num],
950 napt_port_alloc_elem_count, rte_socket_id(), 0);
951 p_nat->port_alloc_ring = port_alloc_ring[vnf_set_num];
952 if (p_nat->port_alloc_ring == NULL) {
953 printf("CGNAPT%d - Failed to create port_alloc_ring\n",
954 p_nat->pipeline_num);
958 /* Create port alloc buffer */
959 /* Only one pool is enough for all vnf sets */
960 if (napt_port_pool == NULL) {
962 napt_port_pool = rte_mempool_create(
964 napt_port_alloc_elem_count,
965 sizeof(struct napt_port_alloc_elem),
966 0, 0, NULL, NULL, NULL,
967 NULL, rte_socket_id(), 0);
970 if (napt_port_pool == NULL) {
971 printf("CGNAPT - Create port pool failed\n");
975 /* Add all available public IP addresses and ports to the ring */
978 #ifdef NAT_ONLY_CONFIG_REQ
979 if (nat_only_config_flag) {
980 printf("******* pub_ip_range_count:%d ***********\n",
981 p_nat->pub_ip_range_count);
982 /* Initialize all public IP's addresses */
984 uint32_t max_ips_remain;
986 for (if_addrs = 0; if_addrs < p_nat->pub_ip_range_count;
988 /* Add all available addresses to the ring */
990 for (i = p_nat->pub_ip_range[if_addrs].start_ip;
991 i <= p_nat->pub_ip_range[if_addrs].end_ip;) {
992 /* 1. Get a port alloc buffer from napt_port_pool */
996 /* get new napt_port_alloc_elem from pool */
997 if (rte_mempool_get(napt_port_pool,
999 printf("CGNAPT - Error in getting port "
1005 /* 2. Populate it with available ports and ip addr */
1006 struct napt_port_alloc_elem *pb =
1007 (struct napt_port_alloc_elem *)portsBuf;
1010 temp = p_nat->pub_ip_range[if_addrs].end_ip -
1013 /* Check if remaining port count is greater
1014 * than or equals to bulk count, if not give
1015 * remaining count ports than giving bulk count
1017 if (temp < NUM_NAPT_PORT_BULK_ALLOC)
1018 max_ips_remain = temp;
1021 NUM_NAPT_PORT_BULK_ALLOC;
1023 for (j = 0; j < max_ips_remain; j++) {
1025 pb->ip_addr[j] = i + j;
1028 p_nat->pub_ip_range[if_addrs].
1033 /* 3. add the port alloc buffer to ring */
1034 if (rte_ring_enqueue(p_nat->port_alloc_ring,
1036 printf("CGNAPT%d - Enqueue error - i %d,",
1037 p_nat->pipeline_num, i);
1038 printf("j %d, if_addrs %d, pb %p\n",
1040 rte_ring_dump(stdout,
1041 p_nat->port_alloc_ring);
1042 rte_mempool_put(napt_port_pool,
1047 /* reset j and advance i */
1049 i += max_ips_remain;
1057 printf("******* p_nat->pub_ip_count:%d ***********\n",
1058 p_nat->pub_ip_count);
1059 /* Initialize all public IP's ports */
1061 uint32_t max_ports_remain;
1063 for (if_ports = 0; if_ports < p_nat->pub_ip_count; if_ports++) {
1064 /* Add all available ports to the ring */
1066 for (i = p_nat->pub_ip_port_set[if_ports].start_port;
1067 i <= p_nat->pub_ip_port_set[if_ports].end_port;) {
1068 /* 1. Get a port alloc buffer from napt_port_pool */
1072 /* get new napt_port_alloc_elem from pool */
1073 if (rte_mempool_get(napt_port_pool, &portsBuf) <
1075 printf("CGNAPT - Error in getting "
1076 "port alloc buffer\n");
1081 /* 2. Populate it with available ports and ip addr */
1082 struct napt_port_alloc_elem *pb =
1083 (struct napt_port_alloc_elem *)portsBuf;
1086 temp = p_nat->pub_ip_port_set[if_ports].end_port -
1088 /* Check if remaining port count is greater
1089 * than or equals to bulk count, if not give
1090 * remaining count ports than giving bulk count
1092 if (temp < NUM_NAPT_PORT_BULK_ALLOC)
1093 max_ports_remain = temp;
1096 NUM_NAPT_PORT_BULK_ALLOC;
1098 for (j = 0; j < max_ports_remain; j++) {
1101 p_nat->pub_ip_port_set[if_ports].ip;
1102 pb->ports[j] = i + j;
1103 if ((i + j) == p_nat->pub_ip_port_set
1104 [if_ports].end_port)
1108 /* 3. add the port alloc buffer to ring */
1109 if (rte_ring_enqueue(p_nat->port_alloc_ring,
1111 printf("CGNAPT%d - Enqueue error - i %d, j %d, "
1112 " if_ports %d, pb %p\n", p_nat->pipeline_num,
1113 i, j, if_ports, pb);
1115 rte_ring_dump(stdout, p_nat->port_alloc_ring);
1116 rte_mempool_put(napt_port_pool, portsBuf);
1120 /* reset j and advance i */
1122 i += max_ports_remain;
1129 static pipeline_msg_req_handler handlers[] = {
1130 [PIPELINE_MSG_REQ_PING] =
1131 pipeline_msg_req_ping_handler,
1132 [PIPELINE_MSG_REQ_STATS_PORT_IN] =
1133 pipeline_msg_req_stats_port_in_handler,
1134 [PIPELINE_MSG_REQ_STATS_PORT_OUT] =
1135 pipeline_msg_req_stats_port_out_handler,
1136 [PIPELINE_MSG_REQ_STATS_TABLE] = pipeline_msg_req_stats_table_handler,
1137 [PIPELINE_MSG_REQ_PORT_IN_ENABLE] =
1138 pipeline_msg_req_port_in_enable_handler,
1139 [PIPELINE_MSG_REQ_PORT_IN_DISABLE] =
1140 pipeline_msg_req_port_in_disable_handler,
1141 [PIPELINE_MSG_REQ_CUSTOM] =
1142 pipeline_cgnapt_msg_req_custom_handler,
1145 static pipeline_msg_req_handler custom_handlers[] = {
1146 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_ADD] =
1147 pipeline_cgnapt_msg_req_entry_add_handler,
1148 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_DEL] =
1149 pipeline_cgnapt_msg_req_entry_del_handler,
1150 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_SYNC] =
1151 pipeline_cgnapt_msg_req_entry_sync_handler,
1152 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_DBG] =
1153 pipeline_cgnapt_msg_req_entry_dbg_handler,
1154 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_ADDM] =
1155 pipeline_cgnapt_msg_req_entry_addm_handler,
1156 [PIPELINE_CGNAPT_MSG_REQ_VER] =
1157 pipeline_cgnapt_msg_req_ver_handler,
1158 [PIPELINE_CGNAPT_MSG_REQ_NSP_ADD] =
1159 pipeline_cgnapt_msg_req_nsp_add_handler,
1160 [PIPELINE_CGNAPT_MSG_REQ_NSP_DEL] =
1161 pipeline_cgnapt_msg_req_nsp_del_handler,
1164 [PIPELINE_CGNAPT_MSG_REQ_PCP] =
1165 pipeline_cgnapt_msg_req_pcp_handler,
1170 * Function to convert an IPv6 packet to IPv4 packet
1173 * A pointer to packet mbuf
1174 * @param in_ipv6_hdr
1175 * A pointer to IPv6 header in the given pkt
1179 convert_ipv6_to_ipv4(struct rte_mbuf *pkt, struct ipv6_hdr *in_ipv6_hdr)
1181 uint32_t ip_hdr_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE;
1183 uint8_t *eth_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1184 uint8_t *ipv6_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, ip_hdr_offset);
1186 struct ether_hdr eth_hdr;
1187 struct ipv4_hdr *ipv4_hdr_p;
1188 uint16_t frag_off = 0x4000;
1189 struct cgnapt_nsp_node *ll = nsp_ll;
1190 uint8_t ipv4_dest[4];
1193 memcpy(ð_hdr, eth_hdr_p, sizeof(struct ether_hdr));
1194 memcpy(in_ipv6_hdr, ipv6_hdr_p, sizeof(struct ipv6_hdr));
1196 eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
1198 char *data_area_p = rte_pktmbuf_adj(pkt, 20);
1199 if (data_area_p == NULL) {
1200 printf("convert_ipv6_to_ipv4:data_area_p is NULL\n");
1203 ipv4_hdr_p = (struct ipv4_hdr *)(data_area_p + ETH_HDR_SIZE);
1204 memset(ipv4_hdr_p, 0, sizeof(struct ipv4_hdr));
1206 memcpy(data_area_p, ð_hdr, sizeof(struct ether_hdr));
1208 #ifdef CGNAPT_DBG_PRNT
1209 if (CGNAPT_DEBUG == 1)
1210 printf("convert_ipv6_to_ipv4: eth_hdr_p(%p), data_area_p(%p), "
1211 "ipv4_hdr_p(%p)\n", eth_hdr_p, data_area_p, ipv4_hdr_p);
1214 ipv4_hdr_p->version_ihl = 0x4 << 4 | 0x5;
1215 ipv4_hdr_p->type_of_service =
1216 rte_be_to_cpu_32(in_ipv6_hdr->vtc_flow) & 0x0ff00000 >> 20;
1217 ipv4_hdr_p->total_length =
1218 rte_cpu_to_be_16(rte_be_to_cpu_16(
1219 in_ipv6_hdr->payload_len) + 20);
1220 ipv4_hdr_p->packet_id = 0;
1221 ipv4_hdr_p->fragment_offset = rte_cpu_to_be_16(frag_off);
1222 ipv4_hdr_p->time_to_live = in_ipv6_hdr->hop_limits;
1223 ipv4_hdr_p->next_proto_id = in_ipv6_hdr->proto;
1224 ipv4_hdr_p->hdr_checksum = 0;
1225 ipv4_hdr_p->src_addr = 0;
1227 while (ll != NULL) {
1229 (&in_ipv6_hdr->dst_addr[0], &ll->nsp.prefix[0],
1230 ll->nsp.depth / 8)) {
1231 if (ll->nsp.depth == 32)
1232 memcpy(&ipv4_dest[0], &in_ipv6_hdr->dst_addr[4],
1234 else if (ll->nsp.depth == 40) {
1235 ipv4_dest[0] = in_ipv6_hdr->dst_addr[5];
1236 ipv4_dest[1] = in_ipv6_hdr->dst_addr[6];
1237 ipv4_dest[2] = in_ipv6_hdr->dst_addr[7];
1238 ipv4_dest[3] = in_ipv6_hdr->dst_addr[9];
1239 } else if (ll->nsp.depth == 48) {
1240 ipv4_dest[0] = in_ipv6_hdr->dst_addr[6];
1241 ipv4_dest[1] = in_ipv6_hdr->dst_addr[7];
1242 ipv4_dest[2] = in_ipv6_hdr->dst_addr[9];
1243 ipv4_dest[3] = in_ipv6_hdr->dst_addr[10];
1244 } else if (ll->nsp.depth == 56) {
1245 ipv4_dest[0] = in_ipv6_hdr->dst_addr[7];
1246 ipv4_dest[1] = in_ipv6_hdr->dst_addr[9];
1247 ipv4_dest[2] = in_ipv6_hdr->dst_addr[10];
1248 ipv4_dest[3] = in_ipv6_hdr->dst_addr[11];
1249 } else if (ll->nsp.depth == 64) {
1250 ipv4_dest[0] = in_ipv6_hdr->dst_addr[9];
1251 ipv4_dest[1] = in_ipv6_hdr->dst_addr[10];
1252 ipv4_dest[2] = in_ipv6_hdr->dst_addr[11];
1253 ipv4_dest[3] = in_ipv6_hdr->dst_addr[12];
1254 } else if (ll->nsp.depth == 96) {
1255 ipv4_dest[0] = in_ipv6_hdr->dst_addr[12];
1256 ipv4_dest[1] = in_ipv6_hdr->dst_addr[13];
1257 ipv4_dest[2] = in_ipv6_hdr->dst_addr[14];
1258 ipv4_dest[3] = in_ipv6_hdr->dst_addr[15];
1269 memcpy(&ipv4_hdr_p->dst_addr, &ipv4_dest[0], 4);
1271 memcpy(&ipv4_hdr_p->dst_addr, &in_ipv6_hdr->dst_addr[12], 4);
1276 * Function to convert an IPv4 packet to IPv6 packet
1279 * A pointer to packet mbuf
1280 * @param in_ipv4_hdr
1281 * A pointer to IPv4 header in the given pkt
1285 convert_ipv4_to_ipv6(struct rte_mbuf *pkt, struct ipv4_hdr *in_ipv4_hdr)
1287 uint32_t ip_hdr_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE;
1289 uint8_t *eth_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1290 uint8_t *ipv4_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, ip_hdr_offset);
1292 struct ether_hdr eth_hdr;
1293 struct ipv6_hdr *ipv6_hdr_p;
1295 memcpy(ð_hdr, eth_hdr_p, sizeof(struct ether_hdr));
1296 memcpy(in_ipv4_hdr, ipv4_hdr_p, sizeof(struct ipv4_hdr));
1298 eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
1300 char *data_area_p = rte_pktmbuf_prepend(pkt, 20);
1301 if (data_area_p == NULL) {
1302 printf("convert_ipv4_to_ipv6:data_area_p is NULL\n");
1305 ipv6_hdr_p = (struct ipv6_hdr *)(data_area_p + ETH_HDR_SIZE);
1306 memset(ipv6_hdr_p, 0, sizeof(struct ipv6_hdr));
1308 memcpy(data_area_p, ð_hdr, sizeof(struct ether_hdr));
1310 ipv6_hdr_p->vtc_flow =
1311 rte_cpu_to_be_32((0x6 << 28) |
1312 (in_ipv4_hdr->type_of_service << 20));
1313 ipv6_hdr_p->payload_len =
1314 rte_cpu_to_be_16(rte_be_to_cpu_16(
1315 in_ipv4_hdr->total_length) - 20);
1316 ipv6_hdr_p->proto = in_ipv4_hdr->next_proto_id;
1317 ipv6_hdr_p->hop_limits = in_ipv4_hdr->time_to_live;
1319 ipv6_hdr_p->src_addr[0] = 0x00;
1320 ipv6_hdr_p->src_addr[1] = 0x64;
1321 ipv6_hdr_p->src_addr[2] = 0xff;
1322 ipv6_hdr_p->src_addr[3] = 0x9b;
1323 ipv6_hdr_p->src_addr[4] = 0x00;
1324 ipv6_hdr_p->src_addr[5] = 0x00;
1325 ipv6_hdr_p->src_addr[6] = 0x00;
1326 ipv6_hdr_p->src_addr[7] = 0x00;
1327 ipv6_hdr_p->src_addr[8] = 0x00;
1328 ipv6_hdr_p->src_addr[9] = 0x00;
1329 ipv6_hdr_p->src_addr[10] = 0x00;
1330 ipv6_hdr_p->src_addr[11] = 0x00;
1331 memcpy(&ipv6_hdr_p->src_addr[12], &in_ipv4_hdr->src_addr, 4);
1333 memset(&ipv6_hdr_p->dst_addr, 0, 16);
1340 * Output port handler
1343 * A pointer to packet mbuf
1345 * Unused void pointer
1348 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1350 pkt_work_cgnapt_out(__rte_unused struct rte_mbuf *pkt, __rte_unused void *arg)
1352 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1353 if ((cgnapt_num_func_to_inst == 5)
1354 && (cgnapt_inst_index < INST_ARRAY_SIZE)) {
1355 if (cgnapt_inst5_flag == 0) {
1356 uint8_t *inst5_sig =
1357 RTE_MBUF_METADATA_UINT8_PTR(pkt,
1359 if (*inst5_sig == CGNAPT_INST5_SIG) {
1360 cgnapt_inst5_flag = 1;
1361 inst_end_time[cgnapt_inst_index] =
1362 rte_get_tsc_cycles();
1363 cgnapt_inst_index++;
1369 /* cgnapt_pkt_out_count++; */
1370 #ifdef CGNAPT_DBG_PRNT
1378 * Output port handler to handle 4 pkts
1381 * A pointer to packet mbuf
1383 * Inport handler argument pointer
1386 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1387 static void pkt4_work_cgnapt_out(struct rte_mbuf **pkt, void *arg)
1391 /* TO BE IMPLEMENTED IF REQUIRED */
1395 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1396 PIPELINE_CGNAPT_PORT_OUT_AH(port_out_ah_cgnapt,
1397 pkt_work_cgnapt_out, pkt4_work_cgnapt_out);
1399 PIPELINE_CGNAPT_PORT_OUT_BAH(port_out_ah_cgnapt_bulk,
1400 pkt_work_cgnapt_out, pkt4_work_cgnapt_out);
1404 * Function to validate the packet and return version
1407 * A pointer to packet mbuf
1410 * IP version of the valid pkt, -1 if invalid pkt
1412 int rte_get_pkt_ver(struct rte_mbuf *pkt)
1414 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
1415 uint16_t *eth_proto =
1416 RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
1418 if (*eth_proto == rte_be_to_cpu_16(ETHER_TYPE_IPv4))
1419 return IP_VERSION_4;
1421 if (dual_stack_enable
1422 && (*eth_proto == rte_be_to_cpu_16(ETHER_TYPE_IPv6)))
1423 return IP_VERSION_6;
1425 /* Check the protocol first, if not UDP or TCP return */
1431 * A method to print the NAPT entry
1434 * A pointer to struct cgnapt_table_entry
1436 void my_print_entry(struct cgnapt_table_entry *ent)
1438 printf("CGNAPT key:\n");
1439 printf("entry_type :%d\n", ent->data.type);
1440 printf("prv_ip: %x %x %x %x\n", ent->data.u.u32_prv_ipv6[0],
1441 ent->data.u.u32_prv_ipv6[1], ent->data.u.u32_prv_ipv6[2],
1442 ent->data.u.u32_prv_ipv6[3]);
1443 printf("prv_port:%d\n", ent->data.prv_port);
1445 printf("pub_ip:%x\n", ent->data.pub_ip);
1446 printf("prv_phy_port:%d\n", ent->data.prv_phy_port);
1447 printf("pub_phy_port:%d\n", ent->data.pub_phy_port);
1451 * Function to print common CGNAPT table entries
1454 void print_common_table(void)
1462 index = rte_hash_iterate(napt_common_table,
1463 &key, &data, &next);
1465 if ((index != -EINVAL) && (index != -ENOENT)) {
1466 printf("\n%04d ", count);
1467 //print_key((struct pipeline_cgnapt_entry_key *)key);
1468 rte_hexdump(stdout, "KEY", key,
1469 sizeof(struct pipeline_cgnapt_entry_key));
1470 int32_t position = rte_hash_lookup(
1471 napt_common_table, key);
1472 print_cgnapt_entry(&napt_hash_tbl_entries[position]);
1476 } while (index != -ENOENT);
1480 * Input port handler for mixed traffic
1481 * This is the main method in this file when running in mixed traffic mode.
1482 * Starting from the packet burst it filters unwanted packets,
1483 * calculates keys, does lookup and then based on the lookup
1484 * updates NAPT table and does packet NAPT translation.
1487 * A pointer to struct rte_pipeline
1489 * A pointer to array of packets mbuf
1491 * Number of packets in the burst
1496 * int that is not checked by caller
1498 static int cgnapt_in_port_ah_mix(struct rte_pipeline *rte_p,
1499 struct rte_mbuf **pkts,
1500 uint32_t n_pkts, void *arg)
1505 * 1. Read packet version, if invalid drop the packet
1506 * 2. Check protocol, if not UDP or TCP drop the packet
1507 * 3. Bring all valid packets together - useful for bulk lookup
1508 * and calculate key for all packets
1509 * a. If IPv4 : calculate key with full IP
1510 * b. If IPv6 : calculate key with last 32-bit of IP
1511 * 4. Do bulk lookup with rte_hash_lookup_bulk(), if something went wrong
1513 * 5. For lookup hit packets, read entry from table
1514 * 6. For lookup miss packets, add dynamic entry to table
1516 * a. If egress pkt, convert to IPv4 and NAPT it
1517 * b. If ingress, drop the pkt
1519 * a. If egress pkt, NAPT it. Get MAC
1520 * b. If first ingress pkt (with no egress entry), drop the pkt
1521 * If not first ingress pkt
1522 * I. If IPv6 converted packet, convert back to IPv6,
1524 * II. If IPv4 packet, NAPT it & get MAC
1525 * 9. Send all packets out to corresponding ports
1527 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
1528 struct pipeline_cgnapt *p_nat = ap->p;
1529 uint8_t compacting_map[RTE_HASH_LOOKUP_BULK_MAX];
1530 uint32_t packets_for_lookup = 0;
1533 p_nat->valid_packets = 0;
1534 p_nat->invalid_packets = 0;
1536 #ifdef CGNAPT_DBG_PRNT
1537 if (CGNAPT_DEBUG > 1)
1538 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
1541 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
1543 uint16_t phy_port = 0;
1544 uint16_t *src_port = NULL;
1545 uint16_t *dst_port = NULL;
1546 uint32_t *src_addr = NULL;
1547 uint32_t *dst_addr = NULL;
1548 uint8_t *protocol = NULL;
1549 uint8_t *eth_dest = NULL;
1550 uint8_t *eth_src = NULL;
1551 uint16_t src_port_offset = 0;
1552 uint16_t dst_port_offset = 0;
1553 uint16_t src_addr_offset = 0;
1554 uint16_t dst_addr_offset = 0;
1555 uint16_t prot_offset = 0;
1556 uint16_t eth_offset = 0;
1559 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
1561 src_port_offset = SRC_PRT_OFST_IP4_TCP;
1562 dst_port_offset = DST_PRT_OFST_IP4_TCP;
1564 for (i = 0; i < n_pkts; i++) {
1565 p_nat->receivedPktCount++;
1567 /* bitmask representing only this packet */
1568 uint64_t pkt_mask = 1LLU << i;
1570 /* remember this pkt as valid pkt */
1571 p_nat->valid_packets |= pkt_mask;
1573 struct rte_mbuf *pkt = pkts[i];
1576 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
1579 int ver = rte_get_pkt_ver(pkt);
1581 #ifdef CGNAPT_DBG_PRNT
1582 printf("ver no. of the pkt:%d\n", ver);
1585 if (unlikely(ver < 0)) {
1586 /* Not a valid pkt , ignore. */
1587 /* remember invalid packets to be dropped */
1588 p_nat->invalid_packets |= pkt_mask;
1589 p_nat->naptDroppedPktCount++;
1591 #ifdef CGNAPT_DEBUGGING
1592 p_nat->naptDroppedPktCount1++;
1597 prot_offset = PROT_OFST_IP4;
1599 prot_offset = PROT_OFST_IP6;
1601 (uint8_t *) RTE_MBUF_METADATA_UINT32_PTR(pkt,
1604 (*protocol == IP_PROTOCOL_TCP
1605 || *protocol == IP_PROTOCOL_UDP
1606 || *protocol == IP_PROTOCOL_ICMP)) {
1607 /* remember invalid packets to be dropped */
1608 p_nat->invalid_packets |= pkt_mask;
1609 p_nat->naptDroppedPktCount++;
1611 #ifdef CGNAPT_DEBUGGING
1612 p_nat->naptDroppedPktCount2++;
1617 #ifdef CGNAPT_DBG_PRNT
1618 if (CGNAPT_DEBUG > 4)
1624 * 1. Handel PCP for egress traffic
1625 * 2. If PCP, then give response (send pkt) from the same port
1626 * 3. Drop the PCP packet, should not be added in the NAPT table
1629 if (*protocol == IP_PROTOCOL_UDP) {
1630 struct udp_hdr *udp;
1632 udp = (struct udp_hdr *)
1633 RTE_MBUF_METADATA_UINT8_PTR(pkt,
1636 udp = (struct udp_hdr *)
1637 RTE_MBUF_METADATA_UINT8_PTR(pkt,
1640 if (rte_bswap16(udp->dst_port) ==
1642 handle_pcp_req(pkt, ver, p_nat);
1643 p_nat->invalid_packets |= pkt_mask;
1653 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1656 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1659 if ((*protocol == IP_PROTOCOL_TCP)
1660 || (*protocol == IP_PROTOCOL_UDP)) {
1662 src_port_offset = SRC_PRT_OFST_IP4_TCP;
1663 dst_port_offset = DST_PRT_OFST_IP4_TCP;
1665 } else if (*protocol == IP_PROTOCOL_ICMP) {
1667 src_port_offset = IDEN_OFST_IP4_ICMP;
1668 /* Sequence number */
1669 dst_port_offset = SEQN_OFST_IP4_ICMP;
1673 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1676 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1681 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1684 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1687 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1690 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1693 /* need to create compacted table of pointers to
1694 * pass to bulk lookup
1697 compacting_map[packets_for_lookup] = i;
1699 //phy_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, phyport_offset);
1700 phy_port = pkt->port;
1702 struct pipeline_cgnapt_entry_key key;
1704 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
1707 if (get_in_port_dir(phy_port)) {
1710 key.ip = rte_bswap32(*src_addr);
1712 key.ip = rte_bswap32(src_addr[3]);
1713 key.port = rte_bswap16(*src_port);
1715 #ifdef NAT_ONLY_CONFIG_REQ
1716 if (nat_only_config_flag)
1721 key.ip = rte_bswap32(*dst_addr);
1723 if (*protocol == IP_PROTOCOL_ICMP) {
1724 /* common table lookupkey preparation from
1725 * incoming ICMP Packet- Indentifier field
1727 key.port = rte_bswap16(*src_port);
1729 key.port = rte_bswap16(*dst_port);
1732 #ifdef NAT_ONLY_CONFIG_REQ
1733 if (nat_only_config_flag)
1740 memcpy(&(p_nat->keys[packets_for_lookup]), &key,
1741 sizeof(struct pipeline_cgnapt_entry_key));
1742 p_nat->key_ptrs[packets_for_lookup] =
1743 &(p_nat->keys[packets_for_lookup]);
1744 packets_for_lookup++;
1747 if (unlikely(packets_for_lookup == 0)) {
1748 /* no suitable packet for lookup */
1749 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
1750 return p_nat->valid_packets;
1753 /* lookup entries in the common napt table */
1755 int lookup_result = rte_hash_lookup_bulk(napt_common_table,
1759 &p_nat->lkup_indx[0]);
1761 if (unlikely(lookup_result < 0)) {
1762 /* unknown error, just discard all packets */
1763 printf("Unexpected hash lookup error %d, discarding all "
1764 "packets", lookup_result);
1765 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
1768 //struct rte_pipeline_table_entry *entries[64];
1769 /* Now one by one check the result of our bulk lookup */
1771 for (i = 0; i < packets_for_lookup; i++) {
1772 /* index into hash table entries */
1773 int hash_table_entry = p_nat->lkup_indx[i];
1774 /* index into packet table of this packet */
1775 uint8_t pkt_index = compacting_map[i];
1776 /*bitmask representing only this packet */
1777 uint64_t pkt_mask = 1LLU << pkt_index;
1779 struct cgnapt_table_entry *entry = NULL;
1780 if (hash_table_entry < 0) {
1782 /* try to add new entry */
1783 struct rte_pipeline_table_entry *table_entry = NULL;
1786 pkt_miss_cgnapt(p_nat->key_ptrs[i],
1789 &p_nat->valid_packets,
1794 /* ICMP Error message generation for
1795 * Destination Host unreachable
1797 if (*protocol == IP_PROTOCOL_ICMP) {
1798 cgnapt_icmp_pkt = pkts[pkt_index];
1799 send_icmp_dest_unreachable_msg();
1802 /* Drop packet by adding to invalid pkt mask */
1804 p_nat->invalid_packets |= dropmask;
1805 #ifdef CGNAPT_DEBUGGING
1806 if (p_nat->kpc2++ < 5) {
1807 printf("in_ah Th: %d",
1808 p_nat->pipeline_num);
1809 print_key(p_nat->key_ptrs[i]);
1813 p_nat->naptDroppedPktCount++;
1815 #ifdef CGNAPT_DEBUGGING
1816 p_nat->naptDroppedPktCount3++;
1821 entry = (struct cgnapt_table_entry *)table_entry;
1823 /* entry found for this packet */
1824 entry = &napt_hash_tbl_entries[hash_table_entry];
1827 /* apply napt and mac changes */
1829 p_nat->entries[pkt_index] = &(entry->head);
1831 phy_port = pkts[pkt_index]->port;
1833 struct ipv6_hdr ipv6_hdr;
1834 struct ipv4_hdr ipv4_hdr;
1836 ver = rte_get_pkt_ver(pkts[pkt_index]);
1837 #ifdef CGNAPT_DEBUGGING
1838 if (CGNAPT_DEBUG >= 1) {
1839 printf("ver:%d\n", ver);
1840 printf("entry->data.type:%d\n", entry->data.type);
1843 if ((ver == 6) && (entry->data.type == CGNAPT_ENTRY_IPV6)
1844 && is_phy_port_privte(phy_port)) {
1845 convert_ipv6_to_ipv4(pkts[pkt_index], &ipv6_hdr);
1847 pkt_type = PKT_TYPE_IPV6to4;
1849 #ifdef CGNAPT_DBG_PRNT
1850 if (CGNAPT_DEBUG >= 1)
1851 printf("pkt_work_cganpt: "
1852 "convert_ipv6_to_ipv4\n");
1855 struct cgnapt_nsp_node *ll = nsp_ll;
1857 while (ll != NULL) {
1858 if (!memcmp(&ipv6_hdr.dst_addr[0],
1860 ll->nsp.depth / 8)) {
1868 && !memcmp(&ipv6_hdr.dst_addr[0],
1869 &well_known_prefix[0], 12)) {
1874 p_nat->invalid_packets |= 1LLU << pkt_index;
1875 p_nat->naptDroppedPktCount++;
1877 #ifdef CGNAPT_DEBUGGING
1878 p_nat->naptDroppedPktCount5++;
1885 /* As packet is already converted into IPv4 we must not operate
1886 * IPv6 offsets on packet
1887 * Only perform IPv4 operations
1892 src_port_offset = SRC_PRT_OFST_IP6t4;
1893 dst_port_offset = DST_PRT_OFST_IP6t4;
1894 src_addr_offset = SRC_ADR_OFST_IP6t4;
1895 dst_addr_offset = DST_ADR_OFST_IP6t4;
1896 prot_offset = PROT_OFST_IP6t4;
1897 eth_offset = ETH_OFST_IP6t4;
1901 if ((*protocol == IP_PROTOCOL_TCP)
1902 || (*protocol == IP_PROTOCOL_UDP)) {
1903 src_port_offset = SRC_PRT_OFST_IP4_TCP;
1904 dst_port_offset = DST_PRT_OFST_IP4_TCP;
1905 } else if (*protocol == IP_PROTOCOL_ICMP) {
1907 src_port_offset = IDEN_OFST_IP4_ICMP;
1908 /* Sequence number */
1909 dst_port_offset = SEQN_OFST_IP4_ICMP;
1912 src_addr_offset = SRC_ADR_OFST_IP4;
1913 dst_addr_offset = DST_ADR_OFST_IP4;
1914 prot_offset = PROT_OFST_IP4;
1915 eth_offset = MBUF_HDR_ROOM;
1920 RTE_MBUF_METADATA_UINT32_PTR(pkts[pkt_index],
1923 RTE_MBUF_METADATA_UINT32_PTR(pkts[pkt_index],
1926 RTE_MBUF_METADATA_UINT16_PTR(pkts[pkt_index],
1929 RTE_MBUF_METADATA_UINT16_PTR(pkts[pkt_index],
1932 RTE_MBUF_METADATA_UINT8_PTR(pkts[pkt_index],
1936 RTE_MBUF_METADATA_UINT8_PTR(pkts[pkt_index],
1939 RTE_MBUF_METADATA_UINT8_PTR(pkts[pkt_index],
1942 if (entry->data.ttl == NAPT_ENTRY_STALE)
1943 entry->data.ttl = NAPT_ENTRY_VALID;
1945 struct ether_addr hw_addr;
1946 uint32_t dest_address = 0;
1947 uint8_t nh_ipv6[16];
1950 uint32_t dest_if = INVALID_DESTIF;
1953 uint16_t *outport_id =
1954 RTE_MBUF_METADATA_UINT16_PTR(pkts[pkt_index],
1955 cgnapt_meta_offset);
1957 if (is_phy_port_privte(phy_port)) {
1959 if (*protocol == IP_PROTOCOL_UDP
1960 && rte_be_to_cpu_16(*dst_port) == 53) {
1961 p_nat->invalid_packets |= 1LLU << pkt_index;
1962 p_nat->naptDroppedPktCount++;
1963 #ifdef CGNAPT_DEBUGGING
1964 p_nat->naptDroppedPktCount6++;
1969 dest_address = rte_bswap32(*dst_addr);
1970 /* Gateway Proc Starts */
1972 struct arp_entry_data *ret_arp_data = NULL;
1973 uint32_t src_phy_port = *src_port;
1975 dest_if = prv_to_pub_map[src_phy_port];
1976 gw_get_route_nh_port_ipv4(dest_address,
1977 &dest_if, &nhip, dest_if);
1979 if (dest_if == INVALID_DESTIF) {
1980 p_nat->invalid_packets |=
1982 p_nat->naptDroppedPktCount++;
1983 #ifdef CGNAPT_DEBUGGING
1984 p_nat->naptDroppedPktCount6++;
1989 *outport_id = p_nat->outport_id[dest_if];
1991 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if, &hw_addr);
1993 if (unlikely(ret_arp_data == NULL)) {
1995 #ifdef CGNAPT_DEBUGGING
1996 printf("%s: NHIP Not Found, nhip: %x, "
1997 "outport_id: %d\n", __func__, nhip,
2001 p_nat->invalid_packets |= pkt_mask;
2002 p_nat->naptDroppedPktCount++;
2004 #ifdef CGNAPT_DEBUGGING
2005 p_nat->naptDroppedPktCount4++;
2010 /* Gateway Proc Ends */
2012 if (ret_arp_data->status == COMPLETE) {
2014 if (ret_arp_data->num_pkts) {
2015 p_nat->naptedPktCount += ret_arp_data->num_pkts;
2016 arp_send_buffered_pkts(ret_arp_data,
2017 &hw_addr, *outport_id);
2020 memcpy(eth_dest, &hw_addr,
2021 sizeof(struct ether_addr));
2022 memcpy(eth_src, get_link_hw_addr(dest_if),
2023 sizeof(struct ether_addr));
2024 #ifdef CGNAPT_DBG_PRNT
2025 if (CGNAPT_DEBUG > 2) {
2026 printf("MAC found for ip 0x%x, port %d - "
2027 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2028 dest_address, *outport_id,
2029 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
2030 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
2031 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
2033 printf("Dest MAC before - "
2034 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2035 eth_dest[0], eth_dest[1], eth_dest[2],
2036 eth_dest[3], eth_dest[4], eth_dest[5]);
2040 #ifdef CGNAPT_DBG_PRNT
2041 if (CGNAPT_DEBUG > 2) {
2042 printf("Dest MAC after - "
2043 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2044 eth_dest[0], eth_dest[1], eth_dest[2],
2045 eth_dest[3], eth_dest[4], eth_dest[5]);
2049 #ifdef CGNAPT_DBG_PRNT
2050 if (CGNAPT_DEBUG > 4)
2051 print_pkt(pkts[pkt_index]);
2054 } else if (ret_arp_data->status == INCOMPLETE ||
2055 ret_arp_data->status == PROBE) {
2056 if (ret_arp_data->num_pkts >= NUM_DESC) {
2058 p_nat->invalid_packets |= pkt_mask;
2059 p_nat->naptDroppedPktCount++;
2061 #ifdef CGNAPT_DEBUGGING
2062 p_nat->naptDroppedPktCount4++;
2066 arp_queue_unresolved_packet(ret_arp_data,
2072 #ifdef CGNAPT_DBG_PRNT
2073 if (CGNAPT_DEBUG > 2)
2074 printf("Egress: \tphy_port:%d\t "
2075 "get_prv_to_pub():%d \tout_port:%d\n",
2081 *src_addr = rte_bswap32(entry->data.pub_ip);
2083 #ifdef NAT_ONLY_CONFIG_REQ
2084 if (!nat_only_config_flag) {
2086 *src_port = rte_bswap16(entry->data.pub_port);
2087 #ifdef NAT_ONLY_CONFIG_REQ
2091 p_nat->enaptedPktCount++;
2094 if (*protocol == IP_PROTOCOL_UDP
2095 && rte_be_to_cpu_16(*src_port) == 53) {
2096 p_nat->invalid_packets |= 1LLU << pkt_index;
2097 p_nat->naptDroppedPktCount++;
2098 #ifdef CGNAPT_DEBUGGING
2099 p_nat->naptDroppedPktCount6++;
2104 #ifdef CGNAPT_DBG_PRNT
2105 if (CGNAPT_DEBUG > 2)
2106 printf("Ingress: \tphy_port:%d\t "
2107 "get_pub_to_prv():%d \tout_port%d\n",
2112 if (entry->data.type == CGNAPT_ENTRY_IPV6) {
2113 convert_ipv4_to_ipv6(pkts[pkt_index],
2115 pkt_type = PKT_TYPE_IPV4to6;
2116 /* Ethernet MTU check */
2117 if ((rte_pktmbuf_data_len(pkts[pkt_index]) -
2119 p_nat->invalid_packets |= pkt_mask;
2120 p_nat->naptDroppedPktCount++;
2124 eth_dest = eth_dest - 20;
2125 eth_src = eth_src - 20;
2127 dst_port_offset = DST_PRT_OFST_IP4t6;
2128 dst_addr_offset = DST_ADR_OFST_IP4t6;
2130 RTE_MBUF_METADATA_UINT32_PTR(
2134 RTE_MBUF_METADATA_UINT16_PTR(
2138 memcpy((uint8_t *) &dst_addr[0],
2139 &entry->data.u.prv_ipv6[0], 16);
2140 memset(nh_ipv6, 0, 16);
2141 struct nd_entry_data *ret_nd_data = NULL;
2143 dest_if = INVALID_DESTIF;
2145 uint32_t src_phy_port = pkts[pkt_index]->port;
2147 gw_get_nh_port_ipv6((uint8_t *) &dst_addr[0],
2148 &dest_if, &nh_ipv6[0]);
2150 ret_nd_data = get_dest_mac_addr_ipv6(&nh_ipv6[0],
2152 *outport_id = p_nat->outport_id[dest_if];
2154 if (nd_cache_dest_mac_present(dest_if)) {
2155 ether_addr_copy(get_link_hw_addr(dest_if),
2156 (struct ether_addr *)eth_src);
2157 update_nhip_access(dest_if);
2159 if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) {
2160 p_nat->naptedPktCount += ret_nd_data->num_pkts;
2161 nd_send_buffered_pkts(ret_nd_data,
2162 (struct ether_addr *)eth_dest,
2166 if (unlikely(ret_nd_data == NULL)) {
2168 #ifdef CGNAPT_DEBUGGING
2169 printf("%s: NHIP Not Found, "
2170 "outport_id: %d\n", __func__,
2175 p_nat->invalid_packets |= pkt_mask;
2176 p_nat->naptDroppedPktCount++;
2178 #ifdef CGNAPT_DEBUGGING
2179 p_nat->naptDroppedPktCount4++;
2184 if (ret_nd_data->status == INCOMPLETE ||
2185 ret_nd_data->status == PROBE) {
2186 if (ret_nd_data->num_pkts >= NUM_DESC) {
2188 p_nat->invalid_packets |= pkt_mask;
2189 p_nat->naptDroppedPktCount++;
2191 #ifdef CGNAPT_DEBUGGING
2192 p_nat->naptDroppedPktCount4++;
2196 arp_pkts_mask |= pkt_mask;
2197 nd_queue_unresolved_packet(ret_nd_data,
2205 #ifdef NAT_ONLY_CONFIG_REQ
2206 if (!nat_only_config_flag) {
2209 rte_bswap16(entry->data.prv_port);
2210 #ifdef NAT_ONLY_CONFIG_REQ
2215 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
2216 dest_address = entry->data.u.prv_ip;
2217 /* Gateway Proc Starts */
2219 struct arp_entry_data *ret_arp_data = NULL;
2220 dest_if = INVALID_DESTIF;
2221 uint32_t src_phy_port = *src_port;
2222 dest_if = pub_to_prv_map[src_phy_port];
2223 gw_get_route_nh_port_ipv4(dest_address,
2224 &dest_if, &nhip, dest_if);
2226 if (dest_if == INVALID_DESTIF) {
2227 p_nat->invalid_packets |=
2229 p_nat->naptDroppedPktCount++;
2230 #ifdef CGNAPT_DEBUGGING
2231 p_nat->naptDroppedPktCount6++;
2236 *outport_id = p_nat->outport_id[dest_if];
2238 ret_arp_data = get_dest_mac_addr_ipv4(nhip,
2239 dest_if, (struct ether_addr *)&hw_addr);
2241 if (unlikely(ret_arp_data == NULL)) {
2243 #ifdef CGNAPT_DEBUGGING
2244 printf("%s: NHIP Not Found, nhip: %x, "
2245 "outport_id: %d\n", __func__, nhip,
2249 p_nat->invalid_packets |= pkt_mask;
2250 p_nat->naptDroppedPktCount++;
2252 #ifdef CGNAPT_DEBUGGING
2253 p_nat->naptDroppedPktCount4++;
2258 /* Gateway Proc Ends */
2260 if (ret_arp_data->status == COMPLETE) {
2262 if (ret_arp_data->num_pkts) {
2263 p_nat->naptedPktCount +=
2264 ret_arp_data->num_pkts;
2265 arp_send_buffered_pkts(ret_arp_data,
2266 &hw_addr, *outport_id);
2269 memcpy(eth_dest, &hw_addr,
2270 sizeof(struct ether_addr));
2271 memcpy(eth_src, get_link_hw_addr(
2273 sizeof(struct ether_addr));
2274 #ifdef CGNAPT_DBG_PRNT
2275 if (CGNAPT_DEBUG > 2) {
2276 printf("MAC found for ip 0x%x, port %d - "
2277 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2278 dest_address, *outport_id,
2279 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
2280 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
2281 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
2283 printf("Dest MAC before - "
2284 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2285 eth_dest[0], eth_dest[1], eth_dest[2],
2286 eth_dest[3], eth_dest[4], eth_dest[5]);
2290 #ifdef CGNAPT_DBG_PRNT
2291 if (CGNAPT_DEBUG > 2) {
2292 printf("Dest MAC after - "
2293 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2294 eth_dest[0], eth_dest[1], eth_dest[2],
2295 eth_dest[3], eth_dest[4], eth_dest[5]);
2299 #ifdef CGNAPT_DBG_PRNT
2300 if (CGNAPT_DEBUG > 4)
2301 print_pkt(pkts[pkt_index]);
2304 } else if (ret_arp_data->status == INCOMPLETE ||
2305 ret_arp_data->status == PROBE) {
2306 arp_queue_unresolved_packet(ret_arp_data,
2311 if (*protocol == IP_PROTOCOL_ICMP) {
2312 // Query ID reverse translation done here
2314 rte_bswap16(entry->data.prv_port);
2316 #ifdef NAT_ONLY_CONFIG_REQ
2317 if (!nat_only_config_flag) {
2322 #ifdef NAT_ONLY_CONFIG_REQ
2328 p_nat->inaptedPktCount++;
2331 p_nat->naptedPktCount++;
2334 if (p_nat->hw_checksum_reqd)
2335 hw_checksum(pkts[pkt_index], pkt_type);
2337 sw_checksum(pkts[pkt_index], pkt_type);
2341 if (p_nat->invalid_packets) {
2342 /* get rid of invalid packets */
2343 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2345 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2347 #ifdef CGNAPT_DBG_PRNT
2348 if (CGNAPT_DEBUG > 1) {
2349 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
2350 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
2351 printf("invalid_packets:0x%jx\n",
2352 p_nat->invalid_packets);
2353 printf("rte_invalid_packets :0x%jx\n",
2354 rte_p->pkts_drop_mask);
2355 printf("Total pkts dropped :0x%jx\n",
2356 rte_p->n_pkts_ah_drop);
2361 return p_nat->valid_packets;
2365 * Input port handler for IPv4 private traffic
2366 * Starting from the packet burst it filters unwanted packets,
2367 * calculates keys, does lookup and then based on the lookup
2368 * updates NAPT table and does packet NAPT translation.
2371 * A pointer to struct rte_pipeline
2373 * A pointer to array of packets mbuf
2375 * Number of packets in the burst
2380 * int that is not checked by caller
2383 static int cgnapt_in_port_ah_ipv4_prv(struct rte_pipeline *rte_p,
2384 struct rte_mbuf **pkts,
2385 uint32_t n_pkts, void *arg)
2388 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
2389 struct pipeline_cgnapt *p_nat = ap->p;
2391 #ifdef CGNAPT_TIMING_INST
2392 uint64_t entry_timestamp = 0, exit_timestamp;
2394 if (p_nat->time_measurements_on) {
2395 entry_timestamp = rte_get_tsc_cycles();
2396 /* check since exit ts not valid first time through */
2397 if (likely(p_nat->in_port_exit_timestamp))
2398 p_nat->external_time_sum +=
2399 entry_timestamp - p_nat->in_port_exit_timestamp;
2403 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
2404 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
2405 p_nat->invalid_packets = 0;
2407 #ifdef CGNAPT_DBG_PRNT
2408 if (CGNAPT_DEBUG > 1)
2409 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
2412 /* prefetching for mbufs should be done here */
2413 for (j = 0; j < n_pkts; j++)
2414 rte_prefetch0(pkts[j]);
2416 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2417 pkt4_work_cgnapt_key_ipv4_prv(&pkts[i], i, arg, p_nat);
2419 for (; i < n_pkts; i++)
2420 pkt_work_cgnapt_key_ipv4_prv(pkts[i], i, arg, p_nat);
2422 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2424 if (unlikely(p_nat->valid_packets == 0)) {
2425 /* no suitable packet for lookup */
2426 printf("no suitable valid packets\n");
2427 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2428 return p_nat->valid_packets;
2431 /* lookup entries in the common napt table */
2433 int lookup_result = rte_hash_lookup_bulk(
2435 (const void **)&p_nat->key_ptrs,
2436 /* should be minus num invalid pkts */
2438 /*new pipeline data member */
2439 &p_nat->lkup_indx[0]);
2441 if (unlikely(lookup_result < 0)) {
2442 /* unknown error, just discard all packets */
2443 printf("Unexpected hash lookup error %d, discarding "
2444 "all packets", lookup_result);
2445 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
2449 /* Now call second stage of pipeline to one by one
2450 * check the result of our bulk lookup
2453 /* prefetching for table entries should be done here */
2454 for (j = 0; j < n_pkts; j++) {
2455 if (p_nat->lkup_indx[j] >= 0)
2456 rte_prefetch0(&napt_hash_tbl_entries
2457 [p_nat->lkup_indx[j]]);
2460 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2461 pkt4_work_cgnapt_ipv4_prv(pkts, i, arg, p_nat);
2463 for (; i < n_pkts; i++)
2464 pkt_work_cgnapt_ipv4_prv(pkts, i, arg, p_nat);
2466 if (arp_pkts_mask) {
2467 p_nat->valid_packets &= ~(arp_pkts_mask);
2468 rte_pipeline_ah_packet_hijack(rte_p, arp_pkts_mask);
2471 if (p_nat->invalid_packets) {
2472 /* get rid of invalid packets */
2473 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2475 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2477 #ifdef CGNAPT_DBG_PRNT
2478 if (CGNAPT_DEBUG > 1) {
2479 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
2480 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
2481 printf("invalid_packets:0x%jx\n",
2482 p_nat->invalid_packets);
2483 printf("rte_invalid_packets :0x%jx\n",
2484 rte_p->pkts_drop_mask);
2485 printf("Total pkts dropped :0x%jx\n",
2486 rte_p->n_pkts_ah_drop);
2491 #ifdef CGNAPT_TIMING_INST
2492 if (p_nat->time_measurements_on) {
2493 exit_timestamp = rte_get_tsc_cycles();
2494 p_nat->in_port_exit_timestamp = exit_timestamp;
2495 p_nat->internal_time_sum += exit_timestamp - entry_timestamp;
2496 p_nat->time_measurements++;
2497 if (p_nat->time_measurements == p_nat->max_time_mesurements)
2498 p_nat->time_measurements_on = 0;
2502 return p_nat->valid_packets;
2506 * Input port handler for IPv4 public traffic
2507 * Starting from the packet burst it filters unwanted packets,
2508 * calculates keys, does lookup and then based on the lookup
2509 * updates NAPT table and does packet NAPT translation.
2512 * A pointer to struct rte_pipeline
2514 * A pointer to array of packets mbuf
2516 * Number of packets in the burst
2521 * int that is not checked by caller
2523 static int cgnapt_in_port_ah_ipv4_pub(struct rte_pipeline *rte_p,
2524 struct rte_mbuf **pkts,
2525 uint32_t n_pkts, void *arg)
2528 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
2529 struct pipeline_cgnapt *p_nat = ap->p;
2531 #ifdef CGNAPT_TIMING_INST
2532 uint64_t entry_timestamp = 0, exit_timestamp;
2534 if (p_nat->time_measurements_on) {
2535 entry_timestamp = rte_get_tsc_cycles();
2537 /* check since exit ts not valid first time through */
2538 if (likely(p_nat->in_port_exit_timestamp))
2539 p_nat->external_time_sum +=
2540 entry_timestamp - p_nat->in_port_exit_timestamp;
2544 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
2545 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
2546 p_nat->invalid_packets = 0;
2548 #ifdef CGNAPT_DBG_PRNT
2549 if (CGNAPT_DEBUG > 1)
2550 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
2553 /* prefetching for mbufs should be done here */
2554 for (j = 0; j < n_pkts; j++)
2555 rte_prefetch0(pkts[j]);
2557 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2558 pkt4_work_cgnapt_key_ipv4_pub(&pkts[i], i, arg, p_nat);
2560 for (; i < n_pkts; i++)
2561 pkt_work_cgnapt_key_ipv4_pub(pkts[i], i, arg, p_nat);
2563 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2565 if (unlikely(p_nat->valid_packets == 0)) {
2566 printf("no valid packets in pub\n");
2567 /* no suitable packet for lookup */
2568 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2569 return p_nat->valid_packets;
2572 /* lookup entries in the common napt table */
2574 int lookup_result = rte_hash_lookup_bulk(
2576 (const void **)&p_nat->key_ptrs,
2577 /* should be minus num invalid pkts */
2579 /*new pipeline data member */
2580 &p_nat->lkup_indx[0]);
2582 if (unlikely(lookup_result < 0)) {
2583 /* unknown error, just discard all packets */
2584 printf("Unexpected hash lookup error %d, discarding "
2585 "all packets", lookup_result);
2586 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
2590 /* Now call second stage of pipeline to one by one
2591 * check the result of our bulk lookup
2594 /* prefetching for table entries should be done here */
2595 for (j = 0; j < n_pkts; j++) {
2596 if (p_nat->lkup_indx[j] >= 0)
2597 rte_prefetch0(&napt_hash_tbl_entries
2598 [p_nat->lkup_indx[j]]);
2601 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2602 pkt4_work_cgnapt_ipv4_pub(pkts, i, arg, p_nat);
2604 for (; i < n_pkts; i++)
2605 pkt_work_cgnapt_ipv4_pub(pkts, i, arg, p_nat);
2607 if (arp_pkts_mask) {
2608 rte_pipeline_ah_packet_hijack(rte_p, arp_pkts_mask);
2609 p_nat->valid_packets &= ~(arp_pkts_mask);
2612 if (p_nat->invalid_packets) {
2613 /* get rid of invalid packets */
2614 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2616 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2618 #ifdef CGNAPT_DBG_PRNT
2619 if (CGNAPT_DEBUG > 1) {
2620 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
2621 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
2622 printf("invalid_packets:0x%jx\n",
2623 p_nat->invalid_packets);
2624 printf("rte_invalid_packets :0x%jx\n",
2625 rte_p->pkts_drop_mask);
2626 printf("Total pkts dropped :0x%jx\n",
2627 rte_p->n_pkts_ah_drop);
2632 #ifdef CGNAPT_TIMING_INST
2633 if (p_nat->time_measurements_on) {
2634 exit_timestamp = rte_get_tsc_cycles();
2635 p_nat->in_port_exit_timestamp = exit_timestamp;
2637 p_nat->internal_time_sum += exit_timestamp - entry_timestamp;
2638 p_nat->time_measurements++;
2639 if (p_nat->time_measurements == p_nat->max_time_mesurements)
2640 p_nat->time_measurements_on = 0;
2644 return p_nat->valid_packets;
2648 * NAPT key calculation function for IPv4 private traffic
2649 * which handles 4 pkts
2652 * A pointer to array of packets mbuf
2654 * Starting pkt number of pkts
2658 * A pointer to main CGNAPT structure
2662 pkt4_work_cgnapt_key_ipv4_prv(
2663 struct rte_mbuf **pkt,
2665 __rte_unused void *arg,
2666 struct pipeline_cgnapt *p_nat)
2668 p_nat->receivedPktCount += 4;
2669 /* bitmask representing only this packet */
2670 uint64_t pkt_mask0 = 1LLU << pkt_num;
2671 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
2672 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
2673 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
2675 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
2677 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
2679 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
2681 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
2684 uint32_t src_addr0 = RTE_MBUF_METADATA_UINT32(pkt[0],
2686 uint32_t src_addr1 = RTE_MBUF_METADATA_UINT32(pkt[1],
2688 uint32_t src_addr2 = RTE_MBUF_METADATA_UINT32(pkt[2],
2690 uint32_t src_addr3 = RTE_MBUF_METADATA_UINT32(pkt[3],
2693 uint16_t src_port_offset0;
2694 uint16_t src_port_offset1;
2695 uint16_t src_port_offset2;
2696 uint16_t src_port_offset3;
2703 uint16_t phy_port0 = pkt[0]->port;
2704 uint16_t phy_port1 = pkt[1]->port;
2705 uint16_t phy_port2 = pkt[2]->port;
2706 uint16_t phy_port3 = pkt[3]->port;
2708 struct pipeline_cgnapt_entry_key key0;
2709 struct pipeline_cgnapt_entry_key key1;
2710 struct pipeline_cgnapt_entry_key key2;
2711 struct pipeline_cgnapt_entry_key key3;
2713 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
2714 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
2715 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
2716 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
2719 #ifdef CGNAPT_DBG_PRNT
2720 if (CGNAPT_DEBUG > 4)
2725 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
2729 switch (protocol0) {
2730 case IP_PROTOCOL_UDP:
2734 struct udp_hdr *udp;
2736 udp = (struct udp_hdr *)
2737 RTE_MBUF_METADATA_UINT8_PTR(pkt[0],
2740 if (rte_bswap16(udp->dst_port) ==
2742 handle_pcp_req(pkt[0], IPV4_SZ, p_nat);
2743 p_nat->invalid_packets |= pkt_mask0;
2749 case IP_PROTOCOL_TCP:
2751 src_port_offset0 = SRC_PRT_OFST_IP4_TCP;
2752 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
2757 case IP_PROTOCOL_ICMP:
2759 src_port_offset0 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
2761 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
2767 /* remember invalid packets to be dropped */
2768 p_nat->invalid_packets |= pkt_mask0;
2769 p_nat->naptDroppedPktCount++;
2771 #ifdef CGNAPT_DEBUGGING
2772 p_nat->naptDroppedPktCount2++;
2777 key0.pid = phy_port0;
2778 key0.ip = rte_bswap32(src_addr0);
2779 key0.port = rte_bswap16(src_port0);
2781 #ifdef NAT_ONLY_CONFIG_REQ
2782 if (nat_only_config_flag)
2786 memcpy(&p_nat->keys[pkt_num], &key0,
2787 sizeof(struct pipeline_cgnapt_entry_key));
2788 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
2793 #ifdef CGNAPT_DBG_PRNT
2794 if (CGNAPT_DEBUG > 4)
2799 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
2802 switch (protocol1) {
2803 case IP_PROTOCOL_UDP:
2807 struct udp_hdr *udp;
2809 udp = (struct udp_hdr *)
2810 RTE_MBUF_METADATA_UINT8_PTR(pkt[1],
2813 if (rte_bswap16(udp->dst_port) ==
2815 handle_pcp_req(pkt[1], IPV4_SZ, p_nat);
2816 p_nat->invalid_packets |= pkt_mask1;
2822 case IP_PROTOCOL_TCP:
2824 src_port_offset1 = SRC_PRT_OFST_IP4_TCP;
2825 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
2830 case IP_PROTOCOL_ICMP:
2832 src_port_offset1 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
2834 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
2840 /* remember invalid packets to be dropped */
2841 p_nat->invalid_packets |= pkt_mask1;
2842 p_nat->naptDroppedPktCount++;
2844 #ifdef CGNAPT_DEBUGGING
2845 p_nat->naptDroppedPktCount2++;
2850 key1.pid = phy_port1;
2851 key1.ip = rte_bswap32(src_addr1);
2852 key1.port = rte_bswap16(src_port1);
2854 #ifdef NAT_ONLY_CONFIG_REQ
2855 if (nat_only_config_flag)
2859 memcpy(&p_nat->keys[pkt_num + 1], &key1,
2860 sizeof(struct pipeline_cgnapt_entry_key));
2861 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
2865 #ifdef CGNAPT_DBG_PRNT
2866 if (CGNAPT_DEBUG > 4)
2871 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
2875 switch (protocol2) {
2876 case IP_PROTOCOL_UDP:
2880 struct udp_hdr *udp;
2882 udp = (struct udp_hdr *)
2883 RTE_MBUF_METADATA_UINT8_PTR(pkt[2],
2886 if (rte_bswap16(udp->dst_port) ==
2888 handle_pcp_req(pkt[2], IPV4_SZ, p_nat);
2889 p_nat->invalid_packets |= pkt_mask2;
2895 case IP_PROTOCOL_TCP:
2897 src_port_offset2 = SRC_PRT_OFST_IP4_TCP;
2898 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
2903 case IP_PROTOCOL_ICMP:
2905 src_port_offset2 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
2907 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
2913 /* remember invalid packets to be dropped */
2914 p_nat->invalid_packets |= pkt_mask2;
2915 p_nat->naptDroppedPktCount++;
2917 #ifdef CGNAPT_DEBUGGING
2918 p_nat->naptDroppedPktCount2++;
2923 key2.pid = phy_port2;
2924 key2.ip = rte_bswap32(src_addr2);
2925 key2.port = rte_bswap16(src_port2);
2927 #ifdef NAT_ONLY_CONFIG_REQ
2928 if (nat_only_config_flag)
2932 memcpy(&p_nat->keys[pkt_num + 2], &key2,
2933 sizeof(struct pipeline_cgnapt_entry_key));
2934 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
2938 #ifdef CGNAPT_DBG_PRNT
2939 if (CGNAPT_DEBUG > 4)
2943 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
2947 switch (protocol3) {
2948 case IP_PROTOCOL_UDP:
2952 struct udp_hdr *udp;
2954 udp = (struct udp_hdr *)
2955 RTE_MBUF_METADATA_UINT8_PTR(pkt[3],
2958 if (rte_bswap16(udp->dst_port) ==
2960 handle_pcp_req(pkt[3], IPV4_SZ, p_nat);
2961 p_nat->invalid_packets |= pkt_mask3;
2967 case IP_PROTOCOL_TCP:
2969 src_port_offset3 = SRC_PRT_OFST_IP4_TCP;
2970 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
2975 case IP_PROTOCOL_ICMP:
2977 src_port_offset3 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
2979 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
2985 /* remember invalid packets to be dropped */
2986 p_nat->invalid_packets |= pkt_mask3;
2987 p_nat->naptDroppedPktCount++;
2989 #ifdef CGNAPT_DEBUGGING
2990 p_nat->naptDroppedPktCount2++;
2995 key3.pid = phy_port3;
2996 key3.ip = rte_bswap32(src_addr3);
2997 key3.port = rte_bswap16(src_port3);
2999 #ifdef NAT_ONLY_CONFIG_REQ
3000 if (nat_only_config_flag)
3004 memcpy(&p_nat->keys[pkt_num + 3], &key3,
3005 sizeof(struct pipeline_cgnapt_entry_key));
3006 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
3010 * NAPT key calculation function for IPv4 public traffic
3011 * which handles 4 pkts
3014 * A pointer to array of packets mbuf
3016 * Starting pkt number of pkts
3020 * A pointer to main CGNAPT structure
3024 pkt4_work_cgnapt_key_ipv4_pub(
3025 struct rte_mbuf **pkt,
3027 __rte_unused void *arg,
3028 struct pipeline_cgnapt *p_nat)
3030 p_nat->receivedPktCount += 4;
3031 /* bitmask representing only this packet */
3032 uint64_t pkt_mask0 = 1LLU << pkt_num;
3033 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
3034 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
3035 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
3037 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
3039 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
3041 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
3043 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
3046 uint32_t dst_addr0 = RTE_MBUF_METADATA_UINT32(pkt[0],
3048 uint32_t dst_addr1 = RTE_MBUF_METADATA_UINT32(pkt[1],
3050 uint32_t dst_addr2 = RTE_MBUF_METADATA_UINT32(pkt[2],
3052 uint32_t dst_addr3 = RTE_MBUF_METADATA_UINT32(pkt[3],
3055 uint16_t src_port_offset0;
3056 uint16_t src_port_offset1;
3057 uint16_t src_port_offset2;
3058 uint16_t src_port_offset3;
3060 uint16_t dst_port_offset0;
3061 uint16_t dst_port_offset1;
3062 uint16_t dst_port_offset2;
3063 uint16_t dst_port_offset3;
3075 struct pipeline_cgnapt_entry_key key0;
3076 struct pipeline_cgnapt_entry_key key1;
3077 struct pipeline_cgnapt_entry_key key2;
3078 struct pipeline_cgnapt_entry_key key3;
3080 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
3081 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
3082 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
3083 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
3086 #ifdef CGNAPT_DBG_PRNT
3087 if (CGNAPT_DEBUG > 4)
3092 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
3096 switch (protocol0) {
3097 case IP_PROTOCOL_UDP:
3098 case IP_PROTOCOL_TCP:
3100 src_port_offset0 = SRC_PRT_OFST_IP4_TCP;
3101 dst_port_offset0 = DST_PRT_OFST_IP4_TCP;
3103 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3105 dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3108 key0.port = rte_bswap16(dst_port0);
3112 case IP_PROTOCOL_ICMP:
3114 src_port_offset0 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3116 /*Sequence number */
3117 dst_port_offset0 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3120 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3122 dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3125 key0.port = rte_bswap16(src_port0);
3130 /* remember invalid packets to be dropped */
3131 p_nat->invalid_packets |= pkt_mask0;
3132 p_nat->naptDroppedPktCount++;
3134 #ifdef CGNAPT_DEBUGGING
3135 p_nat->naptDroppedPktCount2++;
3141 key0.ip = rte_bswap32(dst_addr0);
3143 #ifdef NAT_ONLY_CONFIG_REQ
3144 if (nat_only_config_flag)
3148 memcpy(&p_nat->keys[pkt_num], &key0,
3149 sizeof(struct pipeline_cgnapt_entry_key));
3150 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3155 #ifdef CGNAPT_DBG_PRNT
3156 if (CGNAPT_DEBUG > 4)
3161 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
3165 switch (protocol1) {
3166 case IP_PROTOCOL_UDP:
3167 case IP_PROTOCOL_TCP:
3169 src_port_offset1 = SRC_PRT_OFST_IP4_TCP;
3170 dst_port_offset1 = DST_PRT_OFST_IP4_TCP;
3172 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3174 dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3177 key1.port = rte_bswap16(dst_port1);
3181 case IP_PROTOCOL_ICMP:
3183 src_port_offset1 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3185 /*Sequence number */
3186 dst_port_offset1 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3189 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3191 dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3194 key1.port = rte_bswap16(src_port1);
3198 /* remember invalid packets to be dropped */
3199 p_nat->invalid_packets |= pkt_mask1;
3200 p_nat->naptDroppedPktCount++;
3202 #ifdef CGNAPT_DEBUGGING
3203 p_nat->naptDroppedPktCount2++;
3209 key1.ip = rte_bswap32(dst_addr1);
3211 #ifdef NAT_ONLY_CONFIG_REQ
3212 if (nat_only_config_flag)
3216 memcpy(&p_nat->keys[pkt_num + 1], &key1,
3217 sizeof(struct pipeline_cgnapt_entry_key));
3218 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
3222 #ifdef CGNAPT_DBG_PRNT
3223 if (CGNAPT_DEBUG > 4)
3228 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
3232 switch (protocol2) {
3233 case IP_PROTOCOL_UDP:
3234 case IP_PROTOCOL_TCP:
3236 src_port_offset2 = SRC_PRT_OFST_IP4_TCP;
3237 dst_port_offset2 = DST_PRT_OFST_IP4_TCP;
3239 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3241 dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3244 key2.port = rte_bswap16(dst_port2);
3248 case IP_PROTOCOL_ICMP:
3250 src_port_offset2 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3252 /*Sequence number */
3253 dst_port_offset2 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3256 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3258 dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3261 key2.port = rte_bswap16(src_port2);
3266 /* remember invalid packets to be dropped */
3267 p_nat->invalid_packets |= pkt_mask2;
3268 p_nat->naptDroppedPktCount++;
3270 #ifdef CGNAPT_DEBUGGING
3271 p_nat->naptDroppedPktCount2++;
3277 key2.ip = rte_bswap32(dst_addr2);
3279 #ifdef NAT_ONLY_CONFIG_REQ
3280 if (nat_only_config_flag)
3284 memcpy(&p_nat->keys[pkt_num + 2], &key2,
3285 sizeof(struct pipeline_cgnapt_entry_key));
3286 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
3290 #ifdef CGNAPT_DBG_PRNT
3291 if (CGNAPT_DEBUG > 4)
3296 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
3300 switch (protocol3) {
3301 case IP_PROTOCOL_UDP:
3302 case IP_PROTOCOL_TCP:
3304 src_port_offset3 = SRC_PRT_OFST_IP4_TCP;
3305 dst_port_offset3 = DST_PRT_OFST_IP4_TCP;
3307 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3309 dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3312 key3.port = rte_bswap16(dst_port3);
3316 case IP_PROTOCOL_ICMP:
3318 src_port_offset3 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3320 /*Sequence number */
3321 dst_port_offset3 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3324 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3326 dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3329 key3.port = rte_bswap16(src_port3);
3334 /* remember invalid packets to be dropped */
3335 p_nat->invalid_packets |= pkt_mask3;
3336 p_nat->naptDroppedPktCount++;
3338 #ifdef CGNAPT_DEBUGGING
3339 p_nat->naptDroppedPktCount2++;
3345 key3.ip = rte_bswap32(dst_addr3);
3347 #ifdef NAT_ONLY_CONFIG_REQ
3348 if (nat_only_config_flag)
3352 memcpy(&p_nat->keys[pkt_num + 3], &key3,
3353 sizeof(struct pipeline_cgnapt_entry_key));
3354 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
3358 * NAPT key calculation function for IPv4 private traffic
3359 * which handles 1 pkt
3362 * A pointer to array of packets mbuf
3364 * Pkt number of pkts
3368 * A pointer to main CGNAPT structure
3372 pkt_work_cgnapt_key_ipv4_prv(
3373 struct rte_mbuf *pkt,
3375 __rte_unused void *arg,
3376 struct pipeline_cgnapt *p_nat)
3379 p_nat->receivedPktCount++;
3381 /* bitmask representing only this packet */
3382 uint64_t pkt_mask = 1LLU << pkt_num;
3383 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3385 uint32_t src_addr = RTE_MBUF_METADATA_UINT32(pkt, SRC_ADR_OFST_IP4);
3387 uint16_t src_port_offset;
3391 uint16_t phy_port = pkt->port;
3392 struct pipeline_cgnapt_entry_key key;
3394 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
3397 #ifdef CGNAPT_DBG_PRNT
3398 if (CGNAPT_DEBUG > 4)
3403 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
3408 case IP_PROTOCOL_UDP:
3412 struct udp_hdr *udp;
3414 udp = (struct udp_hdr *)
3415 RTE_MBUF_METADATA_UINT8_PTR(pkt,
3418 if (rte_bswap16(udp->dst_port) ==
3420 handle_pcp_req(pkt, IPV4_SZ, p_nat);
3421 p_nat->invalid_packets |= pkt_mask;
3427 case IP_PROTOCOL_TCP:
3429 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3430 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3432 key.port = rte_bswap16(src_port);
3435 case IP_PROTOCOL_ICMP:
3437 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3439 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3441 key.port = rte_bswap16(src_port);
3445 /* remember invalid packets to be dropped */
3446 p_nat->invalid_packets |= pkt_mask;
3447 p_nat->naptDroppedPktCount++;
3449 #ifdef CGNAPT_DEBUGGING
3450 p_nat->naptDroppedPktCount2++;
3456 key.ip = rte_bswap32(src_addr);
3458 #ifdef NAT_ONLY_CONFIG_REQ
3459 if (nat_only_config_flag)
3463 memcpy(&p_nat->keys[pkt_num], &key,
3464 sizeof(struct pipeline_cgnapt_entry_key));
3465 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3469 * NAPT key calculation function for IPv4 public traffic
3470 * which handles 1 pkt
3473 * A pointer to array of packets mbuf
3475 * Pkt number of pkts
3479 * A pointer to main CGNAPT structure
3483 pkt_work_cgnapt_key_ipv4_pub(
3484 struct rte_mbuf *pkt,
3486 __rte_unused void *arg,
3487 struct pipeline_cgnapt *p_nat)
3489 p_nat->receivedPktCount++;
3491 /* bitmask representing only this packet */
3492 uint64_t pkt_mask = 1LLU << pkt_num;
3493 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3494 uint32_t dst_addr = RTE_MBUF_METADATA_UINT32(pkt, DST_ADR_OFST_IP4);
3495 uint16_t src_port_offset;
3496 uint16_t dst_port_offset;
3499 struct pipeline_cgnapt_entry_key key;
3500 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
3502 #ifdef CGNAPT_DBG_PRNT
3503 if (CGNAPT_DEBUG > 4)
3508 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
3513 case IP_PROTOCOL_UDP:
3514 case IP_PROTOCOL_TCP:
3515 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3516 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3518 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3519 dst_port = RTE_MBUF_METADATA_UINT16(pkt, dst_port_offset);
3521 key.port = rte_bswap16(dst_port);
3523 case IP_PROTOCOL_ICMP:
3525 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3527 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3530 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3531 dst_port = RTE_MBUF_METADATA_UINT16(pkt, dst_port_offset);
3533 /* common table lookupkey preparation from incoming
3534 * ICMP Packet- Indentifier field
3536 key.port = rte_bswap16(src_port);
3539 /* remember invalid packets to be dropped */
3540 p_nat->invalid_packets |= pkt_mask;
3541 p_nat->naptDroppedPktCount++;
3543 #ifdef CGNAPT_DEBUGGING
3544 p_nat->naptDroppedPktCount2++;
3549 key.ip = rte_bswap32(dst_addr);
3551 #ifdef NAT_ONLY_CONFIG_REQ
3552 if (nat_only_config_flag)
3558 memcpy(&p_nat->keys[pkt_num], &key,
3559 sizeof(struct pipeline_cgnapt_entry_key));
3560 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3565 * NAPT function for IPv4 private traffic which handles 1 pkt
3568 * A pointer to array of packet mbuf
3574 * A pointer to main CGNAPT structure
3577 uint64_t last_update;
3579 pkt_work_cgnapt_ipv4_prv(
3580 struct rte_mbuf **pkts,
3582 __rte_unused void *arg,
3583 struct pipeline_cgnapt *p_nat)
3586 struct rte_CT_helper ct_helper;
3587 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
3590 /* index into hash table entries */
3591 int hash_table_entry = p_nat->lkup_indx[pkt_num];
3592 /*bitmask representing only this packet */
3593 uint64_t pkt_mask = 1LLU << pkt_num;
3594 struct rte_mbuf *pkt = pkts[pkt_num];
3596 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3598 uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */
3599 uint16_t *outport_id =
3600 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
3602 struct cgnapt_table_entry *entry = NULL;
3604 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
3606 if (hash_table_entry < 0) {
3608 /* try to add new entry */
3609 struct rte_pipeline_table_entry *table_entry = NULL;
3611 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
3613 &p_nat->valid_packets, pkt_num,
3617 /* ICMP Error message generation for Destination
3620 if (protocol == IP_PROTOCOL_ICMP) {
3621 cgnapt_icmp_pkt = pkt;
3622 send_icmp_dest_unreachable_msg();
3625 /* Drop packet by adding to invalid pkt mask */
3627 p_nat->invalid_packets |= dropmask;
3628 #ifdef CGNAPT_DEBUGGING
3629 if (p_nat->kpc2++ < 5) {
3630 printf("in_ah Th: %d", p_nat->pipeline_num);
3631 print_key(p_nat->key_ptrs[pkt_num]);
3635 p_nat->naptDroppedPktCount++;
3637 #ifdef CGNAPT_DEBUGGING
3638 p_nat->naptDroppedPktCount3++;
3643 entry = (struct cgnapt_table_entry *)table_entry;
3645 /* entry found for this packet */
3646 entry = &napt_hash_tbl_entries[hash_table_entry];
3649 /* apply napt and mac changes */
3651 p_nat->entries[pkt_num] = &(entry->head);
3653 uint32_t *src_addr =
3654 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP4);
3655 uint32_t *dst_addr =
3656 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
3657 uint16_t src_port_offset = 0;
3658 uint16_t dst_port_offset = 0;
3663 case IP_PROTOCOL_TCP:
3664 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3665 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3666 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3667 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3670 if ((rte_be_to_cpu_16(*src_port) == 21) ||
3671 rte_be_to_cpu_16(*dst_port) == 21) {
3674 printf("cgnapt_ct_process: pkt_mask: % "PRIu64", "
3675 "pkt_num: %d\n", pkt_mask, pkt_num);
3678 pkt_mask = cgnapt_ct_process(cgnat_cnxn_tracker, pkts,
3679 pkt_mask, &ct_helper);
3683 case IP_PROTOCOL_UDP:
3684 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3685 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3686 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3687 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3689 case IP_PROTOCOL_ICMP:
3691 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3693 /*Sequence number */
3694 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3696 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3697 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3699 default: /* KW fix: unknown is treated as TCP/UDP */
3700 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3701 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3702 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3703 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3707 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
3708 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
3710 if (entry->data.ttl == NAPT_ENTRY_STALE)
3711 entry->data.ttl = NAPT_ENTRY_VALID;
3713 uint32_t dest_address = 0;
3716 if (unlikely(protocol == IP_PROTOCOL_UDP
3717 && rte_be_to_cpu_16(*dst_port) == 53)) {
3718 p_nat->invalid_packets |= pkt_mask;
3719 p_nat->naptDroppedPktCount++;
3721 #ifdef CGNAPT_DEBUGGING
3722 p_nat->naptDroppedPktCount6++;
3726 last_update = rte_rdtsc();
3727 dest_address = rte_bswap32(*dst_addr);
3729 struct arp_entry_data *ret_arp_data = NULL;
3731 uint32_t src_phy_port = *src_port;
3732 dest_if = prv_to_pub_map[src_phy_port];
3733 gw_get_route_nh_port_ipv4(dest_address,
3734 &dest_if, &nhip, dest_if);
3736 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if,
3737 (struct ether_addr *)eth_dest);
3739 *outport_id = p_nat->outport_id[dest_if];
3741 if (arp_cache_dest_mac_present(dest_if)) {
3742 ether_addr_copy(get_link_hw_addr(dest_if),(struct ether_addr *)eth_src);
3743 update_nhip_access(dest_if);
3744 if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) {
3745 p_nat->naptedPktCount += ret_arp_data->num_pkts;
3746 arp_send_buffered_pkts(ret_arp_data,
3747 (struct ether_addr *)eth_dest, *outport_id);
3752 if (unlikely(ret_arp_data == NULL)) {
3754 #ifdef CGNAPT_DEBUGGING
3755 printf("%s: NHIP Not Found, nhip:%x , "
3756 "outport_id: %d\n", __func__, nhip,
3761 p_nat->invalid_packets |= pkt_mask;
3762 p_nat->naptDroppedPktCount++;
3764 #ifdef CGNAPT_DEBUGGING
3765 p_nat->naptDroppedPktCount4++;
3770 if (ret_arp_data->status == INCOMPLETE ||
3771 ret_arp_data->status == PROBE) {
3772 if (ret_arp_data->num_pkts >= NUM_DESC) {
3774 p_nat->invalid_packets |= pkt_mask;
3775 p_nat->naptDroppedPktCount++;
3777 #ifdef CGNAPT_DEBUGGING
3778 p_nat->naptDroppedPktCount4++;
3782 arp_pkts_mask |= pkt_mask;
3783 arp_queue_unresolved_packet(ret_arp_data, pkt);
3792 *src_addr = rte_bswap32(entry->data.pub_ip);
3795 #ifdef NAT_ONLY_CONFIG_REQ
3796 if (!nat_only_config_flag) {
3798 *src_port = rte_bswap16(entry->data.pub_port);
3799 #ifdef NAT_ONLY_CONFIG_REQ
3804 uint16_t rtp_port = 0, rtcp_port = 0;
3805 struct cgnapt_table_entry *entry_ptr1 = NULL,
3806 *entry_ptr2 = NULL, *entry_ptr3 = NULL,
3809 if (unlikely(protocol == IP_PROTOCOL_UDP
3810 && (rte_be_to_cpu_16(*dst_port) == 5060
3811 || rte_be_to_cpu_16(*src_port) == 5060))) {
3813 int ret = natSipAlgGetAudioPorts(pkt, &rtp_port,
3815 /* Commented code may be required for debug
3816 * and future use, Please keep it*/
3819 printf("%s: Wrong SIP ALG packet1\n",
3821 p_nat->invalid_packets |= pkt_mask;
3823 p_nat->naptDroppedPktCount++;
3825 #ifdef CGNAPT_DEBUGGING
3826 p_nat->naptDroppedPktCount4++;
3832 if (ret >= 0 && rtp_port != 0) {
3833 struct pipeline_cgnapt_entry_key rtp_key;
3834 rtp_key.ip = entry->data.u.prv_ip;
3835 rtp_key.port = rtp_port;
3836 rtp_key.pid = entry->data.prv_phy_port;
3838 if (add_dynamic_cgnapt_entry_alg(
3839 (struct pipeline *)p_nat, &rtp_key,
3840 &entry_ptr1, &entry_ptr2) == 0) {
3841 printf("%s: Wrong SIP ALG packet2\n",
3843 p_nat->invalid_packets |= pkt_mask;
3845 p_nat->naptDroppedPktCount++;
3847 #ifdef CGNAPT_DEBUGGING
3848 p_nat->naptDroppedPktCount4++;
3854 if (ret >= 0 && rtcp_port != 0) {
3855 struct pipeline_cgnapt_entry_key rtcp_key;
3856 rtcp_key.ip = entry->data.u.prv_ip;
3857 rtcp_key.port = rtcp_port;
3858 rtcp_key.pid = entry->data.prv_phy_port;
3860 if (add_dynamic_cgnapt_entry_alg(
3861 (struct pipeline *)p_nat, &rtcp_key,
3862 &entry_ptr3, &entry_ptr4) == 0) {
3863 printf("%s: Wrong SIP ALG packet3\n",
3865 p_nat->invalid_packets |= pkt_mask;
3867 p_nat->naptDroppedPktCount++;
3869 #ifdef CGNAPT_DEBUGGING
3870 p_nat->naptDroppedPktCount4++;
3876 //if(entry_ptr1 != NULL && entry_ptr3 != NULL)
3877 if (sip_alg_dpi(pkt, PRIVATE, entry->data.pub_ip,
3878 entry->data.pub_port, entry->data.u.prv_ip,
3879 entry->data.prv_port, (rtp_port == 0) ? 0 :
3880 entry_ptr1->data.pub_port,
3881 (rtcp_port == 0) ? 0 :
3882 entry_ptr3->data.pub_port) == 0) {
3884 printf("%s: Wrong SIP ALG packet4\n",
3886 p_nat->invalid_packets |= pkt_mask;
3888 p_nat->naptDroppedPktCount++;
3890 #ifdef CGNAPT_DEBUGGING
3891 p_nat->naptDroppedPktCount4++;
3896 #endif /* SIP_ALG */
3901 printf("@CGNAT-pktwork ct_position :%d, pkt_num %d pkt_mask= "
3902 "%" PRIu64 "\n", ct_position, pkt_num, pkt_mask);
3905 if ((rte_be_to_cpu_16(*src_port) == 21) ||
3906 rte_be_to_cpu_16(*dst_port) == 21) {
3908 int32_t ct_position = cgnat_cnxn_tracker->positions[pkt_num];
3909 if (ct_position < 0){
3910 p_nat->invalid_packets |= pkt_mask;
3911 p_nat->naptDroppedPktCount++;
3914 /* Commented code may be required for future usage,
3917 //if (cgnat_cnxn_tracker->hash_table_entries
3918 // [ct_position].alg_bypass_flag != BYPASS)
3920 struct pipeline_cgnapt_entry_key data_channel_entry_key;
3922 data_channel_entry_key.ip = entry->data.pub_ip;
3923 data_channel_entry_key.port = entry->data.pub_port;
3924 data_channel_entry_key.pid = pkt->port;
3925 ftp_alg_dpi(p_nat, &data_channel_entry_key, pkt,
3926 cgnat_cnxn_tracker, ct_position, PRIVATE);
3929 #endif /* FTP_ALG */
3931 p_nat->enaptedPktCount++;
3934 p_nat->naptedPktCount++;
3937 if (p_nat->hw_checksum_reqd)
3938 hw_checksum(pkt, pkt_type);
3940 sw_checksum(pkt, pkt_type);
3947 * NAPT function for IPv4 public traffic which handles 1 pkt
3950 * A pointer to array of packet mbuf
3956 * A pointer to main CGNAPT structure
3960 pkt_work_cgnapt_ipv4_pub(
3961 struct rte_mbuf **pkts,
3963 __rte_unused void *arg,
3964 struct pipeline_cgnapt *p_nat)
3968 struct rte_CT_helper ct_helper;
3969 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
3972 /* index into hash table entries */
3973 int hash_table_entry = p_nat->lkup_indx[pkt_num];
3974 /*bitmask representing only this packet */
3975 uint64_t pkt_mask = 1LLU << pkt_num;
3976 struct rte_mbuf *pkt = pkts[pkt_num];
3978 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3980 uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */
3981 uint16_t *outport_id =
3982 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
3984 struct cgnapt_table_entry *entry = NULL;
3986 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
3988 if (hash_table_entry < 0) {
3990 /* try to add new entry */
3991 struct rte_pipeline_table_entry *table_entry = NULL;
3993 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
3995 &p_nat->valid_packets, pkt_num,
3999 /* ICMP Error message generation for
4000 * Destination Host unreachable
4002 if (protocol == IP_PROTOCOL_ICMP) {
4003 cgnapt_icmp_pkt = pkt;
4004 send_icmp_dest_unreachable_msg();
4007 /* Drop packet by adding to invalid pkt mask */
4009 p_nat->invalid_packets |= dropmask;
4010 #ifdef CGNAPT_DEBUGGING
4011 if (p_nat->kpc2++ < 5) {
4012 printf("in_ah Th: %d", p_nat->pipeline_num);
4013 print_key(p_nat->key_ptrs[pkt_num]);
4017 p_nat->naptDroppedPktCount++;
4019 #ifdef CGNAPT_DEBUGGING
4020 p_nat->naptDroppedPktCount3++;
4025 entry = (struct cgnapt_table_entry *)table_entry;
4027 /* entry found for this packet */
4028 entry = &napt_hash_tbl_entries[hash_table_entry];
4031 /* apply napt and mac changes */
4033 p_nat->entries[pkt_num] = &(entry->head);
4035 uint32_t *dst_addr =
4036 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4037 uint16_t src_port_offset = 0;
4038 uint16_t dst_port_offset = 0;
4040 if ((protocol == IP_PROTOCOL_TCP) || (protocol == IP_PROTOCOL_UDP)) {
4041 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4042 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4043 } else if (protocol == IP_PROTOCOL_ICMP) {
4045 src_port_offset = MBUF_HDR_ROOM +
4048 /*Sequence number */
4049 dst_port_offset = MBUF_HDR_ROOM +
4054 uint16_t *src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
4055 uint16_t *dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
4057 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4058 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4060 if (entry->data.ttl == NAPT_ENTRY_STALE)
4061 entry->data.ttl = NAPT_ENTRY_VALID;
4063 uint32_t dest_address = 0;
4065 /* Multiport Changes */
4071 if (unlikely(protocol == IP_PROTOCOL_UDP
4072 && rte_be_to_cpu_16(*src_port) == 53)) {
4073 p_nat->invalid_packets |= pkt_mask;
4074 p_nat->naptDroppedPktCount++;
4075 #ifdef CGNAPT_DEBUGGING
4076 p_nat->naptDroppedPktCount6++;
4082 dest_address = entry->data.u.prv_ip;
4083 struct arp_entry_data *ret_arp_data = NULL;
4085 uint32_t src_phy_port = *src_port;
4088 dest_if = pub_to_prv_map[src_phy_port];
4089 gw_get_route_nh_port_ipv4(dest_address,
4090 &dest_if, &nhip, dest_if);
4092 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if,
4093 (struct ether_addr *)eth_dest);
4094 *outport_id = p_nat->outport_id[dest_if];
4096 if (arp_cache_dest_mac_present(dest_if)) {
4097 ether_addr_copy(get_link_hw_addr(dest_if), (struct ether_addr *)eth_src);
4098 update_nhip_access(dest_if);
4100 if (ret_arp_data && ret_arp_data->num_pkts) {
4101 p_nat->naptedPktCount += ret_arp_data->num_pkts;
4102 arp_send_buffered_pkts(ret_arp_data,
4103 (struct ether_addr *)eth_dest, *outport_id);
4108 if (unlikely(ret_arp_data == NULL)) {
4110 /* Commented code may be required for debug
4111 * and future use, Please keep it */
4113 #ifdef CGNAPT_DEBUGGING
4114 printf("%s: NHIP Not Found, nhip: %x, "
4115 "outport_id: %d\n", __func__, nhip,
4120 p_nat->invalid_packets |= pkt_mask;
4121 p_nat->naptDroppedPktCount++;
4123 #ifdef CGNAPT_DEBUGGING
4124 p_nat->naptDroppedPktCount4++;
4130 if (ret_arp_data->status == INCOMPLETE ||
4131 ret_arp_data->status == PROBE) {
4132 if (ret_arp_data->num_pkts >= NUM_DESC) {
4134 p_nat->invalid_packets |= pkt_mask;
4135 p_nat->naptDroppedPktCount++;
4137 #ifdef CGNAPT_DEBUGGING
4138 p_nat->naptDroppedPktCount4++;
4142 arp_pkts_mask |= pkt_mask;
4143 arp_queue_unresolved_packet(ret_arp_data, pkt);
4152 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
4153 if (protocol == IP_PROTOCOL_ICMP) {
4154 /* Query ID reverse translation done here */
4155 /* dont care sequence num */
4156 *src_port = rte_bswap16(entry->data.prv_port);
4159 #ifdef NAT_ONLY_CONFIG_REQ
4160 if (!nat_only_config_flag) {
4162 *dst_port = rte_bswap16(entry->data.prv_port);
4164 #ifdef NAT_ONLY_CONFIG_REQ
4168 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4169 rte_be_to_cpu_16(*dst_port) == 21) {
4170 pkt_mask = cgnapt_ct_process(cgnat_cnxn_tracker, pkts,
4171 pkt_mask, &ct_helper);
4177 uint16_t rtp_port = 0, rtcp_port = 0;
4178 struct cgnapt_table_entry *entry_ptr1 = NULL,
4181 /* Commented code may be required for debug
4182 * and future use, Please keep it */
4184 struct cgnapt_table_entry *entry_ptr2 = NULL,
4188 if (unlikely(protocol == IP_PROTOCOL_UDP
4189 && (rte_be_to_cpu_16(*dst_port) == 5060
4190 || rte_be_to_cpu_16(*src_port) == 5060))) {
4191 /* Commented code may be required for future usage,
4195 int ret = natSipAlgGetAudioPorts(pkt, &rtp_port,
4198 printf("%s: Wrong SIP ALG packet1\n",
4200 p_nat->invalid_packets |= pkt_mask;
4202 p_nat->naptDroppedPktCount++;
4204 #ifdef CGNAPT_DEBUGGING
4205 p_nat->naptDroppedPktCount4++;
4209 if (rtp_port != 0) {
4210 struct pipeline_cgnapt_entry_key rtp_key;
4211 rtp_key.ip = entry->data.pub_ip;
4212 rtp_key.port = rtp_port;
4213 rtp_key.pid = 0xffff;
4215 if (retrieve_cgnapt_entry_alg(&rtp_key,
4216 &entry_ptr1, &entry_ptr2) == 0) {
4217 printf("%s: Wrong SIP ALG packet2\n",
4219 p_nat->invalid_packets |= pkt_mask;
4221 p_nat->naptDroppedPktCount++;
4223 #ifdef CGNAPT_DEBUGGING
4224 p_nat->naptDroppedPktCount4++;
4230 if (rtcp_port != 0) {
4231 struct pipeline_cgnapt_entry_key rtcp_key;
4232 rtcp_key.ip = entry->data.pub_ip;
4233 rtcp_key.port = rtcp_port;
4234 rtcp_key.pid = 0xffff;
4236 if (retrieve_cgnapt_entry_alg(&rtcp_key,
4237 &entry_ptr3, &entry_ptr4) == 0) {
4238 printf("%s: Wrong SIP ALG packet3\n",
4240 p_nat->invalid_packets |= pkt_mask;
4242 p_nat->naptDroppedPktCount++;
4244 #ifdef CGNAPT_DEBUGGING
4245 p_nat->naptDroppedPktCount4++;
4253 if (sip_alg_dpi(pkt, PUBLIC, entry->data.u.prv_ip,
4254 entry->data.prv_port, entry->data.pub_ip,
4255 entry->data.pub_port, (rtp_port == 0) ? 0 :
4256 entry_ptr1->data.prv_port,
4257 (rtcp_port == 0) ? 0 :
4258 entry_ptr3->data.prv_port) == 0) {
4260 printf("%s: Wrong SIP ALG packet4\n",
4262 p_nat->invalid_packets |= pkt_mask;
4264 p_nat->naptDroppedPktCount++;
4266 #ifdef CGNAPT_DEBUGGING
4267 p_nat->naptDroppedPktCount4++;
4273 #endif /* SIP_ALG */
4276 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4277 rte_be_to_cpu_16(*dst_port) == 21) {
4278 int32_t ct_position = cgnat_cnxn_tracker->
4280 if (ct_position < 0){
4281 p_nat->invalid_packets |= pkt_mask;
4283 p_nat->naptDroppedPktCount++;
4287 rte_hexdump(stdout, "CT Entry", &cgnat_cnxn_tracker->
4288 hash_table_entries[ct_position].key, 40);
4291 /* Commented code may be required for debug
4292 * and future use, Please keep it*/
4293 //if (cgnat_cnxn_tracker->hash_table_entries
4294 // [ct_position].alg_bypass_flag != BYPASS)
4297 struct pipeline_cgnapt_entry_key
4298 data_channel_entry_key;
4300 data_channel_entry_key.ip = entry->data.pub_ip;
4301 data_channel_entry_key.port = entry->data.pub_port;
4302 data_channel_entry_key.pid = 0xffff;
4303 //printf("pkt_work_pub ftp_alg_dpi\n");
4304 ftp_alg_dpi(p_nat, &data_channel_entry_key, pkt,
4305 cgnat_cnxn_tracker, ct_position, PUBLIC);
4311 p_nat->inaptedPktCount++;
4314 p_nat->naptedPktCount++;
4317 if (p_nat->hw_checksum_reqd)
4318 hw_checksum(pkt, pkt_type);
4320 sw_checksum(pkt, pkt_type);
4326 * NAPT function for IPv4 private traffic which handles 4 pkts
4329 * A pointer to array of packets mbuf
4331 * Starting pkt number of pkts
4335 * A pointer to main CGNAPT structure
4339 pkt4_work_cgnapt_ipv4_prv(
4340 struct rte_mbuf **pkts,
4341 uint32_t in_pkt_num,
4342 __rte_unused void *arg,
4343 struct pipeline_cgnapt *p_nat)
4345 uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */
4346 struct rte_mbuf *pkt;
4349 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4352 struct rte_CT_helper ct_helper;
4353 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4356 for (i = 0; i < 4; i++) {
4357 pkt_num = in_pkt_num + i;
4358 pkt = pkts[pkt_num];
4360 /* index into hash table entries */
4361 int hash_table_entry = p_nat->lkup_indx[pkt_num];
4362 /*bitmask representing only this packet */
4363 uint64_t pkt_mask = 1LLU << pkt_num;
4365 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
4367 uint16_t *outport_id =
4368 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
4370 struct cgnapt_table_entry *entry = NULL;
4372 if (hash_table_entry < 0) {
4374 /* try to add new entry */
4375 struct rte_pipeline_table_entry *table_entry = NULL;
4378 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
4380 &p_nat->valid_packets, pkt_num,
4384 /* ICMP Error message generation for
4385 * Destination Host unreachable
4387 if (protocol == IP_PROTOCOL_ICMP) {
4388 cgnapt_icmp_pkt = pkt;
4389 send_icmp_dest_unreachable_msg();
4392 /* Drop packet by adding to invalid pkt mask */
4394 p_nat->invalid_packets |= dropmask;
4396 #ifdef CGNAPT_DEBUGGING
4397 if (p_nat->kpc2++ < 5) {
4398 printf("in_ah Th: %d",
4399 p_nat->pipeline_num);
4400 print_key(p_nat->key_ptrs[pkt_num]);
4404 p_nat->naptDroppedPktCount++;
4406 #ifdef CGNAPT_DEBUGGING
4407 p_nat->naptDroppedPktCount3++;
4412 entry = (struct cgnapt_table_entry *)table_entry;
4414 /* entry found for this packet */
4415 entry = &napt_hash_tbl_entries[hash_table_entry];
4418 /* apply napt and mac changes */
4420 p_nat->entries[pkt_num] = &(entry->head);
4422 uint32_t *src_addr =
4423 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP4);
4424 uint32_t *dst_addr =
4425 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4426 uint16_t src_port_offset = 0;
4427 uint16_t dst_port_offset = 0;
4432 if ((protocol == IP_PROTOCOL_TCP)
4433 || (protocol == IP_PROTOCOL_UDP)) {
4434 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4435 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4436 } else if (protocol == IP_PROTOCOL_ICMP) {
4438 src_port_offset = MBUF_HDR_ROOM +
4441 /*Sequence number */
4442 dst_port_offset = MBUF_HDR_ROOM +
4449 case IP_PROTOCOL_TCP:
4450 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4451 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4452 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4454 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4458 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4459 rte_be_to_cpu_16(*dst_port) == 21) {
4461 //To process CT , pkt_mask does it need
4462 //to be complemented ??
4464 printf("cgnapt_ct_process: pkt_mask: "
4465 "% "PRIu64", pkt_num: %d\n",
4469 pkt_mask = cgnapt_ct_process(
4470 cgnat_cnxn_tracker, pkts,
4471 pkt_mask, &ct_helper);
4475 case IP_PROTOCOL_UDP:
4476 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4477 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4478 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4480 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4483 case IP_PROTOCOL_ICMP:
4485 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
4487 /*Sequence number */
4488 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
4490 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4492 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4495 default: /* KW fix: unknown is treated as TCP/UDP */
4496 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4497 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4498 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4500 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4507 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4509 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4511 if (entry->data.ttl == NAPT_ENTRY_STALE)
4512 entry->data.ttl = NAPT_ENTRY_VALID;
4514 uint32_t dest_address = 0;
4515 /*Multiport Changes */
4522 if (unlikely(protocol == IP_PROTOCOL_UDP
4523 && rte_be_to_cpu_16(*dst_port) == 53)) {
4524 p_nat->invalid_packets |= pkt_mask;
4525 p_nat->naptDroppedPktCount++;
4527 #ifdef CGNAPT_DEBUGGING
4528 p_nat->naptDroppedPktCount6++;
4534 dest_address = rte_bswap32(*dst_addr);
4535 struct arp_entry_data *ret_arp_data = NULL;
4536 uint64_t start, end;
4537 uint32_t src_phy_port = *src_port;
4538 dest_if = prv_to_pub_map[src_phy_port];
4539 gw_get_route_nh_port_ipv4(dest_address,
4540 &dest_if, &nhip, dest_if);
4542 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if,
4543 (struct ether_addr *)eth_dest);
4545 *outport_id = p_nat->outport_id[dest_if];
4547 if (arp_cache_dest_mac_present(dest_if)) {
4548 ether_addr_copy(get_link_hw_addr(dest_if),
4549 (struct ether_addr *)eth_src);
4550 update_nhip_access(dest_if);
4552 if (ret_arp_data && ret_arp_data->num_pkts) {
4553 p_nat->naptedPktCount += ret_arp_data->num_pkts;
4554 arp_send_buffered_pkts(ret_arp_data,
4555 (struct ether_addr *)eth_dest, *outport_id);
4560 if (unlikely(ret_arp_data == NULL)) {
4562 #ifdef CGNAPT_DEBUGGING
4563 printf("%s: ARP Not Found, nhip: %x, "
4564 "outport_id: %d\n", __func__, nhip,
4569 p_nat->invalid_packets |= pkt_mask;
4570 p_nat->naptDroppedPktCount++;
4572 #ifdef CGNAPT_DEBUGGING
4573 p_nat->naptDroppedPktCount4++;
4579 if (ret_arp_data->status == INCOMPLETE ||
4580 ret_arp_data->status == PROBE) {
4581 if (ret_arp_data->num_pkts >= NUM_DESC) {
4583 p_nat->invalid_packets |= pkt_mask;
4584 p_nat->naptDroppedPktCount++;
4586 #ifdef CGNAPT_DEBUGGING
4587 p_nat->naptDroppedPktCount4++;
4591 arp_pkts_mask |= pkt_mask;
4592 arp_queue_unresolved_packet(ret_arp_data, pkt);
4600 *src_addr = rte_bswap32(entry->data.pub_ip);
4602 #ifdef NAT_ONLY_CONFIG_REQ
4603 if (!nat_only_config_flag) {
4605 *src_port = rte_bswap16(entry->data.pub_port);
4606 #ifdef NAT_ONLY_CONFIG_REQ
4611 uint16_t rtp_port = 0, rtcp_port = 0;
4612 struct cgnapt_table_entry *entry_ptr1 = NULL,
4613 *entry_ptr2 = NULL, *entry_ptr3 = NULL,
4616 if (unlikely(protocol == IP_PROTOCOL_UDP
4617 && (rte_be_to_cpu_16(*dst_port) == 5060
4618 || rte_be_to_cpu_16(*src_port) == 5060))) {
4620 int ret = natSipAlgGetAudioPorts(pkt,
4621 &rtp_port, &rtcp_port);
4622 /* Commented code may be required for future usage,
4627 printf("%s: Wrong SIP ALG packet1\n",
4629 p_nat->invalid_packets |= pkt_mask;
4631 p_nat->naptDroppedPktCount++;
4633 #ifdef CGNAPT_DEBUGGING
4634 p_nat->naptDroppedPktCount4++;
4640 if (ret >= 0 && rtp_port != 0) {
4641 struct pipeline_cgnapt_entry_key rtp_key;
4642 rtp_key.ip = entry->data.u.prv_ip;
4643 rtp_key.port = rtp_port;
4644 rtp_key.pid = entry->data.prv_phy_port;
4646 if (add_dynamic_cgnapt_entry_alg(
4647 (struct pipeline *)p_nat, &rtp_key,
4648 &entry_ptr1, &entry_ptr2) == 0) {
4649 printf("%s: Wrong SIP ALG packet2\n",
4651 p_nat->invalid_packets |= pkt_mask;
4653 p_nat->naptDroppedPktCount++;
4655 #ifdef CGNAPT_DEBUGGING
4656 p_nat->naptDroppedPktCount4++;
4662 if (ret >= 0 && rtcp_port != 0) {
4663 struct pipeline_cgnapt_entry_key rtcp_key;
4664 rtcp_key.ip = entry->data.u.prv_ip;
4665 rtcp_key.port = rtcp_port;
4666 rtcp_key.pid = entry->data.prv_phy_port;
4668 if (add_dynamic_cgnapt_entry_alg(
4669 (struct pipeline *)p_nat, &rtcp_key,
4670 &entry_ptr3, &entry_ptr4) == 0) {
4672 printf("%s: Wrong SIP ALG packet3\n",
4674 p_nat->invalid_packets |= pkt_mask;
4676 p_nat->naptDroppedPktCount++;
4678 #ifdef CGNAPT_DEBUGGING
4679 p_nat->naptDroppedPktCount4++;
4685 //if(entry_ptr1 != NULL && entry_ptr3 != NULL)
4686 if (sip_alg_dpi(pkt, PRIVATE,
4688 entry->data.pub_port,
4689 entry->data.u.prv_ip,
4690 entry->data.prv_port,
4691 (rtp_port == 0) ? 0 :
4692 entry_ptr1->data.pub_port,
4693 (rtcp_port == 0) ? 0 :
4694 entry_ptr3->data.pub_port) == 0) {
4696 printf("%s: Wrong SIP ALG packet4\n",
4698 p_nat->invalid_packets |= pkt_mask;
4700 p_nat->naptDroppedPktCount++;
4702 #ifdef CGNAPT_DEBUGGING
4703 p_nat->naptDroppedPktCount4++;
4708 #endif /* SIP_ALG */
4711 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4712 rte_be_to_cpu_16(*dst_port) == 21) {
4714 int32_t ct_position =
4715 cgnat_cnxn_tracker->positions[pkt_num];
4717 printf("@CGNAT-pkt4work ct_position :%d, pkt_num %d "
4718 "pkt_mask = %" PRIu64 "\n", ct_position,
4722 if (ct_position < 0){
4723 p_nat->invalid_packets |= pkt_mask;
4724 p_nat->naptDroppedPktCount++;
4727 if (cgnat_cnxn_tracker->hash_table_entries[ct_position].
4728 alg_bypass_flag != BYPASS){
4730 struct pipeline_cgnapt_entry_key
4731 data_channel_entry_key;
4733 data_channel_entry_key.ip =
4735 data_channel_entry_key.port =
4736 entry->data.pub_port;
4737 data_channel_entry_key.pid = 0xffff;
4739 ftp_alg_dpi(p_nat, &data_channel_entry_key,
4740 pkt, cgnat_cnxn_tracker, ct_position,
4746 p_nat->enaptedPktCount++;
4749 p_nat->naptedPktCount++;
4752 if (p_nat->hw_checksum_reqd)
4753 hw_checksum(pkt, pkt_type);
4755 sw_checksum(pkt, pkt_type);
4761 * NAPT function for IPv4 public traffic which handles 4 pkts
4764 * A pointer to array of packets mbuf
4766 * Starting pkt number of pkts
4770 * A pointer to main CGNAPT structure
4774 pkt4_work_cgnapt_ipv4_pub(
4775 struct rte_mbuf **pkts,
4776 uint32_t in_pkt_num,
4777 __rte_unused void *arg,
4778 struct pipeline_cgnapt *p_nat)
4781 struct rte_CT_helper ct_helper;
4782 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4784 struct rte_mbuf *pkt;
4787 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4789 for (i = 0; i < 4; i++) {
4790 pkt_num = in_pkt_num + i;
4791 pkt = pkts[pkt_num];
4793 /* index into hash table entries */
4794 int hash_table_entry = p_nat->lkup_indx[pkt_num];
4795 /*bitmask representing only this packet */
4796 uint64_t pkt_mask = 1LLU << pkt_num;
4798 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
4800 uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */
4801 uint16_t *outport_id =
4802 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
4804 struct cgnapt_table_entry *entry = NULL;
4806 if (hash_table_entry < 0) {
4808 /* try to add new entry */
4809 struct rte_pipeline_table_entry *table_entry = NULL;
4812 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
4814 &p_nat->valid_packets, pkt_num,
4818 /* ICMP Error message generation for
4819 * Destination Host unreachable
4821 if (protocol == IP_PROTOCOL_ICMP) {
4822 cgnapt_icmp_pkt = pkt;
4823 send_icmp_dest_unreachable_msg();
4826 /* Drop packet by adding to invalid pkt mask */
4828 p_nat->invalid_packets |= dropmask;
4830 #ifdef CGNAPT_DEBUGGING
4831 if (p_nat->kpc2++ < 5) {
4832 printf("in_ah Th: %d",
4833 p_nat->pipeline_num);
4834 print_key(p_nat->key_ptrs[pkt_num]);
4838 p_nat->naptDroppedPktCount++;
4840 #ifdef CGNAPT_DEBUGGING
4841 p_nat->naptDroppedPktCount3++;
4846 entry = (struct cgnapt_table_entry *)table_entry;
4848 /* entry found for this packet */
4849 entry = &napt_hash_tbl_entries[hash_table_entry];
4852 /* apply napt and mac changes */
4854 p_nat->entries[pkt_num] = &(entry->head);
4856 uint32_t *dst_addr =
4857 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4858 uint16_t src_port_offset = 0;
4859 uint16_t dst_port_offset = 0;
4861 if ((protocol == IP_PROTOCOL_TCP)
4862 || (protocol == IP_PROTOCOL_UDP)) {
4863 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4864 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4865 } else if (protocol == IP_PROTOCOL_ICMP) {
4867 src_port_offset = MBUF_HDR_ROOM +
4870 /*Sequence number */
4871 dst_port_offset = MBUF_HDR_ROOM +
4876 uint16_t *src_port =
4877 RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
4878 uint16_t *dst_port =
4879 RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
4882 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4884 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4886 if (entry->data.ttl == NAPT_ENTRY_STALE)
4887 entry->data.ttl = NAPT_ENTRY_VALID;
4889 uint32_t dest_address = 0;
4890 /* Multiport Changes */
4896 if (unlikely(protocol == IP_PROTOCOL_UDP
4897 && rte_be_to_cpu_16(*src_port) == 53)) {
4898 p_nat->invalid_packets |= pkt_mask;
4899 p_nat->naptDroppedPktCount++;
4900 #ifdef CGNAPT_DEBUGGING
4901 p_nat->naptDroppedPktCount6++;
4906 dest_address = entry->data.u.prv_ip;
4907 struct arp_entry_data *ret_arp_data = NULL;
4908 uint32_t src_phy_port = *src_port;
4909 dest_if = pub_to_prv_map[src_phy_port];
4910 gw_get_route_nh_port_ipv4(dest_address,
4911 &dest_if, &nhip, dest_if);
4913 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if,
4914 (struct ether_addr *)eth_dest);
4916 *outport_id = p_nat->outport_id[dest_if];
4918 if (arp_cache_dest_mac_present(dest_if)) {
4919 ether_addr_copy(get_link_hw_addr(dest_if),
4920 (struct ether_addr *)eth_src);
4921 update_nhip_access(dest_if);
4923 if (ret_arp_data && ret_arp_data->num_pkts) {
4924 p_nat->naptedPktCount += ret_arp_data->num_pkts;
4925 arp_send_buffered_pkts(ret_arp_data,
4926 (struct ether_addr *)eth_dest, *outport_id);
4931 if (unlikely(ret_arp_data == NULL)) {
4933 #ifdef CGNAPT_DEBUGGING
4934 printf("%s: NHIP Not Found, nhip: %x, "
4935 "outport_id: %d\n", __func__, nhip,
4940 p_nat->invalid_packets |= pkt_mask;
4941 p_nat->naptDroppedPktCount++;
4943 #ifdef CGNAPT_DEBUGGING
4944 p_nat->naptDroppedPktCount4++;
4949 if (ret_arp_data->status == INCOMPLETE ||
4950 ret_arp_data->status == PROBE) {
4951 if (ret_arp_data->num_pkts >= NUM_DESC) {
4953 p_nat->invalid_packets |= pkt_mask;
4954 p_nat->naptDroppedPktCount++;
4956 #ifdef CGNAPT_DEBUGGING
4957 p_nat->naptDroppedPktCount4++;
4961 arp_pkts_mask |= pkt_mask;
4962 arp_queue_unresolved_packet(ret_arp_data, pkt);
4971 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
4972 if (protocol == IP_PROTOCOL_ICMP) {
4973 /* Query ID reverse translation done here */
4974 *src_port = rte_bswap16(entry->data.prv_port);
4975 /* dont care sequence num */
4977 #ifdef NAT_ONLY_CONFIG_REQ
4978 if (!nat_only_config_flag) {
4981 rte_bswap16(entry->data.prv_port);
4982 #ifdef NAT_ONLY_CONFIG_REQ
4987 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4988 rte_be_to_cpu_16(*dst_port) == 21) {
4989 pkt_mask = cgnapt_ct_process(
4990 cgnat_cnxn_tracker, pkts,
4991 pkt_mask, &ct_helper);
4997 uint16_t rtp_port = 0, rtcp_port = 0;
4998 struct cgnapt_table_entry *entry_ptr1 = NULL,
5000 /* Commented code may be required for future usage,
5004 struct cgnapt_table_entry *entry_ptr2 = NULL,
5008 if (unlikely(protocol == IP_PROTOCOL_UDP
5009 && (rte_be_to_cpu_16(*dst_port) == 5060
5010 || rte_be_to_cpu_16(*src_port) == 5060))) {
5011 /* Commented code may be required for future usage,
5015 int ret = natSipAlgGetAudioPorts(pkt,
5016 &rtp_port, &rtcp_port);
5018 printf("%s: Wrong SIP ALG packet1\n",
5020 p_nat->invalid_packets |= pkt_mask;
5022 p_nat->naptDroppedPktCount++;
5024 #ifdef CGNAPT_DEBUGGING
5025 p_nat->naptDroppedPktCount4++;
5030 if (rtp_port != 0) {
5031 struct pipeline_cgnapt_entry_key rtp_key;
5032 rtp_key.ip = entry->data.pub_ip;
5033 rtp_key.port = rtp_port;
5034 rtp_key.pid = 0xffff;
5036 if (retrieve_cgnapt_entry_alg(&rtp_key,
5037 &entry_ptr1, &entry_ptr2) == 0) {
5038 printf("%s: Wrong SIP ALG packet2\n",
5040 p_nat->invalid_packets |= pkt_mask;
5042 p_nat->naptDroppedPktCount++;
5044 #ifdef CGNAPT_DEBUGGING
5045 p_nat->naptDroppedPktCount4++;
5051 if (rtcp_port != 0) {
5052 struct pipeline_cgnapt_entry_key rtcp_key;
5053 rtcp_key.ip = entry->data.pub_ip;
5054 rtcp_key.port = rtcp_port;
5055 rtcp_key.pid = 0xffff;
5057 if (retrieve_cgnapt_entry_alg(&rtcp_key,
5058 &entry_ptr3, &entry_ptr4) == 0) {
5059 printf("%s: Wrong SIP ALG packet3\n",
5061 p_nat->invalid_packets |= pkt_mask;
5062 p_nat->naptDroppedPktCount++;
5064 #ifdef CGNAPT_DEBUGGING
5065 p_nat->naptDroppedPktCount4++;
5072 if (sip_alg_dpi(pkt, PUBLIC,
5073 entry->data.u.prv_ip,
5074 entry->data.prv_port,
5076 entry->data.pub_port,
5077 (rtp_port == 0) ? 0 :
5078 entry_ptr1->data.prv_port,
5079 (rtcp_port == 0) ? 0 :
5080 entry_ptr3->data.prv_port) == 0) {
5082 printf("%s: Wrong SIP ALG packet4\n",
5084 p_nat->invalid_packets |= pkt_mask;
5086 p_nat->naptDroppedPktCount++;
5088 #ifdef CGNAPT_DEBUGGING
5089 p_nat->naptDroppedPktCount4++;
5094 #endif /* SIP_ALG */
5097 if ((rte_be_to_cpu_16(*src_port) == 21) ||
5098 rte_be_to_cpu_16(*dst_port) == 21) {
5100 int32_t ct_position =
5101 cgnat_cnxn_tracker->positions[pkt_num];
5102 if (ct_position < 0){
5103 p_nat->invalid_packets |= pkt_mask;
5105 p_nat->naptDroppedPktCount++;
5108 if (cgnat_cnxn_tracker->hash_table_entries
5109 [ct_position].alg_bypass_flag != BYPASS){
5111 struct pipeline_cgnapt_entry_key
5112 data_channel_entry_key;
5115 data_channel_entry_key.ip =
5117 data_channel_entry_key.port =
5118 entry->data.pub_port;
5119 data_channel_entry_key.pid = 0xffff;
5121 ftp_alg_dpi(p_nat, &data_channel_entry_key,
5122 pkt, cgnat_cnxn_tracker,
5123 ct_position, PUBLIC);
5128 p_nat->inaptedPktCount++;
5131 p_nat->naptedPktCount++;
5134 if (p_nat->hw_checksum_reqd)
5135 hw_checksum(pkt, pkt_type);
5137 sw_checksum(pkt, pkt_type);
5143 * NAPT key calculation function for IPv6 private traffic
5144 * which handles 1 pkt
5147 * A pointer to array of packets mbuf
5149 * Pkt number of pkts
5153 * A pointer to main CGNAPT structure
5157 pkt_work_cgnapt_key_ipv6_prv(
5158 struct rte_mbuf *pkt,
5160 __rte_unused void *arg,
5161 struct pipeline_cgnapt *p_nat)
5164 p_nat->receivedPktCount++;
5166 /* bitmask representing only this packet */
5167 uint64_t pkt_mask = 1LLU << pkt_num;
5169 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
5170 uint32_t *src_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
5172 uint16_t src_port = RTE_MBUF_METADATA_UINT16(pkt, SRC_PRT_OFST_IP6);
5174 uint16_t phy_port = pkt->port;
5175 struct pipeline_cgnapt_entry_key key;
5177 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
5179 #ifdef CGNAPT_DBG_PRNT
5180 if (CGNAPT_DEBUG > 4)
5185 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
5190 case IP_PROTOCOL_UDP:
5194 struct udp_hdr *udp;
5196 udp = (struct udp_hdr *)
5197 RTE_MBUF_METADATA_UINT8_PTR(pkt,
5200 if (rte_bswap16(udp->dst_port) ==
5202 handle_pcp_req(pkt, IPV6_SZ, p_nat);
5203 p_nat->invalid_packets |= pkt_mask;
5209 case IP_PROTOCOL_TCP:
5210 case IP_PROTOCOL_ICMP:
5211 /*we don't need icmp check in ipv6 */
5215 printf("wrong protocol: %d\n", protocol);
5216 /* remember invalid packets to be dropped */
5217 p_nat->invalid_packets |= pkt_mask;
5218 p_nat->naptDroppedPktCount++;
5220 #ifdef CGNAPT_DEBUGGING
5221 p_nat->naptDroppedPktCount2++;
5227 key.ip = rte_bswap32(src_addr[3]);
5228 key.port = rte_bswap16(src_port);
5230 #ifdef NAT_ONLY_CONFIG_REQ
5231 if (nat_only_config_flag)
5235 memcpy(&p_nat->keys[pkt_num], &key,
5236 sizeof(struct pipeline_cgnapt_entry_key));
5237 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5241 * NAPT key calculation function for IPv6 public traffic
5242 * which handles 1 pkt
5245 * A pointer to array of packets mbuf
5247 * Pkt number of pkts
5251 * A pointer to main CGNAPT structure
5255 pkt_work_cgnapt_key_ipv6_pub(
5256 struct rte_mbuf *pkt,
5258 __rte_unused void *arg,
5259 struct pipeline_cgnapt *p_nat)
5263 p_nat->receivedPktCount++;
5265 /* bitmask representing only this packet */
5266 uint64_t pkt_mask = 1LLU << pkt_num;
5268 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
5270 uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
5272 uint16_t dst_port = RTE_MBUF_METADATA_UINT16(pkt,
5273 DST_PRT_OFST_IP4_TCP);
5275 struct pipeline_cgnapt_entry_key key;
5277 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
5279 #ifdef CGNAPT_DBG_PRNT
5280 if (CGNAPT_DEBUG > 4)
5285 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
5291 case IP_PROTOCOL_UDP:
5292 case IP_PROTOCOL_TCP:
5293 case IP_PROTOCOL_ICMP:
5294 /*we don't need icmp check in ipv6 */
5298 /* remember invalid packets to be dropped */
5299 p_nat->invalid_packets |= pkt_mask;
5300 p_nat->naptDroppedPktCount++;
5302 #ifdef CGNAPT_DEBUGGING
5303 p_nat->naptDroppedPktCount2++;
5309 key.ip = rte_bswap32(dst_addr[0]);
5310 key.port = rte_bswap16(dst_port);
5312 #ifdef NAT_ONLY_CONFIG_REQ
5313 if (nat_only_config_flag)
5317 memcpy(&p_nat->keys[pkt_num], &key,
5318 sizeof(struct pipeline_cgnapt_entry_key));
5319 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5323 * NAPT key calculation function for IPv6 private traffic
5324 * which handles 4 pkts
5327 * A pointer to array of packets mbuf
5329 * Starting pkt number of pkts
5333 * A pointer to main CGNAPT structure
5337 pkt4_work_cgnapt_key_ipv6_prv(
5338 struct rte_mbuf **pkt,
5340 __rte_unused void *arg,
5341 struct pipeline_cgnapt *p_nat)
5343 p_nat->receivedPktCount += 4;
5345 /* bitmask representing only this packet */
5346 uint64_t pkt_mask0 = 1LLU << pkt_num;
5347 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
5348 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
5349 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
5351 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
5353 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
5355 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
5357 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
5360 uint32_t *src_addr0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0],
5362 uint32_t *src_addr1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1],
5364 uint32_t *src_addr2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2],
5366 uint32_t *src_addr3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3],
5369 uint16_t src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
5371 uint16_t src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
5373 uint16_t src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
5375 uint16_t src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
5378 uint16_t phy_port0 = pkt[0]->port;
5379 uint16_t phy_port1 = pkt[1]->port;
5380 uint16_t phy_port2 = pkt[2]->port;
5381 uint16_t phy_port3 = pkt[3]->port;
5383 struct pipeline_cgnapt_entry_key key0;
5384 struct pipeline_cgnapt_entry_key key1;
5385 struct pipeline_cgnapt_entry_key key2;
5386 struct pipeline_cgnapt_entry_key key3;
5388 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
5389 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
5390 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
5391 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
5395 #ifdef CGNAPT_DBG_PRNT
5396 if (CGNAPT_DEBUG > 4)
5401 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
5405 switch (protocol0) {
5407 case IP_PROTOCOL_UDP:
5411 struct udp_hdr *udp;
5413 udp = (struct udp_hdr *)
5414 RTE_MBUF_METADATA_UINT8_PTR(pkt[0],
5417 if (rte_bswap16(udp->dst_port) ==
5419 handle_pcp_req(pkt[0], IPV6_SZ, p_nat);
5420 p_nat->invalid_packets |= pkt_mask0;
5426 case IP_PROTOCOL_TCP:
5427 case IP_PROTOCOL_ICMP:
5428 /*we don't need icmp check in ipv6 */
5432 /* remember invalid packets to be dropped */
5433 p_nat->invalid_packets |= pkt_mask0;
5434 p_nat->naptDroppedPktCount++;
5436 #ifdef CGNAPT_DEBUGGING
5437 p_nat->naptDroppedPktCount2++;
5444 key0.pid = phy_port0;
5445 key0.ip = rte_bswap32(src_addr0[3]);
5446 key0.port = rte_bswap16(src_port0);
5448 #ifdef NAT_ONLY_CONFIG_REQ
5449 if (nat_only_config_flag)
5453 memcpy(&p_nat->keys[pkt_num], &key0,
5454 sizeof(struct pipeline_cgnapt_entry_key));
5455 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5458 #ifdef CGNAPT_DBG_PRNT
5459 if (CGNAPT_DEBUG > 4)
5464 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
5468 switch (protocol1) {
5469 case IP_PROTOCOL_UDP:
5473 struct udp_hdr *udp;
5475 udp = (struct udp_hdr *)
5476 RTE_MBUF_METADATA_UINT8_PTR(pkt[1],
5479 if (rte_bswap16(udp->dst_port) ==
5481 handle_pcp_req(pkt[1], IPV6_SZ, p_nat);
5482 p_nat->invalid_packets |= pkt_mask1;
5488 case IP_PROTOCOL_TCP:
5489 case IP_PROTOCOL_ICMP:
5490 /*we don't need icmp check in ipv6 */
5494 /* remember invalid packets to be dropped */
5495 p_nat->invalid_packets |= pkt_mask1;
5496 p_nat->naptDroppedPktCount++;
5498 #ifdef CGNAPT_DEBUGGING
5499 p_nat->naptDroppedPktCount2++;
5505 key1.pid = phy_port1;
5506 key1.ip = rte_bswap32(src_addr1[3]);
5507 key1.port = rte_bswap16(src_port1);
5509 #ifdef NAT_ONLY_CONFIG_REQ
5510 if (nat_only_config_flag)
5514 memcpy(&p_nat->keys[pkt_num + 1], &key1,
5515 sizeof(struct pipeline_cgnapt_entry_key));
5516 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
5519 #ifdef CGNAPT_DBG_PRNT
5520 if (CGNAPT_DEBUG > 4)
5525 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
5529 switch (protocol2) {
5530 case IP_PROTOCOL_UDP:
5534 struct udp_hdr *udp;
5536 udp = (struct udp_hdr *)
5537 RTE_MBUF_METADATA_UINT8_PTR(pkt[2],
5540 if (rte_bswap16(udp->dst_port) ==
5542 handle_pcp_req(pkt[2], IPV6_SZ, p_nat);
5543 p_nat->invalid_packets |= pkt_mask2;
5549 case IP_PROTOCOL_TCP:
5550 case IP_PROTOCOL_ICMP:
5551 /*we don't need icmp check in ipv6 */
5555 /* remember invalid packets to be dropped */
5556 p_nat->invalid_packets |= pkt_mask2;
5557 p_nat->naptDroppedPktCount++;
5559 #ifdef CGNAPT_DEBUGGING
5560 p_nat->naptDroppedPktCount2++;
5566 key2.pid = phy_port2;
5567 key2.ip = rte_bswap32(src_addr2[3]);
5568 key2.port = rte_bswap16(src_port2);
5570 #ifdef NAT_ONLY_CONFIG_REQ
5571 if (nat_only_config_flag)
5575 memcpy(&p_nat->keys[pkt_num + 2], &key2,
5576 sizeof(struct pipeline_cgnapt_entry_key));
5577 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
5580 #ifdef CGNAPT_DBG_PRNT
5581 if (CGNAPT_DEBUG > 4)
5586 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
5590 switch (protocol3) {
5591 case IP_PROTOCOL_UDP:
5595 struct udp_hdr *udp;
5597 udp = (struct udp_hdr *)
5598 RTE_MBUF_METADATA_UINT8_PTR(pkt[3],
5601 if (rte_bswap16(udp->dst_port) ==
5603 handle_pcp_req(pkt[3], IPV6_SZ, p_nat);
5604 p_nat->invalid_packets |= pkt_mask3;
5610 case IP_PROTOCOL_TCP:
5611 case IP_PROTOCOL_ICMP:
5612 /*we don't need icmp check in ipv6 */
5616 /* remember invalid packets to be dropped */
5617 p_nat->invalid_packets |= pkt_mask2;
5618 p_nat->naptDroppedPktCount++;
5620 #ifdef CGNAPT_DEBUGGING
5621 p_nat->naptDroppedPktCount2++;
5627 key3.pid = phy_port3;
5628 key3.ip = rte_bswap32(src_addr3[3]);
5629 key3.port = rte_bswap16(src_port3);
5631 #ifdef NAT_ONLY_CONFIG_REQ
5632 if (nat_only_config_flag)
5636 memcpy(&p_nat->keys[pkt_num + 3], &key3,
5637 sizeof(struct pipeline_cgnapt_entry_key));
5638 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
5644 * NAPT key calculation function for IPv4 public traffic
5645 * which handles 4 pkts
5648 * A pointer to array of packets mbuf
5650 * Starting pkt number of pkts
5654 * A pointer to main CGNAPT structure
5658 pkt4_work_cgnapt_key_ipv6_pub(
5659 struct rte_mbuf **pkt,
5661 __rte_unused void *arg,
5662 struct pipeline_cgnapt *p_nat)
5664 p_nat->receivedPktCount += 4;
5666 /* bitmask representing only this packet */
5667 uint64_t pkt_mask0 = 1LLU << pkt_num;
5668 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
5669 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
5670 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
5672 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
5674 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
5676 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
5678 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
5681 uint32_t *dst_addr0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0],
5683 uint32_t *dst_addr1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1],
5685 uint32_t *dst_addr2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2],
5687 uint32_t *dst_addr3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3],
5690 uint16_t dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
5691 DST_PRT_OFST_IP4_TCP);
5692 uint16_t dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
5693 DST_PRT_OFST_IP4_TCP);
5694 uint16_t dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
5695 DST_PRT_OFST_IP4_TCP);
5696 uint16_t dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
5697 DST_PRT_OFST_IP4_TCP);
5699 struct pipeline_cgnapt_entry_key key0;
5700 struct pipeline_cgnapt_entry_key key1;
5701 struct pipeline_cgnapt_entry_key key2;
5702 struct pipeline_cgnapt_entry_key key3;
5704 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
5705 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
5706 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
5707 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
5711 #ifdef CGNAPT_DBG_PRNT
5712 if (CGNAPT_DEBUG > 4)
5717 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
5721 switch (protocol0) {
5723 case IP_PROTOCOL_TCP:
5724 case IP_PROTOCOL_UDP:
5725 case IP_PROTOCOL_ICMP:
5726 /*we don't need icmp check in ipv6 */
5730 /* remember invalid packets to be dropped */
5731 p_nat->invalid_packets |= pkt_mask0;
5732 p_nat->naptDroppedPktCount++;
5734 #ifdef CGNAPT_DEBUGGING
5735 p_nat->naptDroppedPktCount2++;
5741 key0.ip = rte_bswap32(dst_addr0[0]);
5742 key0.port = rte_bswap16(dst_port0);
5744 #ifdef NAT_ONLY_CONFIG_REQ
5745 if (nat_only_config_flag)
5749 memcpy(&p_nat->keys[pkt_num], &key0,
5750 sizeof(struct pipeline_cgnapt_entry_key));
5751 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5757 #ifdef CGNAPT_DBG_PRNT
5758 if (CGNAPT_DEBUG > 4)
5763 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
5767 switch (protocol1) {
5769 case IP_PROTOCOL_TCP:
5770 case IP_PROTOCOL_UDP:
5771 case IP_PROTOCOL_ICMP:
5772 /*we don't need icmp check in ipv6 */
5776 /* remember invalid packets to be dropped */
5777 p_nat->invalid_packets |= pkt_mask1;
5778 p_nat->naptDroppedPktCount++;
5780 #ifdef CGNAPT_DEBUGGING
5781 p_nat->naptDroppedPktCount2++;
5787 key1.ip = rte_bswap32(dst_addr1[0]);
5788 key1.port = rte_bswap16(dst_port1);
5790 #ifdef NAT_ONLY_CONFIG_REQ
5791 if (nat_only_config_flag)
5795 memcpy(&p_nat->keys[pkt_num + 1], &key1,
5796 sizeof(struct pipeline_cgnapt_entry_key));
5797 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
5803 #ifdef CGNAPT_DBG_PRNT
5804 if (CGNAPT_DEBUG > 4)
5809 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
5813 switch (protocol2) {
5815 case IP_PROTOCOL_TCP:
5816 case IP_PROTOCOL_UDP:
5817 case IP_PROTOCOL_ICMP:
5818 /*we don't need icmp check in ipv6 */
5822 /* remember invalid packets to be dropped */
5823 p_nat->invalid_packets |= pkt_mask2;
5824 p_nat->naptDroppedPktCount++;
5826 #ifdef CGNAPT_DEBUGGING
5827 p_nat->naptDroppedPktCount2++;
5833 key2.ip = rte_bswap32(dst_addr2[0]);
5834 key2.port = rte_bswap16(dst_port2);
5836 #ifdef NAT_ONLY_CONFIG_REQ
5837 if (nat_only_config_flag)
5841 memcpy(&p_nat->keys[pkt_num + 2], &key2,
5842 sizeof(struct pipeline_cgnapt_entry_key));
5844 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
5850 #ifdef CGNAPT_DBG_PRNT
5851 if (CGNAPT_DEBUG > 4)
5856 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
5860 switch (protocol3) {
5862 case IP_PROTOCOL_TCP:
5863 case IP_PROTOCOL_UDP:
5864 case IP_PROTOCOL_ICMP:
5865 /*we don't need icmp check in ipv6 */
5869 /* remember invalid packets to be dropped */
5870 p_nat->invalid_packets |= pkt_mask3;
5871 p_nat->naptDroppedPktCount++;
5873 #ifdef CGNAPT_DEBUGGING
5874 p_nat->naptDroppedPktCount2++;
5880 key3.ip = rte_bswap32(dst_addr3[0]);
5881 key3.port = rte_bswap16(dst_port3);
5883 #ifdef NAT_ONLY_CONFIG_REQ
5884 if (nat_only_config_flag)
5888 memcpy(&p_nat->keys[pkt_num + 3], &key3,
5889 sizeof(struct pipeline_cgnapt_entry_key));
5891 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
5895 * NAPT function for IPv6 private traffic which handles 1 pkt
5898 * A pointer to array of packet mbuf
5904 * A pointer to main CGNAPT structure
5908 pkt_work_cgnapt_ipv6_prv(
5909 struct rte_mbuf *pkt,
5911 __rte_unused void *arg,
5912 struct pipeline_cgnapt *p_nat)
5914 /* index into hash table entries */
5915 int hash_table_entry = p_nat->lkup_indx[pkt_num];
5917 /*bitmask representing only this packet */
5918 uint64_t pkt_mask = 1LLU << pkt_num;
5920 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
5922 /* Added for Multiport */
5923 uint32_t dest_if = INVALID_DESTIF;
5924 uint16_t *outport_id = RTE_MBUF_METADATA_UINT16_PTR(pkt,
5925 cgnapt_meta_offset);
5927 struct cgnapt_table_entry *entry = NULL;
5928 enum PKT_TYPE pkt_type = PKT_TYPE_IPV6to4;
5930 if (hash_table_entry < 0) {
5932 /* try to add new entry */
5933 struct rte_pipeline_table_entry *table_entry = NULL;
5935 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
5937 &p_nat->valid_packets, pkt_num,
5941 /* ICMP Error message generation for
5942 * Destination Host unreachable
5944 /* Do we need this check for ipv6? */
5945 if (protocol == IP_PROTOCOL_ICMP) {
5946 cgnapt_icmp_pkt = pkt;
5947 send_icmp_dest_unreachable_msg();
5950 /* Drop packet by adding to invalid pkt mask */
5952 p_nat->invalid_packets |= dropmask;
5954 #ifdef CGNAPT_DEBUGGING
5955 if (p_nat->kpc2++ < 5) {
5956 printf("in_ah Th: %d", p_nat->pipeline_num);
5957 print_key(p_nat->key_ptrs[pkt_num]);
5961 p_nat->naptDroppedPktCount++;
5963 #ifdef CGNAPT_DEBUGGING
5964 p_nat->naptDroppedPktCount3++;
5970 entry = (struct cgnapt_table_entry *)table_entry;
5972 /* entry found for this packet */
5973 entry = &napt_hash_tbl_entries[hash_table_entry];
5976 /* apply napt and mac changes */
5978 p_nat->entries[pkt_num] = &(entry->head);
5980 struct ipv6_hdr ipv6_hdr;
5982 uint32_t dest_address = 0;
5987 convert_ipv6_to_ipv4(pkt, &ipv6_hdr);
5989 #ifdef CGNAPT_DBG_PRNT
5990 if (CGNAPT_DEBUG == 1)
5991 printf("pkt_work_cganpt: convert_ipv6_to_ipv4\n");
5994 struct cgnapt_nsp_node *ll = nsp_ll;
5997 while (ll != NULL) {
5999 (&ipv6_hdr.dst_addr[0], &ll->nsp.prefix[0],
6000 ll->nsp.depth / 8)) {
6008 && !memcmp(&ipv6_hdr.dst_addr[0], &well_known_prefix[0],
6014 p_nat->invalid_packets |= pkt_mask;
6015 p_nat->naptDroppedPktCount++;
6017 #ifdef CGNAPT_DEBUGGING
6018 p_nat->naptDroppedPktCount5++;
6026 /* As packet is already converted into IPv4 we must not
6027 * operate IPv6 offsets on packet
6028 * Only perform IPv4 operations
6031 uint32_t *src_addr =
6032 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP6t4);
6033 uint32_t *dst_addr =
6034 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP6t4);
6035 uint16_t *src_port =
6036 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP6t4);
6037 uint16_t *dst_port =
6038 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP6t4);
6040 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt,
6042 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt,
6043 ETH_OFST_IP6t4 + 6);
6045 if (entry->data.ttl == NAPT_ENTRY_STALE)
6046 entry->data.ttl = NAPT_ENTRY_VALID;
6049 if (unlikely(protocol == IP_PROTOCOL_UDP
6050 && rte_be_to_cpu_16(*dst_port) == 53)) {
6051 p_nat->invalid_packets |= pkt_mask;
6052 p_nat->naptDroppedPktCount++;
6054 #ifdef CGNAPT_DEBUGGING
6055 p_nat->naptDroppedPktCount6++;
6061 dest_address = rte_bswap32(*dst_addr);
6062 /*Multiport Changes */
6065 #ifdef CGNAPT_DBG_PRNT
6066 if (CGNAPT_DEBUG > 2)
6067 printf("Egress: \tphy_port:%d\t get_prv_to_pub():%d "
6068 "\tout_port:%d\n", pkt->port,
6069 dest_if, *outport_id);
6073 #ifdef CGNAPT_DBG_PRNT
6074 static int static_count;
6076 if (static_count++ < 10) {
6078 my_print_entry(entry);
6079 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6080 printf("dest_add:%x\n", entry->data.u.prv_ip);
6081 printf("dest_add:%x\n", *dst_addr);
6082 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6086 struct arp_entry_data *ret_arp_data;
6088 uint32_t src_phy_port = *src_port;
6090 dest_if = prv_to_pub_map[src_phy_port];
6091 gw_get_route_nh_port_ipv4(dest_address,
6092 &dest_if, &nhip, dest_if);
6094 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if,
6095 (struct ether_addr *)eth_dest);
6097 *outport_id = p_nat->outport_id[dest_if];
6099 if (arp_cache_dest_mac_present(dest_if)) {
6100 ether_addr_copy(get_link_hw_addr(dest_if),
6101 (struct ether_addr *)eth_src);
6102 update_nhip_access(dest_if);
6104 if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) {
6105 p_nat->naptedPktCount += ret_arp_data->num_pkts;
6106 arp_send_buffered_pkts(ret_arp_data,
6107 (struct ether_addr *)eth_dest, *outport_id);
6112 if (unlikely(ret_arp_data == NULL)) {
6114 #ifdef CGNAPT_DEBUGGING
6115 printf("%s: NHIP Not Found, nhip:%x , "
6116 "outport_id: %d\n", __func__, nhip,
6121 p_nat->invalid_packets |= pkt_mask;
6122 p_nat->naptDroppedPktCount++;
6124 #ifdef CGNAPT_DEBUGGING
6125 p_nat->naptDroppedPktCount4++;
6130 if (ret_arp_data->status == INCOMPLETE ||
6131 ret_arp_data->status == PROBE) {
6132 if (ret_arp_data->num_pkts >= NUM_DESC) {
6134 p_nat->invalid_packets |= pkt_mask;
6135 p_nat->naptDroppedPktCount++;
6137 #ifdef CGNAPT_DEBUGGING
6138 p_nat->naptDroppedPktCount4++;
6142 arp_pkts_mask |= pkt_mask;
6143 arp_queue_unresolved_packet(ret_arp_data, pkt);
6151 *src_addr = rte_bswap32(entry->data.pub_ip);
6153 #ifdef NAT_ONLY_CONFIG_REQ
6154 if (!nat_only_config_flag) {
6156 *src_port = rte_bswap16(entry->data.pub_port);
6158 #ifdef NAT_ONLY_CONFIG_REQ
6162 p_nat->enaptedPktCount++;
6165 p_nat->naptedPktCount++;
6168 if (p_nat->hw_checksum_reqd)
6169 hw_checksum(pkt, pkt_type);
6171 sw_checksum(pkt, pkt_type);
6177 * NAPT function for IPv6 public traffic which handles 1 pkt
6180 * A pointer to array of packet mbuf
6186 * A pointer to main CGNAPT structure
6190 pkt_work_cgnapt_ipv6_pub(
6191 struct rte_mbuf *pkt,
6193 __rte_unused void *arg,
6194 struct pipeline_cgnapt *p_nat)
6197 /* index into hash table entries */
6198 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6199 /*bitmask representing only this packet */
6200 uint64_t pkt_mask = 1LLU << pkt_num;
6202 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
6204 uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */
6205 uint16_t *outport_id =
6206 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6207 struct cgnapt_table_entry *entry = NULL;
6209 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4to6;
6211 if (hash_table_entry < 0) {
6213 /* Drop ingress initial traffic */
6215 p_nat->invalid_packets |= pkt_mask;
6216 p_nat->naptDroppedPktCount++;
6218 #ifdef CGNAPT_DEBUGGING
6219 p_nat->naptDroppedPktCount3++;
6220 if (p_nat->kpc2++ < 5) {
6221 printf("in_ah Th: %d", p_nat->pipeline_num);
6222 print_key(p_nat->key_ptrs[pkt_num]);
6229 /* entry found for this packet */
6230 entry = &napt_hash_tbl_entries[hash_table_entry];
6233 /* apply napt and mac changes */
6235 p_nat->entries[pkt_num] = &(entry->head);
6236 if (entry->data.type != CGNAPT_ENTRY_IPV6) {
6237 p_nat->invalid_packets |= pkt_mask;
6238 p_nat->naptDroppedPktCount++;
6242 struct ipv4_hdr ipv4_hdr;
6243 uint16_t *src_port =
6244 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP4_TCP);
6246 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
6247 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
6249 if (entry->data.ttl == NAPT_ENTRY_STALE)
6250 entry->data.ttl = NAPT_ENTRY_VALID;
6252 struct ether_addr hw_addr;
6253 uint8_t dest_addr_ipv6[16];
6254 uint8_t nh_ipv6[16];
6259 if (unlikely(protocol == IP_PROTOCOL_UDP
6260 && rte_be_to_cpu_16(*src_port) == 53)) {
6261 p_nat->invalid_packets |= pkt_mask;
6262 p_nat->naptDroppedPktCount++;
6263 #ifdef CGNAPT_DEBUGGING
6264 p_nat->naptDroppedPktCount6++;
6269 memcpy(&dest_addr_ipv6[0], &entry->data.u.prv_ipv6[0], 16);
6272 memset(nh_ipv6, 0, 16);
6273 struct nd_entry_data *ret_nd_data = NULL;
6275 dest_if = INVALID_DESTIF;
6277 uint32_t src_phy_port = pkt->port;
6279 gw_get_nh_port_ipv6((uint8_t *) &dest_addr_ipv6[0],
6280 &dest_if, &nh_ipv6[0]);
6282 ret_nd_data = get_dest_mac_addr_ipv6(&nh_ipv6[0],
6283 dest_if, (struct ether_addr *)eth_dest);
6285 *outport_id = p_nat->outport_id[dest_if];
6287 if (nd_cache_dest_mac_present(dest_if)) {
6288 ether_addr_copy(get_link_hw_addr(dest_if),
6289 (struct ether_addr *)eth_src);
6290 update_nhip_access(dest_if);
6292 if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) {
6293 p_nat->naptedPktCount += ret_nd_data->num_pkts;
6294 nd_send_buffered_pkts(ret_nd_data,
6295 (struct ether_addr *)eth_dest, *outport_id);
6299 if (unlikely(ret_nd_data == NULL)) {
6301 #ifdef CGNAPT_DEBUGGING
6302 printf("%s: NHIP Not Found, "
6303 "outport_id: %d\n", __func__,
6308 p_nat->invalid_packets |= pkt_mask;
6309 p_nat->naptDroppedPktCount++;
6311 #ifdef CGNAPT_DEBUGGING
6312 p_nat->naptDroppedPktCount4++;
6317 if (ret_nd_data->status == INCOMPLETE ||
6318 ret_nd_data->status == PROBE) {
6319 if (ret_nd_data->num_pkts >= NUM_DESC) {
6321 p_nat->invalid_packets |= pkt_mask;
6322 p_nat->naptDroppedPktCount++;
6324 #ifdef CGNAPT_DEBUGGING
6325 p_nat->naptDroppedPktCount4++;
6329 arp_pkts_mask |= pkt_mask;
6330 nd_queue_unresolved_packet(ret_nd_data, pkt);
6340 convert_ipv4_to_ipv6(pkt, &ipv4_hdr);
6342 /* Ethernet MTU check */
6343 if ((rte_pktmbuf_data_len(pkt) - 14) > 1500) {
6344 p_nat->invalid_packets |= pkt_mask;
6345 p_nat->naptDroppedPktCount++;
6348 uint32_t *dst_addr =
6349 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4t6);
6350 uint16_t *dst_port =
6351 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP4t6);
6353 memcpy((uint8_t *) &dst_addr[0], &entry->data.u.prv_ipv6[0],
6356 #ifdef NAT_ONLY_CONFIG_REQ
6357 if (!nat_only_config_flag) {
6359 *dst_port = rte_bswap16(entry->data.prv_port);
6361 #ifdef NAT_ONLY_CONFIG_REQ
6365 p_nat->inaptedPktCount++;
6368 p_nat->naptedPktCount++;
6371 if (p_nat->hw_checksum_reqd)
6372 hw_checksum(pkt, pkt_type);
6374 sw_checksum(pkt, pkt_type);
6380 * NAPT function for IPv6 private traffic which handles 4 pkts
6383 * A pointer to array of packets mbuf
6385 * Starting pkt number of pkts
6389 * A pointer to main CGNAPT structure
6393 pkt4_work_cgnapt_ipv6_prv(
6394 struct rte_mbuf **pkts,
6395 uint32_t in_pkt_num,
6396 __rte_unused void *arg,
6397 struct pipeline_cgnapt *p_nat)
6399 struct rte_mbuf *pkt;
6403 enum PKT_TYPE pkt_type = PKT_TYPE_IPV6to4;
6405 for (i = 0; i < 4; i++) {
6406 pkt_num = in_pkt_num + i;
6409 /* index into hash table entries */
6410 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6411 /*bitmask representing only this packet */
6412 uint64_t pkt_mask = 1LLU << pkt_num;
6414 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
6415 uint32_t dest_if = INVALID_DESTIF;
6416 uint16_t *outport_id =
6417 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6418 struct cgnapt_table_entry *entry = NULL;
6420 if (hash_table_entry < 0) {
6422 /* try to add new entry */
6423 struct rte_pipeline_table_entry *table_entry = NULL;
6426 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
6428 &p_nat->valid_packets, pkt_num,
6432 /* ICMP Error message generation for
6433 * Destination Host unreachable
6435 /* Do we need this check for ipv6? */
6436 if (protocol == IP_PROTOCOL_ICMP) {
6437 cgnapt_icmp_pkt = pkt;
6438 send_icmp_dest_unreachable_msg();
6441 /* Drop packet by adding to invalid pkt mask */
6443 p_nat->invalid_packets |= dropmask;
6445 #ifdef CGNAPT_DEBUGGING
6446 if (p_nat->kpc2++ < 5) {
6447 printf("in_ah Th: %d",
6448 p_nat->pipeline_num);
6449 print_key(p_nat->key_ptrs[pkt_num]);
6453 p_nat->naptDroppedPktCount++;
6455 #ifdef CGNAPT_DEBUGGING
6456 p_nat->naptDroppedPktCount3++;
6462 entry = (struct cgnapt_table_entry *)table_entry;
6464 /* entry found for this packet */
6465 entry = &napt_hash_tbl_entries[hash_table_entry];
6468 /* apply napt and mac changes */
6470 p_nat->entries[pkt_num] = &(entry->head);
6472 struct ipv6_hdr ipv6_hdr;
6473 uint32_t dest_address = 0;
6474 uint8_t nh_ipv6[16];
6479 convert_ipv6_to_ipv4(pkt, &ipv6_hdr);
6481 #ifdef CGNAPT_DBG_PRNT
6482 if (CGNAPT_DEBUG >= 1)
6483 printf("pkt_work_cganpt: "
6484 "convert_ipv6_to_ipv4\n");
6487 struct cgnapt_nsp_node *ll = nsp_ll;
6490 while (ll != NULL) {
6491 if (!memcmp(&ipv6_hdr.dst_addr[0],
6493 ll->nsp.depth / 8)) {
6501 && !memcmp(&ipv6_hdr.dst_addr[0],
6502 &well_known_prefix[0], 12)) {
6507 p_nat->invalid_packets |= pkt_mask;
6508 p_nat->naptDroppedPktCount++;
6510 #ifdef CGNAPT_DEBUGGING
6511 p_nat->naptDroppedPktCount5++;
6518 /* As packet is already converted into IPv4 we must not
6519 * operate IPv6 offsets on packet only perform IPv4 operations
6522 uint32_t *src_addr =
6523 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP6t4);
6524 uint32_t *dst_addr =
6525 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP6t4);
6526 uint16_t *src_port =
6527 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP6t4);
6528 uint16_t *dst_port =
6529 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP6t4);
6532 RTE_MBUF_METADATA_UINT8_PTR(pkt, ETH_OFST_IP6t4);
6534 RTE_MBUF_METADATA_UINT8_PTR(pkt, ETH_OFST_IP6t4 + 6);
6536 if (entry->data.ttl == NAPT_ENTRY_STALE)
6537 entry->data.ttl = NAPT_ENTRY_VALID;
6542 if (unlikely(protocol == IP_PROTOCOL_UDP
6543 && rte_be_to_cpu_16(*dst_port) == 53)) {
6544 p_nat->invalid_packets |= pkt_mask;
6545 p_nat->naptDroppedPktCount++;
6547 #ifdef CGNAPT_DEBUGGING
6548 p_nat->naptDroppedPktCount6++;
6553 dest_address = rte_bswap32(*dst_addr);
6556 #ifdef CGNAPT_DBG_PRNT
6557 if (CGNAPT_DEBUG > 2)
6558 printf("Egress: \tphy_port:%d\t"
6559 "get_prv_to_pub():%d \tout_port:%d\n",
6560 pkt->port, dest_if, *outport_id);
6564 #ifdef CGNAPT_DEBUGGING
6565 static int static_count;
6567 if (static_count++ < 10) {
6569 my_print_entry(entry);
6570 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6571 printf("dest_add:%x\n", entry->data.u.prv_ip);
6572 printf("dest_add:%x\n", *dst_addr);
6573 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6577 memset(nh_ipv6, 0, 16);
6580 struct arp_entry_data *ret_arp_data;
6581 uint32_t src_phy_port = *src_port;
6582 dest_if = prv_to_pub_map[src_phy_port];
6583 gw_get_route_nh_port_ipv4(dest_address,
6584 &dest_if, &nhip, dest_if);
6586 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if,
6587 (struct ether_addr *)eth_dest);
6588 *outport_id = p_nat->outport_id[dest_if];
6590 if (arp_cache_dest_mac_present(dest_if)) {
6591 ether_addr_copy(get_link_hw_addr(dest_if),
6592 (struct ether_addr *)eth_src);
6593 update_nhip_access(dest_if);
6594 if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) {
6595 p_nat->naptedPktCount += ret_arp_data->num_pkts;
6596 arp_send_buffered_pkts(ret_arp_data,
6597 (struct ether_addr *)eth_dest, *outport_id);
6602 if (unlikely(ret_arp_data == NULL)) {
6604 #ifdef CGNAPT_DEBUGGING
6605 printf("%s: NHIP Not Found, nhip:%x , "
6606 "outport_id: %d\n", __func__, nhip,
6611 p_nat->invalid_packets |= pkt_mask;
6612 p_nat->naptDroppedPktCount++;
6614 #ifdef CGNAPT_DEBUGGING
6615 p_nat->naptDroppedPktCount4++;
6620 if (ret_arp_data->status == INCOMPLETE ||
6621 ret_arp_data->status == PROBE) {
6622 if (ret_arp_data->num_pkts >= NUM_DESC) {
6624 p_nat->invalid_packets |= pkt_mask;
6625 p_nat->naptDroppedPktCount++;
6627 #ifdef CGNAPT_DEBUGGING
6628 p_nat->naptDroppedPktCount4++;
6632 arp_pkts_mask |= pkt_mask;
6633 arp_queue_unresolved_packet(ret_arp_data, pkt);
6643 *src_addr = rte_bswap32(entry->data.pub_ip);
6645 #ifdef NAT_ONLY_CONFIG_REQ
6646 if (!nat_only_config_flag) {
6648 *src_port = rte_bswap16(entry->data.pub_port);
6650 #ifdef NAT_ONLY_CONFIG_REQ
6654 p_nat->enaptedPktCount++;
6657 p_nat->naptedPktCount++;
6660 if (p_nat->hw_checksum_reqd)
6661 hw_checksum(pkt, pkt_type);
6663 sw_checksum(pkt, pkt_type);
6669 * NAPT function for IPv6 public traffic which handles 4 pkts
6672 * A pointer to array of packets mbuf
6674 * Starting pkt number of pkts
6678 * A pointer to main CGNAPT structure
6682 pkt4_work_cgnapt_ipv6_pub(
6683 struct rte_mbuf **pkts,
6684 uint32_t in_pkt_num,
6685 __rte_unused void *arg,
6686 struct pipeline_cgnapt *p_nat)
6688 struct rte_mbuf *pkt;
6692 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4to6;
6694 for (i = 0; i < 4; i++) {
6695 pkt_num = in_pkt_num + i;
6698 /* index into hash table entries */
6699 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6700 /*bitmask representing only this packet */
6701 uint64_t pkt_mask = 1LLU << pkt_num;
6703 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
6704 uint16_t *outport_id =
6705 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6706 struct cgnapt_table_entry *entry = NULL;
6708 if (hash_table_entry < 0) {
6710 /* Drop ingress initial traffic */
6712 p_nat->invalid_packets |= pkt_mask;
6713 p_nat->naptDroppedPktCount++;
6714 #ifdef CGNAPT_DEBUGGING
6715 p_nat->naptDroppedPktCount3++;
6716 if (p_nat->kpc2++ < 5) {
6717 printf("in_ah Th: %d", p_nat->pipeline_num);
6718 print_key(p_nat->key_ptrs[pkt_num]);
6725 /* entry found for this packet */
6726 entry = &napt_hash_tbl_entries[hash_table_entry];
6729 /* apply napt and mac changes */
6731 p_nat->entries[pkt_num] = &(entry->head);
6732 if (entry->data.type != CGNAPT_ENTRY_IPV6) {
6733 p_nat->invalid_packets |= pkt_mask;
6734 p_nat->naptDroppedPktCount++;
6738 struct ipv4_hdr ipv4_hdr;
6740 uint16_t *src_port =
6741 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP4_TCP);
6744 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
6746 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
6748 if (entry->data.ttl == NAPT_ENTRY_STALE)
6749 entry->data.ttl = NAPT_ENTRY_VALID;
6751 struct ether_addr hw_addr;
6752 uint8_t dest_addr_ipv6[16];
6753 uint8_t nh_ipv6[16];
6754 uint32_t dest_if = INVALID_DESTIF;
6755 { /*start of Ingress */
6757 if (unlikely(protocol == IP_PROTOCOL_UDP
6758 && rte_be_to_cpu_16(*src_port) == 53)) {
6759 p_nat->invalid_packets |= pkt_mask;
6760 p_nat->naptDroppedPktCount++;
6761 #ifdef CGNAPT_DEBUGGING
6762 p_nat->naptDroppedPktCount6++;
6767 memcpy(&dest_addr_ipv6[0], &entry->data.u.prv_ipv6[0],
6770 }/* end of ingress */
6772 #ifdef CGNAPT_DEBUGGING
6773 static int static_count;
6775 if (static_count++ < 10) {
6777 my_print_entry(entry);
6778 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6779 printf("dest_add:%x\n", entry->data.u.prv_ip);
6780 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6784 memset(nh_ipv6, 0, 16);
6785 struct nd_entry_data *ret_nd_data = NULL;
6786 dest_if = INVALID_DESTIF;
6788 uint32_t src_phy_port = pkt->port;
6790 gw_get_nh_port_ipv6((uint8_t *) &dest_addr_ipv6[0],
6791 &dest_if, &nh_ipv6[0]);
6793 ret_nd_data = get_dest_mac_addr_ipv6(&nh_ipv6[0],
6794 dest_if, (struct ether_addr *)eth_dest);
6795 *outport_id = p_nat->outport_id[dest_if];
6797 if (nd_cache_dest_mac_present(dest_if)) {
6798 ether_addr_copy(get_link_hw_addr(dest_if),
6799 (struct ether_addr *)eth_src);
6800 update_nhip_access(dest_if);
6802 if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) {
6803 p_nat->naptedPktCount += ret_nd_data->num_pkts;
6804 nd_send_buffered_pkts(ret_nd_data,
6805 (struct ether_addr *)eth_dest, *outport_id);
6808 if (unlikely(ret_nd_data == NULL)) {
6810 #ifdef CGNAPT_DEBUGGING
6811 printf("%s: NHIP Not Found "
6812 "outport_id: %d\n", __func__,
6817 p_nat->invalid_packets |= pkt_mask;
6818 p_nat->naptDroppedPktCount++;
6820 #ifdef CGNAPT_DEBUGGING
6821 p_nat->naptDroppedPktCount4++;
6826 if (ret_nd_data->status == INCOMPLETE ||
6827 ret_nd_data->status == PROBE) {
6829 if (ret_nd_data->num_pkts >= NUM_DESC) {
6831 p_nat->invalid_packets |= pkt_mask;
6832 p_nat->naptDroppedPktCount++;
6834 #ifdef CGNAPT_DEBUGGING
6835 p_nat->naptDroppedPktCount4++;
6839 arp_pkts_mask |= pkt_mask;
6840 nd_queue_unresolved_packet(ret_nd_data, pkt);
6848 /* start of Ingress */
6850 convert_ipv4_to_ipv6(pkt, &ipv4_hdr);
6852 /* Ethernet MTU check */
6853 if ((rte_pktmbuf_data_len(pkt) - 14) > 1500) {
6854 p_nat->invalid_packets |= pkt_mask;
6855 p_nat->naptDroppedPktCount++;
6858 uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
6859 DST_ADR_OFST_IP4t6);
6860 uint16_t *dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
6861 DST_PRT_OFST_IP4t6);
6863 memcpy((uint8_t *) &dst_addr[0],
6864 &entry->data.u.prv_ipv6[0], 16);
6866 #ifdef NAT_ONLY_CONFIG_REQ
6867 if (!nat_only_config_flag) {
6869 *dst_port = rte_bswap16(entry->data.prv_port);
6871 #ifdef NAT_ONLY_CONFIG_REQ
6875 p_nat->inaptedPktCount++;
6876 } /* end of ingress */
6878 p_nat->naptedPktCount++;
6881 if (p_nat->hw_checksum_reqd)
6882 hw_checksum(pkt, pkt_type);
6884 sw_checksum(pkt, pkt_type);
6886 } /* end of for loop */
6890 * Input port handler for IPv6 private traffic
6891 * Starting from the packet burst it filters unwanted packets,
6892 * calculates keys, does lookup and then based on the lookup
6893 * updates NAPT table and does packet NAPT translation.
6896 * A pointer to struct rte_pipeline
6898 * A pointer to array of packets mbuf
6900 * Number of packets in the burst
6905 * int that is not checked by caller
6907 static int cgnapt_in_port_ah_ipv6_prv(struct rte_pipeline *rte_p,
6908 struct rte_mbuf **pkts,
6909 uint32_t n_pkts, void *arg)
6912 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
6913 struct pipeline_cgnapt *p_nat = ap->p;
6915 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
6916 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
6917 p_nat->invalid_packets = 0;
6920 #ifdef CGNAPT_DBG_PRNT
6921 if (CGNAPT_DEBUG > 1)
6922 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
6925 /* prefetching for mbufs should be done here */
6926 for (j = 0; j < n_pkts; j++)
6927 rte_prefetch0(pkts[j]);
6929 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
6930 pkt4_work_cgnapt_key_ipv6_prv(&pkts[i], i, arg, p_nat);
6932 for (; i < n_pkts; i++)
6933 pkt_work_cgnapt_key_ipv6_prv(pkts[i], i, arg, p_nat);
6935 p_nat->valid_packets &= ~(p_nat->invalid_packets);
6937 if (arp_pkts_mask) {
6938 p_nat->valid_packets &= ~(arp_pkts_mask);
6939 rte_pipeline_ah_packet_hijack(rte_p, arp_pkts_mask);
6942 if (unlikely(p_nat->valid_packets == 0)) {
6943 /* no suitable packet for lookup */
6944 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
6945 return p_nat->valid_packets;
6948 /* lookup entries in the common napt table */
6950 int lookup_result = rte_hash_lookup_bulk(
6952 (const void **) &p_nat->key_ptrs,
6953 /* should be minus num invalid pkts */
6955 /*new pipeline data member */
6956 &p_nat->lkup_indx[0]);
6958 if (unlikely(lookup_result < 0)) {
6959 /* unknown error, just discard all packets */
6960 printf("Unexpected hash lookup error %d, "
6961 "discarding all packets",
6963 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
6967 /* Now call second stage of pipeline to one by one
6968 * check the result of our bulk lookup
6971 /* prefetching for table entries should be done here */
6972 for (j = 0; j < n_pkts; j++) {
6973 if (p_nat->lkup_indx[j] >= 0)
6974 rte_prefetch0(&napt_hash_tbl_entries
6975 [p_nat->lkup_indx[j]]);
6978 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
6979 pkt4_work_cgnapt_ipv6_prv(&pkts[i], i, arg, p_nat);
6981 for (; i < n_pkts; i++)
6982 pkt_work_cgnapt_ipv6_prv(pkts[i], i, arg, p_nat);
6984 if (p_nat->invalid_packets) {
6985 /* get rid of invalid packets */
6986 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
6988 p_nat->valid_packets &= ~(p_nat->invalid_packets);
6990 #ifdef CGNAPT_DBG_PRNT
6991 if (CGNAPT_DEBUG > 1) {
6992 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
6993 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
6994 printf("invalid_packets:0x%jx\n",
6995 p_nat->invalid_packets);
6996 printf("rte_invalid_packets :0x%jx\n",
6997 rte_p->pkts_drop_mask);
6998 printf("Total pkts dropped :0x%jx\n",
6999 rte_p->n_pkts_ah_drop);
7004 return p_nat->valid_packets;
7009 * Input port handler for IPv6 public traffic
7010 * Starting from the packet burst it filters unwanted packets,
7011 * calculates keys, does lookup and then based on the lookup
7012 * updates NAPT table and does packet NAPT translation.
7015 * A pointer to struct rte_pipeline
7017 * A pointer to array of packets mbuf
7019 * Number of packets in the burst
7024 * int that is not checked by caller
7026 static int cgnapt_in_port_ah_ipv6_pub(struct rte_pipeline *rte_p,
7027 struct rte_mbuf **pkts,
7028 uint32_t n_pkts, void *arg)
7031 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
7032 struct pipeline_cgnapt *p_nat = ap->p;
7034 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
7035 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
7036 p_nat->invalid_packets = 0;
7039 #ifdef CGNAPT_DBG_PRNT
7040 if (CGNAPT_DEBUG > 1)
7041 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
7044 /* prefetching for mbufs should be done here */
7045 for (j = 0; j < n_pkts; j++)
7046 rte_prefetch0(pkts[j]);
7048 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7049 pkt4_work_cgnapt_key_ipv6_pub(&pkts[i], i, arg, p_nat);
7051 for (; i < n_pkts; i++)
7052 pkt_work_cgnapt_key_ipv6_pub(pkts[i], i, arg, p_nat);
7054 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7056 if (arp_pkts_mask) {
7057 p_nat->valid_packets &= ~(arp_pkts_mask);
7058 rte_pipeline_ah_packet_hijack(rte_p, arp_pkts_mask);
7061 if (unlikely(p_nat->valid_packets == 0)) {
7062 /* no suitable packet for lookup */
7063 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7064 return p_nat->valid_packets;
7067 /* lookup entries in the common napt table */
7069 int lookup_result = rte_hash_lookup_bulk(
7071 (const void **) &p_nat->key_ptrs,
7072 /* should be minus num invalid pkts */
7074 /*new pipeline data member */
7075 &p_nat->lkup_indx[0]);
7077 if (unlikely(lookup_result < 0)) {
7078 /* unknown error, just discard all packets */
7079 printf("Unexpected hash lookup error %d, "
7080 "discarding all packets",
7082 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
7086 /* Now call second stage of pipeline to one by one
7087 * check the result of our bulk lookup
7090 /* prefetching for table entries should be done here */
7091 for (j = 0; j < n_pkts; j++) {
7092 if (p_nat->lkup_indx[j] >= 0)
7093 rte_prefetch0(&napt_hash_tbl_entries
7094 [p_nat->lkup_indx[j]]);
7097 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7098 pkt4_work_cgnapt_ipv6_pub(&pkts[i], i, arg, p_nat);
7100 for (; i < n_pkts; i++)
7101 pkt_work_cgnapt_ipv6_pub(pkts[i], i, arg, p_nat);
7103 if (p_nat->invalid_packets) {
7104 /* get rid of invalid packets */
7105 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7107 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7109 #ifdef CGNAPT_DBG_PRNT
7110 if (CGNAPT_DEBUG > 1) {
7111 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
7112 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
7113 printf("invalid_packets:0x%jx\n",
7114 p_nat->invalid_packets);
7115 printf("rte_invalid_packets :0x%jx\n",
7116 rte_p->pkts_drop_mask);
7117 printf("Total pkts dropped :0x%jx\n",
7118 rte_p->n_pkts_ah_drop);
7123 return p_nat->valid_packets;
7127 * Function to send ICMP dest unreachable msg
7130 void send_icmp_dest_unreachable_msg(void)
7133 struct ether_hdr *eth_h;
7134 struct ipv4_hdr *ip_h;
7135 struct icmp_hdr *icmp_h;
7136 struct rte_mbuf *icmp_pkt = cgnapt_icmp_pkt;
7138 if (icmp_pkt == NULL) {
7140 printf("Error allocating icmp_pkt rte_mbuf\n");
7144 port_id = icmp_pkt->port;
7146 struct app_link_params *link;
7147 link = &mylink[port_id];
7148 eth_h = rte_pktmbuf_mtod(icmp_pkt, struct ether_hdr *);
7149 ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
7150 icmp_h = (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
7152 struct ether_addr gw_addr;
7153 struct ether_addr dst_addr;
7154 ether_addr_copy(ð_h->s_addr, &dst_addr);
7155 rte_eth_macaddr_get(port_id, &gw_addr);
7156 ether_addr_copy(&gw_addr, ð_h->s_addr);
7157 ether_addr_copy(&dst_addr, ð_h->d_addr);
7159 eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
7160 ip_h->version_ihl = IP_VHL_DEF;
7161 ip_h->type_of_service = 0;
7162 ip_h->total_length = rte_cpu_to_be_16(sizeof(struct ipv4_hdr) +
7163 sizeof(struct icmp_hdr));
7164 ip_h->packet_id = 0xaabb;
7165 ip_h->fragment_offset = 0x0000;
7166 ip_h->time_to_live = 64;
7167 ip_h->next_proto_id = 1;
7170 uint32_t src_addr_offset =
7171 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_SRC_ADR_OFST;
7173 RTE_MBUF_METADATA_UINT32_PTR(cgnapt_icmp_pkt, src_addr_offset);
7175 ip_h->dst_addr = *src_addr;
7176 ip_h->src_addr = rte_bswap32(link->ip);
7178 ip_h->dst_addr = *src_addr;
7179 ip_h->src_addr = rte_bswap32(link->ip);
7181 ip_h->hdr_checksum = 0;
7182 ip_h->hdr_checksum = rte_ipv4_cksum(ip_h);
7183 icmp_h->icmp_type = 3; /* Destination Unreachable */
7184 icmp_h->icmp_code = 13; /* Communication administratively prohibited */
7186 icmp_h->icmp_cksum = ~rte_raw_cksum(icmp_h, sizeof(struct icmp_hdr));
7188 icmp_pkt->pkt_len = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
7189 sizeof(struct icmp_hdr);
7190 icmp_pkt->data_len = icmp_pkt->pkt_len;
7191 if (ARPICMP_DEBUG) {
7192 printf("Sending ICMP error message - "
7193 "Destination Unreachable\n");
7195 rte_pipeline_port_out_packet_insert(myP, port_id, icmp_pkt);
7199 * Function to add a dynamic NAPT entry pair
7202 * A pointer to struct pipeline
7204 * A pointer to struct pipeline_cgnapt_entry_key
7206 * expairy time of an dynamic or PCP req entry
7208 * uint8_t pointer of source address
7211 * A pointer to struct cgnapt_table_entry for added entry
7214 struct cgnapt_table_entry *add_dynamic_cgnapt_entry(
7216 struct pipeline_cgnapt_entry_key *key,
7223 void *entry_ptr, *ret_ptr;
7226 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
7228 #ifdef CGNAPT_DBG_PRNT
7229 if (CGNAPT_DEBUG >= 1) {
7230 printf("Th%d add_dynamic_cgnapt_entry key detail Entry:"
7231 "0x%x, %d, %d\n", p_nat->pipeline_num, key->ip, key->port,
7236 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX && i < p_nat->pkt_burst_cnt;
7238 if (p_nat->cgnapt_dyn_ent_table[i].ip == key->ip
7239 && p_nat->cgnapt_dyn_ent_table[i].port == key->port
7240 && p_nat->cgnapt_dyn_ent_table[i].pid == key->pid) {
7242 #ifdef CGNAPT_DBG_PRNT
7243 if (CGNAPT_DEBUG > 1)
7244 printf("add_dynamic_cgnapt_entry:pkt_burst "
7245 "array key matched!!!\n");
7248 return &napt_hash_tbl_entries
7249 [p_nat->cgnapt_dyn_ent_index[i]];
7253 #ifdef NAT_ONLY_CONFIG_REQ
7254 if (!nat_only_config_flag) {
7257 ret = increment_max_port_counter(key->ip, key->pid, p_nat);
7258 if (ret == MAX_PORT_INC_ERROR) {
7260 #ifdef CGNAPT_DEBUGGING
7261 p_nat->missedpktcount5++;
7264 #ifdef CGNAPT_DBG_PRNT
7265 if (CGNAPT_DEBUG > 1)
7266 printf("add_dynamic_cgnapt_entry:"
7267 "increment_max_port_counter-1 failed\n");
7274 if (ret == MAX_PORT_INC_REACHED) {
7276 #ifdef CGNAPT_DEBUGGING
7277 p_nat->missedpktcount6++;
7280 #ifdef CGNAPT_DBG_PRNT
7281 if (CGNAPT_DEBUG > 1)
7282 printf("add_dynamic_cgnapt_entry:"
7283 "increment_max_port_counter-2 failed\n");
7290 #ifdef NAT_ONLY_CONFIG_REQ
7295 port_num = get_free_iport(p_nat, &public_ip);
7297 if (port_num == -1) {
7299 #ifdef CGNAPT_DBG_PRNT
7300 if (CGNAPT_DEBUG > 2) {
7301 printf("add_dynamic_cgnapt_entry: %d\n", port_num);
7302 printf("add_dynamic_cgnapt_entry key detail:0x%x, "
7303 "%d, %d\n", key->ip, key->port, key->pid);
7307 #ifdef CGNAPT_DEBUGGING
7308 p_nat->missedpktcount7++;
7315 #ifdef NAT_ONLY_CONFIG_REQ
7316 if (!nat_only_config_flag) {
7319 if (ret == 2) { //MPPC_NEW_ENTRY
7321 /* check for max_clients_per_ip */
7322 if (rte_atomic16_read
7324 [rte_jhash(&public_ip, 4, 0) %
7325 CGNAPT_MAX_PUB_IP].count) ==
7326 p_nat->max_clients_per_ip) {
7328 /* For now just bail out
7329 * In future we can think about
7330 * retrying getting a new iport
7333 release_iport(port_num, public_ip, p_nat);
7335 #ifdef CGNAPT_DEBUGGING
7336 p_nat->missedpktcount10++;
7342 rte_atomic16_inc(&all_public_ip
7343 [rte_jhash(&public_ip, 4, 0) %
7344 CGNAPT_MAX_PUB_IP].count);
7346 #ifdef CGNAPT_DBG_PRNT
7347 if ((rte_jhash(&public_ip, 4, 0) %
7348 CGNAPT_MAX_PUB_IP) == 8)
7349 printf("pub ip:%x coutn:%d\n", public_ip,
7350 rte_atomic16_read(&all_public_ip
7351 [rte_jhash(&public_ip, 4, 0) %
7352 CGNAPT_MAX_PUB_IP].count));
7356 #ifdef NAT_ONLY_CONFIG_REQ
7360 #ifdef CGNAPT_DBG_PRNT
7361 if (CGNAPT_DEBUG > 0) {
7362 printf("add_dynamic_cgnapt_entry: %d\n",
7364 printf("add_dynamic_cgnapt_entry key detail: "
7365 "0x%x, %d, %d\n", key->ip, key->port, key->pid);
7369 struct cgnapt_table_entry entry = {
7371 .action = RTE_PIPELINE_ACTION_PORT,
7372 /* made it configurable below */
7373 {.port_id = p->port_out_id[0]},
7377 .prv_port = key->port,
7378 .pub_ip = public_ip,
7379 .pub_port = port_num,
7380 .prv_phy_port = key->pid,
7381 .pub_phy_port = get_pub_to_prv_port(
7385 /* if(timeout == -1) : static entry
7386 * if(timeout == 0 ) : dynamic entry
7387 * if(timeout > 0 ) : PCP requested entry
7389 .timeout = timeout > 0 ? timeout : 0,
7396 #ifdef NAT_ONLY_CONFIG_REQ
7397 if (nat_only_config_flag) {
7398 entry.data.prv_port = 0xffff;
7399 entry.data.pub_port = 0xffff;
7403 if (pkt_type == CGNAPT_ENTRY_IPV6) {
7404 entry.data.type = CGNAPT_ENTRY_IPV6;
7405 memcpy(&entry.data.u.prv_ipv6[0], src_addr, 16);
7407 entry.data.u.prv_ip = key->ip;
7408 entry.data.type = CGNAPT_ENTRY_IPV4;
7411 //entry.head.port_id = CGNAPT_PUB_PORT_ID; /* outgoing port info */
7412 entry.head.port_id = entry.data.pub_phy_port; /* outgoing port info */
7414 struct pipeline_cgnapt_entry_key second_key;
7415 /* Need to add a second ingress entry */
7416 second_key.ip = public_ip;
7417 second_key.port = port_num;
7418 second_key.pid = 0xffff;
7420 #ifdef NAT_ONLY_CONFIG_REQ
7421 if (nat_only_config_flag)
7422 second_key.port = 0xffff;
7425 #ifdef CGNAPT_DBG_PRNT
7426 if (CGNAPT_DEBUG > 2)
7427 printf("add_dynamic_cgnapt_entry second key detail:"
7428 "0x%x, %d, %d\n", second_key.ip, second_key.port,
7432 int32_t position = rte_hash_add_key(napt_common_table, (void *)key);
7435 #ifdef CGNAPT_DEBUGGING
7436 p_nat->missedpktcount8++;
7439 printf("CG-NAPT entry add failed ...returning "
7440 "without adding ... %d\n", position);
7445 #ifdef CGNAPT_DBG_PRNT
7447 printf("add_dynamic_cgnapt_entry\n");
7449 print_cgnapt_entry(&entry);
7453 memcpy(&napt_hash_tbl_entries[position], &entry,
7454 sizeof(struct cgnapt_table_entry));
7456 /* this pointer is returned to pkt miss function */
7457 ret_ptr = &napt_hash_tbl_entries[position];
7459 p_nat->n_cgnapt_entry_added++;
7460 p_nat->dynCgnaptCount++;
7462 /* Now modify the forward port for reverse entry */
7464 /* outgoing port info */
7465 //entry.head.port_id = CGNAPT_PRV_PORT_ID;
7466 /* outgoing port info */
7467 entry.head.port_id = entry.data.prv_phy_port;
7469 int32_t position2 = rte_hash_add_key(napt_common_table, &second_key);
7471 if (position2 < 0) {
7472 #ifdef CGNAPT_DEBUGGING
7473 p_nat->missedpktcount9++;
7475 printf("CG-NAPT entry reverse bulk add failed ..."
7476 "returning with fwd add ...%d\n",
7482 memcpy(&napt_hash_tbl_entries[position2], &entry,
7483 sizeof(struct cgnapt_table_entry));
7485 entry_ptr = &napt_hash_tbl_entries[position2];
7487 timer_thread_enqueue(key, &second_key, ret_ptr,
7488 entry_ptr, (struct pipeline *)p_nat);
7490 p_nat->n_cgnapt_entry_added++;
7491 p_nat->dynCgnaptCount++;
7493 if (p_nat->pkt_burst_cnt < RTE_PORT_IN_BURST_SIZE_MAX) {
7494 memcpy(&p_nat->cgnapt_dyn_ent_table[p_nat->pkt_burst_cnt], key,
7495 sizeof(struct pipeline_cgnapt_entry_key));
7496 p_nat->cgnapt_dyn_ent_index[p_nat->pkt_burst_cnt] = position;
7497 p_nat->pkt_burst_cnt++;
7502 int pkt_miss_cgnapt_count;
7504 * Function handle a missed NAPT entry lookup
7505 * Will attempt to add a dynamic entry pair.
7508 * A pointer to struct pipeline
7510 * A pointer to struct pipeline_cgnapt_entry_key
7512 * A pointer to pkt struct rte_mbuf
7514 * uint64_t pointer to pkt mask
7515 * @param table_entry
7516 * A pointer to struct rte_pipeline_table_entry to be created and returned
7518 * number of this pkt in current burst
7521 * A uint64_t mask for drop packets
7524 pkt_miss_cgnapt(struct pipeline_cgnapt_entry_key *key,
7525 struct rte_mbuf *pkt,
7526 struct rte_pipeline_table_entry **table_entry,
7527 __rte_unused uint64_t *pkts_mask,
7528 uint32_t pkt_num, void *arg)
7531 #ifdef CGNAPT_DBG_PRNT
7532 if (CGNAPT_DEBUG > 0)
7533 printf("\n pkt_miss_cgnapt\n");
7537 * see if get_port passes for this src address
7538 * if passed add a new egress entry and a
7539 * corresponding new ingress entry
7540 * return the fwd entry to calling function using input pointer
7541 * else if get_port fails drop packet
7544 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)arg;
7546 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
7547 uint32_t src_addr_offset_ipv6 =
7548 MBUF_HDR_ROOM + ETH_HDR_SIZE + IPV6_HDR_SRC_ADR_OFST;
7549 uint16_t phy_port = pkt->port;
7551 uint16_t *eth_proto =
7552 RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
7554 uint8_t *src_addr = NULL;
7555 uint8_t src_addr_ipv6[16];
7556 uint8_t pkt_type = CGNAPT_ENTRY_IPV4;
7557 /* To drop the packet */
7558 uint64_t drop_mask = 0;
7560 if (p_nat->is_static_cgnapt) {
7561 drop_mask |= 1LLU << pkt_num;
7562 p_nat->missedPktCount++;
7564 #ifdef CGNAPT_DEBUGGING
7565 p_nat->missedpktcount1++;
7570 if (rte_be_to_cpu_16(*eth_proto) == ETHER_TYPE_IPv6) {
7572 RTE_MBUF_METADATA_UINT8_PTR(pkt, src_addr_offset_ipv6);
7573 pkt_type = CGNAPT_ENTRY_IPV6;
7574 memcpy(src_addr_ipv6, src_addr, 16);
7579 /* some validation first */
7580 if (is_phy_port_privte(phy_port)) {
7581 /* dynamic NAPT entry creation */
7582 *table_entry = (struct rte_pipeline_table_entry *)
7583 add_dynamic_cgnapt_entry(
7584 (struct pipeline *)&p_nat->p,
7586 DYNAMIC_CGNAPT_TIMEOUT,
7588 src_addr_ipv6, &err);
7590 if (!(*table_entry)) {
7592 drop_mask |= 1LLU << pkt_num;
7593 p_nat->missedPktCount++;
7595 #ifdef CGNAPT_DEBUGGING
7596 p_nat->missedpktcount2++;
7599 #ifdef CGNAPT_DBG_PRNT
7600 if (CGNAPT_DEBUG > 1)
7601 printf("Add Dynamic NAT entry failed "
7605 #ifdef CGNAPT_DEBUGGING
7606 p_nat->missedpktcount11++;
7611 } else if (!is_phy_port_privte(phy_port)) {
7613 #ifdef CGNAPT_DBG_PRNT
7614 if (CGNAPT_DEBUG >= 2) {
7615 printf("Initial Ingress entry creation NOT ALLOWED "
7620 drop_mask |= 1LLU << pkt_num;
7621 p_nat->missedPktCount++;
7623 #ifdef CGNAPT_DEBUGGING
7624 p_nat->missedpktcount3++;
7628 #ifdef CGNAPT_DBG_PRNT
7629 if (CGNAPT_DEBUG > 1)
7630 printf("NOT a PRIVATE or PUBLIC port!!!!!\n");
7633 drop_mask |= 1LLU << pkt_num;
7634 p_nat->missedPktCount++;
7636 #ifdef CGNAPT_DEBUGGING
7637 p_nat->missedpktcount4++;
7641 #ifdef CGNAPT_DBG_PRNT
7642 if (CGNAPT_DEBUG > 5)
7652 * Function to print the contents of a packet
7655 * A pointer to pkt struct rte_mbuf
7657 void print_pkt(struct rte_mbuf *pkt)
7661 printf("\nPacket Contents:\n");
7663 uint8_t *rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
7665 for (i = 0; i < 20; i++) {
7666 for (j = 0; j < 20; j++)
7667 printf("%02x ", rd[(20 * i) + j]);
7673 rte_table_hash_op_hash cgnapt_hash_func[] = {
7685 * Function to parse incoming pipeline arguments
7686 * Called during pipeline initialization
7689 * A pointer to struct pipeline_cgnapt
7691 * A pointer to struct pipeline_params
7694 * 0 if success, negative if failure
7697 pipeline_cgnapt_parse_args(struct pipeline_cgnapt *p,
7698 struct pipeline_params *params)
7700 uint32_t n_flows_present = 0;
7701 uint32_t key_offset_present = 0;
7702 uint32_t key_size_present = 0;
7703 uint32_t hash_offset_present = 0;
7704 uint32_t n_entries_present = 0;
7705 uint32_t max_port_present = 0;
7706 uint32_t max_client_present = 0;
7707 uint32_t public_ip_range_present = 0;
7708 uint32_t public_ip_port_range_present = 0;
7710 uint8_t public_ip_count = 0;
7711 uint8_t public_ip_range_count = 0;
7712 uint8_t dest_if_offset_present = 0;
7713 uint8_t cgnapt_meta_offset_present = 0;
7714 uint8_t prv_que_handler_present = 0;
7715 uint8_t n_prv_in_port = 0;
7717 if (CGNAPT_DEBUG > 2) {
7718 printf("CGNAPT pipeline_cgnapt_parse_args params->n_args: %d\n",
7721 for (i = 0; i < params->n_args; i++) {
7722 char *arg_name = params->args_name[i];
7723 char *arg_value = params->args_value[i];
7725 if (CGNAPT_DEBUG > 2) {
7726 printf("CGNAPT args[%d]: %s %d, %s\n", i, arg_name,
7727 atoi(arg_value), arg_value);
7729 if (strcmp(arg_name, "prv_que_handler") == 0) {
7731 if (prv_que_handler_present) {
7732 printf("Duplicate pktq_in_prv ..\n\n");
7735 prv_que_handler_present = 1;
7740 /* get the first token */
7741 token = strtok(arg_value, "(");
7742 token = strtok(token, ")");
7743 token = strtok(token, ",");
7744 printf("***** prv_que_handler *****\n");
7746 if (token == NULL) {
7747 printf("string is null\n");
7748 printf("invalid prv_que_handler value/n");
7751 printf("string is :%s\n", token);
7753 /* walk through other tokens */
7754 while (token != NULL) {
7755 printf(" %s\n", token);
7756 rxport = atoi(token);
7757 cgnapt_prv_que_port_index[n_prv_in_port++] =
7759 if (rxport < PIPELINE_MAX_PORT_IN)
7760 cgnapt_in_port_egress_prv[rxport] = 1;
7761 token = strtok(NULL, ",");
7764 if (n_prv_in_port == 0) {
7765 printf("VNF common parse err - "
7766 "no prv RX phy port\n");
7772 if (strcmp(arg_name, "cgnapt_meta_offset") == 0) {
7773 if (cgnapt_meta_offset_present) {
7774 printf("CG-NAPT parse error:");
7775 printf("cgnapt_meta_offset initizlized "
7776 "mulitple times\n");
7779 cgnapt_meta_offset_present = 1;
7781 temp = atoi(arg_value);
7784 printf("cgnapt_meta_offset is invalid :");
7785 printf("Not be more than metadata size\n");
7788 cgnapt_meta_offset = (uint16_t) temp;
7790 if (strcmp(arg_name, "vnf_set") == 0)
7793 if (strcmp(arg_name, "public_ip_range") == 0) {
7794 public_ip_range_present = 1;
7795 if (public_ip_port_range_present) {
7796 printf("CG-NAPT parse error:");
7797 printf("public_ip_range with "
7798 "public_ip_port_range_present\n");
7802 p->pub_ip_range = rte_realloc(p->pub_ip_range,
7805 RTE_CACHE_LINE_SIZE);
7807 if (!p->pub_ip_range) {
7808 printf("Memory allocation failed for "
7813 uint32_t sip = 0, eip = 0;
7815 if (sscanf(arg_value, "(%x,%x)", &sip, &eip) != 2) {
7816 printf("public_ip_range is invalid\n");
7820 if (sip <= 0 || eip <= 0 || sip >= eip) {
7821 printf("public_ip_range is invalid %x-%x\n",
7826 printf("public_ip_range: %d-%d\n",
7827 p->pub_ip_range[public_ip_range_count].
7829 p->pub_ip_range[public_ip_range_count].
7832 p->pub_ip_range_count = ++public_ip_range_count;
7836 if (strcmp(arg_name, "public_ip_port_range") == 0) {
7837 public_ip_port_range_present = 1;
7838 if (nat_only_config_flag || public_ip_range_present) {
7840 printf("CG-NAPT parse error:");
7841 printf("nat_only_config_flag OR ");
7842 printf("public_ip_range_present with "
7843 "public_ip_port_range_present\n");
7847 p->pub_ip_port_set = rte_realloc(
7849 sizeof(struct pub_ip_port_set),
7850 RTE_CACHE_LINE_SIZE);
7852 if (!p->pub_ip_port_set) {
7853 printf("Memory allocation failed for "
7861 if (sscanf(arg_value, "%x:(%d,%d)",
7862 &ip, &sp, &ep) != 3) {
7863 printf("Public IP or Port-range is invalid\n");
7867 if (ip <= 0 || sp <= 0 || ep <= 0 || sp > ep) {
7868 printf("Public IP or Port-range is invalid "
7869 "%x:%d-%d\n", ip, sp, ep);
7873 printf("public_ip: 0x%x Range:%d-%d\n",
7874 p->pub_ip_port_set[public_ip_count].ip = ip,
7875 p->pub_ip_port_set[public_ip_count].start_port = sp,
7876 p->pub_ip_port_set[public_ip_count].end_port = ep);
7878 napt_port_alloc_elem_count += (ep - sp + 1);
7879 printf("parse - napt_port_alloc_elem_count :%d\n",
7880 napt_port_alloc_elem_count);
7882 /* Store all public IPs of all CGNAPT threads
7883 * in the global variable
7885 /* to revisit indexing */
7886 all_public_ip[rte_jhash(&ip, 4, 0) %
7887 CGNAPT_MAX_PUB_IP].ip = ip;
7888 p->pub_ip_count = ++public_ip_count;
7889 printf("public_ip_count:%d hash:%d\n", public_ip_count,
7890 rte_jhash(&ip, 4, 0) % CGNAPT_MAX_PUB_IP);
7894 /* hw_checksum_reqd */
7895 if (strcmp(arg_name, "hw_checksum_reqd") == 0) {
7897 temp = atoi(arg_value);
7898 if ((temp != 0) && (temp != 1)) {
7899 printf("hw_checksum_reqd is invalid\n");
7902 p->hw_checksum_reqd = temp;
7906 /* nat_only_config_flag */
7907 if (strcmp(arg_name, "nat_only_config_flag") == 0) {
7908 nat_only_config_flag = 1;
7909 if (public_ip_port_range_present) {
7911 printf("CG-NAPT parse error:");
7912 printf("nat_only_config_flag with "
7913 "public_ip_port_range_present\n");
7919 /* max_port_per_client */
7920 if (strcmp(arg_name, "max_port_per_client") == 0) {
7921 if (max_port_present) {
7922 printf("CG-NAPT Parse Error: "
7923 "duplicate max_port_per_client\n");
7926 max_port_present = 1;
7929 max = atoi(arg_value);
7931 printf("max_port_per_client is invalid !!!\n");
7935 p->max_port_per_client = (uint16_t) max;
7937 if (p->max_port_per_client <= 0) {
7938 printf("max port per client is invalid\n");
7942 printf("max_port_per_client comp: %d\n",
7943 p->max_port_per_client);
7947 /* max_clients_per_ip */
7948 if (strcmp(arg_name, "max_clients_per_ip") == 0) {
7949 if (max_client_present) {
7950 printf("CG-NAPT parse Error: duplicate "
7951 "max_clients_per_ip\n");
7954 max_client_present = 1;
7956 if (nat_only_config_flag) {
7957 printf("CG-NAPT parse error:");
7958 printf("nat_only_config_flag with "
7959 "max_clients_per_ip\n");
7964 max = atoi(arg_value);
7966 printf("max_clients_per_ip is invalid !!!\n");
7970 p->max_clients_per_ip = (uint16_t) max;
7972 if (p->max_clients_per_ip <= 0) {
7973 printf("max_clients_per_ip is invalid\n");
7977 printf("max_clients_per_ip: %d\n",
7978 p->max_clients_per_ip);
7983 if (strcmp(arg_name, "n_entries") == 0) {
7984 if (n_entries_present)
7986 n_entries_present = 1;
7988 p->n_entries = atoi(arg_value);
7989 if (p->n_entries == 0)
7996 if (strcmp(arg_name, "n_flows") == 0) {
7997 if (n_flows_present)
7999 n_flows_present = 1;
8001 p->n_flows = atoi(arg_value);
8002 if (p->n_flows == 0)
8005 napt_common_table_hash_params.entries = p->n_flows;
8008 /* dest_if_offset Multiport Changes */
8009 if (strcmp(arg_name, "dest_if_offset") == 0) {
8010 if (dest_if_offset_present)
8012 //dest_if_offset_present = 1;
8014 dest_if_offset = atoi(arg_value);
8020 if (strcmp(arg_name, "key_offset") == 0) {
8021 if (key_offset_present)
8023 key_offset_present = 1;
8025 p->key_offset = atoi(arg_value);
8031 if (strcmp(arg_name, "key_size") == 0) {
8032 if (key_size_present)
8034 key_size_present = 1;
8036 p->key_size = atoi(arg_value);
8037 if ((p->key_size == 0) ||
8038 (p->key_size > PIPELINE_CGNAPT_KEY_MAX_SIZE) ||
8046 if (strcmp(arg_name, "hash_offset") == 0) {
8047 if (hash_offset_present)
8049 hash_offset_present = 1;
8051 p->hash_offset = atoi(arg_value);
8057 if (strcmp(arg_name, "pkt_type") == 0) {
8058 if (strcmp(arg_value, "ipv4") == 0) {
8059 p->traffic_type = TRAFFIC_TYPE_IPV4;
8060 printf("Traffic is set to IPv4\n");
8061 } else if (strcmp(arg_value, "ipv6") == 0) {
8062 p->traffic_type = TRAFFIC_TYPE_IPV6;
8063 printf("Traffic is set to IPv6\n");
8069 if (strcmp(arg_name, "cgnapt_debug") == 0) {
8070 CGNAPT_DEBUG = atoi(arg_value);
8075 /* any other Unknown argument return -1 */
8078 #ifdef NAT_ONLY_CONFIG_REQ
8079 if (nat_only_config_flag) {
8080 if (!public_ip_range_count) {
8081 printf("No public_ip_range %d for NAT only config.\n",
8082 public_ip_range_count);
8083 printf("Running static NAT only configuration\n");
8084 p->is_static_cgnapt = 1;
8089 if (!p->max_port_per_client)
8090 p->is_static_cgnapt = 1;
8093 /* Check that mandatory arguments are present */
8094 if ((n_flows_present == 0) ||
8095 (cgnapt_meta_offset_present == 0))
8102 * Function to initialize the pipeline
8105 * A pointer to struct pipeline_params
8107 * Void pointer - points to app params
8110 * void pointer to the pipeline, NULL 0 if failure
8112 static void *pipeline_cgnapt_init(struct pipeline_params *params, void *arg)
8113 /* (struct app_params *app) save it for use in port in handler */
8116 struct pipeline_cgnapt *p_nat;
8117 uint32_t size, i, in_ports_arg_size;
8119 /* Check input arguments */
8120 if ((params == NULL) ||
8121 (params->n_ports_in == 0) || (params->n_ports_out == 0))
8124 /* Memory allocation */
8125 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_cgnapt));
8126 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8127 p_nat = (struct pipeline_cgnapt *)p;
8128 global_pnat = p_nat;
8132 all_pipeline_cgnapt[n_cgnapt_pipeline++] = p_nat;
8134 strncpy(p->name, params->name,PIPELINE_NAME_SIZE);
8135 p->log_level = params->log_level;
8137 PLOG(p, HIGH, "CG-NAPT");
8138 /* Initialize all counters and arrays */
8140 p_nat->n_cgnapt_entry_deleted = 0;
8141 p_nat->n_cgnapt_entry_added = 0;
8142 p_nat->naptedPktCount = 0;
8143 p_nat->naptDroppedPktCount = 0;
8144 p_nat->inaptedPktCount = 0;
8145 p_nat->enaptedPktCount = 0;
8146 p_nat->receivedPktCount = 0;
8147 p_nat->missedPktCount = 0;
8148 p_nat->dynCgnaptCount = 0;
8149 p_nat->arpicmpPktCount = 0;
8151 p_nat->app_params_addr = (uint64_t) arg;
8152 for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
8153 p_nat->links_map[i] = 0xff;
8154 p_nat->outport_id[i] = 0xff;
8155 cgnapt_in_port_egress_prv[i] = 0;
8156 cgnapt_prv_que_port_index[i] = 0;
8158 p_nat->pipeline_num = 0xff;
8159 p_nat->hw_checksum_reqd = 0;
8160 p_nat->pub_ip_port_set = NULL;
8161 p_nat->pub_ip_count = 0;
8162 p_nat->traffic_type = TRAFFIC_TYPE_IPV4;
8163 p_nat->vnf_set = 0xff;
8165 /* For every init it should be reset */
8166 napt_port_alloc_elem_count = 0;
8168 #ifdef CGNAPT_TIMING_INST
8169 p_nat->in_port_exit_timestamp = 0;
8170 p_nat->external_time_sum = 0;
8171 p_nat->internal_time_sum = 0;
8172 p_nat->time_measurements = 0;
8173 p_nat->max_time_mesurements = 10000;
8174 p_nat->time_measurements_on = 0;
8177 #ifdef CGNAPT_DEBUGGING
8179 p_nat->naptDebugCount = 0;
8181 p_nat->naptDroppedPktCount1 = 0;
8182 p_nat->naptDroppedPktCount2 = 0;
8183 p_nat->naptDroppedPktCount3 = 0;
8184 p_nat->naptDroppedPktCount4 = 0;
8185 p_nat->naptDroppedPktCount5 = 0;
8186 p_nat->naptDroppedPktCount6 = 0;
8188 p_nat->missedpktcount1 = 0;
8189 p_nat->missedpktcount2 = 0;
8190 p_nat->missedpktcount3 = 0;
8191 p_nat->missedpktcount4 = 0;
8192 p_nat->missedpktcount5 = 0;
8193 p_nat->missedpktcount6 = 0;
8194 p_nat->missedpktcount7 = 0;
8195 p_nat->missedpktcount8 = 0;
8196 p_nat->missedpktcount9 = 0;
8197 p_nat->missedpktcount10 = 0;
8198 p_nat->missedpktcount11 = 0;
8199 p_nat->missedpktcount12 = 0;
8201 p_nat->max_port_dec_err1 = 0;
8202 p_nat->max_port_dec_err2 = 0;
8203 p_nat->max_port_dec_err3 = 0;
8204 p_nat->max_port_dec_success = 0;
8220 static int sip_enabled;
8224 #endif /* SIP_ALG */
8226 /*struct rte_pipeline_table_entry *entries[RTE_HASH_LOOKUP_BULK_MAX];*/
8227 /* bitmap of valid packets */
8228 p_nat->valid_packets = 0;
8229 /* bitmap of invalid packets to be dropped */
8230 p_nat->invalid_packets = 0;
8232 for (i = 0; i < RTE_HASH_LOOKUP_BULK_MAX; i++)
8233 p_nat->key_ptrs[i] = &(p_nat->keys[i]);
8235 p_nat->port_alloc_ring = NULL;
8237 /* Parse arguments */
8238 if (pipeline_cgnapt_parse_args(p_nat, params))
8241 p_nat->vnf_set = vnf_set_count;
8245 struct rte_pipeline_params pipeline_params = {
8246 .name = params->name,
8247 .socket_id = params->socket_id,
8248 .offset_port_id = cgnapt_meta_offset,
8251 p->p = rte_pipeline_create(&pipeline_params);
8259 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8261 uint32_t instr_size =
8262 RTE_CACHE_LINE_ROUNDUP((sizeof(uint64_t)) *
8265 (uint64_t *) rte_zmalloc(NULL, instr_size,
8266 RTE_CACHE_LINE_SIZE);
8268 (uint64_t *) rte_zmalloc(NULL, instr_size,
8269 RTE_CACHE_LINE_SIZE);
8271 (uint32_t *) rte_zmalloc(NULL, instr_size / 2,
8272 RTE_CACHE_LINE_SIZE);
8273 if ((inst_start_time == NULL) || (inst_end_time == NULL)
8274 || (inst_diff_time == NULL)) {
8275 printf("Inst array alloc failed .... ");
8280 /* Memory allocation for in_port_h_arg */
8281 in_ports_arg_size = RTE_CACHE_LINE_ROUNDUP(
8282 (sizeof(struct pipeline_cgnapt_in_port_h_arg)) *
8283 (params->n_ports_in));
8284 struct pipeline_cgnapt_in_port_h_arg *ap =
8285 (struct pipeline_cgnapt_in_port_h_arg *)
8288 RTE_CACHE_LINE_SIZE);
8292 myApp = (struct app_params *) arg;
8295 p->n_ports_in = params->n_ports_in;
8296 for (i = 0; i < p->n_ports_in; i++) {
8297 /* passing our cgnapt pipeline in call back arg */
8299 (ap[i]).in_port_id = i;
8301 struct rte_pipeline_port_in_params port_params = {
8303 pipeline_port_in_params_get_ops(¶ms->port_in
8306 pipeline_port_in_params_convert(¶ms->port_in
8308 .f_action = cgnapt_in_port_ah_mix,
8310 .burst_size = params->port_in[i].burst_size,
8313 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8315 instrumentation_port_in_arg = &(ap[i]);
8318 if (p_nat->traffic_type == TRAFFIC_TYPE_IPV4) {
8319 /* Private in-port handler */
8320 /* Multiport changes */
8321 if (cgnapt_in_port_egress_prv[i]) {
8322 port_params.f_action =
8323 cgnapt_in_port_ah_ipv4_prv;
8324 printf("CGNAPT port %d is IPv4 Prv\n", i);
8326 port_params.f_action =
8327 cgnapt_in_port_ah_ipv4_pub;
8328 printf("CGNAPT port %d is IPv4 Pub\n", i);
8332 if (p_nat->traffic_type == TRAFFIC_TYPE_IPV6) {
8333 if (cgnapt_in_port_egress_prv[i]) {
8334 port_params.f_action =
8335 cgnapt_in_port_ah_ipv6_prv;
8336 printf("CGNAPT port %d is IPv6 Prv\n", i);
8338 port_params.f_action =
8339 cgnapt_in_port_ah_ipv6_pub;
8340 printf("CGNAPT port %d is IPv6 Pub\n", i);
8344 int status = rte_pipeline_port_in_create(p->p,
8349 rte_pipeline_free(p->p);
8357 p->n_ports_out = params->n_ports_out;
8358 for (i = 0; i < p->n_ports_out; i++) {
8359 struct rte_pipeline_port_out_params port_params = {
8360 .ops = pipeline_port_out_params_get_ops(
8361 ¶ms->port_out[i]),
8362 .arg_create = pipeline_port_out_params_convert(
8363 ¶ms->port_out[i]),
8364 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8365 .f_action = port_out_ah_cgnapt,
8372 int status = rte_pipeline_port_out_create(p->p,
8374 &p->port_out_id[i]);
8377 rte_pipeline_free(p->p);
8383 int pipeline_num = 0;
8385 ignore = sscanf(params->name, "PIPELINE%d", &pipeline_num);
8387 printf("Not able to read pipeline number\n");
8390 p_nat->pipeline_num = (uint8_t) pipeline_num;
8391 register_pipeline_Qs(p_nat->pipeline_num, p);
8392 set_link_map(p_nat->pipeline_num, p, p_nat->links_map);
8393 set_outport_id(p_nat->pipeline_num, p, p_nat->outport_id);
8399 if (napt_common_table == NULL) {
8400 if (create_napt_common_table(p_nat->n_flows)) {
8402 "CG-NAPT create_napt_common_table failed.");
8407 struct rte_pipeline_table_params table_params = {
8408 .ops = &rte_table_stub_ops,
8410 .f_action_hit = NULL,
8411 .f_action_miss = NULL,
8413 .action_data_size = 0,
8416 int status = rte_pipeline_table_create(p->p,
8421 rte_pipeline_free(p->p);
8425 struct rte_pipeline_table_entry default_entry = {
8426 .action = RTE_PIPELINE_ACTION_PORT_META
8428 struct rte_pipeline_table_entry *default_entry_ptr;
8429 status = rte_pipeline_table_default_entry_add(
8433 &default_entry_ptr);
8435 rte_pipeline_free(p->p);
8441 /* Connecting input ports to tables */
8442 for (i = 0; i < p->n_ports_in; i++) {
8443 int status = rte_pipeline_port_in_connect_to_table(p->p,
8450 rte_pipeline_free(p->p);
8456 /* Enable input ports */
8457 for (i = 0; i < p->n_ports_in; i++) {
8458 int status = rte_pipeline_port_in_enable(p->p,
8462 rte_pipeline_free(p->p);
8468 /* Check pipeline consistency */
8469 if (rte_pipeline_check(p->p) < 0) {
8470 rte_pipeline_free(p->p);
8475 /* Message queues */
8476 p->n_msgq = params->n_msgq;
8477 for (i = 0; i < p->n_msgq; i++)
8478 p->msgq_in[i] = params->msgq_in[i];
8479 for (i = 0; i < p->n_msgq; i++)
8480 p->msgq_out[i] = params->msgq_out[i];
8482 /* Message handlers */
8483 memcpy(p->handlers, handlers, sizeof(p->handlers));
8484 memcpy(p_nat->custom_handlers,
8485 custom_handlers, sizeof(p_nat->custom_handlers));
8487 if (!p_nat->is_static_cgnapt) {
8488 printf("Initializing dyn napt components ... %d\n",
8489 p_nat->pipeline_num);
8490 if (napt_port_alloc_init(p_nat) == -1) {
8491 printf("Error - napt_port_alloc_init failed - %d\n",
8492 p_nat->pipeline_num);
8497 if (max_port_per_client_hash == NULL) {
8498 rc = init_max_port_per_client(p_nat);
8500 printf("CGNAPT Error - "
8501 "init_max_port_per_client failed %d", rc);
8508 if (!icmp_pool_init) {
8510 /* create the arp_icmp mbuf rx pool */
8511 cgnapt_icmp_pktmbuf_tx_pool =
8512 rte_pktmbuf_pool_create("icmp_mbuf_tx_pool", 63, 32, 0,
8513 RTE_MBUF_DEFAULT_BUF_SIZE,
8515 if (cgnapt_icmp_pktmbuf_tx_pool == NULL) {
8516 PLOG(p, HIGH, "ICMP mbuf pool create failed.");
8521 rte_pktmbuf_alloc(cgnapt_icmp_pktmbuf_tx_pool);
8523 if (cgnapt_icmp_pkt == NULL) {
8524 printf("Failed to allocate cgnapt_icmp_pkt\n");
8531 cgnat_cnxn_tracker = rte_zmalloc(NULL, rte_ct_get_cnxn_tracker_size(),
8532 RTE_CACHE_LINE_SIZE);
8534 if (cgnat_cnxn_tracker == NULL) {
8535 printf("CGNAPT CT memory not allocated\n");
8538 rte_ct_initialize_default_timeouts(cgnat_cnxn_tracker);
8540 printf("CGNAPT CT Flows %d\n", p_nat->n_flows);
8542 ret = rte_ct_initialize_cnxn_tracker(cgnat_cnxn_tracker,
8544 "CGNAT_CT_COMMON_TABLE");
8554 if (pcp_init() == PCP_INIT_SUCCESS)
8555 printf("PCP contents are initialized successfully\n");
8557 printf("Error in initializing PCP contents\n");
8564 * Function for pipeline cleanup
8567 * A void pointer to pipeline
8572 static int pipeline_cgnapt_free(void *pipeline)
8574 struct pipeline *p = (struct pipeline *)pipeline;
8576 /* Check input arguments */
8580 /* Free resources */
8581 rte_pipeline_free(p->p);
8587 pipeline_cgnapt_track(void *pipeline, __rte_unused uint32_t port_in,
8590 struct pipeline *p = (struct pipeline *)pipeline;
8592 /* Check input arguments */
8593 if ((p == NULL) || (port_in >= p->n_ports_in) || (port_out == NULL))
8596 if (p->n_ports_in == 1) {
8605 * Function for pipeline timers
8608 * A void pointer to pipeline
8613 static int pipeline_cgnapt_timer(void *pipeline)
8615 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)pipeline;
8617 pipeline_msg_req_handle(&p_nat->p);
8619 rte_pipeline_flush(((struct pipeline *)p_nat)->p);
8625 * Function for pipeline custom handlers
8628 * A void pointer to pipeline
8630 * void pointer for incoming data
8633 * void pointer of response
8635 void *pipeline_cgnapt_msg_req_custom_handler(struct pipeline *p, void *msg)
8637 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
8638 struct pipeline_custom_msg_req *req = msg;
8639 pipeline_msg_req_handler f_handle;
8641 f_handle = (req->subtype < PIPELINE_CGNAPT_MSG_REQS) ?
8642 p_nat->custom_handlers[req->subtype] :
8643 pipeline_msg_req_invalid_handler;
8645 if (f_handle == NULL)
8646 f_handle = pipeline_msg_req_invalid_handler;
8648 return f_handle(p, req);
8652 * Function for adding NSP data
8655 * A void pointer to pipeline
8657 * void pointer for incoming data
8660 * void pointer of response
8662 void *pipeline_cgnapt_msg_req_nsp_add_handler(
8663 __rte_unused struct pipeline *p,
8666 struct pipeline_cgnapt_nsp_add_msg_req *req = msg;
8667 struct pipeline_cgnapt_nsp_add_msg_rsp *rsp = msg;
8669 struct cgnapt_nsp_node *node = NULL, *ll = nsp_ll;
8672 (req->nsp.depth == 32 || req->nsp.depth == 40
8673 || req->nsp.depth == 48 || req->nsp.depth == 56
8674 || req->nsp.depth == 64 || req->nsp.depth == 96)) {
8680 printf("be initial cond\n");
8681 if (nsp_ll == NULL) {
8682 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_nsp_node));
8683 node = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8685 printf("be 1st cond\n");
8691 memcpy(&node->nsp, &req->nsp,
8692 sizeof(struct pipeline_cgnapt_nsp_t));
8696 while (ll != NULL) {
8697 if (!memcmp(ll->nsp.prefix, req->nsp.prefix, 16)
8698 && ll->nsp.depth == req->nsp.depth) {
8699 printf("be 2st cond\n");
8707 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_nsp_node));
8708 node = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8710 printf("be 3st cond\n");
8716 memcpy(&node->nsp, &req->nsp,
8717 sizeof(struct pipeline_cgnapt_nsp_t));
8718 node->next = nsp_ll;
8725 printf("be 4st cond\n");
8730 * Function for deleting NSP data
8733 * A void pointer to pipeline
8735 * void pointer for incoming data
8738 * void pointer of response
8740 void *pipeline_cgnapt_msg_req_nsp_del_handler(
8741 __rte_unused struct pipeline *p,
8744 struct pipeline_cgnapt_nsp_del_msg_req *req = msg;
8745 struct pipeline_cgnapt_nsp_del_msg_rsp *rsp = msg;
8746 struct cgnapt_nsp_node *prev = NULL, *ll = nsp_ll;
8748 while (ll != NULL) {
8749 if (!memcmp(ll->nsp.prefix, req->nsp.prefix, 16)
8750 && ll->nsp.depth == req->nsp.depth) {
8752 prev->next = ll->next;
8775 * Function for adding NAPT entry
8778 * A void pointer to pipeline
8780 * void pointer for incoming data
8783 * void pointer of response
8785 void *pipeline_cgnapt_msg_req_entry_add_handler(struct pipeline *p, void *msg)
8787 struct pipeline_cgnapt_entry_add_msg_req *req = msg;
8788 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
8789 uint8_t type = req->data.type;
8790 uint32_t src_ip = (type == CGNAPT_ENTRY_IPV4) ?
8791 req->data.u.prv_ip :
8792 rte_bswap32(req->data.u.u32_prv_ipv6[3]);
8794 uint8_t src_ipv6[16];
8796 uint32_t dest_ip = req->data.pub_ip;
8797 uint16_t src_port = req->data.prv_port;
8798 uint16_t dest_port = req->data.pub_port;
8799 uint16_t rx_port = req->data.prv_phy_port;
8800 uint32_t ttl = req->data.ttl;
8802 if (type == CGNAPT_ENTRY_IPV6)
8803 memcpy(src_ipv6, req->data.u.prv_ipv6, 16);
8805 printf("CG-NAPT addm - PrvIP %x, PrvPort %d,", src_ip, src_port);
8806 printf("PubIP %x, PubPort %d,", dest_ip, dest_port);
8808 printf("PhyPort %d, ttl %u,", rx_port, ttl);
8809 printf("entry_type %d\n", type);
8810 #ifdef NAT_ONLY_CONFIG_REQ
8811 if (nat_only_config_flag) {
8812 if (!p_nat->is_static_cgnapt) {
8815 for (i = 0; i < p_nat->pub_ip_range_count; i++) {
8816 if (((dest_ip >= p_nat->pub_ip_range[i].start_ip)
8817 && (dest_ip <= p_nat->pub_ip_range[i].end_ip))) {
8818 printf("Error - static port cannot be in Dynamic "
8820 printf("%x-%x\n", p_nat->pub_ip_range[i].start_ip,
8821 p_nat->pub_ip_range[i].end_ip);
8827 if (pipeline_cgnapt_msg_req_entry_addm_pair(p, msg,
8833 printf("pipeline_cgnapt_msg_req_entry_addm_handler\n");
8837 #ifdef CGNAPT_DBG_PRNT
8838 printf("Success - pipeline_cgnapt_msg_req_entry_addm_handler");
8839 printf("added %d rule pairs.\n", count);
8845 if (!p_nat->is_static_cgnapt) {
8848 for (i = 0; i < p_nat->pub_ip_count; i++) {
8849 /* Check port range if same Public-IP */
8850 if (dest_ip != p_nat->pub_ip_port_set[i].ip)
8852 if (((dest_port >= p_nat->pub_ip_port_set[i].start_port) &&
8853 (dest_port <= p_nat->pub_ip_port_set[i].end_port))) {
8854 printf("Error - port cannot be in Dynamic "
8855 "port range %d-%d\n",
8856 p_nat->pub_ip_port_set[i].start_port,
8857 p_nat->pub_ip_port_set[i].end_port);
8863 if (pipeline_cgnapt_msg_req_entry_addm_pair
8864 (p, msg, src_ip, src_port, dest_ip, dest_port, rx_port,
8865 ttl, type, src_ipv6)) {
8866 printf("Error - pipeline_cgnapt_msg_req_entry_add_handler\n");
8871 #ifdef CGNAPT_DBG_PRNT
8872 printf("\nSuccess - pipeline_cgnapt_msg_req_entry_add_handler "
8879 * Function for adding a NAPT entry pair
8882 * A void pointer to pipeline
8884 * void pointer for incoming data
8890 * destination ip address
8894 * Physical receive port
8896 * time to live value
8898 * type of entry IPv4 vs IPv6
8900 * uint8_t array of IPv6 address
8903 * 0 if success, negative if fails
8906 pipeline_cgnapt_msg_req_entry_addm_pair(
8907 struct pipeline *p, __rte_unused void *msg,
8908 uint32_t src_ip, uint16_t src_port,
8909 uint32_t dest_ip, uint16_t dest_port,
8910 uint16_t rx_port, uint32_t ttl,
8911 uint8_t type, uint8_t src_ipv6[16])
8914 struct pipeline_cgnapt_entry_key key;
8915 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
8918 key.port = src_port;
8921 struct cgnapt_table_entry entry = {
8923 .action = RTE_PIPELINE_ACTION_PORT,
8924 .port_id = CGNAPT_PUB_PORT_ID,
8928 /*.prv_ip = src_ip, */
8929 .prv_port = src_port,
8931 .pub_port = dest_port,
8932 .prv_phy_port = rx_port,
8933 .pub_phy_port = get_prv_to_pub_port(&dest_ip,
8936 .timeout = STATIC_CGNAPT_TIMEOUT,
8943 if (type == CGNAPT_ENTRY_IPV4) {
8944 entry.data.type = CGNAPT_ENTRY_IPV4;
8945 entry.data.u.prv_ip = src_ip;
8947 entry.data.type = CGNAPT_ENTRY_IPV6;
8948 memcpy(entry.data.u.prv_ipv6, src_ipv6, 16);
8951 /* Also need to add a paired entry on our own */
8953 * Need to change key
8954 * Need to change entry header
8955 * Will keep the same entry and take care
8956 * of translation in table hit handler
8958 struct pipeline_cgnapt_entry_key second_key;
8960 /* Need to add a second ingress entry */
8961 second_key.ip = dest_ip;
8962 second_key.port = dest_port;
8963 second_key.pid = 0xffff;
8965 #ifdef NAT_ONLY_CONFIG_REQ
8966 if (nat_only_config_flag) {
8968 entry.data.pub_port = 0xffff;
8969 second_key.port = 0xffff;
8973 int32_t position = rte_hash_add_key(napt_common_table, &key);
8976 printf("CG-NAPT entry bulk add failed");
8977 printf(" ... returning without adding ...\n");
8981 memcpy(&napt_hash_tbl_entries[position], &entry,
8982 sizeof(struct cgnapt_table_entry));
8984 #ifdef CGNAPT_DEBUGGING
8985 if (p_nat->kpc1++ < 5)
8989 p_nat->n_cgnapt_entry_added++;
8991 /* Now modify the forward port for reverse entry */
8992 entry.head.port_id = CGNAPT_PRV_PORT_ID;
8994 position = rte_hash_add_key(napt_common_table, &second_key);
8997 printf("CG-NAPT entry reverse bulk add failed");
8998 printf(" ... returning with fwd add ...%d\n", position);
9002 memcpy(&napt_hash_tbl_entries[position], &entry,
9003 sizeof(struct cgnapt_table_entry));
9005 #ifdef CGNAPT_DEBUGGING
9006 if (p_nat->kpc1 < 5)
9007 print_key(&second_key);
9010 p_nat->n_cgnapt_entry_added++;
9015 * Function for adding multiple NAPT entries
9018 * A void pointer to pipeline
9020 * void pointer for incoming data
9023 * void pointer of response
9025 void *pipeline_cgnapt_msg_req_entry_addm_handler(struct pipeline *p, void *msg)
9027 struct pipeline_cgnapt_entry_addm_msg_req *req = msg;
9028 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9030 uint32_t max_ue = req->data.num_ue;
9031 uint8_t type = req->data.type;
9032 uint32_t src_ip = (type == CGNAPT_ENTRY_IPV4) ?
9033 req->data.u.prv_ip :
9034 rte_bswap32(req->data.u.u32_prv_ipv6[3]);
9036 uint8_t src_ipv6[16];
9038 uint32_t dest_ip = req->data.pub_ip;
9039 uint16_t src_port = req->data.prv_port;
9040 uint16_t dest_port = req->data.pub_port;
9041 uint16_t rx_port = req->data.prv_phy_port;
9042 uint32_t ttl = req->data.ttl;
9043 uint16_t max_src_port = req->data.prv_port_max;
9044 uint16_t max_dest_port = req->data.pub_port_max;
9046 uint16_t src_port_start = src_port;
9047 uint16_t dest_port_start = dest_port;
9048 uint32_t src_ip_temp;
9050 if (type == CGNAPT_ENTRY_IPV6)
9051 memcpy(src_ipv6, req->data.u.prv_ipv6, 16);
9053 printf("CG-NAPT addm - PrvIP %x, PrvPort %d,", src_ip, src_port);
9054 printf("PubIP %x, PubPort %d,", dest_ip, dest_port);
9055 printf("PhyPort %d, ttl %u, NumUe %d,", rx_port, ttl, max_ue);
9056 printf("mPrvPort %d, mPubPort %d,", max_src_port, max_dest_port);
9057 printf("entry_type %d\n", type);
9058 #ifdef NAT_ONLY_CONFIG_REQ
9059 if (nat_only_config_flag) {
9060 if (!p_nat->is_static_cgnapt) {
9063 for (i = 0; i < p_nat->pub_ip_range_count; i++) {
9064 if (((dest_ip >= p_nat->pub_ip_range[i].start_ip)
9065 && (dest_ip <= p_nat->pub_ip_range[i].end_ip)) ||
9066 (((dest_ip + max_ue) >=
9067 p_nat->pub_ip_range[i].start_ip) &&
9068 ((dest_ip + max_ue) <=
9069 p_nat->pub_ip_range[i].end_ip))) {
9070 printf("Error - static port cannot be in Dynamic "
9072 printf("%x-%x\n", p_nat->pub_ip_range[i].start_ip,
9073 p_nat->pub_ip_range[i].end_ip);
9080 for (uenum = 0; uenum < max_ue; uenum++) {
9082 if (pipeline_cgnapt_msg_req_entry_addm_pair(p, msg,
9088 printf("pipeline_cgnapt_msg_req_entry_addm_handler\n");
9098 #ifdef CGNAPT_DBG_PRNT
9099 printf("Success - pipeline_cgnapt_msg_req_entry_addm_handler");
9100 printf("added %d rule pairs.\n", count);
9107 if (!p_nat->is_static_cgnapt) {
9110 for (i = 0; i < p_nat->pub_ip_count; i++) {
9111 /* Check port range if same Public-IP */
9112 if (dest_ip != p_nat->pub_ip_port_set[i].ip)
9114 if (((dest_port >= p_nat->pub_ip_port_set[i].start_port) &&
9115 (dest_port <= p_nat->pub_ip_port_set[i].end_port)) ||
9116 ((max_dest_port >= p_nat->pub_ip_port_set[i].start_port)
9117 && max_dest_port <= p_nat->pub_ip_port_set[i].end_port)) {
9118 printf("Error - port cannot be in Dynamic port range %d-%d\n",
9119 p_nat->pub_ip_port_set[i].start_port,
9120 p_nat->pub_ip_port_set[i].end_port);
9126 for (uenum = 0; uenum < max_ue; uenum++) {
9127 if (pipeline_cgnapt_msg_req_entry_addm_pair
9128 (p, msg, src_ip, src_port, dest_ip, dest_port, rx_port,
9129 ttl, type, src_ipv6)) {
9130 printf("Error - pipeline_cgnapt_msg_req_entry_addm_handler\n");
9137 if (src_port > max_src_port) {
9138 src_port = src_port_start;
9140 if (req->data.type == CGNAPT_ENTRY_IPV6) {
9141 src_ip_temp = rte_bswap32(src_ip);
9142 memcpy(&src_ipv6[12], &src_ip_temp, 4);
9146 if (dest_port > max_dest_port) {
9147 dest_port = dest_port_start;
9152 #ifdef CGNAPT_DBG_PRNT
9153 printf("\nSuccess - pipeline_cgnapt_msg_req_entry_addm_handler added");
9154 printf("%d rule pairs.\n", count);
9160 * Function for deleting NAPT entry
9163 * A void pointer to pipeline
9165 * void pointer for incoming data
9168 * void pointer of response
9170 void *pipeline_cgnapt_msg_req_entry_del_handler(struct pipeline *p, void *msg)
9172 struct pipeline_cgnapt_entry_delete_msg_req *req = msg;
9173 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9174 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9177 uint8_t *KeyP = (void *)(&req->key);
9180 printf("pipeline_cgnapt_msg_req_entry_del_handler - Key: ");
9181 for (i = 0; i < (int)sizeof(struct pipeline_cgnapt_entry_key);
9183 printf(" %02x", KeyP[i]);
9184 printf(" ,KeySize %u\n",
9185 (int)sizeof(struct pipeline_cgnapt_entry_key));
9188 struct cgnapt_table_entry entry;
9190 /* If ingress key */
9191 if (!is_phy_port_privte(req->key.pid))
9192 req->key.pid = 0xffff;
9194 #ifdef NAT_ONLY_CONFIG_REQ
9195 if (nat_only_config_flag)
9196 req->key.port = 0xffff;
9200 position = rte_hash_lookup(napt_common_table, &req->key);
9201 if (position == -ENOENT) {
9202 printf("Entry not found\n");
9205 memcpy(&entry, &napt_hash_tbl_entries[position],
9206 sizeof(struct cgnapt_table_entry));
9207 position = rte_hash_del_key(napt_common_table, &req->key);
9208 p_nat->n_cgnapt_entry_deleted++;
9210 struct pipeline_cgnapt_entry_key second_key;
9212 if (is_phy_port_privte(req->key.pid)) {
9213 /* key is for egress - make second key for ingress */
9214 second_key.ip = entry.data.pub_ip;
9215 second_key.port = entry.data.pub_port;
9216 second_key.pid = 0xffff;
9219 /* key is for ingress - make second key for egress */
9220 second_key.ip = entry.data.u.prv_ip;
9221 second_key.port = entry.data.prv_port;
9222 second_key.pid = entry.data.prv_phy_port;
9225 #ifdef NAT_ONLY_CONFIG_REQ
9226 if (nat_only_config_flag)
9227 second_key.port = 0xffff;
9230 position = rte_hash_del_key(napt_common_table, &second_key);
9231 p_nat->n_cgnapt_entry_deleted++;
9236 void *pipeline_cgnapt_msg_req_entry_sync_handler(struct pipeline *p, void *msg)
9238 struct pipeline_cgnapt_entry_delete_msg_req *req = msg;
9239 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9241 rsp->status = rte_pipeline_table_entry_delete(
9245 &rsp->key_found, NULL);
9251 * Function to print the NAPT key
9254 * A pointer to struct pipeline_cgnapt_entry_key
9256 void print_key(struct pipeline_cgnapt_entry_key *key)
9258 uint8_t *KeyP = (void *)(key);
9262 for (i = 0; i < (int)sizeof(struct pipeline_cgnapt_entry_key); i++)
9263 printf(" %02x", KeyP[i]);
9267 * Function to print the table entry
9270 * A pointer to struct rte_pipeline_table_entry
9272 void print_entry1(struct rte_pipeline_table_entry *entry)
9274 uint8_t *entryP = (void *)(entry);
9278 for (i = 0; i < (int)sizeof(struct rte_pipeline_table_entry); i++)
9279 printf(" %02x", entryP[i]);
9283 * Function to print the NAPT table entry
9286 * A pointer to struct cgnapt_table_entry
9288 void print_cgnapt_entry(struct cgnapt_table_entry *entry)
9290 uint8_t *entryP = (void *)(entry);
9293 printf("CGNAPT Entry: ");
9294 for (i = 0; i < (int)sizeof(struct cgnapt_table_entry); i++)
9295 printf(" %02x", entryP[i]);
9296 printf(" size:%d\n", (int)sizeof(struct cgnapt_table_entry));
9300 * Function to get a free port
9303 * A pointer to struct pipeline_cgnapt
9305 * A uint32_t pointer to return corresponding ip address
9308 * free port number, 0 if error
9310 int get_free_iport(struct pipeline_cgnapt *p_nat, uint32_t *public_ip)
9313 /* If we don't have a valid napt_port_alloc_elem get one from
9316 if (p_nat->allocated_ports == NULL) {
9320 ret = rte_ring_dequeue(p_nat->port_alloc_ring, &ports);
9322 p_nat->allocated_ports =
9323 (struct napt_port_alloc_elem *)ports;
9325 #ifdef CGNAPT_DEBUGGING
9329 #ifdef CGNAPT_DBG_PRNT
9330 if (CGNAPT_DEBUG > 3)
9331 printf("p_nat->allocated_ports %p\n",
9332 p_nat->allocated_ports);
9335 printf("CGNAPT Err - get_free_iport rte_ring_dequeue "
9337 printf("%d, %d, %d\n", rte_ring_count(
9338 p_nat->port_alloc_ring), rte_ring_free_count(
9339 p_nat->port_alloc_ring), ret);
9341 #ifdef CGNAPT_DEBUGGING
9342 #ifdef CGNAPT_DBG_PRNT
9343 printf("Th%d GFP:: %" PRIu64 ", %" PRIu64 ", "
9344 "%" PRIu64", %" PRIu64 ",\n", p_nat->pipeline_num,
9345 p_nat->gfp_get, p_nat->gfp_ret, p_nat->gfp_suc,
9355 /* get the port from index count-1 and decrease count */
9356 port = p_nat->allocated_ports->ports
9357 [p_nat->allocated_ports->count - 1];
9358 *public_ip = p_nat->allocated_ports->ip_addr
9359 [p_nat->allocated_ports->count - 1];
9361 p_nat->allocated_ports->count -= 1;
9363 /* if count is zero, return buffer to mem pool */
9364 if (p_nat->allocated_ports->count == 0) {
9365 rte_mempool_put(napt_port_pool, p_nat->allocated_ports);
9367 #ifdef CGNAPT_DEBUGGING
9369 #ifdef CGNAPT_DBG_PRNT
9370 printf("Th%d Returned to pool p_nat->allocated_ports %p,",
9371 p_nat->pipeline_num, p_nat->allocated_ports);
9372 printf("%" PRIu64 ", %" PRIu64 ",",
9373 p_nat->gfp_get, p_nat->gfp_ret);
9374 printf("%" PRIu64 ", %" PRIu64 ",\n",
9375 p_nat->gfp_suc, p_nat->gfp_err);
9379 p_nat->allocated_ports = NULL;
9382 #ifdef CGNAPT_DEBUGGING
9390 * Function to free a port
9393 * Port number to free
9395 * Corresponding ip address
9397 * A pointer to struct pipeline_cgnapt
9400 void release_iport(uint16_t port_num, uint32_t public_ip,
9401 struct pipeline_cgnapt *p_nat)
9403 /* If we don't have a valid napt_port_alloc_elem get one
9406 if (p_nat->free_ports == NULL) {
9409 #ifdef CGNAPT_DEBUGGING
9413 if (rte_mempool_get(napt_port_pool, &ports) < 0) {
9414 #ifdef CGNAPT_DEBUGGING
9417 printf("CGNAPT release_iport error in getting "
9418 "port alloc buffer\n");
9422 p_nat->free_ports = (struct napt_port_alloc_elem *)ports;
9423 p_nat->free_ports->count = 0;
9426 /* put the port at index count and increase count */
9427 p_nat->free_ports->ip_addr[p_nat->free_ports->count] = public_ip;
9428 p_nat->free_ports->ports[p_nat->free_ports->count] = port_num;
9429 p_nat->free_ports->count += 1;
9431 /* if napt_port_alloc_elem is full add it to ring */
9434 #ifdef CGNAPT_DEBUGGING
9438 #ifdef CGNAPT_DBG_PRNT
9439 if (CGNAPT_DEBUG >= 2) {
9440 printf("CGNAPT port_alloc_ring before EnQ Cnt %d, Free %d\n",
9441 rte_ring_count(p_nat->port_alloc_ring),
9442 rte_ring_free_count(p_nat->port_alloc_ring));
9446 if (rte_ring_enqueue(p_nat->port_alloc_ring,
9447 (void *)p_nat->free_ports) != 0) {
9448 printf("CGNAPT release_iport Enqueue error %p\n",
9451 #ifdef CGNAPT_DEBUGGING
9456 #ifdef CGNAPT_DBG_PRNT
9457 if (CGNAPT_DEBUG >= 2) {
9458 printf("CGNAPT port_alloc_ring after EnQ Cnt %d",
9459 rte_ring_count(p_nat->port_alloc_ring));
9461 rte_ring_free_count(p_nat->port_alloc_ring));
9465 p_nat->free_ports = NULL;
9468 #ifdef CGNAPT_DEBUGGING
9474 * Function to initialize max ports per client data structures
9475 * Called during dynamic NAPT initialization.
9478 * A pointer to struct pipeline_cgnapt
9481 * 0 if success, negative if error
9483 int init_max_port_per_client(
9484 __rte_unused struct pipeline_cgnapt *p_nat)
9486 if (max_port_per_client_hash)
9489 /*MPPC_ALREADY_EXISTS */
9493 max_port_per_client_hash =
9494 rte_hash_create(&max_port_per_client_hash_params);
9495 if (!max_port_per_client_hash)
9498 /*MPPC_HASH_CREATE_ERROR */
9500 max_port_per_client_array =
9502 sizeof(struct max_port_per_client) * MAX_DYN_ENTRY,
9503 RTE_CACHE_LINE_SIZE);
9504 if (!max_port_per_client_array)
9507 /*MPPC_ARRAY_CREATE_ERROR */
9509 for (i = 0; i < MAX_DYN_ENTRY; i++) {
9510 max_port_per_client_array[i].prv_ip = 0;
9511 max_port_per_client_array[i].prv_phy_port = 0;
9512 max_port_per_client_array[i].max_port_cnt = 0;
9520 * Function to check if max ports for a client is reached
9522 * @param prv_ip_param
9523 * A uint32_t ip address of client
9524 * @param prv_phy_port_param
9525 * A uint32_t physical port id of the client
9527 * A pointer to struct pipeline_cgnapt
9530 * 0 if max port not reached, 1 if reached, -1 if error
9532 int is_max_port_per_client_reached(uint32_t prv_ip_param,
9533 uint32_t prv_phy_port_param,
9534 struct pipeline_cgnapt *p_nat)
9536 int index = MAX_PORT_INVALID_KEY;
9538 struct max_port_per_client_key key = {
9539 .prv_ip = prv_ip_param,
9540 .prv_phy_port = prv_phy_port_param,
9543 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9546 return MAX_PORT_INVALID_KEY;
9548 if (max_port_per_client_array[index].max_port_cnt >=
9549 p_nat->max_port_per_client)
9550 return MAX_PORT_REACHED;
9552 return MAX_PORT_NOT_REACHED;
9556 * Function to increase max ports for a client
9558 * @param prv_ip_param
9559 * A uint32_t ip address of client
9560 * @param prv_phy_port_param
9561 * A uint32_t physical port id of the client
9563 * A pointer to struct pipeline_cgnapt
9566 * 0 if max port reached, 1 if success, 2 if new entry, -1 if error
9568 int increment_max_port_counter(uint32_t prv_ip_param,
9569 uint32_t prv_phy_port_param,
9570 struct pipeline_cgnapt *p_nat)
9572 int index = MAX_PORT_INC_ERROR;
9574 struct max_port_per_client_key key = {
9575 .prv_ip = prv_ip_param,
9576 .prv_phy_port = prv_phy_port_param,
9579 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9581 if (index == -EINVAL)
9582 return MAX_PORT_INC_ERROR;
9584 if (index == -ENOENT) {
9585 if (max_port_per_client_add_entry(prv_ip_param,
9588 return MAX_PORT_INC_ERROR;
9590 return 2; /*return MAX_PORT_NEW_ENTRY; */
9593 if (CGNAPT_DEBUG > 2)
9594 printf("%s: max_port_cnt(%d), p_nat_max(%d)\n", __func__,
9595 max_port_per_client_array[index].max_port_cnt,
9596 p_nat->max_port_per_client);
9598 if (max_port_per_client_array[index].max_port_cnt <
9599 p_nat->max_port_per_client) {
9600 max_port_per_client_array[index].max_port_cnt++;
9601 return MAX_PORT_INC_SUCCESS;
9604 return MAX_PORT_INC_REACHED;
9608 * Function to decrease max ports for a client
9610 * @param prv_ip_param
9611 * A uint32_t ip address of client
9612 * @param prv_phy_port_param
9613 * A uint32_t physical port id of the client
9615 * A pointer to struct pipeline_cgnapt
9618 * 0 if count already 0, 1 if success, -1 if error
9620 int decrement_max_port_counter(uint32_t prv_ip_param,
9621 uint32_t prv_phy_port_param,
9622 struct pipeline_cgnapt *p_nat)
9624 int index = MAX_PORT_DEC_ERROR;
9626 struct max_port_per_client_key key = {
9627 .prv_ip = prv_ip_param,
9628 .prv_phy_port = prv_phy_port_param,
9631 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9634 #ifdef CGNAPT_DEBUGGING
9635 p_nat->max_port_dec_err1++;
9637 return MAX_PORT_DEC_ERROR;
9641 if (max_port_per_client_array[index].max_port_cnt > 0) {
9642 /* If it is the last port,ret this info which is used for
9643 * max_cli_per_pub_ip
9646 max_port_per_client_array[index].max_port_cnt--;
9647 /* Count should be atomic but we are good as we have only
9648 * one task handling this counter at a time (core affinity)
9652 if (max_port_per_client_array[index].max_port_cnt <= 0) {
9653 if (max_port_per_client_del_entry
9654 (prv_ip_param, prv_phy_port_param, p_nat) <= 0) {
9656 #ifdef CGNAPT_DEBUGGING
9657 p_nat->max_port_dec_err2++;
9659 return MAX_PORT_DEC_ERROR;
9662 #ifdef CGNAPT_DEBUGGING
9663 p_nat->max_port_dec_err3++;
9666 return MAX_PORT_DEC_REACHED;
9669 #ifdef CGNAPT_DEBUGGING
9670 p_nat->max_port_dec_success++;
9673 return MAX_PORT_DEC_SUCCESS;
9677 * Function to add a max ports per client entry
9679 * @param prv_ip_param
9680 * A uint32_t ip address of client
9681 * @param prv_phy_port_param
9682 * A uint32_t physical port id of the client
9684 * A pointer to struct pipeline_cgnapt
9687 * 0 no success, 1 if success, -1 if error
9689 int max_port_per_client_add_entry(
9690 uint32_t prv_ip_param,
9691 uint32_t prv_phy_port_param,
9692 __rte_unused struct pipeline_cgnapt *p_nat)
9694 int index = MAX_PORT_ADD_ERROR;
9696 struct max_port_per_client_key key = {
9697 .prv_ip = prv_ip_param,
9698 .prv_phy_port = prv_phy_port_param,
9701 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9702 if (index == -EINVAL)
9703 return MAX_PORT_ADD_ERROR;
9706 return MAX_PORT_ADD_UNSUCCESS;
9708 if (index == -ENOENT) {
9710 #ifdef CGNAPT_DBG_PRNT
9711 if (CGNAPT_DEBUG > 2)
9712 printf("max_port_per_client_add_entry fn: "
9713 "Entry does not exist\n");
9717 rte_hash_add_key(max_port_per_client_hash,
9718 (const void *)&key);
9719 if (index == -ENOSPC)
9720 return MAX_PORT_ADD_UNSUCCESS;
9722 #ifdef CGNAPT_DBG_PRNT
9723 if (CGNAPT_DEBUG > 2)
9724 printf("max_port_per_client_add_entry fn:"
9725 "Add entry index(%d)\n", index);
9728 max_port_per_client_array[index].prv_ip = prv_ip_param;
9729 max_port_per_client_array[index].prv_phy_port =
9733 max_port_per_client_array[index].max_port_cnt++;
9734 return MAX_PORT_ADD_SUCCESS;
9738 * Function to delete a max ports per client entry
9740 * @param prv_ip_param
9741 * A uint32_t ip address of client
9742 * @param prv_phy_port_param
9743 * A uint32_t physical port id of the client
9745 * A pointer to struct pipeline_cgnapt
9748 * 0 no success, 1 if success, -1 if error
9750 int max_port_per_client_del_entry(
9751 uint32_t prv_ip_param,
9752 uint32_t prv_phy_port_param,
9753 __rte_unused struct pipeline_cgnapt *p_nat)
9755 int index = MAX_PORT_DEL_ERROR;
9757 struct max_port_per_client_key key = {
9758 .prv_ip = prv_ip_param,
9759 .prv_phy_port = prv_phy_port_param,
9762 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9764 if (index == -EINVAL)
9765 return MAX_PORT_DEL_ERROR;
9767 if (index == -ENOENT)
9768 return MAX_PORT_DEL_UNSUCCESS;
9770 index = rte_hash_del_key(max_port_per_client_hash, (const void *)&key);
9771 max_port_per_client_array[index].prv_ip = 0;
9772 max_port_per_client_array[index].prv_phy_port = 0;
9773 max_port_per_client_array[index].max_port_cnt = 0;
9775 return MAX_PORT_DEL_SUCCESS;
9779 * Function to execute debug commands
9782 * A pointer to struct pipeline
9784 * void pointer to incoming arguments
9786 void *pipeline_cgnapt_msg_req_entry_dbg_handler(struct pipeline *p, void *msg)
9788 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9790 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9794 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_STATS_SHOW) {
9795 printf("\nCG-NAPT Packet Stats:\n");
9796 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
9797 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
9798 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
9799 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
9800 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
9801 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
9802 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
9804 #ifdef CGNAPT_DEBUGGING
9805 printf("\n Drop detail 1:%" PRIu64 ",",
9806 p_nat->naptDroppedPktCount1);
9807 printf("\n Drop detail 2:%" PRIu64 ",",
9808 p_nat->naptDroppedPktCount2);
9809 printf("\n Drop detail 3:%" PRIu64 ",",
9810 p_nat->naptDroppedPktCount3);
9811 printf("\n Drop detail 4:%" PRIu64 ",",
9812 p_nat->naptDroppedPktCount4);
9813 printf("\n Drop detail 5:%" PRIu64 ",",
9814 p_nat->naptDroppedPktCount5);
9815 printf("\n Drop detail 6:%" PRIu64 "",
9816 p_nat->naptDroppedPktCount6);
9818 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9819 p_nat->missedpktcount1,
9820 p_nat->missedpktcount2);
9821 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9822 p_nat->missedpktcount3,
9823 p_nat->missedpktcount4);
9824 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9825 p_nat->missedpktcount5,
9826 p_nat->missedpktcount6);
9827 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9828 p_nat->missedpktcount7,
9829 p_nat->missedpktcount8);
9830 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9831 p_nat->missedpktcount9,
9832 p_nat->missedpktcount10);
9839 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_STATS_CLEAR) {
9840 printf("\nCG-NAPT Packet Stats:\n");
9841 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
9842 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
9843 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
9844 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
9845 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
9846 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
9847 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
9849 p_nat->naptedPktCount = 0;
9850 p_nat->naptDroppedPktCount = 0;
9851 p_nat->inaptedPktCount = 0;
9852 p_nat->enaptedPktCount = 0;
9853 p_nat->receivedPktCount = 0;
9854 p_nat->missedPktCount = 0;
9855 p_nat->arpicmpPktCount = 0;
9856 printf("CG-NAPT Packet Stats cleared\n");
9860 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DBG_LEVEL) {
9861 CGNAPT_DEBUG = Msg[CGNAPT_DBG_CMD_OFST + 1];
9862 printf("CG-NAPT debug level set to %d\n", CGNAPT_DEBUG);
9866 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DBG_SHOW) {
9868 printf("\nNAPT entries - added %" PRIu64 ",",
9869 p_nat->n_cgnapt_entry_added);
9870 printf("deleted %" PRIu64 ",", p_nat->n_cgnapt_entry_deleted);
9871 printf("current %" PRIu64 "", p_nat->n_cgnapt_entry_added -
9872 p_nat->n_cgnapt_entry_deleted);
9874 printf("\nCG-NAPT Packet Stats:\n");
9875 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
9876 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
9877 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
9878 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
9879 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
9880 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
9881 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
9885 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
9886 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_INSTRUMENTATION) {
9887 if (Msg[CGNAPT_DBG_CMD_OFST1] ==
9888 CGNAPT_CMD_INSTRUMENTATION_SUB0) {
9891 uint32_t diff_sum = 0;
9893 printf("CG-NAPT Instrumentation ...\n");
9894 printf("Instrumentation data collected for fn# %d\n",
9895 cgnapt_num_func_to_inst);
9896 printf("Current collection index %d\n",
9899 if (Msg[CGNAPT_DBG_CMD_OFST + 2] == 2) {
9900 printf("Timer Start:\n");
9902 for (index = 0; index < INST_ARRAY_SIZE; index++) {
9903 if ((index % 5) == 0)
9905 printf(" 0x%jx", inst_start_time[index]);
9907 printf("\n\nTimer End:\n");
9909 for (index = 0; index < INST_ARRAY_SIZE; index++) {
9910 if ((index % 5) == 0)
9912 printf(" 0x%jx", inst_end_time[index]);
9916 for (index = 0; index < INST_ARRAY_SIZE; index++) {
9917 inst_diff_time[index] = (uint32_t) (inst_end_time[index] -
9918 inst_start_time[index]);
9921 if (Msg[CGNAPT_DBG_CMD_OFST + 2] ==
9922 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
9923 printf("\n\nTimer Diff:\n");
9925 for (index = 0; index < INST_ARRAY_SIZE; index++) {
9926 if (Msg[CGNAPT_DBG_CMD_OFST + 2] ==
9927 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
9928 if ((index % 5) == 0)
9930 printf(" 0x%08x", inst_diff_time[index]);
9933 diff_sum += inst_diff_time[index];
9936 printf("\ndiff_sum %u, INST_ARRAY_SIZE %d, Ave Time %u\n",
9937 diff_sum, INST_ARRAY_SIZE, (diff_sum / INST_ARRAY_SIZE));
9938 } else if (Msg[CGNAPT_DBG_CMD_OFST + 1] ==
9939 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
9940 /* p plid entry dbg 7 1 0
9941 * p plid entry dbg 7 1 1 <--- pkt_work_cgnapt
9942 * p plid entry dbg 7 1 2 <--- pkt4_work_cgnapt
9943 * p plid entry dbg 7 1 3 <--- pkt_work_cgnapt_key
9944 * p plid entry dbg 7 1 4 <--- pkt4_work_cgnapt_key
9945 * p plid entry dbg 7 1 5 <--- in port ah to out port ah
9946 * - pkt life in the system
9947 * p plid entry dbg 7 1 6 <--- how long this instrumentation
9950 cgnapt_inst_index = 0;
9951 cgnapt_num_func_to_inst = Msg[CGNAPT_DBG_CMD_OFST + 2];
9952 printf("Instrumentation data collection started for fn# %d\n",
9953 cgnapt_num_func_to_inst);
9954 } else if (Msg[CGNAPT_DBG_CMD_OFST + 1] ==
9955 CGNAPT_CMD_INSTRUMENTATION_SUB2) {
9956 /* p plid entry dbg 7 2 0
9957 * Test all major functions by calling them multiple times
9958 * pkt_work_cgnapt, pkt4_work_cgnapt, pkt_work_cgnapt_key,
9959 * pkt4_work_cgnapt_key
9961 if (cgnapt_test_pktmbuf_pool == NULL) {
9962 cgnapt_test_pktmbuf_pool = rte_pktmbuf_pool_create(
9963 "cgnapt_test_pktmbuf_pool", 63, 32, 0,
9964 RTE_MBUF_DEFAULT_BUF_SIZE,
9968 if (cgnapt_test_pktmbuf_pool == NULL)
9969 printf("CGNAPT test mbuf pool create failed.\n");
9971 struct rte_mbuf *cgnapt_test_pkt0 =
9972 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
9973 if (cgnapt_test_pkt0 == NULL)
9974 printf("CGNAPT test pkt 0 alloc failed.");
9975 struct rte_mbuf *cgnapt_test_pkt1 =
9976 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
9977 if (cgnapt_test_pkt1 == NULL)
9978 printf("CGNAPT test pkt 1 alloc failed.");
9979 struct rte_mbuf *cgnapt_test_pkt2 =
9980 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
9981 if (cgnapt_test_pkt2 == NULL)
9982 printf("CGNAPT test pkt 2 alloc failed.");
9983 struct rte_mbuf *cgnapt_test_pkt3 =
9984 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
9985 if (cgnapt_test_pkt3 == NULL)
9986 printf("CGNAPT test pkt 3 alloc failed.");
9988 struct rte_mbuf *cgnapt_test_pkts[4];
9990 cgnapt_test_pkts[0] = cgnapt_test_pkt0;
9991 cgnapt_test_pkts[1] = cgnapt_test_pkt1;
9992 cgnapt_test_pkts[2] = cgnapt_test_pkt2;
9993 cgnapt_test_pkts[3] = cgnapt_test_pkt3;
9995 uint32_t src_addr_offset =
9996 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_SRC_ADR_OFST;
9997 /* header room + eth hdr size +
9998 * src_aadr offset in ip header
10000 uint32_t dst_addr_offset =
10001 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
10002 /* header room + eth hdr size +
10003 * dst_aadr offset in ip header
10005 uint32_t prot_offset =
10006 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_PROTOCOL_OFST;
10007 /* header room + eth hdr size +
10008 * srprotocol char offset in ip header
10010 int pktCnt = 0, entCnt = 0, exCnt = 0;
10012 for (pktCnt = 0; pktCnt < 4; pktCnt++) {
10013 uint32_t *src_addr =
10014 RTE_MBUF_METADATA_UINT32_PTR
10015 (cgnapt_test_pkts[pktCnt], src_addr_offset);
10016 uint32_t *dst_addr =
10017 RTE_MBUF_METADATA_UINT32_PTR
10018 (cgnapt_test_pkts[pktCnt], dst_addr_offset);
10019 uint8_t *protocol =
10020 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10023 uint8_t *phy_port =
10024 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10026 uint8_t *eth_dest =
10027 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10031 RTE_MBUF_METADATA_UINT8_PTR(
10032 cgnapt_test_pkts[pktCnt],
10035 uint16_t *src_port =
10036 RTE_MBUF_METADATA_UINT16_PTR
10037 (cgnapt_test_pkts[pktCnt],
10038 MBUF_HDR_ROOM + ETH_HDR_SIZE +
10040 uint16_t *dst_port =
10041 RTE_MBUF_METADATA_UINT16_PTR
10042 (cgnapt_test_pkts[pktCnt],
10043 MBUF_HDR_ROOM + ETH_HDR_SIZE +
10045 *src_addr = 0xc0a80001;
10046 *dst_addr = 0x90418634;
10057 eth_dest[0] = 0x90;
10058 eth_dest[1] = 0xE2;
10059 eth_dest[2] = 0xba;
10060 eth_dest[3] = 0x54;
10061 eth_dest[4] = 0x67;
10062 eth_dest[5] = 0xc8;
10064 struct rte_pipeline_table_entry *table_entries[4];
10065 struct cgnapt_table_entry ctable_entries[4];
10066 table_entries[0] = (struct rte_pipeline_table_entry *)
10067 &ctable_entries[0];
10068 table_entries[1] = (struct rte_pipeline_table_entry *)
10069 &ctable_entries[1];
10070 table_entries[2] = (struct rte_pipeline_table_entry *)
10071 &ctable_entries[2];
10072 table_entries[3] = (struct rte_pipeline_table_entry *)
10073 &ctable_entries[3];
10074 for (entCnt = 0; entCnt < 4; entCnt++) {
10075 ctable_entries[entCnt].head.action =
10076 RTE_PIPELINE_ACTION_PORT;
10077 ctable_entries[entCnt].head.port_id = 0;
10079 ctable_entries[entCnt].data.prv_ip = 0x01020304;
10080 ctable_entries[entCnt].data.prv_port = 1234;
10081 ctable_entries[entCnt].data.pub_ip = 0x0a0b0c0d;
10082 ctable_entries[entCnt].data.pub_port = 4000;
10083 ctable_entries[entCnt].data.prv_phy_port = 0;
10084 ctable_entries[entCnt].data.pub_phy_port = 1;
10085 ctable_entries[entCnt].data.ttl = 500;
10088 uint64_t time1 = rte_get_tsc_cycles();
10090 for (exCnt = 0; exCnt < 1000; exCnt++) {
10091 pkt_work_cgnapt_key(cgnapt_test_pkts[0],
10092 instrumentation_port_in_arg);
10094 uint64_t time2 = rte_get_tsc_cycles();
10096 printf("times for %d times execution of "
10097 "pkt_work_cgnapt_key 0x%jx",
10099 printf(", 0x%jx, diff %" PRIu64 "\n", time2,
10102 time1 = rte_get_tsc_cycles();
10103 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10104 pkt_work_cgnapt_key(cgnapt_test_pkts[0],
10105 instrumentation_port_in_arg);
10107 time2 = rte_get_tsc_cycles();
10108 printf("times for %d times execution of "
10109 "pkt_work_cgnapt_key 0x%jx", exCnt, time1);
10110 printf("0x%jx, diff %" PRIu64 "\n", time2,
10113 time1 = rte_get_tsc_cycles();
10114 for (exCnt = 0; exCnt < 1000; exCnt++) {
10115 pkt4_work_cgnapt_key(cgnapt_test_pkts,
10116 instrumentation_port_in_arg);
10118 time2 = rte_get_tsc_cycles();
10119 printf("times for %d times execution of "
10120 "pkt4_work_cgnapt_key 0x%jx",
10122 printf(" 0x%jx, diff %" PRIu64 "\n", time2,
10125 time1 = rte_get_tsc_cycles();
10126 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10127 pkt4_work_cgnapt_key(cgnapt_test_pkts,
10128 instrumentation_port_in_arg);
10130 time2 = rte_get_tsc_cycles();
10131 printf("times for %d times execution of "
10132 "pkt4_work_cgnapt_key 0x%jx",
10134 printf("0x%jx, diff %" PRIu64 "\n", time2,
10137 uint64_t mask = 0xff;
10139 time1 = rte_get_tsc_cycles();
10140 for (exCnt = 0; exCnt < 1000; exCnt++) {
10141 pkt_work_cgnapt(cgnapt_test_pkts[0],
10142 table_entries[0], 3, &mask,
10145 time2 = rte_get_tsc_cycles();
10146 printf("times for %d times execution of "
10147 "pkt_work_cgnapt 0x%jx",
10149 printf("0x%jx, diff %" PRIu64 "\n", time2,
10152 time1 = rte_get_tsc_cycles();
10153 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10154 pkt_work_cgnapt(cgnapt_test_pkts[0],
10155 table_entries[0], 3, &mask,
10158 time2 = rte_get_tsc_cycles();
10159 printf("times for %d times execution of "
10160 "pkt_work_cgnapt 0x%jx",
10162 printf("0x%jx, diff %" PRIu64 "\n", time2,
10165 time1 = rte_get_tsc_cycles();
10166 for (exCnt = 0; exCnt < 1000; exCnt++) {
10167 pkt4_work_cgnapt(cgnapt_test_pkts,
10168 table_entries, 0, &mask, NULL);
10170 time2 = rte_get_tsc_cycles();
10171 printf("times for %d times execution of "
10172 "pkt4_work_cgnapt 0x%jx",
10174 printf("0x%jx, diff % " PRIu64 "\n", time2,
10177 int idummy = ctable_entries[0].data.prv_port;
10187 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_LS_ENTRY) {
10188 printf("CG-NAPT be entries are:\n");
10189 printf("Pipeline pointer %p\n", p);
10193 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DYN) {
10194 printf("Total Number of dynamic napt entries: %" PRIu64 "\n",
10195 p_nat->dynCgnaptCount);
10197 #ifdef CGNAPT_DEBUGGING
10198 printf("MAX PORT PER CLIENT:");
10199 printf("%" PRIu64 ",%" PRIu64 ",%" PRIu64 "\n",
10200 p_nat->max_port_dec_err1, p_nat->max_port_dec_err2,
10201 p_nat->max_port_dec_err3);
10202 printf("MPPC success : %" PRIu64 "\n",
10203 p_nat->max_port_dec_success);
10205 printf("Release port:err:%" PRIu64 ",ret::%" PRIu64 ",get::%"
10206 PRIu64 ",suc::%" PRIu64 "\n", p_nat->pfb_err,
10207 p_nat->pfb_ret, p_nat->pfb_get, p_nat->pfb_suc);
10208 printf("Get port::err:%" PRIu64 ",ret::%" PRIu64 ",get::%"
10209 PRIu64 ",suc::%" PRIu64 "\n", p_nat->gfp_err,
10210 p_nat->gfp_ret, p_nat->gfp_get, p_nat->gfp_suc);
10211 printf("Ring Info:\n");
10212 rte_ring_dump(stdout, p_nat->port_alloc_ring);
10216 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_IPV6) {
10217 dual_stack_enable = Msg[CGNAPT_DBG_CMD_OFST + 1];
10218 printf("Dual Stack option set: %x\n", dual_stack_enable);
10222 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_MAPS_INFO) {
10223 pipelines_port_info();
10224 pipelines_map_info();
10228 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_ITER_COM_TBL) {
10229 uint32_t count = 0;
10237 rte_hash_iterate(napt_common_table, &key, &data,
10240 if ((index != -EINVAL) && (index != -ENOENT)) {
10241 printf("\n%04d ", count);
10242 rte_hexdump(stdout, "KEY", key,
10244 pipeline_cgnapt_entry_key));
10246 //print_key((struct pipeline_cgnapt_entry_key *)
10249 rte_hash_lookup(napt_common_table,
10251 print_cgnapt_entry(&napt_hash_tbl_entries
10256 } while (index != -ENOENT);
10260 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_IF_STATS) {
10262 struct app_params *app =
10263 (struct app_params *)p_nat->app_params_addr;
10266 cmd[0] = Msg[CGNAPT_DBG_CMD_OFST + 1];
10267 cmd[1] = Msg[CGNAPT_DBG_CMD_OFST + 2];
10269 case CGNAPT_IF_STATS_HWQ:
10270 printf("n_pktq_hwq_int :%d\n", app->n_pktq_hwq_in);
10271 printf("n_pktq_hwq_out :%d\n", app->n_pktq_hwq_out);
10275 for (i = 0; i < app->n_pktq_hwq_in; i++) {
10276 struct rte_eth_stats stats;
10278 rte_eth_stats_get(p_nat->links_map[i], &stats);
10280 if (is_phy_port_privte(i))
10281 printf("Private Port Stats %d\n", i);
10283 printf("Public Port Stats %d\n", i);
10285 printf("\n\tipackets : %" PRIu64 "",
10287 printf("\n\topackets : %" PRIu64 "",
10289 printf("\n\tierrors : %" PRIu64 "",
10291 printf("\n\toerrors : %" PRIu64 "",
10293 printf("\n\trx_nombuf: %" PRIu64 "",
10296 if (is_phy_port_privte(i))
10297 printf("Private Q:");
10299 printf("Public Q:");
10300 for (j = 0; j < RTE_ETHDEV_QUEUE_STAT_CNTRS;
10302 printf(" %" PRIu64 ", %" PRIu64 "|",
10303 stats.q_ipackets[j],
10304 stats.q_opackets[j]);
10312 case CGNAPT_IF_STATS_SWQ:
10314 printf("n_pktq_swq :%d\n", app->n_pktq_swq);
10316 if (cmd[1] < app->n_pktq_swq) {
10317 rte_ring_dump(stdout, app->swq[cmd[1]]);
10320 printf("SWQ number is invalid\n");
10323 case CGNAPT_IF_STATS_OTH:
10325 printf("config_file:%s\n", app->config_file);
10326 printf("script_file:%s\n", app->script_file);
10327 printf("parser_file:%s\n", app->parser_file);
10328 printf("output_file:%s\n", app->output_file);
10329 printf("n_msgq :%d\n", app->n_msgq);
10330 printf("n_pktq_tm :%d\n", app->n_pktq_tm);
10331 printf("n_pktq_source :%d\n", app->n_pktq_source);
10332 printf("n_pktq_sink :%d\n", app->n_pktq_sink);
10333 printf("n_pipelines :%d\n", app->n_pipelines);
10337 printf("Command does not match\n\n");
10345 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_MAX_CLI_PER_PUB_IP) {
10346 if (nat_only_config_flag) {
10347 printf("Command not supported for NAT only config.\n");
10352 printf("\tPublic IP: Num Clients\n");
10353 for (ii = 0; ii < CGNAPT_MAX_PUB_IP; ii++)
10354 printf("\t%x : %7d\n", all_public_ip[ii].ip,
10355 rte_atomic16_read(&all_public_ip[ii].count));
10359 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_PUB_IP_LIST) {
10362 for (i = 0; i < p_nat->pub_ip_count; i++)
10363 printf("%x : (%d,%d)\n", p_nat->pub_ip_port_set[i].ip,
10364 p_nat->pub_ip_port_set[i].start_port,
10365 p_nat->pub_ip_port_set[i].end_port);
10369 #ifdef CGNAPT_TIMING_INST
10370 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_TIMING_INST) {
10371 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 0) {
10372 p_nat->time_measurements_on = 1;
10373 p_nat->time_measurements = 0;
10374 printf("CGNAPT timing instrumentation turned on.\n");
10375 printf("Max samples %d\n", p_nat->max_time_mesurements);
10377 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 1) {
10378 p_nat->time_measurements_on = 0;
10379 printf("CGNAPT timing instrumentation turned off.\n");
10380 printf("Cur Samples %d\n", p_nat->time_measurements);
10382 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 2) {
10383 uint64_t sum = p_nat->external_time_sum +
10384 p_nat->internal_time_sum;
10385 uint64_t isump = (p_nat->internal_time_sum * 100) / sum;
10386 uint64_t esump = (p_nat->external_time_sum * 100) / sum;
10387 printf("CGNAPT timing instrumentation status ...\n");
10388 printf("Max Count %d, Cur Count %d, Status %d (1=ON)\n",
10389 p_nat->max_time_mesurements,
10390 p_nat->time_measurements,
10391 p_nat->time_measurements_on);
10392 printf("Internal Time Sum %" PRIu64 " , Ave %" PRIu64
10393 ", percent %" PRIu64 "\n",
10394 p_nat->internal_time_sum,
10395 (p_nat->internal_time_sum /
10396 p_nat->time_measurements), isump);
10397 printf("External Time Sum %" PRIu64 " , Ave %" PRIu64
10398 ", percent %" PRIu64 "\n",
10399 p_nat->external_time_sum,
10400 (p_nat->external_time_sum /
10401 p_nat->time_measurements), esump);
10408 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_PRINT_NSP) {
10409 struct cgnapt_nsp_node *ll = nsp_ll;
10411 while (ll != NULL) {
10412 fprintf(stderr, "NSP Prefix/Depth=>%x%x:%x%x:%x%x: "
10413 "%x%x:%x%x:%x%x:%x%x:%x%x/%d",
10414 ll->nsp.prefix[0], ll->nsp.prefix[1],
10415 ll->nsp.prefix[2], ll->nsp.prefix[3],
10416 ll->nsp.prefix[4], ll->nsp.prefix[5],
10417 ll->nsp.prefix[6], ll->nsp.prefix[7],
10418 ll->nsp.prefix[8], ll->nsp.prefix[9],
10419 ll->nsp.prefix[10], ll->nsp.prefix[11],
10420 ll->nsp.prefix[12], ll->nsp.prefix[13],
10421 ll->nsp.prefix[14], ll->nsp.prefix[15],
10430 printf("CG-NAPT debug handler called with wrong args %x %x\n", Msg[0],
10434 for (i = 0; i < 20; i++)
10435 printf("%02x ", Msg[i]);
10441 * Function to print num of clients per IP address
10444 void print_num_ip_clients(void)
10446 if (nat_only_config_flag) {
10447 printf("Command not supported for NAT only config.\n");
10452 printf("\tPublic IP: Num Clients\n");
10453 for (ii = 0; ii < CGNAPT_MAX_PUB_IP; ii++)
10454 printf("\t%08x : %7d\n", all_public_ip[ii].ip,
10455 rte_atomic16_read(&all_public_ip[ii].count));
10459 * Function to print CGNAPT version info
10462 * An unused pointer to struct pipeline
10464 * void pointer to incoming arguments
10466 void *pipeline_cgnapt_msg_req_ver_handler(__rte_unused struct pipeline *p,
10469 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
10470 uint8_t *Msg = msg;
10474 printf("CG-NAPT debug handler called with args %x %x, offset %d\n",
10475 Msg[CGNAPT_VER_CMD_OFST], Msg[CGNAPT_VER_CMD_OFST + 1],
10476 CGNAPT_VER_CMD_OFST);
10478 if (Msg[CGNAPT_VER_CMD_OFST] == CGNAPT_VER_CMD_VER) {
10479 printf("CGNAPT Version %s\n", CGNAPT_VERSION);
10482 printf("CG-NAPT Version handler called with wrong args %x %x\n",
10486 for (i = 0; i < 20; i++)
10487 printf("%02x ", Msg[i]);
10493 * Function to show CGNAPT stats
10496 void all_cgnapt_stats(char *buf)
10499 struct pipeline_cgnapt *p_nat;
10500 uint64_t receivedPktCount = 0;
10501 uint64_t missedPktCount = 0;
10502 uint64_t naptDroppedPktCount = 0;
10503 uint64_t naptedPktCount = 0;
10504 uint64_t inaptedPktCount = 0;
10505 uint64_t enaptedPktCount = 0;
10506 uint64_t arpicmpPktCount = 0;
10508 len += sprintf(buf + len, "\nCG-NAPT Packet Stats:\n");
10509 for (i = 0; i < n_cgnapt_pipeline; i++) {
10510 p_nat = all_pipeline_cgnapt[i];
10512 receivedPktCount += p_nat->receivedPktCount;
10513 missedPktCount += p_nat->missedPktCount;
10514 naptDroppedPktCount += p_nat->naptDroppedPktCount;
10515 naptedPktCount += p_nat->naptedPktCount;
10516 inaptedPktCount += p_nat->inaptedPktCount;
10517 enaptedPktCount += p_nat->enaptedPktCount;
10518 arpicmpPktCount += p_nat->arpicmpPktCount;
10520 len += sprintf(buf + len, "pipeline %d stats:\n", p_nat->pipeline_num);
10521 len += sprintf(buf + len, "Received %" PRIu64 ",", p_nat->receivedPktCount);
10522 len += sprintf(buf + len, "Missed %" PRIu64 ",", p_nat->missedPktCount);
10523 len += sprintf(buf + len, "Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10524 len += sprintf(buf + len, "Translated %" PRIu64 ",", p_nat->naptedPktCount);
10525 len += sprintf(buf + len, "ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10526 len += sprintf(buf + len, "egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10527 len += sprintf(buf + len, "arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10529 printf("\nCG-NAPT Packet Stats:\n");
10530 printf("pipeline %d stats:\n", p_nat->pipeline_num);
10531 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10532 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10533 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10534 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10535 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10536 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10537 printf("arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10541 #ifdef CGNAPT_DEBUGGING
10542 len += sprintf(buf + len, "\n Drop detail 1:%" PRIu64 ",",
10543 p_nat->naptDroppedPktCount1);
10544 len += sprintf(buf + len, "\n Drop detail 2:%" PRIu64 ",",
10545 p_nat->naptDroppedPktCount2);
10546 len += sprintf(buf + len, "\n Drop detail 3:%" PRIu64 ",",
10547 p_nat->naptDroppedPktCount3);
10548 len += sprintf(buf + len, "\n Drop detail 4:%" PRIu64 ",",
10549 p_nat->naptDroppedPktCount4);
10550 len += sprintf(buf + len, "\n Drop detail 5:%" PRIu64 ",",
10551 p_nat->naptDroppedPktCount5);
10552 len += sprintf(buf + len, "\n Drop detail 6:%" PRIu64 "",
10553 p_nat->naptDroppedPktCount6);
10555 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10556 p_nat->missedpktcount1,
10557 p_nat->missedpktcount2);
10558 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10559 p_nat->missedpktcount3,
10560 p_nat->missedpktcount4);
10561 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10562 p_nat->missedpktcount5,
10563 p_nat->missedpktcount6);
10564 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10565 p_nat->missedpktcount7,
10566 p_nat->missedpktcount8);
10567 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10568 p_nat->missedpktcount9,
10569 p_nat->missedpktcount10);
10575 len += sprintf(buf + len, "\nTotal pipeline stats:\n");
10576 len += sprintf(buf + len, "Received %" PRIu64 ",", receivedPktCount);
10577 len += sprintf(buf + len, "Missed %" PRIu64 ",", missedPktCount);
10578 len += sprintf(buf + len, "Dropped %" PRIu64 ",", naptDroppedPktCount);
10579 len += sprintf(buf + len, "Translated %" PRIu64 ",", naptedPktCount);
10580 len += sprintf(buf + len, "ingress %" PRIu64 ",", inaptedPktCount);
10581 len += sprintf(buf + len, "egress %" PRIu64 "\n", enaptedPktCount);
10582 len += sprintf(buf + len, "arpicmp pkts %" PRIu64 "\n", arpicmpPktCount);
10584 printf("\nTotal pipeline stats:\n");
10585 printf("Received %" PRIu64 ",", receivedPktCount);
10586 printf("Missed %" PRIu64 ",", missedPktCount);
10587 printf("Dropped %" PRIu64 ",", naptDroppedPktCount);
10588 printf("Translated %" PRIu64 ",", naptedPktCount);
10589 printf("ingress %" PRIu64 ",", inaptedPktCount);
10590 printf("egress %" PRIu64 "\n", enaptedPktCount);
10591 printf("arpicmp pkts %" PRIu64 "\n", arpicmpPktCount);
10593 if (!rest_api_supported())
10594 printf("%s\n", buf);
10597 void all_cgnapt_clear_stats(char *buf)
10600 struct pipeline_cgnapt *p_nat;
10601 len += sprintf(buf + len, "\nCG-NAPT Packet Stats:\n");
10602 for (i = 0; i < n_cgnapt_pipeline; i++) {
10603 p_nat = all_pipeline_cgnapt[i];
10605 len += sprintf(buf + len, "pipeline %d stats:\n", p_nat->pipeline_num);
10606 len += sprintf(buf + len, "Received %" PRIu64 ",", p_nat->receivedPktCount);
10607 len += sprintf(buf + len, "Missed %" PRIu64 ",", p_nat->missedPktCount);
10608 len += sprintf(buf + len, "Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10609 len += sprintf(buf + len, "Translated %" PRIu64 ",", p_nat->naptedPktCount);
10610 len += sprintf(buf + len, "ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10611 len += sprintf(buf + len, "egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10612 len += sprintf(buf + len, "arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10614 p_nat->receivedPktCount = 0;
10615 p_nat->missedPktCount = 0;
10616 p_nat->naptDroppedPktCount = 0;
10617 p_nat->naptedPktCount = 0;
10618 p_nat->inaptedPktCount = 0;
10619 p_nat->enaptedPktCount = 0;
10620 p_nat->arpicmpPktCount = 0;
10622 #ifdef CGNAPT_DEBUGGING
10623 len += sprintf(buf + len, "\n Drop detail 1:%" PRIu64 ",",
10624 p_nat->naptDroppedPktCount1);
10625 len += sprintf(buf + len, "\n Drop detail 2:%" PRIu64 ",",
10626 p_nat->naptDroppedPktCount2);
10627 len += sprintf(buf + len, "\n Drop detail 3:%" PRIu64 ",",
10628 p_nat->naptDroppedPktCount3);
10629 len += sprintf(buf + len, "\n Drop detail 4:%" PRIu64 ",",
10630 p_nat->naptDroppedPktCount4);
10631 len += sprintf(buf + len, "\n Drop detail 5:%" PRIu64 ",",
10632 p_nat->naptDroppedPktCount5);
10633 len += sprintf(buf + len, "\n Drop detail 6:%" PRIu64 "",
10634 p_nat->naptDroppedPktCount6);
10636 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10637 p_nat->missedpktcount1,
10638 p_nat->missedpktcount2);
10639 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10640 p_nat->missedpktcount3,
10641 p_nat->missedpktcount4);
10642 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10643 p_nat->missedpktcount5,
10644 p_nat->missedpktcount6);
10645 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10646 p_nat->missedpktcount7,
10647 p_nat->missedpktcount8);
10648 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10649 p_nat->missedpktcount9,
10650 p_nat->missedpktcount10);
10656 if (!rest_api_supported())
10657 printf("%s\n", buf);
10661 * Function to print common CGNAPT table entries
10664 void print_static_cgnapt_entries(void)
10666 uint32_t count = 0;
10671 struct cgnapt_table_entry *entry;
10673 index = rte_hash_iterate(napt_common_table,
10674 &key, &data, &next);
10676 if ((index != -EINVAL) && (index != -ENOENT)) {
10677 printf("\n%04d ", count);
10678 rte_hexdump(stdout, "KEY", key,
10679 sizeof(struct pipeline_cgnapt_entry_key));
10680 int32_t position = rte_hash_lookup(
10681 napt_common_table, key);
10682 entry = &napt_hash_tbl_entries[position];
10684 if (entry->data.timeout == STATIC_CGNAPT_TIMEOUT)
10685 rte_hexdump(stdout, "Entry",
10686 (const void *)entry,
10687 sizeof(struct cgnapt_table_entry));
10691 } while (index != -ENOENT);
10695 * Function to show CGNAPT stats
10699 struct pipeline_be_ops pipeline_cgnapt_be_ops = {
10700 .f_init = pipeline_cgnapt_init,
10701 .f_free = pipeline_cgnapt_free,
10703 .f_timer = pipeline_cgnapt_timer,
10704 .f_track = pipeline_cgnapt_track,