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 gw_get_nh_port_ipv4(dest_address,
1978 if (dest_if == INVALID_DESTIF) {
1979 p_nat->invalid_packets |=
1981 p_nat->naptDroppedPktCount++;
1982 #ifdef CGNAPT_DEBUGGING
1983 p_nat->naptDroppedPktCount6++;
1988 *outport_id = p_nat->outport_id[dest_if];
1990 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if, &hw_addr);
1992 if (unlikely(ret_arp_data == NULL)) {
1994 #ifdef CGNAPT_DEBUGGING
1995 printf("%s: NHIP Not Found, nhip: %x, "
1996 "outport_id: %d\n", __func__, nhip,
2000 p_nat->invalid_packets |= pkt_mask;
2001 p_nat->naptDroppedPktCount++;
2003 #ifdef CGNAPT_DEBUGGING
2004 p_nat->naptDroppedPktCount4++;
2009 /* Gateway Proc Ends */
2011 if (ret_arp_data->status == COMPLETE) {
2013 if (ret_arp_data->num_pkts) {
2014 p_nat->naptedPktCount += ret_arp_data->num_pkts;
2015 arp_send_buffered_pkts(ret_arp_data,
2016 &hw_addr, *outport_id);
2019 memcpy(eth_dest, &hw_addr,
2020 sizeof(struct ether_addr));
2021 memcpy(eth_src, get_link_hw_addr(dest_if),
2022 sizeof(struct ether_addr));
2023 #ifdef CGNAPT_DBG_PRNT
2024 if (CGNAPT_DEBUG > 2) {
2025 printf("MAC found for ip 0x%x, port %d - "
2026 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2027 dest_address, *outport_id,
2028 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
2029 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
2030 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
2032 printf("Dest MAC before - "
2033 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2034 eth_dest[0], eth_dest[1], eth_dest[2],
2035 eth_dest[3], eth_dest[4], eth_dest[5]);
2039 #ifdef CGNAPT_DBG_PRNT
2040 if (CGNAPT_DEBUG > 2) {
2041 printf("Dest MAC after - "
2042 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2043 eth_dest[0], eth_dest[1], eth_dest[2],
2044 eth_dest[3], eth_dest[4], eth_dest[5]);
2048 #ifdef CGNAPT_DBG_PRNT
2049 if (CGNAPT_DEBUG > 4)
2050 print_pkt(pkts[pkt_index]);
2053 } else if (ret_arp_data->status == INCOMPLETE ||
2054 ret_arp_data->status == PROBE) {
2055 if (ret_arp_data->num_pkts >= NUM_DESC) {
2057 p_nat->invalid_packets |= pkt_mask;
2058 p_nat->naptDroppedPktCount++;
2060 #ifdef CGNAPT_DEBUGGING
2061 p_nat->naptDroppedPktCount4++;
2065 arp_queue_unresolved_packet(ret_arp_data,
2071 #ifdef CGNAPT_DBG_PRNT
2072 if (CGNAPT_DEBUG > 2)
2073 printf("Egress: \tphy_port:%d\t "
2074 "get_prv_to_pub():%d \tout_port:%d\n",
2080 *src_addr = rte_bswap32(entry->data.pub_ip);
2082 #ifdef NAT_ONLY_CONFIG_REQ
2083 if (!nat_only_config_flag) {
2085 *src_port = rte_bswap16(entry->data.pub_port);
2086 #ifdef NAT_ONLY_CONFIG_REQ
2090 p_nat->enaptedPktCount++;
2093 if (*protocol == IP_PROTOCOL_UDP
2094 && rte_be_to_cpu_16(*src_port) == 53) {
2095 p_nat->invalid_packets |= 1LLU << pkt_index;
2096 p_nat->naptDroppedPktCount++;
2097 #ifdef CGNAPT_DEBUGGING
2098 p_nat->naptDroppedPktCount6++;
2103 #ifdef CGNAPT_DBG_PRNT
2104 if (CGNAPT_DEBUG > 2)
2105 printf("Ingress: \tphy_port:%d\t "
2106 "get_pub_to_prv():%d \tout_port%d\n",
2111 if (entry->data.type == CGNAPT_ENTRY_IPV6) {
2112 convert_ipv4_to_ipv6(pkts[pkt_index],
2114 pkt_type = PKT_TYPE_IPV4to6;
2115 /* Ethernet MTU check */
2116 if ((rte_pktmbuf_data_len(pkts[pkt_index]) -
2118 p_nat->invalid_packets |= pkt_mask;
2119 p_nat->naptDroppedPktCount++;
2123 eth_dest = eth_dest - 20;
2124 eth_src = eth_src - 20;
2126 dst_port_offset = DST_PRT_OFST_IP4t6;
2127 dst_addr_offset = DST_ADR_OFST_IP4t6;
2129 RTE_MBUF_METADATA_UINT32_PTR(
2133 RTE_MBUF_METADATA_UINT16_PTR(
2137 memcpy((uint8_t *) &dst_addr[0],
2138 &entry->data.u.prv_ipv6[0], 16);
2139 memset(nh_ipv6, 0, 16);
2140 struct nd_entry_data *ret_nd_data = NULL;
2142 dest_if = INVALID_DESTIF;
2144 uint32_t src_phy_port = pkts[pkt_index]->port;
2146 gw_get_nh_port_ipv6((uint8_t *) &dst_addr[0],
2147 &dest_if, &nh_ipv6[0]);
2149 ret_nd_data = get_dest_mac_addr_ipv6(&nh_ipv6[0],
2151 *outport_id = p_nat->outport_id[dest_if];
2153 if (nd_cache_dest_mac_present(dest_if)) {
2154 ether_addr_copy(get_link_hw_addr(dest_if),
2155 (struct ether_addr *)eth_src);
2156 update_nhip_access(dest_if);
2158 if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) {
2159 p_nat->naptedPktCount += ret_nd_data->num_pkts;
2160 nd_send_buffered_pkts(ret_nd_data,
2161 (struct ether_addr *)eth_dest,
2165 if (unlikely(ret_nd_data == NULL)) {
2167 #ifdef CGNAPT_DEBUGGING
2168 printf("%s: NHIP Not Found, "
2169 "outport_id: %d\n", __func__,
2174 p_nat->invalid_packets |= pkt_mask;
2175 p_nat->naptDroppedPktCount++;
2177 #ifdef CGNAPT_DEBUGGING
2178 p_nat->naptDroppedPktCount4++;
2183 if (ret_nd_data->status == INCOMPLETE ||
2184 ret_nd_data->status == PROBE) {
2185 if (ret_nd_data->num_pkts >= NUM_DESC) {
2187 p_nat->invalid_packets |= pkt_mask;
2188 p_nat->naptDroppedPktCount++;
2190 #ifdef CGNAPT_DEBUGGING
2191 p_nat->naptDroppedPktCount4++;
2195 arp_pkts_mask |= pkt_mask;
2196 nd_queue_unresolved_packet(ret_nd_data,
2204 #ifdef NAT_ONLY_CONFIG_REQ
2205 if (!nat_only_config_flag) {
2208 rte_bswap16(entry->data.prv_port);
2209 #ifdef NAT_ONLY_CONFIG_REQ
2214 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
2215 dest_address = entry->data.u.prv_ip;
2216 /* Gateway Proc Starts */
2218 struct arp_entry_data *ret_arp_data = NULL;
2219 dest_if = INVALID_DESTIF;
2220 uint32_t src_phy_port = *src_port;
2222 gw_get_nh_port_ipv4(dest_address,
2225 if (dest_if == INVALID_DESTIF) {
2226 p_nat->invalid_packets |=
2228 p_nat->naptDroppedPktCount++;
2229 #ifdef CGNAPT_DEBUGGING
2230 p_nat->naptDroppedPktCount6++;
2235 *outport_id = p_nat->outport_id[dest_if];
2237 ret_arp_data = get_dest_mac_addr_ipv4(nhip,
2238 dest_if, (struct ether_addr *)&hw_addr);
2240 if (unlikely(ret_arp_data == NULL)) {
2242 #ifdef CGNAPT_DEBUGGING
2243 printf("%s: NHIP Not Found, nhip: %x, "
2244 "outport_id: %d\n", __func__, nhip,
2248 p_nat->invalid_packets |= pkt_mask;
2249 p_nat->naptDroppedPktCount++;
2251 #ifdef CGNAPT_DEBUGGING
2252 p_nat->naptDroppedPktCount4++;
2257 /* Gateway Proc Ends */
2259 if (ret_arp_data->status == COMPLETE) {
2261 if (ret_arp_data->num_pkts) {
2262 p_nat->naptedPktCount +=
2263 ret_arp_data->num_pkts;
2264 arp_send_buffered_pkts(ret_arp_data,
2265 &hw_addr, *outport_id);
2268 memcpy(eth_dest, &hw_addr,
2269 sizeof(struct ether_addr));
2270 memcpy(eth_src, get_link_hw_addr(
2272 sizeof(struct ether_addr));
2273 #ifdef CGNAPT_DBG_PRNT
2274 if (CGNAPT_DEBUG > 2) {
2275 printf("MAC found for ip 0x%x, port %d - "
2276 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2277 dest_address, *outport_id,
2278 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
2279 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
2280 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
2282 printf("Dest MAC before - "
2283 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2284 eth_dest[0], eth_dest[1], eth_dest[2],
2285 eth_dest[3], eth_dest[4], eth_dest[5]);
2289 #ifdef CGNAPT_DBG_PRNT
2290 if (CGNAPT_DEBUG > 2) {
2291 printf("Dest MAC after - "
2292 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2293 eth_dest[0], eth_dest[1], eth_dest[2],
2294 eth_dest[3], eth_dest[4], eth_dest[5]);
2298 #ifdef CGNAPT_DBG_PRNT
2299 if (CGNAPT_DEBUG > 4)
2300 print_pkt(pkts[pkt_index]);
2303 } else if (ret_arp_data->status == INCOMPLETE ||
2304 ret_arp_data->status == PROBE) {
2305 arp_queue_unresolved_packet(ret_arp_data,
2310 if (*protocol == IP_PROTOCOL_ICMP) {
2311 // Query ID reverse translation done here
2313 rte_bswap16(entry->data.prv_port);
2315 #ifdef NAT_ONLY_CONFIG_REQ
2316 if (!nat_only_config_flag) {
2321 #ifdef NAT_ONLY_CONFIG_REQ
2327 p_nat->inaptedPktCount++;
2330 p_nat->naptedPktCount++;
2333 if (p_nat->hw_checksum_reqd)
2334 hw_checksum(pkts[pkt_index], pkt_type);
2336 sw_checksum(pkts[pkt_index], pkt_type);
2340 if (p_nat->invalid_packets) {
2341 /* get rid of invalid packets */
2342 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2344 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2346 #ifdef CGNAPT_DBG_PRNT
2347 if (CGNAPT_DEBUG > 1) {
2348 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
2349 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
2350 printf("invalid_packets:0x%jx\n",
2351 p_nat->invalid_packets);
2352 printf("rte_invalid_packets :0x%jx\n",
2353 rte_p->pkts_drop_mask);
2354 printf("Total pkts dropped :0x%jx\n",
2355 rte_p->n_pkts_ah_drop);
2360 return p_nat->valid_packets;
2364 * Input port handler for IPv4 private traffic
2365 * Starting from the packet burst it filters unwanted packets,
2366 * calculates keys, does lookup and then based on the lookup
2367 * updates NAPT table and does packet NAPT translation.
2370 * A pointer to struct rte_pipeline
2372 * A pointer to array of packets mbuf
2374 * Number of packets in the burst
2379 * int that is not checked by caller
2382 static int cgnapt_in_port_ah_ipv4_prv(struct rte_pipeline *rte_p,
2383 struct rte_mbuf **pkts,
2384 uint32_t n_pkts, void *arg)
2387 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
2388 struct pipeline_cgnapt *p_nat = ap->p;
2390 #ifdef CGNAPT_TIMING_INST
2391 uint64_t entry_timestamp = 0, exit_timestamp;
2393 if (p_nat->time_measurements_on) {
2394 entry_timestamp = rte_get_tsc_cycles();
2395 /* check since exit ts not valid first time through */
2396 if (likely(p_nat->in_port_exit_timestamp))
2397 p_nat->external_time_sum +=
2398 entry_timestamp - p_nat->in_port_exit_timestamp;
2402 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
2403 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
2404 p_nat->invalid_packets = 0;
2406 #ifdef CGNAPT_DBG_PRNT
2407 if (CGNAPT_DEBUG > 1)
2408 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
2411 /* prefetching for mbufs should be done here */
2412 for (j = 0; j < n_pkts; j++)
2413 rte_prefetch0(pkts[j]);
2415 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2416 pkt4_work_cgnapt_key_ipv4_prv(&pkts[i], i, arg, p_nat);
2418 for (; i < n_pkts; i++)
2419 pkt_work_cgnapt_key_ipv4_prv(pkts[i], i, arg, p_nat);
2421 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2423 if (unlikely(p_nat->valid_packets == 0)) {
2424 /* no suitable packet for lookup */
2425 printf("no suitable valid packets\n");
2426 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2427 return p_nat->valid_packets;
2430 /* lookup entries in the common napt table */
2432 int lookup_result = rte_hash_lookup_bulk(
2434 (const void **)&p_nat->key_ptrs,
2435 /* should be minus num invalid pkts */
2437 /*new pipeline data member */
2438 &p_nat->lkup_indx[0]);
2440 if (unlikely(lookup_result < 0)) {
2441 /* unknown error, just discard all packets */
2442 printf("Unexpected hash lookup error %d, discarding "
2443 "all packets", lookup_result);
2444 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
2448 /* Now call second stage of pipeline to one by one
2449 * check the result of our bulk lookup
2452 /* prefetching for table entries should be done here */
2453 for (j = 0; j < n_pkts; j++) {
2454 if (p_nat->lkup_indx[j] >= 0)
2455 rte_prefetch0(&napt_hash_tbl_entries
2456 [p_nat->lkup_indx[j]]);
2459 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2460 pkt4_work_cgnapt_ipv4_prv(pkts, i, arg, p_nat);
2462 for (; i < n_pkts; i++)
2463 pkt_work_cgnapt_ipv4_prv(pkts, i, arg, p_nat);
2465 if (arp_pkts_mask) {
2466 p_nat->valid_packets &= ~(arp_pkts_mask);
2467 rte_pipeline_ah_packet_hijack(rte_p, arp_pkts_mask);
2470 if (p_nat->invalid_packets) {
2471 /* get rid of invalid packets */
2472 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2474 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2476 #ifdef CGNAPT_DBG_PRNT
2477 if (CGNAPT_DEBUG > 1) {
2478 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
2479 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
2480 printf("invalid_packets:0x%jx\n",
2481 p_nat->invalid_packets);
2482 printf("rte_invalid_packets :0x%jx\n",
2483 rte_p->pkts_drop_mask);
2484 printf("Total pkts dropped :0x%jx\n",
2485 rte_p->n_pkts_ah_drop);
2490 #ifdef CGNAPT_TIMING_INST
2491 if (p_nat->time_measurements_on) {
2492 exit_timestamp = rte_get_tsc_cycles();
2493 p_nat->in_port_exit_timestamp = exit_timestamp;
2494 p_nat->internal_time_sum += exit_timestamp - entry_timestamp;
2495 p_nat->time_measurements++;
2496 if (p_nat->time_measurements == p_nat->max_time_mesurements)
2497 p_nat->time_measurements_on = 0;
2501 return p_nat->valid_packets;
2505 * Input port handler for IPv4 public traffic
2506 * Starting from the packet burst it filters unwanted packets,
2507 * calculates keys, does lookup and then based on the lookup
2508 * updates NAPT table and does packet NAPT translation.
2511 * A pointer to struct rte_pipeline
2513 * A pointer to array of packets mbuf
2515 * Number of packets in the burst
2520 * int that is not checked by caller
2522 static int cgnapt_in_port_ah_ipv4_pub(struct rte_pipeline *rte_p,
2523 struct rte_mbuf **pkts,
2524 uint32_t n_pkts, void *arg)
2527 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
2528 struct pipeline_cgnapt *p_nat = ap->p;
2530 #ifdef CGNAPT_TIMING_INST
2531 uint64_t entry_timestamp = 0, exit_timestamp;
2533 if (p_nat->time_measurements_on) {
2534 entry_timestamp = rte_get_tsc_cycles();
2536 /* check since exit ts not valid first time through */
2537 if (likely(p_nat->in_port_exit_timestamp))
2538 p_nat->external_time_sum +=
2539 entry_timestamp - p_nat->in_port_exit_timestamp;
2543 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
2544 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
2545 p_nat->invalid_packets = 0;
2547 #ifdef CGNAPT_DBG_PRNT
2548 if (CGNAPT_DEBUG > 1)
2549 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
2552 /* prefetching for mbufs should be done here */
2553 for (j = 0; j < n_pkts; j++)
2554 rte_prefetch0(pkts[j]);
2556 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2557 pkt4_work_cgnapt_key_ipv4_pub(&pkts[i], i, arg, p_nat);
2559 for (; i < n_pkts; i++)
2560 pkt_work_cgnapt_key_ipv4_pub(pkts[i], i, arg, p_nat);
2562 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2564 if (unlikely(p_nat->valid_packets == 0)) {
2565 printf("no valid packets in pub\n");
2566 /* no suitable packet for lookup */
2567 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2568 return p_nat->valid_packets;
2571 /* lookup entries in the common napt table */
2573 int lookup_result = rte_hash_lookup_bulk(
2575 (const void **)&p_nat->key_ptrs,
2576 /* should be minus num invalid pkts */
2578 /*new pipeline data member */
2579 &p_nat->lkup_indx[0]);
2581 if (unlikely(lookup_result < 0)) {
2582 /* unknown error, just discard all packets */
2583 printf("Unexpected hash lookup error %d, discarding "
2584 "all packets", lookup_result);
2585 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
2589 /* Now call second stage of pipeline to one by one
2590 * check the result of our bulk lookup
2593 /* prefetching for table entries should be done here */
2594 for (j = 0; j < n_pkts; j++) {
2595 if (p_nat->lkup_indx[j] >= 0)
2596 rte_prefetch0(&napt_hash_tbl_entries
2597 [p_nat->lkup_indx[j]]);
2600 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
2601 pkt4_work_cgnapt_ipv4_pub(pkts, i, arg, p_nat);
2603 for (; i < n_pkts; i++)
2604 pkt_work_cgnapt_ipv4_pub(pkts, i, arg, p_nat);
2606 if (arp_pkts_mask) {
2607 rte_pipeline_ah_packet_hijack(rte_p, arp_pkts_mask);
2608 p_nat->valid_packets &= ~(arp_pkts_mask);
2611 if (p_nat->invalid_packets) {
2612 /* get rid of invalid packets */
2613 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
2615 p_nat->valid_packets &= ~(p_nat->invalid_packets);
2617 #ifdef CGNAPT_DBG_PRNT
2618 if (CGNAPT_DEBUG > 1) {
2619 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
2620 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
2621 printf("invalid_packets:0x%jx\n",
2622 p_nat->invalid_packets);
2623 printf("rte_invalid_packets :0x%jx\n",
2624 rte_p->pkts_drop_mask);
2625 printf("Total pkts dropped :0x%jx\n",
2626 rte_p->n_pkts_ah_drop);
2631 #ifdef CGNAPT_TIMING_INST
2632 if (p_nat->time_measurements_on) {
2633 exit_timestamp = rte_get_tsc_cycles();
2634 p_nat->in_port_exit_timestamp = exit_timestamp;
2636 p_nat->internal_time_sum += exit_timestamp - entry_timestamp;
2637 p_nat->time_measurements++;
2638 if (p_nat->time_measurements == p_nat->max_time_mesurements)
2639 p_nat->time_measurements_on = 0;
2643 return p_nat->valid_packets;
2647 * NAPT key calculation function for IPv4 private traffic
2648 * which handles 4 pkts
2651 * A pointer to array of packets mbuf
2653 * Starting pkt number of pkts
2657 * A pointer to main CGNAPT structure
2661 pkt4_work_cgnapt_key_ipv4_prv(
2662 struct rte_mbuf **pkt,
2664 __rte_unused void *arg,
2665 struct pipeline_cgnapt *p_nat)
2667 p_nat->receivedPktCount += 4;
2668 /* bitmask representing only this packet */
2669 uint64_t pkt_mask0 = 1LLU << pkt_num;
2670 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
2671 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
2672 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
2674 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
2676 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
2678 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
2680 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
2683 uint32_t src_addr0 = RTE_MBUF_METADATA_UINT32(pkt[0],
2685 uint32_t src_addr1 = RTE_MBUF_METADATA_UINT32(pkt[1],
2687 uint32_t src_addr2 = RTE_MBUF_METADATA_UINT32(pkt[2],
2689 uint32_t src_addr3 = RTE_MBUF_METADATA_UINT32(pkt[3],
2692 uint16_t src_port_offset0;
2693 uint16_t src_port_offset1;
2694 uint16_t src_port_offset2;
2695 uint16_t src_port_offset3;
2702 uint16_t phy_port0 = pkt[0]->port;
2703 uint16_t phy_port1 = pkt[1]->port;
2704 uint16_t phy_port2 = pkt[2]->port;
2705 uint16_t phy_port3 = pkt[3]->port;
2707 struct pipeline_cgnapt_entry_key key0;
2708 struct pipeline_cgnapt_entry_key key1;
2709 struct pipeline_cgnapt_entry_key key2;
2710 struct pipeline_cgnapt_entry_key key3;
2712 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
2713 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
2714 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
2715 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
2718 #ifdef CGNAPT_DBG_PRNT
2719 if (CGNAPT_DEBUG > 4)
2724 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
2728 switch (protocol0) {
2729 case IP_PROTOCOL_UDP:
2733 struct udp_hdr *udp;
2735 udp = (struct udp_hdr *)
2736 RTE_MBUF_METADATA_UINT8_PTR(pkt[0],
2739 if (rte_bswap16(udp->dst_port) ==
2741 handle_pcp_req(pkt[0], IPV4_SZ, p_nat);
2742 p_nat->invalid_packets |= pkt_mask0;
2748 case IP_PROTOCOL_TCP:
2750 src_port_offset0 = SRC_PRT_OFST_IP4_TCP;
2751 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
2756 case IP_PROTOCOL_ICMP:
2758 src_port_offset0 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
2760 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
2766 /* remember invalid packets to be dropped */
2767 p_nat->invalid_packets |= pkt_mask0;
2768 p_nat->naptDroppedPktCount++;
2770 #ifdef CGNAPT_DEBUGGING
2771 p_nat->naptDroppedPktCount2++;
2776 key0.pid = phy_port0;
2777 key0.ip = rte_bswap32(src_addr0);
2778 key0.port = rte_bswap16(src_port0);
2780 #ifdef NAT_ONLY_CONFIG_REQ
2781 if (nat_only_config_flag)
2785 memcpy(&p_nat->keys[pkt_num], &key0,
2786 sizeof(struct pipeline_cgnapt_entry_key));
2787 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
2792 #ifdef CGNAPT_DBG_PRNT
2793 if (CGNAPT_DEBUG > 4)
2798 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
2801 switch (protocol1) {
2802 case IP_PROTOCOL_UDP:
2806 struct udp_hdr *udp;
2808 udp = (struct udp_hdr *)
2809 RTE_MBUF_METADATA_UINT8_PTR(pkt[1],
2812 if (rte_bswap16(udp->dst_port) ==
2814 handle_pcp_req(pkt[1], IPV4_SZ, p_nat);
2815 p_nat->invalid_packets |= pkt_mask1;
2821 case IP_PROTOCOL_TCP:
2823 src_port_offset1 = SRC_PRT_OFST_IP4_TCP;
2824 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
2829 case IP_PROTOCOL_ICMP:
2831 src_port_offset1 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
2833 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
2839 /* remember invalid packets to be dropped */
2840 p_nat->invalid_packets |= pkt_mask1;
2841 p_nat->naptDroppedPktCount++;
2843 #ifdef CGNAPT_DEBUGGING
2844 p_nat->naptDroppedPktCount2++;
2849 key1.pid = phy_port1;
2850 key1.ip = rte_bswap32(src_addr1);
2851 key1.port = rte_bswap16(src_port1);
2853 #ifdef NAT_ONLY_CONFIG_REQ
2854 if (nat_only_config_flag)
2858 memcpy(&p_nat->keys[pkt_num + 1], &key1,
2859 sizeof(struct pipeline_cgnapt_entry_key));
2860 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
2864 #ifdef CGNAPT_DBG_PRNT
2865 if (CGNAPT_DEBUG > 4)
2870 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
2874 switch (protocol2) {
2875 case IP_PROTOCOL_UDP:
2879 struct udp_hdr *udp;
2881 udp = (struct udp_hdr *)
2882 RTE_MBUF_METADATA_UINT8_PTR(pkt[2],
2885 if (rte_bswap16(udp->dst_port) ==
2887 handle_pcp_req(pkt[2], IPV4_SZ, p_nat);
2888 p_nat->invalid_packets |= pkt_mask2;
2894 case IP_PROTOCOL_TCP:
2896 src_port_offset2 = SRC_PRT_OFST_IP4_TCP;
2897 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
2902 case IP_PROTOCOL_ICMP:
2904 src_port_offset2 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
2906 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
2912 /* remember invalid packets to be dropped */
2913 p_nat->invalid_packets |= pkt_mask2;
2914 p_nat->naptDroppedPktCount++;
2916 #ifdef CGNAPT_DEBUGGING
2917 p_nat->naptDroppedPktCount2++;
2922 key2.pid = phy_port2;
2923 key2.ip = rte_bswap32(src_addr2);
2924 key2.port = rte_bswap16(src_port2);
2926 #ifdef NAT_ONLY_CONFIG_REQ
2927 if (nat_only_config_flag)
2931 memcpy(&p_nat->keys[pkt_num + 2], &key2,
2932 sizeof(struct pipeline_cgnapt_entry_key));
2933 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
2937 #ifdef CGNAPT_DBG_PRNT
2938 if (CGNAPT_DEBUG > 4)
2942 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
2946 switch (protocol3) {
2947 case IP_PROTOCOL_UDP:
2951 struct udp_hdr *udp;
2953 udp = (struct udp_hdr *)
2954 RTE_MBUF_METADATA_UINT8_PTR(pkt[3],
2957 if (rte_bswap16(udp->dst_port) ==
2959 handle_pcp_req(pkt[3], IPV4_SZ, p_nat);
2960 p_nat->invalid_packets |= pkt_mask3;
2966 case IP_PROTOCOL_TCP:
2968 src_port_offset3 = SRC_PRT_OFST_IP4_TCP;
2969 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
2974 case IP_PROTOCOL_ICMP:
2976 src_port_offset3 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
2978 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
2984 /* remember invalid packets to be dropped */
2985 p_nat->invalid_packets |= pkt_mask3;
2986 p_nat->naptDroppedPktCount++;
2988 #ifdef CGNAPT_DEBUGGING
2989 p_nat->naptDroppedPktCount2++;
2994 key3.pid = phy_port3;
2995 key3.ip = rte_bswap32(src_addr3);
2996 key3.port = rte_bswap16(src_port3);
2998 #ifdef NAT_ONLY_CONFIG_REQ
2999 if (nat_only_config_flag)
3003 memcpy(&p_nat->keys[pkt_num + 3], &key3,
3004 sizeof(struct pipeline_cgnapt_entry_key));
3005 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
3009 * NAPT key calculation function for IPv4 public traffic
3010 * which handles 4 pkts
3013 * A pointer to array of packets mbuf
3015 * Starting pkt number of pkts
3019 * A pointer to main CGNAPT structure
3023 pkt4_work_cgnapt_key_ipv4_pub(
3024 struct rte_mbuf **pkt,
3026 __rte_unused void *arg,
3027 struct pipeline_cgnapt *p_nat)
3029 p_nat->receivedPktCount += 4;
3030 /* bitmask representing only this packet */
3031 uint64_t pkt_mask0 = 1LLU << pkt_num;
3032 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
3033 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
3034 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
3036 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
3038 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
3040 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
3042 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
3045 uint32_t dst_addr0 = RTE_MBUF_METADATA_UINT32(pkt[0],
3047 uint32_t dst_addr1 = RTE_MBUF_METADATA_UINT32(pkt[1],
3049 uint32_t dst_addr2 = RTE_MBUF_METADATA_UINT32(pkt[2],
3051 uint32_t dst_addr3 = RTE_MBUF_METADATA_UINT32(pkt[3],
3054 uint16_t src_port_offset0;
3055 uint16_t src_port_offset1;
3056 uint16_t src_port_offset2;
3057 uint16_t src_port_offset3;
3059 uint16_t dst_port_offset0;
3060 uint16_t dst_port_offset1;
3061 uint16_t dst_port_offset2;
3062 uint16_t dst_port_offset3;
3074 struct pipeline_cgnapt_entry_key key0;
3075 struct pipeline_cgnapt_entry_key key1;
3076 struct pipeline_cgnapt_entry_key key2;
3077 struct pipeline_cgnapt_entry_key key3;
3079 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
3080 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
3081 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
3082 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
3085 #ifdef CGNAPT_DBG_PRNT
3086 if (CGNAPT_DEBUG > 4)
3091 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
3095 switch (protocol0) {
3096 case IP_PROTOCOL_UDP:
3097 case IP_PROTOCOL_TCP:
3099 src_port_offset0 = SRC_PRT_OFST_IP4_TCP;
3100 dst_port_offset0 = DST_PRT_OFST_IP4_TCP;
3102 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3104 dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3107 key0.port = rte_bswap16(dst_port0);
3111 case IP_PROTOCOL_ICMP:
3113 src_port_offset0 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3115 /*Sequence number */
3116 dst_port_offset0 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3119 src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3121 dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
3124 key0.port = rte_bswap16(src_port0);
3129 /* remember invalid packets to be dropped */
3130 p_nat->invalid_packets |= pkt_mask0;
3131 p_nat->naptDroppedPktCount++;
3133 #ifdef CGNAPT_DEBUGGING
3134 p_nat->naptDroppedPktCount2++;
3140 key0.ip = rte_bswap32(dst_addr0);
3142 #ifdef NAT_ONLY_CONFIG_REQ
3143 if (nat_only_config_flag)
3147 memcpy(&p_nat->keys[pkt_num], &key0,
3148 sizeof(struct pipeline_cgnapt_entry_key));
3149 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3154 #ifdef CGNAPT_DBG_PRNT
3155 if (CGNAPT_DEBUG > 4)
3160 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
3164 switch (protocol1) {
3165 case IP_PROTOCOL_UDP:
3166 case IP_PROTOCOL_TCP:
3168 src_port_offset1 = SRC_PRT_OFST_IP4_TCP;
3169 dst_port_offset1 = DST_PRT_OFST_IP4_TCP;
3171 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3173 dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3176 key1.port = rte_bswap16(dst_port1);
3180 case IP_PROTOCOL_ICMP:
3182 src_port_offset1 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3184 /*Sequence number */
3185 dst_port_offset1 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3188 src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3190 dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
3193 key1.port = rte_bswap16(src_port1);
3197 /* remember invalid packets to be dropped */
3198 p_nat->invalid_packets |= pkt_mask1;
3199 p_nat->naptDroppedPktCount++;
3201 #ifdef CGNAPT_DEBUGGING
3202 p_nat->naptDroppedPktCount2++;
3208 key1.ip = rte_bswap32(dst_addr1);
3210 #ifdef NAT_ONLY_CONFIG_REQ
3211 if (nat_only_config_flag)
3215 memcpy(&p_nat->keys[pkt_num + 1], &key1,
3216 sizeof(struct pipeline_cgnapt_entry_key));
3217 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
3221 #ifdef CGNAPT_DBG_PRNT
3222 if (CGNAPT_DEBUG > 4)
3227 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
3231 switch (protocol2) {
3232 case IP_PROTOCOL_UDP:
3233 case IP_PROTOCOL_TCP:
3235 src_port_offset2 = SRC_PRT_OFST_IP4_TCP;
3236 dst_port_offset2 = DST_PRT_OFST_IP4_TCP;
3238 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3240 dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3243 key2.port = rte_bswap16(dst_port2);
3247 case IP_PROTOCOL_ICMP:
3249 src_port_offset2 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3251 /*Sequence number */
3252 dst_port_offset2 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3255 src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3257 dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
3260 key2.port = rte_bswap16(src_port2);
3265 /* remember invalid packets to be dropped */
3266 p_nat->invalid_packets |= pkt_mask2;
3267 p_nat->naptDroppedPktCount++;
3269 #ifdef CGNAPT_DEBUGGING
3270 p_nat->naptDroppedPktCount2++;
3276 key2.ip = rte_bswap32(dst_addr2);
3278 #ifdef NAT_ONLY_CONFIG_REQ
3279 if (nat_only_config_flag)
3283 memcpy(&p_nat->keys[pkt_num + 2], &key2,
3284 sizeof(struct pipeline_cgnapt_entry_key));
3285 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
3289 #ifdef CGNAPT_DBG_PRNT
3290 if (CGNAPT_DEBUG > 4)
3295 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
3299 switch (protocol3) {
3300 case IP_PROTOCOL_UDP:
3301 case IP_PROTOCOL_TCP:
3303 src_port_offset3 = SRC_PRT_OFST_IP4_TCP;
3304 dst_port_offset3 = DST_PRT_OFST_IP4_TCP;
3306 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3308 dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3311 key3.port = rte_bswap16(dst_port3);
3315 case IP_PROTOCOL_ICMP:
3317 src_port_offset3 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3319 /*Sequence number */
3320 dst_port_offset3 = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3323 src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3325 dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
3328 key3.port = rte_bswap16(src_port3);
3333 /* remember invalid packets to be dropped */
3334 p_nat->invalid_packets |= pkt_mask3;
3335 p_nat->naptDroppedPktCount++;
3337 #ifdef CGNAPT_DEBUGGING
3338 p_nat->naptDroppedPktCount2++;
3344 key3.ip = rte_bswap32(dst_addr3);
3346 #ifdef NAT_ONLY_CONFIG_REQ
3347 if (nat_only_config_flag)
3351 memcpy(&p_nat->keys[pkt_num + 3], &key3,
3352 sizeof(struct pipeline_cgnapt_entry_key));
3353 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
3357 * NAPT key calculation function for IPv4 private traffic
3358 * which handles 1 pkt
3361 * A pointer to array of packets mbuf
3363 * Pkt number of pkts
3367 * A pointer to main CGNAPT structure
3371 pkt_work_cgnapt_key_ipv4_prv(
3372 struct rte_mbuf *pkt,
3374 __rte_unused void *arg,
3375 struct pipeline_cgnapt *p_nat)
3378 p_nat->receivedPktCount++;
3380 /* bitmask representing only this packet */
3381 uint64_t pkt_mask = 1LLU << pkt_num;
3382 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3384 uint32_t src_addr = RTE_MBUF_METADATA_UINT32(pkt, SRC_ADR_OFST_IP4);
3386 uint16_t src_port_offset;
3390 uint16_t phy_port = pkt->port;
3391 struct pipeline_cgnapt_entry_key key;
3393 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
3396 #ifdef CGNAPT_DBG_PRNT
3397 if (CGNAPT_DEBUG > 4)
3402 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
3407 case IP_PROTOCOL_UDP:
3411 struct udp_hdr *udp;
3413 udp = (struct udp_hdr *)
3414 RTE_MBUF_METADATA_UINT8_PTR(pkt,
3417 if (rte_bswap16(udp->dst_port) ==
3419 handle_pcp_req(pkt, IPV4_SZ, p_nat);
3420 p_nat->invalid_packets |= pkt_mask;
3426 case IP_PROTOCOL_TCP:
3428 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3429 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3431 key.port = rte_bswap16(src_port);
3434 case IP_PROTOCOL_ICMP:
3436 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3438 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3440 key.port = rte_bswap16(src_port);
3444 /* remember invalid packets to be dropped */
3445 p_nat->invalid_packets |= pkt_mask;
3446 p_nat->naptDroppedPktCount++;
3448 #ifdef CGNAPT_DEBUGGING
3449 p_nat->naptDroppedPktCount2++;
3455 key.ip = rte_bswap32(src_addr);
3457 #ifdef NAT_ONLY_CONFIG_REQ
3458 if (nat_only_config_flag)
3462 memcpy(&p_nat->keys[pkt_num], &key,
3463 sizeof(struct pipeline_cgnapt_entry_key));
3464 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3468 * NAPT key calculation function for IPv4 public traffic
3469 * which handles 1 pkt
3472 * A pointer to array of packets mbuf
3474 * Pkt number of pkts
3478 * A pointer to main CGNAPT structure
3482 pkt_work_cgnapt_key_ipv4_pub(
3483 struct rte_mbuf *pkt,
3485 __rte_unused void *arg,
3486 struct pipeline_cgnapt *p_nat)
3488 p_nat->receivedPktCount++;
3490 /* bitmask representing only this packet */
3491 uint64_t pkt_mask = 1LLU << pkt_num;
3492 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3493 uint32_t dst_addr = RTE_MBUF_METADATA_UINT32(pkt, DST_ADR_OFST_IP4);
3494 uint16_t src_port_offset;
3495 uint16_t dst_port_offset;
3498 struct pipeline_cgnapt_entry_key key;
3499 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
3501 #ifdef CGNAPT_DBG_PRNT
3502 if (CGNAPT_DEBUG > 4)
3507 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
3512 case IP_PROTOCOL_UDP:
3513 case IP_PROTOCOL_TCP:
3514 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3515 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3517 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3518 dst_port = RTE_MBUF_METADATA_UINT16(pkt, dst_port_offset);
3520 key.port = rte_bswap16(dst_port);
3522 case IP_PROTOCOL_ICMP:
3524 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3526 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3529 src_port = RTE_MBUF_METADATA_UINT16(pkt, src_port_offset);
3530 dst_port = RTE_MBUF_METADATA_UINT16(pkt, dst_port_offset);
3532 /* common table lookupkey preparation from incoming
3533 * ICMP Packet- Indentifier field
3535 key.port = rte_bswap16(src_port);
3538 /* remember invalid packets to be dropped */
3539 p_nat->invalid_packets |= pkt_mask;
3540 p_nat->naptDroppedPktCount++;
3542 #ifdef CGNAPT_DEBUGGING
3543 p_nat->naptDroppedPktCount2++;
3548 key.ip = rte_bswap32(dst_addr);
3550 #ifdef NAT_ONLY_CONFIG_REQ
3551 if (nat_only_config_flag)
3557 memcpy(&p_nat->keys[pkt_num], &key,
3558 sizeof(struct pipeline_cgnapt_entry_key));
3559 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
3564 * NAPT function for IPv4 private traffic which handles 1 pkt
3567 * A pointer to array of packet mbuf
3573 * A pointer to main CGNAPT structure
3576 uint64_t last_update;
3578 pkt_work_cgnapt_ipv4_prv(
3579 struct rte_mbuf **pkts,
3581 __rte_unused void *arg,
3582 struct pipeline_cgnapt *p_nat)
3585 struct rte_CT_helper ct_helper;
3586 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
3589 /* index into hash table entries */
3590 int hash_table_entry = p_nat->lkup_indx[pkt_num];
3591 /*bitmask representing only this packet */
3592 uint64_t pkt_mask = 1LLU << pkt_num;
3593 struct rte_mbuf *pkt = pkts[pkt_num];
3595 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3597 uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */
3598 uint16_t *outport_id =
3599 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
3601 struct cgnapt_table_entry *entry = NULL;
3603 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
3605 if (hash_table_entry < 0) {
3607 /* try to add new entry */
3608 struct rte_pipeline_table_entry *table_entry = NULL;
3610 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
3612 &p_nat->valid_packets, pkt_num,
3616 /* ICMP Error message generation for Destination
3619 if (protocol == IP_PROTOCOL_ICMP) {
3620 cgnapt_icmp_pkt = pkt;
3621 send_icmp_dest_unreachable_msg();
3624 /* Drop packet by adding to invalid pkt mask */
3626 p_nat->invalid_packets |= dropmask;
3627 #ifdef CGNAPT_DEBUGGING
3628 if (p_nat->kpc2++ < 5) {
3629 printf("in_ah Th: %d", p_nat->pipeline_num);
3630 print_key(p_nat->key_ptrs[pkt_num]);
3634 p_nat->naptDroppedPktCount++;
3636 #ifdef CGNAPT_DEBUGGING
3637 p_nat->naptDroppedPktCount3++;
3642 entry = (struct cgnapt_table_entry *)table_entry;
3644 /* entry found for this packet */
3645 entry = &napt_hash_tbl_entries[hash_table_entry];
3648 /* apply napt and mac changes */
3650 p_nat->entries[pkt_num] = &(entry->head);
3652 uint32_t *src_addr =
3653 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP4);
3654 uint32_t *dst_addr =
3655 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
3656 uint16_t src_port_offset = 0;
3657 uint16_t dst_port_offset = 0;
3662 case IP_PROTOCOL_TCP:
3663 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3664 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3665 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3666 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3669 if ((rte_be_to_cpu_16(*src_port) == 21) ||
3670 rte_be_to_cpu_16(*dst_port) == 21) {
3673 printf("cgnapt_ct_process: pkt_mask: % "PRIu64", "
3674 "pkt_num: %d\n", pkt_mask, pkt_num);
3677 pkt_mask = cgnapt_ct_process(cgnat_cnxn_tracker, pkts,
3678 pkt_mask, &ct_helper);
3682 case IP_PROTOCOL_UDP:
3683 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3684 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3685 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3686 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3688 case IP_PROTOCOL_ICMP:
3690 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3692 /*Sequence number */
3693 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
3695 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3696 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3698 default: /* KW fix: unknown is treated as TCP/UDP */
3699 src_port_offset = SRC_PRT_OFST_IP4_TCP;
3700 dst_port_offset = DST_PRT_OFST_IP4_TCP;
3701 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
3702 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
3706 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
3707 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
3709 if (entry->data.ttl == NAPT_ENTRY_STALE)
3710 entry->data.ttl = NAPT_ENTRY_VALID;
3712 uint32_t dest_address = 0;
3715 if (unlikely(protocol == IP_PROTOCOL_UDP
3716 && rte_be_to_cpu_16(*dst_port) == 53)) {
3717 p_nat->invalid_packets |= pkt_mask;
3718 p_nat->naptDroppedPktCount++;
3720 #ifdef CGNAPT_DEBUGGING
3721 p_nat->naptDroppedPktCount6++;
3725 last_update = rte_rdtsc();
3726 dest_address = rte_bswap32(*dst_addr);
3728 struct arp_entry_data *ret_arp_data = NULL;
3730 uint32_t src_phy_port = *src_port;
3732 gw_get_nh_port_ipv4(dest_address, &dest_if, &nhip);
3734 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if,
3735 (struct ether_addr *)eth_dest);
3737 *outport_id = p_nat->outport_id[dest_if];
3739 if (arp_cache_dest_mac_present(dest_if)) {
3740 ether_addr_copy(get_link_hw_addr(dest_if),(struct ether_addr *)eth_src);
3741 update_nhip_access(dest_if);
3742 if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) {
3743 p_nat->naptedPktCount += ret_arp_data->num_pkts;
3744 arp_send_buffered_pkts(ret_arp_data,
3745 (struct ether_addr *)eth_dest, *outport_id);
3750 if (unlikely(ret_arp_data == NULL)) {
3752 #ifdef CGNAPT_DEBUGGING
3753 printf("%s: NHIP Not Found, nhip:%x , "
3754 "outport_id: %d\n", __func__, nhip,
3759 p_nat->invalid_packets |= pkt_mask;
3760 p_nat->naptDroppedPktCount++;
3762 #ifdef CGNAPT_DEBUGGING
3763 p_nat->naptDroppedPktCount4++;
3768 if (ret_arp_data->status == INCOMPLETE ||
3769 ret_arp_data->status == PROBE) {
3770 if (ret_arp_data->num_pkts >= NUM_DESC) {
3772 p_nat->invalid_packets |= pkt_mask;
3773 p_nat->naptDroppedPktCount++;
3775 #ifdef CGNAPT_DEBUGGING
3776 p_nat->naptDroppedPktCount4++;
3780 arp_pkts_mask |= pkt_mask;
3781 arp_queue_unresolved_packet(ret_arp_data, pkt);
3790 *src_addr = rte_bswap32(entry->data.pub_ip);
3793 #ifdef NAT_ONLY_CONFIG_REQ
3794 if (!nat_only_config_flag) {
3796 *src_port = rte_bswap16(entry->data.pub_port);
3797 #ifdef NAT_ONLY_CONFIG_REQ
3802 uint16_t rtp_port = 0, rtcp_port = 0;
3803 struct cgnapt_table_entry *entry_ptr1 = NULL,
3804 *entry_ptr2 = NULL, *entry_ptr3 = NULL,
3807 if (unlikely(protocol == IP_PROTOCOL_UDP
3808 && (rte_be_to_cpu_16(*dst_port) == 5060
3809 || rte_be_to_cpu_16(*src_port) == 5060))) {
3811 int ret = natSipAlgGetAudioPorts(pkt, &rtp_port,
3813 /* Commented code may be required for debug
3814 * and future use, Please keep it*/
3817 printf("%s: Wrong SIP ALG packet1\n",
3819 p_nat->invalid_packets |= pkt_mask;
3821 p_nat->naptDroppedPktCount++;
3823 #ifdef CGNAPT_DEBUGGING
3824 p_nat->naptDroppedPktCount4++;
3830 if (ret >= 0 && rtp_port != 0) {
3831 struct pipeline_cgnapt_entry_key rtp_key;
3832 rtp_key.ip = entry->data.u.prv_ip;
3833 rtp_key.port = rtp_port;
3834 rtp_key.pid = entry->data.prv_phy_port;
3836 if (add_dynamic_cgnapt_entry_alg(
3837 (struct pipeline *)p_nat, &rtp_key,
3838 &entry_ptr1, &entry_ptr2) == 0) {
3839 printf("%s: Wrong SIP ALG packet2\n",
3841 p_nat->invalid_packets |= pkt_mask;
3843 p_nat->naptDroppedPktCount++;
3845 #ifdef CGNAPT_DEBUGGING
3846 p_nat->naptDroppedPktCount4++;
3852 if (ret >= 0 && rtcp_port != 0) {
3853 struct pipeline_cgnapt_entry_key rtcp_key;
3854 rtcp_key.ip = entry->data.u.prv_ip;
3855 rtcp_key.port = rtcp_port;
3856 rtcp_key.pid = entry->data.prv_phy_port;
3858 if (add_dynamic_cgnapt_entry_alg(
3859 (struct pipeline *)p_nat, &rtcp_key,
3860 &entry_ptr3, &entry_ptr4) == 0) {
3861 printf("%s: Wrong SIP ALG packet3\n",
3863 p_nat->invalid_packets |= pkt_mask;
3865 p_nat->naptDroppedPktCount++;
3867 #ifdef CGNAPT_DEBUGGING
3868 p_nat->naptDroppedPktCount4++;
3874 //if(entry_ptr1 != NULL && entry_ptr3 != NULL)
3875 if (sip_alg_dpi(pkt, PRIVATE, entry->data.pub_ip,
3876 entry->data.pub_port, entry->data.u.prv_ip,
3877 entry->data.prv_port, (rtp_port == 0) ? 0 :
3878 entry_ptr1->data.pub_port,
3879 (rtcp_port == 0) ? 0 :
3880 entry_ptr3->data.pub_port) == 0) {
3882 printf("%s: Wrong SIP ALG packet4\n",
3884 p_nat->invalid_packets |= pkt_mask;
3886 p_nat->naptDroppedPktCount++;
3888 #ifdef CGNAPT_DEBUGGING
3889 p_nat->naptDroppedPktCount4++;
3894 #endif /* SIP_ALG */
3899 printf("@CGNAT-pktwork ct_position :%d, pkt_num %d pkt_mask= "
3900 "%" PRIu64 "\n", ct_position, pkt_num, pkt_mask);
3903 if ((rte_be_to_cpu_16(*src_port) == 21) ||
3904 rte_be_to_cpu_16(*dst_port) == 21) {
3906 int32_t ct_position = cgnat_cnxn_tracker->positions[pkt_num];
3907 if (ct_position < 0){
3908 p_nat->invalid_packets |= pkt_mask;
3909 p_nat->naptDroppedPktCount++;
3912 /* Commented code may be required for future usage,
3915 //if (cgnat_cnxn_tracker->hash_table_entries
3916 // [ct_position].alg_bypass_flag != BYPASS)
3918 struct pipeline_cgnapt_entry_key data_channel_entry_key;
3920 data_channel_entry_key.ip = entry->data.pub_ip;
3921 data_channel_entry_key.port = entry->data.pub_port;
3922 data_channel_entry_key.pid = pkt->port;
3923 ftp_alg_dpi(p_nat, &data_channel_entry_key, pkt,
3924 cgnat_cnxn_tracker, ct_position, PRIVATE);
3927 #endif /* FTP_ALG */
3929 p_nat->enaptedPktCount++;
3932 p_nat->naptedPktCount++;
3935 if (p_nat->hw_checksum_reqd)
3936 hw_checksum(pkt, pkt_type);
3938 sw_checksum(pkt, pkt_type);
3945 * NAPT function for IPv4 public traffic which handles 1 pkt
3948 * A pointer to array of packet mbuf
3954 * A pointer to main CGNAPT structure
3958 pkt_work_cgnapt_ipv4_pub(
3959 struct rte_mbuf **pkts,
3961 __rte_unused void *arg,
3962 struct pipeline_cgnapt *p_nat)
3966 struct rte_CT_helper ct_helper;
3967 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
3970 /* index into hash table entries */
3971 int hash_table_entry = p_nat->lkup_indx[pkt_num];
3972 /*bitmask representing only this packet */
3973 uint64_t pkt_mask = 1LLU << pkt_num;
3974 struct rte_mbuf *pkt = pkts[pkt_num];
3976 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3978 uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */
3979 uint16_t *outport_id =
3980 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
3982 struct cgnapt_table_entry *entry = NULL;
3984 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
3986 if (hash_table_entry < 0) {
3988 /* try to add new entry */
3989 struct rte_pipeline_table_entry *table_entry = NULL;
3991 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
3993 &p_nat->valid_packets, pkt_num,
3997 /* ICMP Error message generation for
3998 * Destination Host unreachable
4000 if (protocol == IP_PROTOCOL_ICMP) {
4001 cgnapt_icmp_pkt = pkt;
4002 send_icmp_dest_unreachable_msg();
4005 /* Drop packet by adding to invalid pkt mask */
4007 p_nat->invalid_packets |= dropmask;
4008 #ifdef CGNAPT_DEBUGGING
4009 if (p_nat->kpc2++ < 5) {
4010 printf("in_ah Th: %d", p_nat->pipeline_num);
4011 print_key(p_nat->key_ptrs[pkt_num]);
4015 p_nat->naptDroppedPktCount++;
4017 #ifdef CGNAPT_DEBUGGING
4018 p_nat->naptDroppedPktCount3++;
4023 entry = (struct cgnapt_table_entry *)table_entry;
4025 /* entry found for this packet */
4026 entry = &napt_hash_tbl_entries[hash_table_entry];
4029 /* apply napt and mac changes */
4031 p_nat->entries[pkt_num] = &(entry->head);
4033 uint32_t *dst_addr =
4034 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4035 uint16_t src_port_offset = 0;
4036 uint16_t dst_port_offset = 0;
4038 if ((protocol == IP_PROTOCOL_TCP) || (protocol == IP_PROTOCOL_UDP)) {
4039 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4040 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4041 } else if (protocol == IP_PROTOCOL_ICMP) {
4043 src_port_offset = MBUF_HDR_ROOM +
4046 /*Sequence number */
4047 dst_port_offset = MBUF_HDR_ROOM +
4052 uint16_t *src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
4053 uint16_t *dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
4055 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4056 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4058 if (entry->data.ttl == NAPT_ENTRY_STALE)
4059 entry->data.ttl = NAPT_ENTRY_VALID;
4061 uint32_t dest_address = 0;
4063 /* Multiport Changes */
4069 if (unlikely(protocol == IP_PROTOCOL_UDP
4070 && rte_be_to_cpu_16(*src_port) == 53)) {
4071 p_nat->invalid_packets |= pkt_mask;
4072 p_nat->naptDroppedPktCount++;
4073 #ifdef CGNAPT_DEBUGGING
4074 p_nat->naptDroppedPktCount6++;
4080 dest_address = entry->data.u.prv_ip;
4081 struct arp_entry_data *ret_arp_data = NULL;
4083 uint32_t src_phy_port = *src_port;
4085 gw_get_nh_port_ipv4(dest_address, &dest_if, &nhip);
4087 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if,
4088 (struct ether_addr *)eth_dest);
4089 *outport_id = p_nat->outport_id[dest_if];
4091 if (arp_cache_dest_mac_present(dest_if)) {
4092 ether_addr_copy(get_link_hw_addr(dest_if), (struct ether_addr *)eth_src);
4093 update_nhip_access(dest_if);
4095 if (ret_arp_data && ret_arp_data->num_pkts) {
4096 p_nat->naptedPktCount += ret_arp_data->num_pkts;
4097 arp_send_buffered_pkts(ret_arp_data,
4098 (struct ether_addr *)eth_dest, *outport_id);
4103 if (unlikely(ret_arp_data == NULL)) {
4105 /* Commented code may be required for debug
4106 * and future use, Please keep it */
4108 #ifdef CGNAPT_DEBUGGING
4109 printf("%s: NHIP Not Found, nhip: %x, "
4110 "outport_id: %d\n", __func__, nhip,
4115 p_nat->invalid_packets |= pkt_mask;
4116 p_nat->naptDroppedPktCount++;
4118 #ifdef CGNAPT_DEBUGGING
4119 p_nat->naptDroppedPktCount4++;
4125 if (ret_arp_data->status == INCOMPLETE ||
4126 ret_arp_data->status == PROBE) {
4127 if (ret_arp_data->num_pkts >= NUM_DESC) {
4129 p_nat->invalid_packets |= pkt_mask;
4130 p_nat->naptDroppedPktCount++;
4132 #ifdef CGNAPT_DEBUGGING
4133 p_nat->naptDroppedPktCount4++;
4137 arp_pkts_mask |= pkt_mask;
4138 arp_queue_unresolved_packet(ret_arp_data, pkt);
4147 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
4148 if (protocol == IP_PROTOCOL_ICMP) {
4149 /* Query ID reverse translation done here */
4150 /* dont care sequence num */
4151 *src_port = rte_bswap16(entry->data.prv_port);
4154 #ifdef NAT_ONLY_CONFIG_REQ
4155 if (!nat_only_config_flag) {
4157 *dst_port = rte_bswap16(entry->data.prv_port);
4159 #ifdef NAT_ONLY_CONFIG_REQ
4163 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4164 rte_be_to_cpu_16(*dst_port) == 21) {
4165 pkt_mask = cgnapt_ct_process(cgnat_cnxn_tracker, pkts,
4166 pkt_mask, &ct_helper);
4172 uint16_t rtp_port = 0, rtcp_port = 0;
4173 struct cgnapt_table_entry *entry_ptr1 = NULL,
4176 /* Commented code may be required for debug
4177 * and future use, Please keep it */
4179 struct cgnapt_table_entry *entry_ptr2 = NULL,
4183 if (unlikely(protocol == IP_PROTOCOL_UDP
4184 && (rte_be_to_cpu_16(*dst_port) == 5060
4185 || rte_be_to_cpu_16(*src_port) == 5060))) {
4186 /* Commented code may be required for future usage,
4190 int ret = natSipAlgGetAudioPorts(pkt, &rtp_port,
4193 printf("%s: Wrong SIP ALG packet1\n",
4195 p_nat->invalid_packets |= pkt_mask;
4197 p_nat->naptDroppedPktCount++;
4199 #ifdef CGNAPT_DEBUGGING
4200 p_nat->naptDroppedPktCount4++;
4204 if (rtp_port != 0) {
4205 struct pipeline_cgnapt_entry_key rtp_key;
4206 rtp_key.ip = entry->data.pub_ip;
4207 rtp_key.port = rtp_port;
4208 rtp_key.pid = 0xffff;
4210 if (retrieve_cgnapt_entry_alg(&rtp_key,
4211 &entry_ptr1, &entry_ptr2) == 0) {
4212 printf("%s: Wrong SIP ALG packet2\n",
4214 p_nat->invalid_packets |= pkt_mask;
4216 p_nat->naptDroppedPktCount++;
4218 #ifdef CGNAPT_DEBUGGING
4219 p_nat->naptDroppedPktCount4++;
4225 if (rtcp_port != 0) {
4226 struct pipeline_cgnapt_entry_key rtcp_key;
4227 rtcp_key.ip = entry->data.pub_ip;
4228 rtcp_key.port = rtcp_port;
4229 rtcp_key.pid = 0xffff;
4231 if (retrieve_cgnapt_entry_alg(&rtcp_key,
4232 &entry_ptr3, &entry_ptr4) == 0) {
4233 printf("%s: Wrong SIP ALG packet3\n",
4235 p_nat->invalid_packets |= pkt_mask;
4237 p_nat->naptDroppedPktCount++;
4239 #ifdef CGNAPT_DEBUGGING
4240 p_nat->naptDroppedPktCount4++;
4248 if (sip_alg_dpi(pkt, PUBLIC, entry->data.u.prv_ip,
4249 entry->data.prv_port, entry->data.pub_ip,
4250 entry->data.pub_port, (rtp_port == 0) ? 0 :
4251 entry_ptr1->data.prv_port,
4252 (rtcp_port == 0) ? 0 :
4253 entry_ptr3->data.prv_port) == 0) {
4255 printf("%s: Wrong SIP ALG packet4\n",
4257 p_nat->invalid_packets |= pkt_mask;
4259 p_nat->naptDroppedPktCount++;
4261 #ifdef CGNAPT_DEBUGGING
4262 p_nat->naptDroppedPktCount4++;
4268 #endif /* SIP_ALG */
4271 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4272 rte_be_to_cpu_16(*dst_port) == 21) {
4273 int32_t ct_position = cgnat_cnxn_tracker->
4275 if (ct_position < 0){
4276 p_nat->invalid_packets |= pkt_mask;
4278 p_nat->naptDroppedPktCount++;
4282 rte_hexdump(stdout, "CT Entry", &cgnat_cnxn_tracker->
4283 hash_table_entries[ct_position].key, 40);
4286 /* Commented code may be required for debug
4287 * and future use, Please keep it*/
4288 //if (cgnat_cnxn_tracker->hash_table_entries
4289 // [ct_position].alg_bypass_flag != BYPASS)
4292 struct pipeline_cgnapt_entry_key
4293 data_channel_entry_key;
4295 data_channel_entry_key.ip = entry->data.pub_ip;
4296 data_channel_entry_key.port = entry->data.pub_port;
4297 data_channel_entry_key.pid = 0xffff;
4298 //printf("pkt_work_pub ftp_alg_dpi\n");
4299 ftp_alg_dpi(p_nat, &data_channel_entry_key, pkt,
4300 cgnat_cnxn_tracker, ct_position, PUBLIC);
4306 p_nat->inaptedPktCount++;
4309 p_nat->naptedPktCount++;
4312 if (p_nat->hw_checksum_reqd)
4313 hw_checksum(pkt, pkt_type);
4315 sw_checksum(pkt, pkt_type);
4321 * NAPT function for IPv4 private traffic which handles 4 pkts
4324 * A pointer to array of packets mbuf
4326 * Starting pkt number of pkts
4330 * A pointer to main CGNAPT structure
4334 pkt4_work_cgnapt_ipv4_prv(
4335 struct rte_mbuf **pkts,
4336 uint32_t in_pkt_num,
4337 __rte_unused void *arg,
4338 struct pipeline_cgnapt *p_nat)
4340 uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */
4341 struct rte_mbuf *pkt;
4344 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4347 struct rte_CT_helper ct_helper;
4348 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4351 for (i = 0; i < 4; i++) {
4352 pkt_num = in_pkt_num + i;
4353 pkt = pkts[pkt_num];
4355 /* index into hash table entries */
4356 int hash_table_entry = p_nat->lkup_indx[pkt_num];
4357 /*bitmask representing only this packet */
4358 uint64_t pkt_mask = 1LLU << pkt_num;
4360 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
4362 uint16_t *outport_id =
4363 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
4365 struct cgnapt_table_entry *entry = NULL;
4367 if (hash_table_entry < 0) {
4369 /* try to add new entry */
4370 struct rte_pipeline_table_entry *table_entry = NULL;
4373 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
4375 &p_nat->valid_packets, pkt_num,
4379 /* ICMP Error message generation for
4380 * Destination Host unreachable
4382 if (protocol == IP_PROTOCOL_ICMP) {
4383 cgnapt_icmp_pkt = pkt;
4384 send_icmp_dest_unreachable_msg();
4387 /* Drop packet by adding to invalid pkt mask */
4389 p_nat->invalid_packets |= dropmask;
4391 #ifdef CGNAPT_DEBUGGING
4392 if (p_nat->kpc2++ < 5) {
4393 printf("in_ah Th: %d",
4394 p_nat->pipeline_num);
4395 print_key(p_nat->key_ptrs[pkt_num]);
4399 p_nat->naptDroppedPktCount++;
4401 #ifdef CGNAPT_DEBUGGING
4402 p_nat->naptDroppedPktCount3++;
4407 entry = (struct cgnapt_table_entry *)table_entry;
4409 /* entry found for this packet */
4410 entry = &napt_hash_tbl_entries[hash_table_entry];
4413 /* apply napt and mac changes */
4415 p_nat->entries[pkt_num] = &(entry->head);
4417 uint32_t *src_addr =
4418 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP4);
4419 uint32_t *dst_addr =
4420 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4421 uint16_t src_port_offset = 0;
4422 uint16_t dst_port_offset = 0;
4427 if ((protocol == IP_PROTOCOL_TCP)
4428 || (protocol == IP_PROTOCOL_UDP)) {
4429 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4430 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4431 } else if (protocol == IP_PROTOCOL_ICMP) {
4433 src_port_offset = MBUF_HDR_ROOM +
4436 /*Sequence number */
4437 dst_port_offset = MBUF_HDR_ROOM +
4444 case IP_PROTOCOL_TCP:
4445 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4446 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4447 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4449 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4453 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4454 rte_be_to_cpu_16(*dst_port) == 21) {
4456 //To process CT , pkt_mask does it need
4457 //to be complemented ??
4459 printf("cgnapt_ct_process: pkt_mask: "
4460 "% "PRIu64", pkt_num: %d\n",
4464 pkt_mask = cgnapt_ct_process(
4465 cgnat_cnxn_tracker, pkts,
4466 pkt_mask, &ct_helper);
4470 case IP_PROTOCOL_UDP:
4471 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4472 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4473 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4475 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4478 case IP_PROTOCOL_ICMP:
4480 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
4482 /*Sequence number */
4483 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
4485 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4487 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4490 default: /* KW fix: unknown is treated as TCP/UDP */
4491 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4492 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4493 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4495 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4502 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4504 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4506 if (entry->data.ttl == NAPT_ENTRY_STALE)
4507 entry->data.ttl = NAPT_ENTRY_VALID;
4509 uint32_t dest_address = 0;
4510 /*Multiport Changes */
4517 if (unlikely(protocol == IP_PROTOCOL_UDP
4518 && rte_be_to_cpu_16(*dst_port) == 53)) {
4519 p_nat->invalid_packets |= pkt_mask;
4520 p_nat->naptDroppedPktCount++;
4522 #ifdef CGNAPT_DEBUGGING
4523 p_nat->naptDroppedPktCount6++;
4529 dest_address = rte_bswap32(*dst_addr);
4530 struct arp_entry_data *ret_arp_data = NULL;
4531 uint64_t start, end;
4532 uint32_t src_phy_port = *src_port;
4534 gw_get_nh_port_ipv4(dest_address, &dest_if, &nhip);
4536 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if,
4537 (struct ether_addr *)eth_dest);
4539 *outport_id = p_nat->outport_id[dest_if];
4541 if (arp_cache_dest_mac_present(dest_if)) {
4542 ether_addr_copy(get_link_hw_addr(dest_if),
4543 (struct ether_addr *)eth_src);
4544 update_nhip_access(dest_if);
4546 if (ret_arp_data && ret_arp_data->num_pkts) {
4547 p_nat->naptedPktCount += ret_arp_data->num_pkts;
4548 arp_send_buffered_pkts(ret_arp_data,
4549 (struct ether_addr *)eth_dest, *outport_id);
4554 if (unlikely(ret_arp_data == NULL)) {
4556 #ifdef CGNAPT_DEBUGGING
4557 printf("%s: ARP Not Found, nhip: %x, "
4558 "outport_id: %d\n", __func__, nhip,
4563 p_nat->invalid_packets |= pkt_mask;
4564 p_nat->naptDroppedPktCount++;
4566 #ifdef CGNAPT_DEBUGGING
4567 p_nat->naptDroppedPktCount4++;
4573 if (ret_arp_data->status == INCOMPLETE ||
4574 ret_arp_data->status == PROBE) {
4575 if (ret_arp_data->num_pkts >= NUM_DESC) {
4577 p_nat->invalid_packets |= pkt_mask;
4578 p_nat->naptDroppedPktCount++;
4580 #ifdef CGNAPT_DEBUGGING
4581 p_nat->naptDroppedPktCount4++;
4585 arp_pkts_mask |= pkt_mask;
4586 arp_queue_unresolved_packet(ret_arp_data, pkt);
4594 *src_addr = rte_bswap32(entry->data.pub_ip);
4596 #ifdef NAT_ONLY_CONFIG_REQ
4597 if (!nat_only_config_flag) {
4599 *src_port = rte_bswap16(entry->data.pub_port);
4600 #ifdef NAT_ONLY_CONFIG_REQ
4605 uint16_t rtp_port = 0, rtcp_port = 0;
4606 struct cgnapt_table_entry *entry_ptr1 = NULL,
4607 *entry_ptr2 = NULL, *entry_ptr3 = NULL,
4610 if (unlikely(protocol == IP_PROTOCOL_UDP
4611 && (rte_be_to_cpu_16(*dst_port) == 5060
4612 || rte_be_to_cpu_16(*src_port) == 5060))) {
4614 int ret = natSipAlgGetAudioPorts(pkt,
4615 &rtp_port, &rtcp_port);
4616 /* Commented code may be required for future usage,
4621 printf("%s: Wrong SIP ALG packet1\n",
4623 p_nat->invalid_packets |= pkt_mask;
4625 p_nat->naptDroppedPktCount++;
4627 #ifdef CGNAPT_DEBUGGING
4628 p_nat->naptDroppedPktCount4++;
4634 if (ret >= 0 && rtp_port != 0) {
4635 struct pipeline_cgnapt_entry_key rtp_key;
4636 rtp_key.ip = entry->data.u.prv_ip;
4637 rtp_key.port = rtp_port;
4638 rtp_key.pid = entry->data.prv_phy_port;
4640 if (add_dynamic_cgnapt_entry_alg(
4641 (struct pipeline *)p_nat, &rtp_key,
4642 &entry_ptr1, &entry_ptr2) == 0) {
4643 printf("%s: Wrong SIP ALG packet2\n",
4645 p_nat->invalid_packets |= pkt_mask;
4647 p_nat->naptDroppedPktCount++;
4649 #ifdef CGNAPT_DEBUGGING
4650 p_nat->naptDroppedPktCount4++;
4656 if (ret >= 0 && rtcp_port != 0) {
4657 struct pipeline_cgnapt_entry_key rtcp_key;
4658 rtcp_key.ip = entry->data.u.prv_ip;
4659 rtcp_key.port = rtcp_port;
4660 rtcp_key.pid = entry->data.prv_phy_port;
4662 if (add_dynamic_cgnapt_entry_alg(
4663 (struct pipeline *)p_nat, &rtcp_key,
4664 &entry_ptr3, &entry_ptr4) == 0) {
4666 printf("%s: Wrong SIP ALG packet3\n",
4668 p_nat->invalid_packets |= pkt_mask;
4670 p_nat->naptDroppedPktCount++;
4672 #ifdef CGNAPT_DEBUGGING
4673 p_nat->naptDroppedPktCount4++;
4679 //if(entry_ptr1 != NULL && entry_ptr3 != NULL)
4680 if (sip_alg_dpi(pkt, PRIVATE,
4682 entry->data.pub_port,
4683 entry->data.u.prv_ip,
4684 entry->data.prv_port,
4685 (rtp_port == 0) ? 0 :
4686 entry_ptr1->data.pub_port,
4687 (rtcp_port == 0) ? 0 :
4688 entry_ptr3->data.pub_port) == 0) {
4690 printf("%s: Wrong SIP ALG packet4\n",
4692 p_nat->invalid_packets |= pkt_mask;
4694 p_nat->naptDroppedPktCount++;
4696 #ifdef CGNAPT_DEBUGGING
4697 p_nat->naptDroppedPktCount4++;
4702 #endif /* SIP_ALG */
4705 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4706 rte_be_to_cpu_16(*dst_port) == 21) {
4708 int32_t ct_position =
4709 cgnat_cnxn_tracker->positions[pkt_num];
4711 printf("@CGNAT-pkt4work ct_position :%d, pkt_num %d "
4712 "pkt_mask = %" PRIu64 "\n", ct_position,
4716 if (ct_position < 0){
4717 p_nat->invalid_packets |= pkt_mask;
4718 p_nat->naptDroppedPktCount++;
4721 if (cgnat_cnxn_tracker->hash_table_entries[ct_position].
4722 alg_bypass_flag != BYPASS){
4724 struct pipeline_cgnapt_entry_key
4725 data_channel_entry_key;
4727 data_channel_entry_key.ip =
4729 data_channel_entry_key.port =
4730 entry->data.pub_port;
4731 data_channel_entry_key.pid = 0xffff;
4733 ftp_alg_dpi(p_nat, &data_channel_entry_key,
4734 pkt, cgnat_cnxn_tracker, ct_position,
4740 p_nat->enaptedPktCount++;
4743 p_nat->naptedPktCount++;
4746 if (p_nat->hw_checksum_reqd)
4747 hw_checksum(pkt, pkt_type);
4749 sw_checksum(pkt, pkt_type);
4755 * NAPT function for IPv4 public traffic which handles 4 pkts
4758 * A pointer to array of packets mbuf
4760 * Starting pkt number of pkts
4764 * A pointer to main CGNAPT structure
4768 pkt4_work_cgnapt_ipv4_pub(
4769 struct rte_mbuf **pkts,
4770 uint32_t in_pkt_num,
4771 __rte_unused void *arg,
4772 struct pipeline_cgnapt *p_nat)
4775 struct rte_CT_helper ct_helper;
4776 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4778 struct rte_mbuf *pkt;
4781 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4783 for (i = 0; i < 4; i++) {
4784 pkt_num = in_pkt_num + i;
4785 pkt = pkts[pkt_num];
4787 /* index into hash table entries */
4788 int hash_table_entry = p_nat->lkup_indx[pkt_num];
4789 /*bitmask representing only this packet */
4790 uint64_t pkt_mask = 1LLU << pkt_num;
4792 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
4794 uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */
4795 uint16_t *outport_id =
4796 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
4798 struct cgnapt_table_entry *entry = NULL;
4800 if (hash_table_entry < 0) {
4802 /* try to add new entry */
4803 struct rte_pipeline_table_entry *table_entry = NULL;
4806 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
4808 &p_nat->valid_packets, pkt_num,
4812 /* ICMP Error message generation for
4813 * Destination Host unreachable
4815 if (protocol == IP_PROTOCOL_ICMP) {
4816 cgnapt_icmp_pkt = pkt;
4817 send_icmp_dest_unreachable_msg();
4820 /* Drop packet by adding to invalid pkt mask */
4822 p_nat->invalid_packets |= dropmask;
4824 #ifdef CGNAPT_DEBUGGING
4825 if (p_nat->kpc2++ < 5) {
4826 printf("in_ah Th: %d",
4827 p_nat->pipeline_num);
4828 print_key(p_nat->key_ptrs[pkt_num]);
4832 p_nat->naptDroppedPktCount++;
4834 #ifdef CGNAPT_DEBUGGING
4835 p_nat->naptDroppedPktCount3++;
4840 entry = (struct cgnapt_table_entry *)table_entry;
4842 /* entry found for this packet */
4843 entry = &napt_hash_tbl_entries[hash_table_entry];
4846 /* apply napt and mac changes */
4848 p_nat->entries[pkt_num] = &(entry->head);
4850 uint32_t *dst_addr =
4851 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4852 uint16_t src_port_offset = 0;
4853 uint16_t dst_port_offset = 0;
4855 if ((protocol == IP_PROTOCOL_TCP)
4856 || (protocol == IP_PROTOCOL_UDP)) {
4857 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4858 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4859 } else if (protocol == IP_PROTOCOL_ICMP) {
4861 src_port_offset = MBUF_HDR_ROOM +
4864 /*Sequence number */
4865 dst_port_offset = MBUF_HDR_ROOM +
4870 uint16_t *src_port =
4871 RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
4872 uint16_t *dst_port =
4873 RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
4876 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4878 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4880 if (entry->data.ttl == NAPT_ENTRY_STALE)
4881 entry->data.ttl = NAPT_ENTRY_VALID;
4883 uint32_t dest_address = 0;
4884 /* Multiport Changes */
4890 if (unlikely(protocol == IP_PROTOCOL_UDP
4891 && rte_be_to_cpu_16(*src_port) == 53)) {
4892 p_nat->invalid_packets |= pkt_mask;
4893 p_nat->naptDroppedPktCount++;
4894 #ifdef CGNAPT_DEBUGGING
4895 p_nat->naptDroppedPktCount6++;
4900 dest_address = entry->data.u.prv_ip;
4901 struct arp_entry_data *ret_arp_data = NULL;
4902 uint32_t src_phy_port = *src_port;
4904 gw_get_nh_port_ipv4(dest_address, &dest_if, &nhip);
4906 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if,
4907 (struct ether_addr *)eth_dest);
4909 *outport_id = p_nat->outport_id[dest_if];
4911 if (arp_cache_dest_mac_present(dest_if)) {
4912 ether_addr_copy(get_link_hw_addr(dest_if),
4913 (struct ether_addr *)eth_src);
4914 update_nhip_access(dest_if);
4916 if (ret_arp_data && ret_arp_data->num_pkts) {
4917 p_nat->naptedPktCount += ret_arp_data->num_pkts;
4918 arp_send_buffered_pkts(ret_arp_data,
4919 (struct ether_addr *)eth_dest, *outport_id);
4924 if (unlikely(ret_arp_data == NULL)) {
4926 #ifdef CGNAPT_DEBUGGING
4927 printf("%s: NHIP Not Found, nhip: %x, "
4928 "outport_id: %d\n", __func__, nhip,
4933 p_nat->invalid_packets |= pkt_mask;
4934 p_nat->naptDroppedPktCount++;
4936 #ifdef CGNAPT_DEBUGGING
4937 p_nat->naptDroppedPktCount4++;
4942 if (ret_arp_data->status == INCOMPLETE ||
4943 ret_arp_data->status == PROBE) {
4944 if (ret_arp_data->num_pkts >= NUM_DESC) {
4946 p_nat->invalid_packets |= pkt_mask;
4947 p_nat->naptDroppedPktCount++;
4949 #ifdef CGNAPT_DEBUGGING
4950 p_nat->naptDroppedPktCount4++;
4954 arp_pkts_mask |= pkt_mask;
4955 arp_queue_unresolved_packet(ret_arp_data, pkt);
4964 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
4965 if (protocol == IP_PROTOCOL_ICMP) {
4966 /* Query ID reverse translation done here */
4967 *src_port = rte_bswap16(entry->data.prv_port);
4968 /* dont care sequence num */
4970 #ifdef NAT_ONLY_CONFIG_REQ
4971 if (!nat_only_config_flag) {
4974 rte_bswap16(entry->data.prv_port);
4975 #ifdef NAT_ONLY_CONFIG_REQ
4980 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4981 rte_be_to_cpu_16(*dst_port) == 21) {
4982 pkt_mask = cgnapt_ct_process(
4983 cgnat_cnxn_tracker, pkts,
4984 pkt_mask, &ct_helper);
4990 uint16_t rtp_port = 0, rtcp_port = 0;
4991 struct cgnapt_table_entry *entry_ptr1 = NULL,
4993 /* Commented code may be required for future usage,
4997 struct cgnapt_table_entry *entry_ptr2 = NULL,
5001 if (unlikely(protocol == IP_PROTOCOL_UDP
5002 && (rte_be_to_cpu_16(*dst_port) == 5060
5003 || rte_be_to_cpu_16(*src_port) == 5060))) {
5004 /* Commented code may be required for future usage,
5008 int ret = natSipAlgGetAudioPorts(pkt,
5009 &rtp_port, &rtcp_port);
5011 printf("%s: Wrong SIP ALG packet1\n",
5013 p_nat->invalid_packets |= pkt_mask;
5015 p_nat->naptDroppedPktCount++;
5017 #ifdef CGNAPT_DEBUGGING
5018 p_nat->naptDroppedPktCount4++;
5023 if (rtp_port != 0) {
5024 struct pipeline_cgnapt_entry_key rtp_key;
5025 rtp_key.ip = entry->data.pub_ip;
5026 rtp_key.port = rtp_port;
5027 rtp_key.pid = 0xffff;
5029 if (retrieve_cgnapt_entry_alg(&rtp_key,
5030 &entry_ptr1, &entry_ptr2) == 0) {
5031 printf("%s: Wrong SIP ALG packet2\n",
5033 p_nat->invalid_packets |= pkt_mask;
5035 p_nat->naptDroppedPktCount++;
5037 #ifdef CGNAPT_DEBUGGING
5038 p_nat->naptDroppedPktCount4++;
5044 if (rtcp_port != 0) {
5045 struct pipeline_cgnapt_entry_key rtcp_key;
5046 rtcp_key.ip = entry->data.pub_ip;
5047 rtcp_key.port = rtcp_port;
5048 rtcp_key.pid = 0xffff;
5050 if (retrieve_cgnapt_entry_alg(&rtcp_key,
5051 &entry_ptr3, &entry_ptr4) == 0) {
5052 printf("%s: Wrong SIP ALG packet3\n",
5054 p_nat->invalid_packets |= pkt_mask;
5055 p_nat->naptDroppedPktCount++;
5057 #ifdef CGNAPT_DEBUGGING
5058 p_nat->naptDroppedPktCount4++;
5065 if (sip_alg_dpi(pkt, PUBLIC,
5066 entry->data.u.prv_ip,
5067 entry->data.prv_port,
5069 entry->data.pub_port,
5070 (rtp_port == 0) ? 0 :
5071 entry_ptr1->data.prv_port,
5072 (rtcp_port == 0) ? 0 :
5073 entry_ptr3->data.prv_port) == 0) {
5075 printf("%s: Wrong SIP ALG packet4\n",
5077 p_nat->invalid_packets |= pkt_mask;
5079 p_nat->naptDroppedPktCount++;
5081 #ifdef CGNAPT_DEBUGGING
5082 p_nat->naptDroppedPktCount4++;
5087 #endif /* SIP_ALG */
5090 if ((rte_be_to_cpu_16(*src_port) == 21) ||
5091 rte_be_to_cpu_16(*dst_port) == 21) {
5093 int32_t ct_position =
5094 cgnat_cnxn_tracker->positions[pkt_num];
5095 if (ct_position < 0){
5096 p_nat->invalid_packets |= pkt_mask;
5098 p_nat->naptDroppedPktCount++;
5101 if (cgnat_cnxn_tracker->hash_table_entries
5102 [ct_position].alg_bypass_flag != BYPASS){
5104 struct pipeline_cgnapt_entry_key
5105 data_channel_entry_key;
5108 data_channel_entry_key.ip =
5110 data_channel_entry_key.port =
5111 entry->data.pub_port;
5112 data_channel_entry_key.pid = 0xffff;
5114 ftp_alg_dpi(p_nat, &data_channel_entry_key,
5115 pkt, cgnat_cnxn_tracker,
5116 ct_position, PUBLIC);
5121 p_nat->inaptedPktCount++;
5124 p_nat->naptedPktCount++;
5127 if (p_nat->hw_checksum_reqd)
5128 hw_checksum(pkt, pkt_type);
5130 sw_checksum(pkt, pkt_type);
5136 * NAPT key calculation function for IPv6 private traffic
5137 * which handles 1 pkt
5140 * A pointer to array of packets mbuf
5142 * Pkt number of pkts
5146 * A pointer to main CGNAPT structure
5150 pkt_work_cgnapt_key_ipv6_prv(
5151 struct rte_mbuf *pkt,
5153 __rte_unused void *arg,
5154 struct pipeline_cgnapt *p_nat)
5157 p_nat->receivedPktCount++;
5159 /* bitmask representing only this packet */
5160 uint64_t pkt_mask = 1LLU << pkt_num;
5162 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
5163 uint32_t *src_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
5165 uint16_t src_port = RTE_MBUF_METADATA_UINT16(pkt, SRC_PRT_OFST_IP6);
5167 uint16_t phy_port = pkt->port;
5168 struct pipeline_cgnapt_entry_key key;
5170 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
5172 #ifdef CGNAPT_DBG_PRNT
5173 if (CGNAPT_DEBUG > 4)
5178 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
5183 case IP_PROTOCOL_UDP:
5187 struct udp_hdr *udp;
5189 udp = (struct udp_hdr *)
5190 RTE_MBUF_METADATA_UINT8_PTR(pkt,
5193 if (rte_bswap16(udp->dst_port) ==
5195 handle_pcp_req(pkt, IPV6_SZ, p_nat);
5196 p_nat->invalid_packets |= pkt_mask;
5202 case IP_PROTOCOL_TCP:
5203 case IP_PROTOCOL_ICMP:
5204 /*we don't need icmp check in ipv6 */
5208 printf("wrong protocol: %d\n", protocol);
5209 /* remember invalid packets to be dropped */
5210 p_nat->invalid_packets |= pkt_mask;
5211 p_nat->naptDroppedPktCount++;
5213 #ifdef CGNAPT_DEBUGGING
5214 p_nat->naptDroppedPktCount2++;
5220 key.ip = rte_bswap32(src_addr[3]);
5221 key.port = rte_bswap16(src_port);
5223 #ifdef NAT_ONLY_CONFIG_REQ
5224 if (nat_only_config_flag)
5228 memcpy(&p_nat->keys[pkt_num], &key,
5229 sizeof(struct pipeline_cgnapt_entry_key));
5230 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5234 * NAPT key calculation function for IPv6 public traffic
5235 * which handles 1 pkt
5238 * A pointer to array of packets mbuf
5240 * Pkt number of pkts
5244 * A pointer to main CGNAPT structure
5248 pkt_work_cgnapt_key_ipv6_pub(
5249 struct rte_mbuf *pkt,
5251 __rte_unused void *arg,
5252 struct pipeline_cgnapt *p_nat)
5256 p_nat->receivedPktCount++;
5258 /* bitmask representing only this packet */
5259 uint64_t pkt_mask = 1LLU << pkt_num;
5261 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
5263 uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
5265 uint16_t dst_port = RTE_MBUF_METADATA_UINT16(pkt,
5266 DST_PRT_OFST_IP4_TCP);
5268 struct pipeline_cgnapt_entry_key key;
5270 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
5272 #ifdef CGNAPT_DBG_PRNT
5273 if (CGNAPT_DEBUG > 4)
5278 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
5284 case IP_PROTOCOL_UDP:
5285 case IP_PROTOCOL_TCP:
5286 case IP_PROTOCOL_ICMP:
5287 /*we don't need icmp check in ipv6 */
5291 /* remember invalid packets to be dropped */
5292 p_nat->invalid_packets |= pkt_mask;
5293 p_nat->naptDroppedPktCount++;
5295 #ifdef CGNAPT_DEBUGGING
5296 p_nat->naptDroppedPktCount2++;
5302 key.ip = rte_bswap32(dst_addr[0]);
5303 key.port = rte_bswap16(dst_port);
5305 #ifdef NAT_ONLY_CONFIG_REQ
5306 if (nat_only_config_flag)
5310 memcpy(&p_nat->keys[pkt_num], &key,
5311 sizeof(struct pipeline_cgnapt_entry_key));
5312 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5316 * NAPT key calculation function for IPv6 private traffic
5317 * which handles 4 pkts
5320 * A pointer to array of packets mbuf
5322 * Starting pkt number of pkts
5326 * A pointer to main CGNAPT structure
5330 pkt4_work_cgnapt_key_ipv6_prv(
5331 struct rte_mbuf **pkt,
5333 __rte_unused void *arg,
5334 struct pipeline_cgnapt *p_nat)
5336 p_nat->receivedPktCount += 4;
5338 /* bitmask representing only this packet */
5339 uint64_t pkt_mask0 = 1LLU << pkt_num;
5340 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
5341 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
5342 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
5344 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
5346 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
5348 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
5350 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
5353 uint32_t *src_addr0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0],
5355 uint32_t *src_addr1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1],
5357 uint32_t *src_addr2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2],
5359 uint32_t *src_addr3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3],
5362 uint16_t src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
5364 uint16_t src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
5366 uint16_t src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
5368 uint16_t src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
5371 uint16_t phy_port0 = pkt[0]->port;
5372 uint16_t phy_port1 = pkt[1]->port;
5373 uint16_t phy_port2 = pkt[2]->port;
5374 uint16_t phy_port3 = pkt[3]->port;
5376 struct pipeline_cgnapt_entry_key key0;
5377 struct pipeline_cgnapt_entry_key key1;
5378 struct pipeline_cgnapt_entry_key key2;
5379 struct pipeline_cgnapt_entry_key key3;
5381 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
5382 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
5383 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
5384 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
5388 #ifdef CGNAPT_DBG_PRNT
5389 if (CGNAPT_DEBUG > 4)
5394 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
5398 switch (protocol0) {
5400 case IP_PROTOCOL_UDP:
5404 struct udp_hdr *udp;
5406 udp = (struct udp_hdr *)
5407 RTE_MBUF_METADATA_UINT8_PTR(pkt[0],
5410 if (rte_bswap16(udp->dst_port) ==
5412 handle_pcp_req(pkt[0], IPV6_SZ, p_nat);
5413 p_nat->invalid_packets |= pkt_mask0;
5419 case IP_PROTOCOL_TCP:
5420 case IP_PROTOCOL_ICMP:
5421 /*we don't need icmp check in ipv6 */
5425 /* remember invalid packets to be dropped */
5426 p_nat->invalid_packets |= pkt_mask0;
5427 p_nat->naptDroppedPktCount++;
5429 #ifdef CGNAPT_DEBUGGING
5430 p_nat->naptDroppedPktCount2++;
5437 key0.pid = phy_port0;
5438 key0.ip = rte_bswap32(src_addr0[3]);
5439 key0.port = rte_bswap16(src_port0);
5441 #ifdef NAT_ONLY_CONFIG_REQ
5442 if (nat_only_config_flag)
5446 memcpy(&p_nat->keys[pkt_num], &key0,
5447 sizeof(struct pipeline_cgnapt_entry_key));
5448 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5451 #ifdef CGNAPT_DBG_PRNT
5452 if (CGNAPT_DEBUG > 4)
5457 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
5461 switch (protocol1) {
5462 case IP_PROTOCOL_UDP:
5466 struct udp_hdr *udp;
5468 udp = (struct udp_hdr *)
5469 RTE_MBUF_METADATA_UINT8_PTR(pkt[1],
5472 if (rte_bswap16(udp->dst_port) ==
5474 handle_pcp_req(pkt[1], IPV6_SZ, p_nat);
5475 p_nat->invalid_packets |= pkt_mask1;
5481 case IP_PROTOCOL_TCP:
5482 case IP_PROTOCOL_ICMP:
5483 /*we don't need icmp check in ipv6 */
5487 /* remember invalid packets to be dropped */
5488 p_nat->invalid_packets |= pkt_mask1;
5489 p_nat->naptDroppedPktCount++;
5491 #ifdef CGNAPT_DEBUGGING
5492 p_nat->naptDroppedPktCount2++;
5498 key1.pid = phy_port1;
5499 key1.ip = rte_bswap32(src_addr1[3]);
5500 key1.port = rte_bswap16(src_port1);
5502 #ifdef NAT_ONLY_CONFIG_REQ
5503 if (nat_only_config_flag)
5507 memcpy(&p_nat->keys[pkt_num + 1], &key1,
5508 sizeof(struct pipeline_cgnapt_entry_key));
5509 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
5512 #ifdef CGNAPT_DBG_PRNT
5513 if (CGNAPT_DEBUG > 4)
5518 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
5522 switch (protocol2) {
5523 case IP_PROTOCOL_UDP:
5527 struct udp_hdr *udp;
5529 udp = (struct udp_hdr *)
5530 RTE_MBUF_METADATA_UINT8_PTR(pkt[2],
5533 if (rte_bswap16(udp->dst_port) ==
5535 handle_pcp_req(pkt[2], IPV6_SZ, p_nat);
5536 p_nat->invalid_packets |= pkt_mask2;
5542 case IP_PROTOCOL_TCP:
5543 case IP_PROTOCOL_ICMP:
5544 /*we don't need icmp check in ipv6 */
5548 /* remember invalid packets to be dropped */
5549 p_nat->invalid_packets |= pkt_mask2;
5550 p_nat->naptDroppedPktCount++;
5552 #ifdef CGNAPT_DEBUGGING
5553 p_nat->naptDroppedPktCount2++;
5559 key2.pid = phy_port2;
5560 key2.ip = rte_bswap32(src_addr2[3]);
5561 key2.port = rte_bswap16(src_port2);
5563 #ifdef NAT_ONLY_CONFIG_REQ
5564 if (nat_only_config_flag)
5568 memcpy(&p_nat->keys[pkt_num + 2], &key2,
5569 sizeof(struct pipeline_cgnapt_entry_key));
5570 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
5573 #ifdef CGNAPT_DBG_PRNT
5574 if (CGNAPT_DEBUG > 4)
5579 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
5583 switch (protocol3) {
5584 case IP_PROTOCOL_UDP:
5588 struct udp_hdr *udp;
5590 udp = (struct udp_hdr *)
5591 RTE_MBUF_METADATA_UINT8_PTR(pkt[3],
5594 if (rte_bswap16(udp->dst_port) ==
5596 handle_pcp_req(pkt[3], IPV6_SZ, p_nat);
5597 p_nat->invalid_packets |= pkt_mask3;
5603 case IP_PROTOCOL_TCP:
5604 case IP_PROTOCOL_ICMP:
5605 /*we don't need icmp check in ipv6 */
5609 /* remember invalid packets to be dropped */
5610 p_nat->invalid_packets |= pkt_mask2;
5611 p_nat->naptDroppedPktCount++;
5613 #ifdef CGNAPT_DEBUGGING
5614 p_nat->naptDroppedPktCount2++;
5620 key3.pid = phy_port3;
5621 key3.ip = rte_bswap32(src_addr3[3]);
5622 key3.port = rte_bswap16(src_port3);
5624 #ifdef NAT_ONLY_CONFIG_REQ
5625 if (nat_only_config_flag)
5629 memcpy(&p_nat->keys[pkt_num + 3], &key3,
5630 sizeof(struct pipeline_cgnapt_entry_key));
5631 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
5637 * NAPT key calculation function for IPv4 public traffic
5638 * which handles 4 pkts
5641 * A pointer to array of packets mbuf
5643 * Starting pkt number of pkts
5647 * A pointer to main CGNAPT structure
5651 pkt4_work_cgnapt_key_ipv6_pub(
5652 struct rte_mbuf **pkt,
5654 __rte_unused void *arg,
5655 struct pipeline_cgnapt *p_nat)
5657 p_nat->receivedPktCount += 4;
5659 /* bitmask representing only this packet */
5660 uint64_t pkt_mask0 = 1LLU << pkt_num;
5661 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
5662 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
5663 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
5665 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
5667 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
5669 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
5671 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
5674 uint32_t *dst_addr0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0],
5676 uint32_t *dst_addr1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1],
5678 uint32_t *dst_addr2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2],
5680 uint32_t *dst_addr3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3],
5683 uint16_t dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
5684 DST_PRT_OFST_IP4_TCP);
5685 uint16_t dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
5686 DST_PRT_OFST_IP4_TCP);
5687 uint16_t dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
5688 DST_PRT_OFST_IP4_TCP);
5689 uint16_t dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
5690 DST_PRT_OFST_IP4_TCP);
5692 struct pipeline_cgnapt_entry_key key0;
5693 struct pipeline_cgnapt_entry_key key1;
5694 struct pipeline_cgnapt_entry_key key2;
5695 struct pipeline_cgnapt_entry_key key3;
5697 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
5698 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
5699 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
5700 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
5704 #ifdef CGNAPT_DBG_PRNT
5705 if (CGNAPT_DEBUG > 4)
5710 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
5714 switch (protocol0) {
5716 case IP_PROTOCOL_TCP:
5717 case IP_PROTOCOL_UDP:
5718 case IP_PROTOCOL_ICMP:
5719 /*we don't need icmp check in ipv6 */
5723 /* remember invalid packets to be dropped */
5724 p_nat->invalid_packets |= pkt_mask0;
5725 p_nat->naptDroppedPktCount++;
5727 #ifdef CGNAPT_DEBUGGING
5728 p_nat->naptDroppedPktCount2++;
5734 key0.ip = rte_bswap32(dst_addr0[0]);
5735 key0.port = rte_bswap16(dst_port0);
5737 #ifdef NAT_ONLY_CONFIG_REQ
5738 if (nat_only_config_flag)
5742 memcpy(&p_nat->keys[pkt_num], &key0,
5743 sizeof(struct pipeline_cgnapt_entry_key));
5744 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5750 #ifdef CGNAPT_DBG_PRNT
5751 if (CGNAPT_DEBUG > 4)
5756 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
5760 switch (protocol1) {
5762 case IP_PROTOCOL_TCP:
5763 case IP_PROTOCOL_UDP:
5764 case IP_PROTOCOL_ICMP:
5765 /*we don't need icmp check in ipv6 */
5769 /* remember invalid packets to be dropped */
5770 p_nat->invalid_packets |= pkt_mask1;
5771 p_nat->naptDroppedPktCount++;
5773 #ifdef CGNAPT_DEBUGGING
5774 p_nat->naptDroppedPktCount2++;
5780 key1.ip = rte_bswap32(dst_addr1[0]);
5781 key1.port = rte_bswap16(dst_port1);
5783 #ifdef NAT_ONLY_CONFIG_REQ
5784 if (nat_only_config_flag)
5788 memcpy(&p_nat->keys[pkt_num + 1], &key1,
5789 sizeof(struct pipeline_cgnapt_entry_key));
5790 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
5796 #ifdef CGNAPT_DBG_PRNT
5797 if (CGNAPT_DEBUG > 4)
5802 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
5806 switch (protocol2) {
5808 case IP_PROTOCOL_TCP:
5809 case IP_PROTOCOL_UDP:
5810 case IP_PROTOCOL_ICMP:
5811 /*we don't need icmp check in ipv6 */
5815 /* remember invalid packets to be dropped */
5816 p_nat->invalid_packets |= pkt_mask2;
5817 p_nat->naptDroppedPktCount++;
5819 #ifdef CGNAPT_DEBUGGING
5820 p_nat->naptDroppedPktCount2++;
5826 key2.ip = rte_bswap32(dst_addr2[0]);
5827 key2.port = rte_bswap16(dst_port2);
5829 #ifdef NAT_ONLY_CONFIG_REQ
5830 if (nat_only_config_flag)
5834 memcpy(&p_nat->keys[pkt_num + 2], &key2,
5835 sizeof(struct pipeline_cgnapt_entry_key));
5837 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
5843 #ifdef CGNAPT_DBG_PRNT
5844 if (CGNAPT_DEBUG > 4)
5849 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
5853 switch (protocol3) {
5855 case IP_PROTOCOL_TCP:
5856 case IP_PROTOCOL_UDP:
5857 case IP_PROTOCOL_ICMP:
5858 /*we don't need icmp check in ipv6 */
5862 /* remember invalid packets to be dropped */
5863 p_nat->invalid_packets |= pkt_mask3;
5864 p_nat->naptDroppedPktCount++;
5866 #ifdef CGNAPT_DEBUGGING
5867 p_nat->naptDroppedPktCount2++;
5873 key3.ip = rte_bswap32(dst_addr3[0]);
5874 key3.port = rte_bswap16(dst_port3);
5876 #ifdef NAT_ONLY_CONFIG_REQ
5877 if (nat_only_config_flag)
5881 memcpy(&p_nat->keys[pkt_num + 3], &key3,
5882 sizeof(struct pipeline_cgnapt_entry_key));
5884 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
5888 * NAPT function for IPv6 private traffic which handles 1 pkt
5891 * A pointer to array of packet mbuf
5897 * A pointer to main CGNAPT structure
5901 pkt_work_cgnapt_ipv6_prv(
5902 struct rte_mbuf *pkt,
5904 __rte_unused void *arg,
5905 struct pipeline_cgnapt *p_nat)
5907 /* index into hash table entries */
5908 int hash_table_entry = p_nat->lkup_indx[pkt_num];
5910 /*bitmask representing only this packet */
5911 uint64_t pkt_mask = 1LLU << pkt_num;
5913 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
5915 /* Added for Multiport */
5916 uint32_t dest_if = INVALID_DESTIF;
5917 uint16_t *outport_id = RTE_MBUF_METADATA_UINT16_PTR(pkt,
5918 cgnapt_meta_offset);
5920 struct cgnapt_table_entry *entry = NULL;
5921 enum PKT_TYPE pkt_type = PKT_TYPE_IPV6to4;
5923 if (hash_table_entry < 0) {
5925 /* try to add new entry */
5926 struct rte_pipeline_table_entry *table_entry = NULL;
5928 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
5930 &p_nat->valid_packets, pkt_num,
5934 /* ICMP Error message generation for
5935 * Destination Host unreachable
5937 /* Do we need this check for ipv6? */
5938 if (protocol == IP_PROTOCOL_ICMP) {
5939 cgnapt_icmp_pkt = pkt;
5940 send_icmp_dest_unreachable_msg();
5943 /* Drop packet by adding to invalid pkt mask */
5945 p_nat->invalid_packets |= dropmask;
5947 #ifdef CGNAPT_DEBUGGING
5948 if (p_nat->kpc2++ < 5) {
5949 printf("in_ah Th: %d", p_nat->pipeline_num);
5950 print_key(p_nat->key_ptrs[pkt_num]);
5954 p_nat->naptDroppedPktCount++;
5956 #ifdef CGNAPT_DEBUGGING
5957 p_nat->naptDroppedPktCount3++;
5963 entry = (struct cgnapt_table_entry *)table_entry;
5965 /* entry found for this packet */
5966 entry = &napt_hash_tbl_entries[hash_table_entry];
5969 /* apply napt and mac changes */
5971 p_nat->entries[pkt_num] = &(entry->head);
5973 struct ipv6_hdr ipv6_hdr;
5975 uint32_t dest_address = 0;
5980 convert_ipv6_to_ipv4(pkt, &ipv6_hdr);
5982 #ifdef CGNAPT_DBG_PRNT
5983 if (CGNAPT_DEBUG == 1)
5984 printf("pkt_work_cganpt: convert_ipv6_to_ipv4\n");
5987 struct cgnapt_nsp_node *ll = nsp_ll;
5990 while (ll != NULL) {
5992 (&ipv6_hdr.dst_addr[0], &ll->nsp.prefix[0],
5993 ll->nsp.depth / 8)) {
6001 && !memcmp(&ipv6_hdr.dst_addr[0], &well_known_prefix[0],
6007 p_nat->invalid_packets |= pkt_mask;
6008 p_nat->naptDroppedPktCount++;
6010 #ifdef CGNAPT_DEBUGGING
6011 p_nat->naptDroppedPktCount5++;
6019 /* As packet is already converted into IPv4 we must not
6020 * operate IPv6 offsets on packet
6021 * Only perform IPv4 operations
6024 uint32_t *src_addr =
6025 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP6t4);
6026 uint32_t *dst_addr =
6027 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP6t4);
6028 uint16_t *src_port =
6029 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP6t4);
6030 uint16_t *dst_port =
6031 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP6t4);
6033 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt,
6035 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt,
6036 ETH_OFST_IP6t4 + 6);
6038 if (entry->data.ttl == NAPT_ENTRY_STALE)
6039 entry->data.ttl = NAPT_ENTRY_VALID;
6042 if (unlikely(protocol == IP_PROTOCOL_UDP
6043 && rte_be_to_cpu_16(*dst_port) == 53)) {
6044 p_nat->invalid_packets |= pkt_mask;
6045 p_nat->naptDroppedPktCount++;
6047 #ifdef CGNAPT_DEBUGGING
6048 p_nat->naptDroppedPktCount6++;
6054 dest_address = rte_bswap32(*dst_addr);
6055 /*Multiport Changes */
6058 #ifdef CGNAPT_DBG_PRNT
6059 if (CGNAPT_DEBUG > 2)
6060 printf("Egress: \tphy_port:%d\t get_prv_to_pub():%d "
6061 "\tout_port:%d\n", pkt->port,
6062 dest_if, *outport_id);
6066 #ifdef CGNAPT_DBG_PRNT
6067 static int static_count;
6069 if (static_count++ < 10) {
6071 my_print_entry(entry);
6072 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6073 printf("dest_add:%x\n", entry->data.u.prv_ip);
6074 printf("dest_add:%x\n", *dst_addr);
6075 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6079 struct arp_entry_data *ret_arp_data;
6081 uint32_t src_phy_port = *src_port;
6083 gw_get_nh_port_ipv4(dest_address, &dest_if, &nhip);
6085 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if,
6086 (struct ether_addr *)eth_dest);
6088 *outport_id = p_nat->outport_id[dest_if];
6090 if (arp_cache_dest_mac_present(dest_if)) {
6091 ether_addr_copy(get_link_hw_addr(dest_if),
6092 (struct ether_addr *)eth_src);
6093 update_nhip_access(dest_if);
6095 if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) {
6096 p_nat->naptedPktCount += ret_arp_data->num_pkts;
6097 arp_send_buffered_pkts(ret_arp_data,
6098 (struct ether_addr *)eth_dest, *outport_id);
6103 if (unlikely(ret_arp_data == NULL)) {
6105 #ifdef CGNAPT_DEBUGGING
6106 printf("%s: NHIP Not Found, nhip:%x , "
6107 "outport_id: %d\n", __func__, nhip,
6112 p_nat->invalid_packets |= pkt_mask;
6113 p_nat->naptDroppedPktCount++;
6115 #ifdef CGNAPT_DEBUGGING
6116 p_nat->naptDroppedPktCount4++;
6121 if (ret_arp_data->status == INCOMPLETE ||
6122 ret_arp_data->status == PROBE) {
6123 if (ret_arp_data->num_pkts >= NUM_DESC) {
6125 p_nat->invalid_packets |= pkt_mask;
6126 p_nat->naptDroppedPktCount++;
6128 #ifdef CGNAPT_DEBUGGING
6129 p_nat->naptDroppedPktCount4++;
6133 arp_pkts_mask |= pkt_mask;
6134 arp_queue_unresolved_packet(ret_arp_data, pkt);
6142 *src_addr = rte_bswap32(entry->data.pub_ip);
6144 #ifdef NAT_ONLY_CONFIG_REQ
6145 if (!nat_only_config_flag) {
6147 *src_port = rte_bswap16(entry->data.pub_port);
6149 #ifdef NAT_ONLY_CONFIG_REQ
6153 p_nat->enaptedPktCount++;
6156 p_nat->naptedPktCount++;
6159 if (p_nat->hw_checksum_reqd)
6160 hw_checksum(pkt, pkt_type);
6162 sw_checksum(pkt, pkt_type);
6168 * NAPT function for IPv6 public traffic which handles 1 pkt
6171 * A pointer to array of packet mbuf
6177 * A pointer to main CGNAPT structure
6181 pkt_work_cgnapt_ipv6_pub(
6182 struct rte_mbuf *pkt,
6184 __rte_unused void *arg,
6185 struct pipeline_cgnapt *p_nat)
6188 /* index into hash table entries */
6189 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6190 /*bitmask representing only this packet */
6191 uint64_t pkt_mask = 1LLU << pkt_num;
6193 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
6195 uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */
6196 uint16_t *outport_id =
6197 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6198 struct cgnapt_table_entry *entry = NULL;
6200 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4to6;
6202 if (hash_table_entry < 0) {
6204 /* Drop ingress initial traffic */
6206 p_nat->invalid_packets |= pkt_mask;
6207 p_nat->naptDroppedPktCount++;
6209 #ifdef CGNAPT_DEBUGGING
6210 p_nat->naptDroppedPktCount3++;
6211 if (p_nat->kpc2++ < 5) {
6212 printf("in_ah Th: %d", p_nat->pipeline_num);
6213 print_key(p_nat->key_ptrs[pkt_num]);
6220 /* entry found for this packet */
6221 entry = &napt_hash_tbl_entries[hash_table_entry];
6224 /* apply napt and mac changes */
6226 p_nat->entries[pkt_num] = &(entry->head);
6227 if (entry->data.type != CGNAPT_ENTRY_IPV6) {
6228 p_nat->invalid_packets |= pkt_mask;
6229 p_nat->naptDroppedPktCount++;
6233 struct ipv4_hdr ipv4_hdr;
6234 uint16_t *src_port =
6235 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP4_TCP);
6237 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
6238 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
6240 if (entry->data.ttl == NAPT_ENTRY_STALE)
6241 entry->data.ttl = NAPT_ENTRY_VALID;
6243 struct ether_addr hw_addr;
6244 uint8_t dest_addr_ipv6[16];
6245 uint8_t nh_ipv6[16];
6250 if (unlikely(protocol == IP_PROTOCOL_UDP
6251 && rte_be_to_cpu_16(*src_port) == 53)) {
6252 p_nat->invalid_packets |= pkt_mask;
6253 p_nat->naptDroppedPktCount++;
6254 #ifdef CGNAPT_DEBUGGING
6255 p_nat->naptDroppedPktCount6++;
6260 memcpy(&dest_addr_ipv6[0], &entry->data.u.prv_ipv6[0], 16);
6263 memset(nh_ipv6, 0, 16);
6264 struct nd_entry_data *ret_nd_data = NULL;
6266 dest_if = INVALID_DESTIF;
6268 uint32_t src_phy_port = pkt->port;
6270 gw_get_nh_port_ipv6((uint8_t *) &dest_addr_ipv6[0],
6271 &dest_if, &nh_ipv6[0]);
6273 ret_nd_data = get_dest_mac_addr_ipv6(&nh_ipv6[0],
6274 dest_if, (struct ether_addr *)eth_dest);
6276 *outport_id = p_nat->outport_id[dest_if];
6278 if (nd_cache_dest_mac_present(dest_if)) {
6279 ether_addr_copy(get_link_hw_addr(dest_if),
6280 (struct ether_addr *)eth_src);
6281 update_nhip_access(dest_if);
6283 if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) {
6284 p_nat->naptedPktCount += ret_nd_data->num_pkts;
6285 nd_send_buffered_pkts(ret_nd_data,
6286 (struct ether_addr *)eth_dest, *outport_id);
6290 if (unlikely(ret_nd_data == NULL)) {
6292 #ifdef CGNAPT_DEBUGGING
6293 printf("%s: NHIP Not Found, "
6294 "outport_id: %d\n", __func__,
6299 p_nat->invalid_packets |= pkt_mask;
6300 p_nat->naptDroppedPktCount++;
6302 #ifdef CGNAPT_DEBUGGING
6303 p_nat->naptDroppedPktCount4++;
6308 if (ret_nd_data->status == INCOMPLETE ||
6309 ret_nd_data->status == PROBE) {
6310 if (ret_nd_data->num_pkts >= NUM_DESC) {
6312 p_nat->invalid_packets |= pkt_mask;
6313 p_nat->naptDroppedPktCount++;
6315 #ifdef CGNAPT_DEBUGGING
6316 p_nat->naptDroppedPktCount4++;
6320 arp_pkts_mask |= pkt_mask;
6321 nd_queue_unresolved_packet(ret_nd_data, pkt);
6331 convert_ipv4_to_ipv6(pkt, &ipv4_hdr);
6333 /* Ethernet MTU check */
6334 if ((rte_pktmbuf_data_len(pkt) - 14) > 1500) {
6335 p_nat->invalid_packets |= pkt_mask;
6336 p_nat->naptDroppedPktCount++;
6339 uint32_t *dst_addr =
6340 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4t6);
6341 uint16_t *dst_port =
6342 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP4t6);
6344 memcpy((uint8_t *) &dst_addr[0], &entry->data.u.prv_ipv6[0],
6347 #ifdef NAT_ONLY_CONFIG_REQ
6348 if (!nat_only_config_flag) {
6350 *dst_port = rte_bswap16(entry->data.prv_port);
6352 #ifdef NAT_ONLY_CONFIG_REQ
6356 p_nat->inaptedPktCount++;
6359 p_nat->naptedPktCount++;
6362 if (p_nat->hw_checksum_reqd)
6363 hw_checksum(pkt, pkt_type);
6365 sw_checksum(pkt, pkt_type);
6371 * NAPT function for IPv6 private traffic which handles 4 pkts
6374 * A pointer to array of packets mbuf
6376 * Starting pkt number of pkts
6380 * A pointer to main CGNAPT structure
6384 pkt4_work_cgnapt_ipv6_prv(
6385 struct rte_mbuf **pkts,
6386 uint32_t in_pkt_num,
6387 __rte_unused void *arg,
6388 struct pipeline_cgnapt *p_nat)
6390 struct rte_mbuf *pkt;
6394 enum PKT_TYPE pkt_type = PKT_TYPE_IPV6to4;
6396 for (i = 0; i < 4; i++) {
6397 pkt_num = in_pkt_num + i;
6400 /* index into hash table entries */
6401 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6402 /*bitmask representing only this packet */
6403 uint64_t pkt_mask = 1LLU << pkt_num;
6405 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
6406 uint32_t dest_if = INVALID_DESTIF;
6407 uint16_t *outport_id =
6408 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6409 struct cgnapt_table_entry *entry = NULL;
6411 if (hash_table_entry < 0) {
6413 /* try to add new entry */
6414 struct rte_pipeline_table_entry *table_entry = NULL;
6417 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
6419 &p_nat->valid_packets, pkt_num,
6423 /* ICMP Error message generation for
6424 * Destination Host unreachable
6426 /* Do we need this check for ipv6? */
6427 if (protocol == IP_PROTOCOL_ICMP) {
6428 cgnapt_icmp_pkt = pkt;
6429 send_icmp_dest_unreachable_msg();
6432 /* Drop packet by adding to invalid pkt mask */
6434 p_nat->invalid_packets |= dropmask;
6436 #ifdef CGNAPT_DEBUGGING
6437 if (p_nat->kpc2++ < 5) {
6438 printf("in_ah Th: %d",
6439 p_nat->pipeline_num);
6440 print_key(p_nat->key_ptrs[pkt_num]);
6444 p_nat->naptDroppedPktCount++;
6446 #ifdef CGNAPT_DEBUGGING
6447 p_nat->naptDroppedPktCount3++;
6453 entry = (struct cgnapt_table_entry *)table_entry;
6455 /* entry found for this packet */
6456 entry = &napt_hash_tbl_entries[hash_table_entry];
6459 /* apply napt and mac changes */
6461 p_nat->entries[pkt_num] = &(entry->head);
6463 struct ipv6_hdr ipv6_hdr;
6464 uint32_t dest_address = 0;
6465 uint8_t nh_ipv6[16];
6470 convert_ipv6_to_ipv4(pkt, &ipv6_hdr);
6472 #ifdef CGNAPT_DBG_PRNT
6473 if (CGNAPT_DEBUG >= 1)
6474 printf("pkt_work_cganpt: "
6475 "convert_ipv6_to_ipv4\n");
6478 struct cgnapt_nsp_node *ll = nsp_ll;
6481 while (ll != NULL) {
6482 if (!memcmp(&ipv6_hdr.dst_addr[0],
6484 ll->nsp.depth / 8)) {
6492 && !memcmp(&ipv6_hdr.dst_addr[0],
6493 &well_known_prefix[0], 12)) {
6498 p_nat->invalid_packets |= pkt_mask;
6499 p_nat->naptDroppedPktCount++;
6501 #ifdef CGNAPT_DEBUGGING
6502 p_nat->naptDroppedPktCount5++;
6509 /* As packet is already converted into IPv4 we must not
6510 * operate IPv6 offsets on packet only perform IPv4 operations
6513 uint32_t *src_addr =
6514 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP6t4);
6515 uint32_t *dst_addr =
6516 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP6t4);
6517 uint16_t *src_port =
6518 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP6t4);
6519 uint16_t *dst_port =
6520 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP6t4);
6523 RTE_MBUF_METADATA_UINT8_PTR(pkt, ETH_OFST_IP6t4);
6525 RTE_MBUF_METADATA_UINT8_PTR(pkt, ETH_OFST_IP6t4 + 6);
6527 if (entry->data.ttl == NAPT_ENTRY_STALE)
6528 entry->data.ttl = NAPT_ENTRY_VALID;
6533 if (unlikely(protocol == IP_PROTOCOL_UDP
6534 && rte_be_to_cpu_16(*dst_port) == 53)) {
6535 p_nat->invalid_packets |= pkt_mask;
6536 p_nat->naptDroppedPktCount++;
6538 #ifdef CGNAPT_DEBUGGING
6539 p_nat->naptDroppedPktCount6++;
6544 dest_address = rte_bswap32(*dst_addr);
6547 #ifdef CGNAPT_DBG_PRNT
6548 if (CGNAPT_DEBUG > 2)
6549 printf("Egress: \tphy_port:%d\t"
6550 "get_prv_to_pub():%d \tout_port:%d\n",
6551 pkt->port, dest_if, *outport_id);
6555 #ifdef CGNAPT_DEBUGGING
6556 static int static_count;
6558 if (static_count++ < 10) {
6560 my_print_entry(entry);
6561 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6562 printf("dest_add:%x\n", entry->data.u.prv_ip);
6563 printf("dest_add:%x\n", *dst_addr);
6564 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6568 memset(nh_ipv6, 0, 16);
6571 struct arp_entry_data *ret_arp_data;
6572 uint32_t src_phy_port = *src_port;
6574 gw_get_nh_port_ipv4(dest_address, &dest_if, &nhip);
6576 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if,
6577 (struct ether_addr *)eth_dest);
6578 *outport_id = p_nat->outport_id[dest_if];
6580 if (arp_cache_dest_mac_present(dest_if)) {
6581 ether_addr_copy(get_link_hw_addr(dest_if),
6582 (struct ether_addr *)eth_src);
6583 update_nhip_access(dest_if);
6584 if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) {
6585 p_nat->naptedPktCount += ret_arp_data->num_pkts;
6586 arp_send_buffered_pkts(ret_arp_data,
6587 (struct ether_addr *)eth_dest, *outport_id);
6592 if (unlikely(ret_arp_data == NULL)) {
6594 #ifdef CGNAPT_DEBUGGING
6595 printf("%s: NHIP Not Found, nhip:%x , "
6596 "outport_id: %d\n", __func__, nhip,
6601 p_nat->invalid_packets |= pkt_mask;
6602 p_nat->naptDroppedPktCount++;
6604 #ifdef CGNAPT_DEBUGGING
6605 p_nat->naptDroppedPktCount4++;
6610 if (ret_arp_data->status == INCOMPLETE ||
6611 ret_arp_data->status == PROBE) {
6612 if (ret_arp_data->num_pkts >= NUM_DESC) {
6614 p_nat->invalid_packets |= pkt_mask;
6615 p_nat->naptDroppedPktCount++;
6617 #ifdef CGNAPT_DEBUGGING
6618 p_nat->naptDroppedPktCount4++;
6622 arp_pkts_mask |= pkt_mask;
6623 arp_queue_unresolved_packet(ret_arp_data, pkt);
6633 *src_addr = rte_bswap32(entry->data.pub_ip);
6635 #ifdef NAT_ONLY_CONFIG_REQ
6636 if (!nat_only_config_flag) {
6638 *src_port = rte_bswap16(entry->data.pub_port);
6640 #ifdef NAT_ONLY_CONFIG_REQ
6644 p_nat->enaptedPktCount++;
6647 p_nat->naptedPktCount++;
6650 if (p_nat->hw_checksum_reqd)
6651 hw_checksum(pkt, pkt_type);
6653 sw_checksum(pkt, pkt_type);
6659 * NAPT function for IPv6 public traffic which handles 4 pkts
6662 * A pointer to array of packets mbuf
6664 * Starting pkt number of pkts
6668 * A pointer to main CGNAPT structure
6672 pkt4_work_cgnapt_ipv6_pub(
6673 struct rte_mbuf **pkts,
6674 uint32_t in_pkt_num,
6675 __rte_unused void *arg,
6676 struct pipeline_cgnapt *p_nat)
6678 struct rte_mbuf *pkt;
6682 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4to6;
6684 for (i = 0; i < 4; i++) {
6685 pkt_num = in_pkt_num + i;
6688 /* index into hash table entries */
6689 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6690 /*bitmask representing only this packet */
6691 uint64_t pkt_mask = 1LLU << pkt_num;
6693 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
6694 uint16_t *outport_id =
6695 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6696 struct cgnapt_table_entry *entry = NULL;
6698 if (hash_table_entry < 0) {
6700 /* Drop ingress initial traffic */
6702 p_nat->invalid_packets |= pkt_mask;
6703 p_nat->naptDroppedPktCount++;
6704 #ifdef CGNAPT_DEBUGGING
6705 p_nat->naptDroppedPktCount3++;
6706 if (p_nat->kpc2++ < 5) {
6707 printf("in_ah Th: %d", p_nat->pipeline_num);
6708 print_key(p_nat->key_ptrs[pkt_num]);
6715 /* entry found for this packet */
6716 entry = &napt_hash_tbl_entries[hash_table_entry];
6719 /* apply napt and mac changes */
6721 p_nat->entries[pkt_num] = &(entry->head);
6722 if (entry->data.type != CGNAPT_ENTRY_IPV6) {
6723 p_nat->invalid_packets |= pkt_mask;
6724 p_nat->naptDroppedPktCount++;
6728 struct ipv4_hdr ipv4_hdr;
6730 uint16_t *src_port =
6731 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP4_TCP);
6734 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
6736 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
6738 if (entry->data.ttl == NAPT_ENTRY_STALE)
6739 entry->data.ttl = NAPT_ENTRY_VALID;
6741 struct ether_addr hw_addr;
6742 uint8_t dest_addr_ipv6[16];
6743 uint8_t nh_ipv6[16];
6744 uint32_t dest_if = INVALID_DESTIF;
6745 { /*start of Ingress */
6747 if (unlikely(protocol == IP_PROTOCOL_UDP
6748 && rte_be_to_cpu_16(*src_port) == 53)) {
6749 p_nat->invalid_packets |= pkt_mask;
6750 p_nat->naptDroppedPktCount++;
6751 #ifdef CGNAPT_DEBUGGING
6752 p_nat->naptDroppedPktCount6++;
6757 memcpy(&dest_addr_ipv6[0], &entry->data.u.prv_ipv6[0],
6760 }/* end of ingress */
6762 #ifdef CGNAPT_DEBUGGING
6763 static int static_count;
6765 if (static_count++ < 10) {
6767 my_print_entry(entry);
6768 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6769 printf("dest_add:%x\n", entry->data.u.prv_ip);
6770 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6774 memset(nh_ipv6, 0, 16);
6775 struct nd_entry_data *ret_nd_data = NULL;
6776 dest_if = INVALID_DESTIF;
6778 uint32_t src_phy_port = pkt->port;
6780 gw_get_nh_port_ipv6((uint8_t *) &dest_addr_ipv6[0],
6781 &dest_if, &nh_ipv6[0]);
6783 ret_nd_data = get_dest_mac_addr_ipv6(&nh_ipv6[0],
6784 dest_if, (struct ether_addr *)eth_dest);
6785 *outport_id = p_nat->outport_id[dest_if];
6787 if (nd_cache_dest_mac_present(dest_if)) {
6788 ether_addr_copy(get_link_hw_addr(dest_if),
6789 (struct ether_addr *)eth_src);
6790 update_nhip_access(dest_if);
6792 if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) {
6793 p_nat->naptedPktCount += ret_nd_data->num_pkts;
6794 nd_send_buffered_pkts(ret_nd_data,
6795 (struct ether_addr *)eth_dest, *outport_id);
6798 if (unlikely(ret_nd_data == NULL)) {
6800 #ifdef CGNAPT_DEBUGGING
6801 printf("%s: NHIP Not Found "
6802 "outport_id: %d\n", __func__,
6807 p_nat->invalid_packets |= pkt_mask;
6808 p_nat->naptDroppedPktCount++;
6810 #ifdef CGNAPT_DEBUGGING
6811 p_nat->naptDroppedPktCount4++;
6816 if (ret_nd_data->status == INCOMPLETE ||
6817 ret_nd_data->status == PROBE) {
6819 if (ret_nd_data->num_pkts >= NUM_DESC) {
6821 p_nat->invalid_packets |= pkt_mask;
6822 p_nat->naptDroppedPktCount++;
6824 #ifdef CGNAPT_DEBUGGING
6825 p_nat->naptDroppedPktCount4++;
6829 arp_pkts_mask |= pkt_mask;
6830 nd_queue_unresolved_packet(ret_nd_data, pkt);
6838 /* start of Ingress */
6840 convert_ipv4_to_ipv6(pkt, &ipv4_hdr);
6842 /* Ethernet MTU check */
6843 if ((rte_pktmbuf_data_len(pkt) - 14) > 1500) {
6844 p_nat->invalid_packets |= pkt_mask;
6845 p_nat->naptDroppedPktCount++;
6848 uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
6849 DST_ADR_OFST_IP4t6);
6850 uint16_t *dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
6851 DST_PRT_OFST_IP4t6);
6853 memcpy((uint8_t *) &dst_addr[0],
6854 &entry->data.u.prv_ipv6[0], 16);
6856 #ifdef NAT_ONLY_CONFIG_REQ
6857 if (!nat_only_config_flag) {
6859 *dst_port = rte_bswap16(entry->data.prv_port);
6861 #ifdef NAT_ONLY_CONFIG_REQ
6865 p_nat->inaptedPktCount++;
6866 } /* end of ingress */
6868 p_nat->naptedPktCount++;
6871 if (p_nat->hw_checksum_reqd)
6872 hw_checksum(pkt, pkt_type);
6874 sw_checksum(pkt, pkt_type);
6876 } /* end of for loop */
6880 * Input port handler for IPv6 private traffic
6881 * Starting from the packet burst it filters unwanted packets,
6882 * calculates keys, does lookup and then based on the lookup
6883 * updates NAPT table and does packet NAPT translation.
6886 * A pointer to struct rte_pipeline
6888 * A pointer to array of packets mbuf
6890 * Number of packets in the burst
6895 * int that is not checked by caller
6897 static int cgnapt_in_port_ah_ipv6_prv(struct rte_pipeline *rte_p,
6898 struct rte_mbuf **pkts,
6899 uint32_t n_pkts, void *arg)
6902 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
6903 struct pipeline_cgnapt *p_nat = ap->p;
6905 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
6906 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
6907 p_nat->invalid_packets = 0;
6910 #ifdef CGNAPT_DBG_PRNT
6911 if (CGNAPT_DEBUG > 1)
6912 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
6915 /* prefetching for mbufs should be done here */
6916 for (j = 0; j < n_pkts; j++)
6917 rte_prefetch0(pkts[j]);
6919 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
6920 pkt4_work_cgnapt_key_ipv6_prv(&pkts[i], i, arg, p_nat);
6922 for (; i < n_pkts; i++)
6923 pkt_work_cgnapt_key_ipv6_prv(pkts[i], i, arg, p_nat);
6925 p_nat->valid_packets &= ~(p_nat->invalid_packets);
6927 if (arp_pkts_mask) {
6928 p_nat->valid_packets &= ~(arp_pkts_mask);
6929 rte_pipeline_ah_packet_hijack(rte_p, arp_pkts_mask);
6932 if (unlikely(p_nat->valid_packets == 0)) {
6933 /* no suitable packet for lookup */
6934 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
6935 return p_nat->valid_packets;
6938 /* lookup entries in the common napt table */
6940 int lookup_result = rte_hash_lookup_bulk(
6942 (const void **) &p_nat->key_ptrs,
6943 /* should be minus num invalid pkts */
6945 /*new pipeline data member */
6946 &p_nat->lkup_indx[0]);
6948 if (unlikely(lookup_result < 0)) {
6949 /* unknown error, just discard all packets */
6950 printf("Unexpected hash lookup error %d, "
6951 "discarding all packets",
6953 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
6957 /* Now call second stage of pipeline to one by one
6958 * check the result of our bulk lookup
6961 /* prefetching for table entries should be done here */
6962 for (j = 0; j < n_pkts; j++) {
6963 if (p_nat->lkup_indx[j] >= 0)
6964 rte_prefetch0(&napt_hash_tbl_entries
6965 [p_nat->lkup_indx[j]]);
6968 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
6969 pkt4_work_cgnapt_ipv6_prv(&pkts[i], i, arg, p_nat);
6971 for (; i < n_pkts; i++)
6972 pkt_work_cgnapt_ipv6_prv(pkts[i], i, arg, p_nat);
6974 if (p_nat->invalid_packets) {
6975 /* get rid of invalid packets */
6976 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
6978 p_nat->valid_packets &= ~(p_nat->invalid_packets);
6980 #ifdef CGNAPT_DBG_PRNT
6981 if (CGNAPT_DEBUG > 1) {
6982 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
6983 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
6984 printf("invalid_packets:0x%jx\n",
6985 p_nat->invalid_packets);
6986 printf("rte_invalid_packets :0x%jx\n",
6987 rte_p->pkts_drop_mask);
6988 printf("Total pkts dropped :0x%jx\n",
6989 rte_p->n_pkts_ah_drop);
6994 return p_nat->valid_packets;
6999 * Input port handler for IPv6 public traffic
7000 * Starting from the packet burst it filters unwanted packets,
7001 * calculates keys, does lookup and then based on the lookup
7002 * updates NAPT table and does packet NAPT translation.
7005 * A pointer to struct rte_pipeline
7007 * A pointer to array of packets mbuf
7009 * Number of packets in the burst
7014 * int that is not checked by caller
7016 static int cgnapt_in_port_ah_ipv6_pub(struct rte_pipeline *rte_p,
7017 struct rte_mbuf **pkts,
7018 uint32_t n_pkts, void *arg)
7021 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
7022 struct pipeline_cgnapt *p_nat = ap->p;
7024 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
7025 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
7026 p_nat->invalid_packets = 0;
7029 #ifdef CGNAPT_DBG_PRNT
7030 if (CGNAPT_DEBUG > 1)
7031 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
7034 /* prefetching for mbufs should be done here */
7035 for (j = 0; j < n_pkts; j++)
7036 rte_prefetch0(pkts[j]);
7038 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7039 pkt4_work_cgnapt_key_ipv6_pub(&pkts[i], i, arg, p_nat);
7041 for (; i < n_pkts; i++)
7042 pkt_work_cgnapt_key_ipv6_pub(pkts[i], i, arg, p_nat);
7044 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7046 if (arp_pkts_mask) {
7047 p_nat->valid_packets &= ~(arp_pkts_mask);
7048 rte_pipeline_ah_packet_hijack(rte_p, arp_pkts_mask);
7051 if (unlikely(p_nat->valid_packets == 0)) {
7052 /* no suitable packet for lookup */
7053 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7054 return p_nat->valid_packets;
7057 /* lookup entries in the common napt table */
7059 int lookup_result = rte_hash_lookup_bulk(
7061 (const void **) &p_nat->key_ptrs,
7062 /* should be minus num invalid pkts */
7064 /*new pipeline data member */
7065 &p_nat->lkup_indx[0]);
7067 if (unlikely(lookup_result < 0)) {
7068 /* unknown error, just discard all packets */
7069 printf("Unexpected hash lookup error %d, "
7070 "discarding all packets",
7072 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
7076 /* Now call second stage of pipeline to one by one
7077 * check the result of our bulk lookup
7080 /* prefetching for table entries should be done here */
7081 for (j = 0; j < n_pkts; j++) {
7082 if (p_nat->lkup_indx[j] >= 0)
7083 rte_prefetch0(&napt_hash_tbl_entries
7084 [p_nat->lkup_indx[j]]);
7087 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7088 pkt4_work_cgnapt_ipv6_pub(&pkts[i], i, arg, p_nat);
7090 for (; i < n_pkts; i++)
7091 pkt_work_cgnapt_ipv6_pub(pkts[i], i, arg, p_nat);
7093 if (p_nat->invalid_packets) {
7094 /* get rid of invalid packets */
7095 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7097 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7099 #ifdef CGNAPT_DBG_PRNT
7100 if (CGNAPT_DEBUG > 1) {
7101 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
7102 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
7103 printf("invalid_packets:0x%jx\n",
7104 p_nat->invalid_packets);
7105 printf("rte_invalid_packets :0x%jx\n",
7106 rte_p->pkts_drop_mask);
7107 printf("Total pkts dropped :0x%jx\n",
7108 rte_p->n_pkts_ah_drop);
7113 return p_nat->valid_packets;
7117 * Function to send ICMP dest unreachable msg
7120 void send_icmp_dest_unreachable_msg(void)
7123 struct ether_hdr *eth_h;
7124 struct ipv4_hdr *ip_h;
7125 struct icmp_hdr *icmp_h;
7126 struct rte_mbuf *icmp_pkt = cgnapt_icmp_pkt;
7128 if (icmp_pkt == NULL) {
7130 printf("Error allocating icmp_pkt rte_mbuf\n");
7134 port_id = icmp_pkt->port;
7136 struct app_link_params *link;
7137 link = &mylink[port_id];
7138 eth_h = rte_pktmbuf_mtod(icmp_pkt, struct ether_hdr *);
7139 ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
7140 icmp_h = (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
7142 struct ether_addr gw_addr;
7143 struct ether_addr dst_addr;
7144 ether_addr_copy(ð_h->s_addr, &dst_addr);
7145 rte_eth_macaddr_get(port_id, &gw_addr);
7146 ether_addr_copy(&gw_addr, ð_h->s_addr);
7147 ether_addr_copy(&dst_addr, ð_h->d_addr);
7149 eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
7150 ip_h->version_ihl = IP_VHL_DEF;
7151 ip_h->type_of_service = 0;
7152 ip_h->total_length = rte_cpu_to_be_16(sizeof(struct ipv4_hdr) +
7153 sizeof(struct icmp_hdr));
7154 ip_h->packet_id = 0xaabb;
7155 ip_h->fragment_offset = 0x0000;
7156 ip_h->time_to_live = 64;
7157 ip_h->next_proto_id = 1;
7160 uint32_t src_addr_offset =
7161 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_SRC_ADR_OFST;
7163 RTE_MBUF_METADATA_UINT32_PTR(cgnapt_icmp_pkt, src_addr_offset);
7165 ip_h->dst_addr = *src_addr;
7166 ip_h->src_addr = rte_bswap32(link->ip);
7168 ip_h->dst_addr = *src_addr;
7169 ip_h->src_addr = rte_bswap32(link->ip);
7171 ip_h->hdr_checksum = 0;
7172 ip_h->hdr_checksum = rte_ipv4_cksum(ip_h);
7173 icmp_h->icmp_type = 3; /* Destination Unreachable */
7174 icmp_h->icmp_code = 13; /* Communication administratively prohibited */
7176 icmp_h->icmp_cksum = ~rte_raw_cksum(icmp_h, sizeof(struct icmp_hdr));
7178 icmp_pkt->pkt_len = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
7179 sizeof(struct icmp_hdr);
7180 icmp_pkt->data_len = icmp_pkt->pkt_len;
7181 if (ARPICMP_DEBUG) {
7182 printf("Sending ICMP error message - "
7183 "Destination Unreachable\n");
7185 rte_pipeline_port_out_packet_insert(myP, port_id, icmp_pkt);
7189 * Function to add a dynamic NAPT entry pair
7192 * A pointer to struct pipeline
7194 * A pointer to struct pipeline_cgnapt_entry_key
7196 * expairy time of an dynamic or PCP req entry
7198 * uint8_t pointer of source address
7201 * A pointer to struct cgnapt_table_entry for added entry
7204 struct cgnapt_table_entry *add_dynamic_cgnapt_entry(
7206 struct pipeline_cgnapt_entry_key *key,
7213 void *entry_ptr, *ret_ptr;
7216 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
7218 #ifdef CGNAPT_DBG_PRNT
7219 if (CGNAPT_DEBUG >= 1) {
7220 printf("Th%d add_dynamic_cgnapt_entry key detail Entry:"
7221 "0x%x, %d, %d\n", p_nat->pipeline_num, key->ip, key->port,
7226 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX && i < p_nat->pkt_burst_cnt;
7228 if (p_nat->cgnapt_dyn_ent_table[i].ip == key->ip
7229 && p_nat->cgnapt_dyn_ent_table[i].port == key->port
7230 && p_nat->cgnapt_dyn_ent_table[i].pid == key->pid) {
7232 #ifdef CGNAPT_DBG_PRNT
7233 if (CGNAPT_DEBUG > 1)
7234 printf("add_dynamic_cgnapt_entry:pkt_burst "
7235 "array key matched!!!\n");
7238 return &napt_hash_tbl_entries
7239 [p_nat->cgnapt_dyn_ent_index[i]];
7243 #ifdef NAT_ONLY_CONFIG_REQ
7244 if (!nat_only_config_flag) {
7247 ret = increment_max_port_counter(key->ip, key->pid, p_nat);
7248 if (ret == MAX_PORT_INC_ERROR) {
7250 #ifdef CGNAPT_DEBUGGING
7251 p_nat->missedpktcount5++;
7254 #ifdef CGNAPT_DBG_PRNT
7255 if (CGNAPT_DEBUG > 1)
7256 printf("add_dynamic_cgnapt_entry:"
7257 "increment_max_port_counter-1 failed\n");
7264 if (ret == MAX_PORT_INC_REACHED) {
7266 #ifdef CGNAPT_DEBUGGING
7267 p_nat->missedpktcount6++;
7270 #ifdef CGNAPT_DBG_PRNT
7271 if (CGNAPT_DEBUG > 1)
7272 printf("add_dynamic_cgnapt_entry:"
7273 "increment_max_port_counter-2 failed\n");
7280 #ifdef NAT_ONLY_CONFIG_REQ
7285 port_num = get_free_iport(p_nat, &public_ip);
7287 if (port_num == -1) {
7289 #ifdef CGNAPT_DBG_PRNT
7290 if (CGNAPT_DEBUG > 2) {
7291 printf("add_dynamic_cgnapt_entry: %d\n", port_num);
7292 printf("add_dynamic_cgnapt_entry key detail:0x%x, "
7293 "%d, %d\n", key->ip, key->port, key->pid);
7297 #ifdef CGNAPT_DEBUGGING
7298 p_nat->missedpktcount7++;
7305 #ifdef NAT_ONLY_CONFIG_REQ
7306 if (!nat_only_config_flag) {
7309 if (ret == 2) { //MPPC_NEW_ENTRY
7311 /* check for max_clients_per_ip */
7312 if (rte_atomic16_read
7314 [rte_jhash(&public_ip, 4, 0) %
7315 CGNAPT_MAX_PUB_IP].count) ==
7316 p_nat->max_clients_per_ip) {
7318 /* For now just bail out
7319 * In future we can think about
7320 * retrying getting a new iport
7323 release_iport(port_num, public_ip, p_nat);
7325 #ifdef CGNAPT_DEBUGGING
7326 p_nat->missedpktcount10++;
7332 rte_atomic16_inc(&all_public_ip
7333 [rte_jhash(&public_ip, 4, 0) %
7334 CGNAPT_MAX_PUB_IP].count);
7336 #ifdef CGNAPT_DBG_PRNT
7337 if ((rte_jhash(&public_ip, 4, 0) %
7338 CGNAPT_MAX_PUB_IP) == 8)
7339 printf("pub ip:%x coutn:%d\n", public_ip,
7340 rte_atomic16_read(&all_public_ip
7341 [rte_jhash(&public_ip, 4, 0) %
7342 CGNAPT_MAX_PUB_IP].count));
7346 #ifdef NAT_ONLY_CONFIG_REQ
7350 #ifdef CGNAPT_DBG_PRNT
7351 if (CGNAPT_DEBUG > 0) {
7352 printf("add_dynamic_cgnapt_entry: %d\n",
7354 printf("add_dynamic_cgnapt_entry key detail: "
7355 "0x%x, %d, %d\n", key->ip, key->port, key->pid);
7359 struct cgnapt_table_entry entry = {
7361 .action = RTE_PIPELINE_ACTION_PORT,
7362 /* made it configurable below */
7363 {.port_id = p->port_out_id[0]},
7367 .prv_port = key->port,
7368 .pub_ip = public_ip,
7369 .pub_port = port_num,
7370 .prv_phy_port = key->pid,
7371 .pub_phy_port = get_pub_to_prv_port(
7375 /* if(timeout == -1) : static entry
7376 * if(timeout == 0 ) : dynamic entry
7377 * if(timeout > 0 ) : PCP requested entry
7379 .timeout = timeout > 0 ? timeout : 0,
7386 #ifdef NAT_ONLY_CONFIG_REQ
7387 if (nat_only_config_flag) {
7388 entry.data.prv_port = 0xffff;
7389 entry.data.pub_port = 0xffff;
7393 if (pkt_type == CGNAPT_ENTRY_IPV6) {
7394 entry.data.type = CGNAPT_ENTRY_IPV6;
7395 memcpy(&entry.data.u.prv_ipv6[0], src_addr, 16);
7397 entry.data.u.prv_ip = key->ip;
7398 entry.data.type = CGNAPT_ENTRY_IPV4;
7401 //entry.head.port_id = CGNAPT_PUB_PORT_ID; /* outgoing port info */
7402 entry.head.port_id = entry.data.pub_phy_port; /* outgoing port info */
7404 struct pipeline_cgnapt_entry_key second_key;
7405 /* Need to add a second ingress entry */
7406 second_key.ip = public_ip;
7407 second_key.port = port_num;
7408 second_key.pid = 0xffff;
7410 #ifdef NAT_ONLY_CONFIG_REQ
7411 if (nat_only_config_flag)
7412 second_key.port = 0xffff;
7415 #ifdef CGNAPT_DBG_PRNT
7416 if (CGNAPT_DEBUG > 2)
7417 printf("add_dynamic_cgnapt_entry second key detail:"
7418 "0x%x, %d, %d\n", second_key.ip, second_key.port,
7422 int32_t position = rte_hash_add_key(napt_common_table, (void *)key);
7425 #ifdef CGNAPT_DEBUGGING
7426 p_nat->missedpktcount8++;
7429 printf("CG-NAPT entry add failed ...returning "
7430 "without adding ... %d\n", position);
7435 #ifdef CGNAPT_DBG_PRNT
7437 printf("add_dynamic_cgnapt_entry\n");
7439 print_cgnapt_entry(&entry);
7443 memcpy(&napt_hash_tbl_entries[position], &entry,
7444 sizeof(struct cgnapt_table_entry));
7446 /* this pointer is returned to pkt miss function */
7447 ret_ptr = &napt_hash_tbl_entries[position];
7449 p_nat->n_cgnapt_entry_added++;
7450 p_nat->dynCgnaptCount++;
7452 /* Now modify the forward port for reverse entry */
7454 /* outgoing port info */
7455 //entry.head.port_id = CGNAPT_PRV_PORT_ID;
7456 /* outgoing port info */
7457 entry.head.port_id = entry.data.prv_phy_port;
7459 int32_t position2 = rte_hash_add_key(napt_common_table, &second_key);
7461 if (position2 < 0) {
7462 #ifdef CGNAPT_DEBUGGING
7463 p_nat->missedpktcount9++;
7465 printf("CG-NAPT entry reverse bulk add failed ..."
7466 "returning with fwd add ...%d\n",
7472 memcpy(&napt_hash_tbl_entries[position2], &entry,
7473 sizeof(struct cgnapt_table_entry));
7475 entry_ptr = &napt_hash_tbl_entries[position2];
7477 timer_thread_enqueue(key, &second_key, ret_ptr,
7478 entry_ptr, (struct pipeline *)p_nat);
7480 p_nat->n_cgnapt_entry_added++;
7481 p_nat->dynCgnaptCount++;
7483 if (p_nat->pkt_burst_cnt < RTE_PORT_IN_BURST_SIZE_MAX) {
7484 memcpy(&p_nat->cgnapt_dyn_ent_table[p_nat->pkt_burst_cnt], key,
7485 sizeof(struct pipeline_cgnapt_entry_key));
7486 p_nat->cgnapt_dyn_ent_index[p_nat->pkt_burst_cnt] = position;
7487 p_nat->pkt_burst_cnt++;
7492 int pkt_miss_cgnapt_count;
7494 * Function handle a missed NAPT entry lookup
7495 * Will attempt to add a dynamic entry pair.
7498 * A pointer to struct pipeline
7500 * A pointer to struct pipeline_cgnapt_entry_key
7502 * A pointer to pkt struct rte_mbuf
7504 * uint64_t pointer to pkt mask
7505 * @param table_entry
7506 * A pointer to struct rte_pipeline_table_entry to be created and returned
7508 * number of this pkt in current burst
7511 * A uint64_t mask for drop packets
7514 pkt_miss_cgnapt(struct pipeline_cgnapt_entry_key *key,
7515 struct rte_mbuf *pkt,
7516 struct rte_pipeline_table_entry **table_entry,
7517 __rte_unused uint64_t *pkts_mask,
7518 uint32_t pkt_num, void *arg)
7521 #ifdef CGNAPT_DBG_PRNT
7522 if (CGNAPT_DEBUG > 0)
7523 printf("\n pkt_miss_cgnapt\n");
7527 * see if get_port passes for this src address
7528 * if passed add a new egress entry and a
7529 * corresponding new ingress entry
7530 * return the fwd entry to calling function using input pointer
7531 * else if get_port fails drop packet
7534 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)arg;
7536 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
7537 uint32_t src_addr_offset_ipv6 =
7538 MBUF_HDR_ROOM + ETH_HDR_SIZE + IPV6_HDR_SRC_ADR_OFST;
7539 uint16_t phy_port = pkt->port;
7541 uint16_t *eth_proto =
7542 RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
7544 uint8_t *src_addr = NULL;
7545 uint8_t src_addr_ipv6[16];
7546 uint8_t pkt_type = CGNAPT_ENTRY_IPV4;
7547 /* To drop the packet */
7548 uint64_t drop_mask = 0;
7550 if (p_nat->is_static_cgnapt) {
7551 drop_mask |= 1LLU << pkt_num;
7552 p_nat->missedPktCount++;
7554 #ifdef CGNAPT_DEBUGGING
7555 p_nat->missedpktcount1++;
7560 if (rte_be_to_cpu_16(*eth_proto) == ETHER_TYPE_IPv6) {
7562 RTE_MBUF_METADATA_UINT8_PTR(pkt, src_addr_offset_ipv6);
7563 pkt_type = CGNAPT_ENTRY_IPV6;
7564 memcpy(src_addr_ipv6, src_addr, 16);
7569 /* some validation first */
7570 if (is_phy_port_privte(phy_port)) {
7571 /* dynamic NAPT entry creation */
7572 *table_entry = (struct rte_pipeline_table_entry *)
7573 add_dynamic_cgnapt_entry(
7574 (struct pipeline *)&p_nat->p,
7576 DYNAMIC_CGNAPT_TIMEOUT,
7578 src_addr_ipv6, &err);
7580 if (!(*table_entry)) {
7582 drop_mask |= 1LLU << pkt_num;
7583 p_nat->missedPktCount++;
7585 #ifdef CGNAPT_DEBUGGING
7586 p_nat->missedpktcount2++;
7589 #ifdef CGNAPT_DBG_PRNT
7590 if (CGNAPT_DEBUG > 1)
7591 printf("Add Dynamic NAT entry failed "
7595 #ifdef CGNAPT_DEBUGGING
7596 p_nat->missedpktcount11++;
7601 } else if (!is_phy_port_privte(phy_port)) {
7603 #ifdef CGNAPT_DBG_PRNT
7604 if (CGNAPT_DEBUG >= 2) {
7605 printf("Initial Ingress entry creation NOT ALLOWED "
7610 drop_mask |= 1LLU << pkt_num;
7611 p_nat->missedPktCount++;
7613 #ifdef CGNAPT_DEBUGGING
7614 p_nat->missedpktcount3++;
7618 #ifdef CGNAPT_DBG_PRNT
7619 if (CGNAPT_DEBUG > 1)
7620 printf("NOT a PRIVATE or PUBLIC port!!!!!\n");
7623 drop_mask |= 1LLU << pkt_num;
7624 p_nat->missedPktCount++;
7626 #ifdef CGNAPT_DEBUGGING
7627 p_nat->missedpktcount4++;
7631 #ifdef CGNAPT_DBG_PRNT
7632 if (CGNAPT_DEBUG > 5)
7642 * Function to print the contents of a packet
7645 * A pointer to pkt struct rte_mbuf
7647 void print_pkt(struct rte_mbuf *pkt)
7651 printf("\nPacket Contents:\n");
7653 uint8_t *rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
7655 for (i = 0; i < 20; i++) {
7656 for (j = 0; j < 20; j++)
7657 printf("%02x ", rd[(20 * i) + j]);
7663 rte_table_hash_op_hash cgnapt_hash_func[] = {
7675 * Function to parse incoming pipeline arguments
7676 * Called during pipeline initialization
7679 * A pointer to struct pipeline_cgnapt
7681 * A pointer to struct pipeline_params
7684 * 0 if success, negative if failure
7687 pipeline_cgnapt_parse_args(struct pipeline_cgnapt *p,
7688 struct pipeline_params *params)
7690 uint32_t n_flows_present = 0;
7691 uint32_t key_offset_present = 0;
7692 uint32_t key_size_present = 0;
7693 uint32_t hash_offset_present = 0;
7694 uint32_t n_entries_present = 0;
7695 uint32_t max_port_present = 0;
7696 uint32_t max_client_present = 0;
7697 uint32_t public_ip_range_present = 0;
7698 uint32_t public_ip_port_range_present = 0;
7700 uint8_t public_ip_count = 0;
7701 uint8_t public_ip_range_count = 0;
7702 uint8_t dest_if_offset_present = 0;
7703 uint8_t cgnapt_meta_offset_present = 0;
7704 uint8_t prv_que_handler_present = 0;
7705 uint8_t n_prv_in_port = 0;
7707 if (CGNAPT_DEBUG > 2) {
7708 printf("CGNAPT pipeline_cgnapt_parse_args params->n_args: %d\n",
7711 for (i = 0; i < params->n_args; i++) {
7712 char *arg_name = params->args_name[i];
7713 char *arg_value = params->args_value[i];
7715 if (CGNAPT_DEBUG > 2) {
7716 printf("CGNAPT args[%d]: %s %d, %s\n", i, arg_name,
7717 atoi(arg_value), arg_value);
7719 if (strcmp(arg_name, "prv_que_handler") == 0) {
7721 if (prv_que_handler_present) {
7722 printf("Duplicate pktq_in_prv ..\n\n");
7725 prv_que_handler_present = 1;
7730 /* get the first token */
7731 token = strtok(arg_value, "(");
7732 token = strtok(token, ")");
7733 token = strtok(token, ",");
7734 printf("***** prv_que_handler *****\n");
7736 if (token == NULL) {
7737 printf("string is null\n");
7738 printf("invalid prv_que_handler value/n");
7741 printf("string is :%s\n", token);
7743 /* walk through other tokens */
7744 while (token != NULL) {
7745 printf(" %s\n", token);
7746 rxport = atoi(token);
7747 cgnapt_prv_que_port_index[n_prv_in_port++] =
7749 if (rxport < PIPELINE_MAX_PORT_IN)
7750 cgnapt_in_port_egress_prv[rxport] = 1;
7751 token = strtok(NULL, ",");
7754 if (n_prv_in_port == 0) {
7755 printf("VNF common parse err - "
7756 "no prv RX phy port\n");
7762 if (strcmp(arg_name, "cgnapt_meta_offset") == 0) {
7763 if (cgnapt_meta_offset_present) {
7764 printf("CG-NAPT parse error:");
7765 printf("cgnapt_meta_offset initizlized "
7766 "mulitple times\n");
7769 cgnapt_meta_offset_present = 1;
7771 temp = atoi(arg_value);
7774 printf("cgnapt_meta_offset is invalid :");
7775 printf("Not be more than metadata size\n");
7778 cgnapt_meta_offset = (uint16_t) temp;
7780 if (strcmp(arg_name, "vnf_set") == 0)
7783 if (strcmp(arg_name, "public_ip_range") == 0) {
7784 public_ip_range_present = 1;
7785 if (public_ip_port_range_present) {
7786 printf("CG-NAPT parse error:");
7787 printf("public_ip_range with "
7788 "public_ip_port_range_present\n");
7792 p->pub_ip_range = rte_realloc(p->pub_ip_range,
7795 RTE_CACHE_LINE_SIZE);
7797 if (!p->pub_ip_range) {
7798 printf("Memory allocation failed for "
7803 uint32_t sip = 0, eip = 0;
7805 if (sscanf(arg_value, "(%x,%x)", &sip, &eip) != 2) {
7806 printf("public_ip_range is invalid\n");
7810 if (sip <= 0 || eip <= 0 || sip >= eip) {
7811 printf("public_ip_range is invalid %x-%x\n",
7816 printf("public_ip_range: %d-%d\n",
7817 p->pub_ip_range[public_ip_range_count].
7819 p->pub_ip_range[public_ip_range_count].
7822 p->pub_ip_range_count = ++public_ip_range_count;
7826 if (strcmp(arg_name, "public_ip_port_range") == 0) {
7827 public_ip_port_range_present = 1;
7828 if (nat_only_config_flag || public_ip_range_present) {
7830 printf("CG-NAPT parse error:");
7831 printf("nat_only_config_flag OR ");
7832 printf("public_ip_range_present with "
7833 "public_ip_port_range_present\n");
7837 p->pub_ip_port_set = rte_realloc(
7839 sizeof(struct pub_ip_port_set),
7840 RTE_CACHE_LINE_SIZE);
7842 if (!p->pub_ip_port_set) {
7843 printf("Memory allocation failed for "
7851 if (sscanf(arg_value, "%x:(%d,%d)",
7852 &ip, &sp, &ep) != 3) {
7853 printf("Public IP or Port-range is invalid\n");
7857 if (ip <= 0 || sp <= 0 || ep <= 0 || sp > ep) {
7858 printf("Public IP or Port-range is invalid "
7859 "%x:%d-%d\n", ip, sp, ep);
7863 printf("public_ip: 0x%x Range:%d-%d\n",
7864 p->pub_ip_port_set[public_ip_count].ip = ip,
7865 p->pub_ip_port_set[public_ip_count].start_port = sp,
7866 p->pub_ip_port_set[public_ip_count].end_port = ep);
7868 napt_port_alloc_elem_count += (ep - sp + 1);
7869 printf("parse - napt_port_alloc_elem_count :%d\n",
7870 napt_port_alloc_elem_count);
7872 /* Store all public IPs of all CGNAPT threads
7873 * in the global variable
7875 /* to revisit indexing */
7876 all_public_ip[rte_jhash(&ip, 4, 0) %
7877 CGNAPT_MAX_PUB_IP].ip = ip;
7878 p->pub_ip_count = ++public_ip_count;
7879 printf("public_ip_count:%d hash:%d\n", public_ip_count,
7880 rte_jhash(&ip, 4, 0) % CGNAPT_MAX_PUB_IP);
7884 /* hw_checksum_reqd */
7885 if (strcmp(arg_name, "hw_checksum_reqd") == 0) {
7887 temp = atoi(arg_value);
7888 if ((temp != 0) && (temp != 1)) {
7889 printf("hw_checksum_reqd is invalid\n");
7892 p->hw_checksum_reqd = temp;
7896 /* nat_only_config_flag */
7897 if (strcmp(arg_name, "nat_only_config_flag") == 0) {
7898 nat_only_config_flag = 1;
7899 if (public_ip_port_range_present) {
7901 printf("CG-NAPT parse error:");
7902 printf("nat_only_config_flag with "
7903 "public_ip_port_range_present\n");
7909 /* max_port_per_client */
7910 if (strcmp(arg_name, "max_port_per_client") == 0) {
7911 if (max_port_present) {
7912 printf("CG-NAPT Parse Error: "
7913 "duplicate max_port_per_client\n");
7916 max_port_present = 1;
7919 max = atoi(arg_value);
7921 printf("max_port_per_client is invalid !!!\n");
7925 p->max_port_per_client = (uint16_t) max;
7927 if (p->max_port_per_client <= 0) {
7928 printf("max port per client is invalid\n");
7932 printf("max_port_per_client comp: %d\n",
7933 p->max_port_per_client);
7937 /* max_clients_per_ip */
7938 if (strcmp(arg_name, "max_clients_per_ip") == 0) {
7939 if (max_client_present) {
7940 printf("CG-NAPT parse Error: duplicate "
7941 "max_clients_per_ip\n");
7944 max_client_present = 1;
7946 if (nat_only_config_flag) {
7947 printf("CG-NAPT parse error:");
7948 printf("nat_only_config_flag with "
7949 "max_clients_per_ip\n");
7954 max = atoi(arg_value);
7956 printf("max_clients_per_ip is invalid !!!\n");
7960 p->max_clients_per_ip = (uint16_t) max;
7962 if (p->max_clients_per_ip <= 0) {
7963 printf("max_clients_per_ip is invalid\n");
7967 printf("max_clients_per_ip: %d\n",
7968 p->max_clients_per_ip);
7973 if (strcmp(arg_name, "n_entries") == 0) {
7974 if (n_entries_present)
7976 n_entries_present = 1;
7978 p->n_entries = atoi(arg_value);
7979 if (p->n_entries == 0)
7986 if (strcmp(arg_name, "n_flows") == 0) {
7987 if (n_flows_present)
7989 n_flows_present = 1;
7991 p->n_flows = atoi(arg_value);
7992 if (p->n_flows == 0)
7995 napt_common_table_hash_params.entries = p->n_flows;
7998 /* dest_if_offset Multiport Changes */
7999 if (strcmp(arg_name, "dest_if_offset") == 0) {
8000 if (dest_if_offset_present)
8002 //dest_if_offset_present = 1;
8004 dest_if_offset = atoi(arg_value);
8010 if (strcmp(arg_name, "key_offset") == 0) {
8011 if (key_offset_present)
8013 key_offset_present = 1;
8015 p->key_offset = atoi(arg_value);
8021 if (strcmp(arg_name, "key_size") == 0) {
8022 if (key_size_present)
8024 key_size_present = 1;
8026 p->key_size = atoi(arg_value);
8027 if ((p->key_size == 0) ||
8028 (p->key_size > PIPELINE_CGNAPT_KEY_MAX_SIZE) ||
8036 if (strcmp(arg_name, "hash_offset") == 0) {
8037 if (hash_offset_present)
8039 hash_offset_present = 1;
8041 p->hash_offset = atoi(arg_value);
8047 if (strcmp(arg_name, "pkt_type") == 0) {
8048 if (strcmp(arg_value, "ipv4") == 0) {
8049 p->traffic_type = TRAFFIC_TYPE_IPV4;
8050 printf("Traffic is set to IPv4\n");
8051 } else if (strcmp(arg_value, "ipv6") == 0) {
8052 p->traffic_type = TRAFFIC_TYPE_IPV6;
8053 printf("Traffic is set to IPv6\n");
8059 if (strcmp(arg_name, "cgnapt_debug") == 0) {
8060 CGNAPT_DEBUG = atoi(arg_value);
8065 /* any other Unknown argument return -1 */
8068 #ifdef NAT_ONLY_CONFIG_REQ
8069 if (nat_only_config_flag) {
8070 if (!public_ip_range_count) {
8071 printf("No public_ip_range %d for NAT only config.\n",
8072 public_ip_range_count);
8073 printf("Running static NAT only configuration\n");
8074 p->is_static_cgnapt = 1;
8079 if (!p->max_port_per_client)
8080 p->is_static_cgnapt = 1;
8083 /* Check that mandatory arguments are present */
8084 if ((n_flows_present == 0) ||
8085 (cgnapt_meta_offset_present == 0))
8092 * Function to initialize the pipeline
8095 * A pointer to struct pipeline_params
8097 * Void pointer - points to app params
8100 * void pointer to the pipeline, NULL 0 if failure
8102 static void *pipeline_cgnapt_init(struct pipeline_params *params, void *arg)
8103 /* (struct app_params *app) save it for use in port in handler */
8106 struct pipeline_cgnapt *p_nat;
8107 uint32_t size, i, in_ports_arg_size;
8109 /* Check input arguments */
8110 if ((params == NULL) ||
8111 (params->n_ports_in == 0) || (params->n_ports_out == 0))
8114 /* Memory allocation */
8115 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_cgnapt));
8116 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8117 p_nat = (struct pipeline_cgnapt *)p;
8118 global_pnat = p_nat;
8122 all_pipeline_cgnapt[n_cgnapt_pipeline++] = p_nat;
8124 strncpy(p->name, params->name,PIPELINE_NAME_SIZE);
8125 p->log_level = params->log_level;
8127 PLOG(p, HIGH, "CG-NAPT");
8128 /* Initialize all counters and arrays */
8130 p_nat->n_cgnapt_entry_deleted = 0;
8131 p_nat->n_cgnapt_entry_added = 0;
8132 p_nat->naptedPktCount = 0;
8133 p_nat->naptDroppedPktCount = 0;
8134 p_nat->inaptedPktCount = 0;
8135 p_nat->enaptedPktCount = 0;
8136 p_nat->receivedPktCount = 0;
8137 p_nat->missedPktCount = 0;
8138 p_nat->dynCgnaptCount = 0;
8139 p_nat->arpicmpPktCount = 0;
8141 p_nat->app_params_addr = (uint64_t) arg;
8142 for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
8143 p_nat->links_map[i] = 0xff;
8144 p_nat->outport_id[i] = 0xff;
8145 cgnapt_in_port_egress_prv[i] = 0;
8146 cgnapt_prv_que_port_index[i] = 0;
8148 p_nat->pipeline_num = 0xff;
8149 p_nat->hw_checksum_reqd = 0;
8150 p_nat->pub_ip_port_set = NULL;
8151 p_nat->pub_ip_count = 0;
8152 p_nat->traffic_type = TRAFFIC_TYPE_IPV4;
8153 p_nat->vnf_set = 0xff;
8155 /* For every init it should be reset */
8156 napt_port_alloc_elem_count = 0;
8158 #ifdef CGNAPT_TIMING_INST
8159 p_nat->in_port_exit_timestamp = 0;
8160 p_nat->external_time_sum = 0;
8161 p_nat->internal_time_sum = 0;
8162 p_nat->time_measurements = 0;
8163 p_nat->max_time_mesurements = 10000;
8164 p_nat->time_measurements_on = 0;
8167 #ifdef CGNAPT_DEBUGGING
8169 p_nat->naptDebugCount = 0;
8171 p_nat->naptDroppedPktCount1 = 0;
8172 p_nat->naptDroppedPktCount2 = 0;
8173 p_nat->naptDroppedPktCount3 = 0;
8174 p_nat->naptDroppedPktCount4 = 0;
8175 p_nat->naptDroppedPktCount5 = 0;
8176 p_nat->naptDroppedPktCount6 = 0;
8178 p_nat->missedpktcount1 = 0;
8179 p_nat->missedpktcount2 = 0;
8180 p_nat->missedpktcount3 = 0;
8181 p_nat->missedpktcount4 = 0;
8182 p_nat->missedpktcount5 = 0;
8183 p_nat->missedpktcount6 = 0;
8184 p_nat->missedpktcount7 = 0;
8185 p_nat->missedpktcount8 = 0;
8186 p_nat->missedpktcount9 = 0;
8187 p_nat->missedpktcount10 = 0;
8188 p_nat->missedpktcount11 = 0;
8189 p_nat->missedpktcount12 = 0;
8191 p_nat->max_port_dec_err1 = 0;
8192 p_nat->max_port_dec_err2 = 0;
8193 p_nat->max_port_dec_err3 = 0;
8194 p_nat->max_port_dec_success = 0;
8210 static int sip_enabled;
8214 #endif /* SIP_ALG */
8216 /*struct rte_pipeline_table_entry *entries[RTE_HASH_LOOKUP_BULK_MAX];*/
8217 /* bitmap of valid packets */
8218 p_nat->valid_packets = 0;
8219 /* bitmap of invalid packets to be dropped */
8220 p_nat->invalid_packets = 0;
8222 for (i = 0; i < RTE_HASH_LOOKUP_BULK_MAX; i++)
8223 p_nat->key_ptrs[i] = &(p_nat->keys[i]);
8225 p_nat->port_alloc_ring = NULL;
8227 /* Parse arguments */
8228 if (pipeline_cgnapt_parse_args(p_nat, params))
8231 p_nat->vnf_set = vnf_set_count;
8235 struct rte_pipeline_params pipeline_params = {
8236 .name = params->name,
8237 .socket_id = params->socket_id,
8238 .offset_port_id = cgnapt_meta_offset,
8241 p->p = rte_pipeline_create(&pipeline_params);
8249 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8251 uint32_t instr_size =
8252 RTE_CACHE_LINE_ROUNDUP((sizeof(uint64_t)) *
8255 (uint64_t *) rte_zmalloc(NULL, instr_size,
8256 RTE_CACHE_LINE_SIZE);
8258 (uint64_t *) rte_zmalloc(NULL, instr_size,
8259 RTE_CACHE_LINE_SIZE);
8261 (uint32_t *) rte_zmalloc(NULL, instr_size / 2,
8262 RTE_CACHE_LINE_SIZE);
8263 if ((inst_start_time == NULL) || (inst_end_time == NULL)
8264 || (inst_diff_time == NULL)) {
8265 printf("Inst array alloc failed .... ");
8270 /* Memory allocation for in_port_h_arg */
8271 in_ports_arg_size = RTE_CACHE_LINE_ROUNDUP(
8272 (sizeof(struct pipeline_cgnapt_in_port_h_arg)) *
8273 (params->n_ports_in));
8274 struct pipeline_cgnapt_in_port_h_arg *ap =
8275 (struct pipeline_cgnapt_in_port_h_arg *)
8278 RTE_CACHE_LINE_SIZE);
8282 myApp = (struct app_params *) arg;
8285 p->n_ports_in = params->n_ports_in;
8286 for (i = 0; i < p->n_ports_in; i++) {
8287 /* passing our cgnapt pipeline in call back arg */
8289 (ap[i]).in_port_id = i;
8291 struct rte_pipeline_port_in_params port_params = {
8293 pipeline_port_in_params_get_ops(¶ms->port_in
8296 pipeline_port_in_params_convert(¶ms->port_in
8298 .f_action = cgnapt_in_port_ah_mix,
8300 .burst_size = params->port_in[i].burst_size,
8303 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8305 instrumentation_port_in_arg = &(ap[i]);
8308 if (p_nat->traffic_type == TRAFFIC_TYPE_IPV4) {
8309 /* Private in-port handler */
8310 /* Multiport changes */
8311 if (cgnapt_in_port_egress_prv[i]) {
8312 port_params.f_action =
8313 cgnapt_in_port_ah_ipv4_prv;
8314 printf("CGNAPT port %d is IPv4 Prv\n", i);
8316 port_params.f_action =
8317 cgnapt_in_port_ah_ipv4_pub;
8318 printf("CGNAPT port %d is IPv4 Pub\n", i);
8322 if (p_nat->traffic_type == TRAFFIC_TYPE_IPV6) {
8323 if (cgnapt_in_port_egress_prv[i]) {
8324 port_params.f_action =
8325 cgnapt_in_port_ah_ipv6_prv;
8326 printf("CGNAPT port %d is IPv6 Prv\n", i);
8328 port_params.f_action =
8329 cgnapt_in_port_ah_ipv6_pub;
8330 printf("CGNAPT port %d is IPv6 Pub\n", i);
8334 int status = rte_pipeline_port_in_create(p->p,
8339 rte_pipeline_free(p->p);
8347 p->n_ports_out = params->n_ports_out;
8348 for (i = 0; i < p->n_ports_out; i++) {
8349 struct rte_pipeline_port_out_params port_params = {
8350 .ops = pipeline_port_out_params_get_ops(
8351 ¶ms->port_out[i]),
8352 .arg_create = pipeline_port_out_params_convert(
8353 ¶ms->port_out[i]),
8354 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8355 .f_action = port_out_ah_cgnapt,
8362 int status = rte_pipeline_port_out_create(p->p,
8364 &p->port_out_id[i]);
8367 rte_pipeline_free(p->p);
8373 int pipeline_num = 0;
8375 ignore = sscanf(params->name, "PIPELINE%d", &pipeline_num);
8377 printf("Not able to read pipeline number\n");
8380 p_nat->pipeline_num = (uint8_t) pipeline_num;
8381 register_pipeline_Qs(p_nat->pipeline_num, p);
8382 set_link_map(p_nat->pipeline_num, p, p_nat->links_map);
8383 set_outport_id(p_nat->pipeline_num, p, p_nat->outport_id);
8389 if (napt_common_table == NULL) {
8390 if (create_napt_common_table(p_nat->n_flows)) {
8392 "CG-NAPT create_napt_common_table failed.");
8397 struct rte_pipeline_table_params table_params = {
8398 .ops = &rte_table_stub_ops,
8400 .f_action_hit = NULL,
8401 .f_action_miss = NULL,
8403 .action_data_size = 0,
8406 int status = rte_pipeline_table_create(p->p,
8411 rte_pipeline_free(p->p);
8415 struct rte_pipeline_table_entry default_entry = {
8416 .action = RTE_PIPELINE_ACTION_PORT_META
8418 struct rte_pipeline_table_entry *default_entry_ptr;
8419 status = rte_pipeline_table_default_entry_add(
8423 &default_entry_ptr);
8425 rte_pipeline_free(p->p);
8431 /* Connecting input ports to tables */
8432 for (i = 0; i < p->n_ports_in; i++) {
8433 int status = rte_pipeline_port_in_connect_to_table(p->p,
8440 rte_pipeline_free(p->p);
8446 /* Enable input ports */
8447 for (i = 0; i < p->n_ports_in; i++) {
8448 int status = rte_pipeline_port_in_enable(p->p,
8452 rte_pipeline_free(p->p);
8458 /* Check pipeline consistency */
8459 if (rte_pipeline_check(p->p) < 0) {
8460 rte_pipeline_free(p->p);
8465 /* Message queues */
8466 p->n_msgq = params->n_msgq;
8467 for (i = 0; i < p->n_msgq; i++)
8468 p->msgq_in[i] = params->msgq_in[i];
8469 for (i = 0; i < p->n_msgq; i++)
8470 p->msgq_out[i] = params->msgq_out[i];
8472 /* Message handlers */
8473 memcpy(p->handlers, handlers, sizeof(p->handlers));
8474 memcpy(p_nat->custom_handlers,
8475 custom_handlers, sizeof(p_nat->custom_handlers));
8477 if (!p_nat->is_static_cgnapt) {
8478 printf("Initializing dyn napt components ... %d\n",
8479 p_nat->pipeline_num);
8480 if (napt_port_alloc_init(p_nat) == -1) {
8481 printf("Error - napt_port_alloc_init failed - %d\n",
8482 p_nat->pipeline_num);
8487 if (max_port_per_client_hash == NULL) {
8488 rc = init_max_port_per_client(p_nat);
8490 printf("CGNAPT Error - "
8491 "init_max_port_per_client failed %d", rc);
8498 if (!icmp_pool_init) {
8500 /* create the arp_icmp mbuf rx pool */
8501 cgnapt_icmp_pktmbuf_tx_pool =
8502 rte_pktmbuf_pool_create("icmp_mbuf_tx_pool", 63, 32, 0,
8503 RTE_MBUF_DEFAULT_BUF_SIZE,
8505 if (cgnapt_icmp_pktmbuf_tx_pool == NULL) {
8506 PLOG(p, HIGH, "ICMP mbuf pool create failed.");
8511 rte_pktmbuf_alloc(cgnapt_icmp_pktmbuf_tx_pool);
8513 if (cgnapt_icmp_pkt == NULL) {
8514 printf("Failed to allocate cgnapt_icmp_pkt\n");
8521 cgnat_cnxn_tracker = rte_zmalloc(NULL, rte_ct_get_cnxn_tracker_size(),
8522 RTE_CACHE_LINE_SIZE);
8524 if (cgnat_cnxn_tracker == NULL) {
8525 printf("CGNAPT CT memory not allocated\n");
8528 rte_ct_initialize_default_timeouts(cgnat_cnxn_tracker);
8530 printf("CGNAPT CT Flows %d\n", p_nat->n_flows);
8532 ret = rte_ct_initialize_cnxn_tracker(cgnat_cnxn_tracker,
8534 "CGNAT_CT_COMMON_TABLE");
8544 if (pcp_init() == PCP_INIT_SUCCESS)
8545 printf("PCP contents are initialized successfully\n");
8547 printf("Error in initializing PCP contents\n");
8554 * Function for pipeline cleanup
8557 * A void pointer to pipeline
8562 static int pipeline_cgnapt_free(void *pipeline)
8564 struct pipeline *p = (struct pipeline *)pipeline;
8566 /* Check input arguments */
8570 /* Free resources */
8571 rte_pipeline_free(p->p);
8577 pipeline_cgnapt_track(void *pipeline, __rte_unused uint32_t port_in,
8580 struct pipeline *p = (struct pipeline *)pipeline;
8582 /* Check input arguments */
8583 if ((p == NULL) || (port_in >= p->n_ports_in) || (port_out == NULL))
8586 if (p->n_ports_in == 1) {
8595 * Function for pipeline timers
8598 * A void pointer to pipeline
8603 static int pipeline_cgnapt_timer(void *pipeline)
8605 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)pipeline;
8607 pipeline_msg_req_handle(&p_nat->p);
8609 rte_pipeline_flush(((struct pipeline *)p_nat)->p);
8615 * Function for pipeline custom handlers
8618 * A void pointer to pipeline
8620 * void pointer for incoming data
8623 * void pointer of response
8625 void *pipeline_cgnapt_msg_req_custom_handler(struct pipeline *p, void *msg)
8627 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
8628 struct pipeline_custom_msg_req *req = msg;
8629 pipeline_msg_req_handler f_handle;
8631 f_handle = (req->subtype < PIPELINE_CGNAPT_MSG_REQS) ?
8632 p_nat->custom_handlers[req->subtype] :
8633 pipeline_msg_req_invalid_handler;
8635 if (f_handle == NULL)
8636 f_handle = pipeline_msg_req_invalid_handler;
8638 return f_handle(p, req);
8642 * Function for adding NSP data
8645 * A void pointer to pipeline
8647 * void pointer for incoming data
8650 * void pointer of response
8652 void *pipeline_cgnapt_msg_req_nsp_add_handler(
8653 __rte_unused struct pipeline *p,
8656 struct pipeline_cgnapt_nsp_add_msg_req *req = msg;
8657 struct pipeline_cgnapt_nsp_add_msg_rsp *rsp = msg;
8659 struct cgnapt_nsp_node *node = NULL, *ll = nsp_ll;
8662 (req->nsp.depth == 32 || req->nsp.depth == 40
8663 || req->nsp.depth == 48 || req->nsp.depth == 56
8664 || req->nsp.depth == 64 || req->nsp.depth == 96)) {
8670 printf("be initial cond\n");
8671 if (nsp_ll == NULL) {
8672 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_nsp_node));
8673 node = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8675 printf("be 1st cond\n");
8681 memcpy(&node->nsp, &req->nsp,
8682 sizeof(struct pipeline_cgnapt_nsp_t));
8686 while (ll != NULL) {
8687 if (!memcmp(ll->nsp.prefix, req->nsp.prefix, 16)
8688 && ll->nsp.depth == req->nsp.depth) {
8689 printf("be 2st cond\n");
8697 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_nsp_node));
8698 node = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8700 printf("be 3st cond\n");
8706 memcpy(&node->nsp, &req->nsp,
8707 sizeof(struct pipeline_cgnapt_nsp_t));
8708 node->next = nsp_ll;
8715 printf("be 4st cond\n");
8720 * Function for deleting NSP data
8723 * A void pointer to pipeline
8725 * void pointer for incoming data
8728 * void pointer of response
8730 void *pipeline_cgnapt_msg_req_nsp_del_handler(
8731 __rte_unused struct pipeline *p,
8734 struct pipeline_cgnapt_nsp_del_msg_req *req = msg;
8735 struct pipeline_cgnapt_nsp_del_msg_rsp *rsp = msg;
8736 struct cgnapt_nsp_node *prev = NULL, *ll = nsp_ll;
8738 while (ll != NULL) {
8739 if (!memcmp(ll->nsp.prefix, req->nsp.prefix, 16)
8740 && ll->nsp.depth == req->nsp.depth) {
8742 prev->next = ll->next;
8765 * Function for adding NAPT entry
8768 * A void pointer to pipeline
8770 * void pointer for incoming data
8773 * void pointer of response
8775 void *pipeline_cgnapt_msg_req_entry_add_handler(struct pipeline *p, void *msg)
8777 struct pipeline_cgnapt_entry_add_msg_req *req = msg;
8778 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
8779 uint8_t type = req->data.type;
8780 uint32_t src_ip = (type == CGNAPT_ENTRY_IPV4) ?
8781 req->data.u.prv_ip :
8782 rte_bswap32(req->data.u.u32_prv_ipv6[3]);
8784 uint8_t src_ipv6[16];
8786 uint32_t dest_ip = req->data.pub_ip;
8787 uint16_t src_port = req->data.prv_port;
8788 uint16_t dest_port = req->data.pub_port;
8789 uint16_t rx_port = req->data.prv_phy_port;
8790 uint32_t ttl = req->data.ttl;
8792 if (type == CGNAPT_ENTRY_IPV6)
8793 memcpy(src_ipv6, req->data.u.prv_ipv6, 16);
8795 printf("CG-NAPT addm - PrvIP %x, PrvPort %d,", src_ip, src_port);
8796 printf("PubIP %x, PubPort %d,", dest_ip, dest_port);
8798 printf("PhyPort %d, ttl %u,", rx_port, ttl);
8799 printf("entry_type %d\n", type);
8800 #ifdef NAT_ONLY_CONFIG_REQ
8801 if (nat_only_config_flag) {
8802 if (!p_nat->is_static_cgnapt) {
8805 for (i = 0; i < p_nat->pub_ip_range_count; i++) {
8806 if (((dest_ip >= p_nat->pub_ip_range[i].start_ip)
8807 && (dest_ip <= p_nat->pub_ip_range[i].end_ip))) {
8808 printf("Error - static port cannot be in Dynamic "
8810 printf("%x-%x\n", p_nat->pub_ip_range[i].start_ip,
8811 p_nat->pub_ip_range[i].end_ip);
8817 if (pipeline_cgnapt_msg_req_entry_addm_pair(p, msg,
8823 printf("pipeline_cgnapt_msg_req_entry_addm_handler\n");
8827 #ifdef CGNAPT_DBG_PRNT
8828 printf("Success - pipeline_cgnapt_msg_req_entry_addm_handler");
8829 printf("added %d rule pairs.\n", count);
8835 if (!p_nat->is_static_cgnapt) {
8838 for (i = 0; i < p_nat->pub_ip_count; i++) {
8839 /* Check port range if same Public-IP */
8840 if (dest_ip != p_nat->pub_ip_port_set[i].ip)
8842 if (((dest_port >= p_nat->pub_ip_port_set[i].start_port) &&
8843 (dest_port <= p_nat->pub_ip_port_set[i].end_port))) {
8844 printf("Error - port cannot be in Dynamic "
8845 "port range %d-%d\n",
8846 p_nat->pub_ip_port_set[i].start_port,
8847 p_nat->pub_ip_port_set[i].end_port);
8853 if (pipeline_cgnapt_msg_req_entry_addm_pair
8854 (p, msg, src_ip, src_port, dest_ip, dest_port, rx_port,
8855 ttl, type, src_ipv6)) {
8856 printf("Error - pipeline_cgnapt_msg_req_entry_add_handler\n");
8861 #ifdef CGNAPT_DBG_PRNT
8862 printf("\nSuccess - pipeline_cgnapt_msg_req_entry_add_handler "
8869 * Function for adding a NAPT entry pair
8872 * A void pointer to pipeline
8874 * void pointer for incoming data
8880 * destination ip address
8884 * Physical receive port
8886 * time to live value
8888 * type of entry IPv4 vs IPv6
8890 * uint8_t array of IPv6 address
8893 * 0 if success, negative if fails
8896 pipeline_cgnapt_msg_req_entry_addm_pair(
8897 struct pipeline *p, __rte_unused void *msg,
8898 uint32_t src_ip, uint16_t src_port,
8899 uint32_t dest_ip, uint16_t dest_port,
8900 uint16_t rx_port, uint32_t ttl,
8901 uint8_t type, uint8_t src_ipv6[16])
8904 struct pipeline_cgnapt_entry_key key;
8905 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
8908 key.port = src_port;
8911 struct cgnapt_table_entry entry = {
8913 .action = RTE_PIPELINE_ACTION_PORT,
8914 .port_id = CGNAPT_PUB_PORT_ID,
8918 /*.prv_ip = src_ip, */
8919 .prv_port = src_port,
8921 .pub_port = dest_port,
8922 .prv_phy_port = rx_port,
8923 .pub_phy_port = get_prv_to_pub_port(&dest_ip,
8926 .timeout = STATIC_CGNAPT_TIMEOUT,
8933 if (type == CGNAPT_ENTRY_IPV4) {
8934 entry.data.type = CGNAPT_ENTRY_IPV4;
8935 entry.data.u.prv_ip = src_ip;
8937 entry.data.type = CGNAPT_ENTRY_IPV6;
8938 memcpy(entry.data.u.prv_ipv6, src_ipv6, 16);
8941 /* Also need to add a paired entry on our own */
8943 * Need to change key
8944 * Need to change entry header
8945 * Will keep the same entry and take care
8946 * of translation in table hit handler
8948 struct pipeline_cgnapt_entry_key second_key;
8950 /* Need to add a second ingress entry */
8951 second_key.ip = dest_ip;
8952 second_key.port = dest_port;
8953 second_key.pid = 0xffff;
8955 #ifdef NAT_ONLY_CONFIG_REQ
8956 if (nat_only_config_flag) {
8958 entry.data.pub_port = 0xffff;
8959 second_key.port = 0xffff;
8963 int32_t position = rte_hash_add_key(napt_common_table, &key);
8966 printf("CG-NAPT entry bulk add failed");
8967 printf(" ... returning without adding ...\n");
8971 memcpy(&napt_hash_tbl_entries[position], &entry,
8972 sizeof(struct cgnapt_table_entry));
8974 #ifdef CGNAPT_DEBUGGING
8975 if (p_nat->kpc1++ < 5)
8979 p_nat->n_cgnapt_entry_added++;
8981 /* Now modify the forward port for reverse entry */
8982 entry.head.port_id = CGNAPT_PRV_PORT_ID;
8984 position = rte_hash_add_key(napt_common_table, &second_key);
8987 printf("CG-NAPT entry reverse bulk add failed");
8988 printf(" ... returning with fwd add ...%d\n", position);
8992 memcpy(&napt_hash_tbl_entries[position], &entry,
8993 sizeof(struct cgnapt_table_entry));
8995 #ifdef CGNAPT_DEBUGGING
8996 if (p_nat->kpc1 < 5)
8997 print_key(&second_key);
9000 p_nat->n_cgnapt_entry_added++;
9005 * Function for adding multiple NAPT entries
9008 * A void pointer to pipeline
9010 * void pointer for incoming data
9013 * void pointer of response
9015 void *pipeline_cgnapt_msg_req_entry_addm_handler(struct pipeline *p, void *msg)
9017 struct pipeline_cgnapt_entry_addm_msg_req *req = msg;
9018 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9020 uint32_t max_ue = req->data.num_ue;
9021 uint8_t type = req->data.type;
9022 uint32_t src_ip = (type == CGNAPT_ENTRY_IPV4) ?
9023 req->data.u.prv_ip :
9024 rte_bswap32(req->data.u.u32_prv_ipv6[3]);
9026 uint8_t src_ipv6[16];
9028 uint32_t dest_ip = req->data.pub_ip;
9029 uint16_t src_port = req->data.prv_port;
9030 uint16_t dest_port = req->data.pub_port;
9031 uint16_t rx_port = req->data.prv_phy_port;
9032 uint32_t ttl = req->data.ttl;
9033 uint16_t max_src_port = req->data.prv_port_max;
9034 uint16_t max_dest_port = req->data.pub_port_max;
9036 uint16_t src_port_start = src_port;
9037 uint16_t dest_port_start = dest_port;
9038 uint32_t src_ip_temp;
9040 if (type == CGNAPT_ENTRY_IPV6)
9041 memcpy(src_ipv6, req->data.u.prv_ipv6, 16);
9043 printf("CG-NAPT addm - PrvIP %x, PrvPort %d,", src_ip, src_port);
9044 printf("PubIP %x, PubPort %d,", dest_ip, dest_port);
9045 printf("PhyPort %d, ttl %u, NumUe %d,", rx_port, ttl, max_ue);
9046 printf("mPrvPort %d, mPubPort %d,", max_src_port, max_dest_port);
9047 printf("entry_type %d\n", type);
9048 #ifdef NAT_ONLY_CONFIG_REQ
9049 if (nat_only_config_flag) {
9050 if (!p_nat->is_static_cgnapt) {
9053 for (i = 0; i < p_nat->pub_ip_range_count; i++) {
9054 if (((dest_ip >= p_nat->pub_ip_range[i].start_ip)
9055 && (dest_ip <= p_nat->pub_ip_range[i].end_ip)) ||
9056 (((dest_ip + max_ue) >=
9057 p_nat->pub_ip_range[i].start_ip) &&
9058 ((dest_ip + max_ue) <=
9059 p_nat->pub_ip_range[i].end_ip))) {
9060 printf("Error - static port cannot be in Dynamic "
9062 printf("%x-%x\n", p_nat->pub_ip_range[i].start_ip,
9063 p_nat->pub_ip_range[i].end_ip);
9070 for (uenum = 0; uenum < max_ue; uenum++) {
9072 if (pipeline_cgnapt_msg_req_entry_addm_pair(p, msg,
9078 printf("pipeline_cgnapt_msg_req_entry_addm_handler\n");
9088 #ifdef CGNAPT_DBG_PRNT
9089 printf("Success - pipeline_cgnapt_msg_req_entry_addm_handler");
9090 printf("added %d rule pairs.\n", count);
9097 if (!p_nat->is_static_cgnapt) {
9100 for (i = 0; i < p_nat->pub_ip_count; i++) {
9101 /* Check port range if same Public-IP */
9102 if (dest_ip != p_nat->pub_ip_port_set[i].ip)
9104 if (((dest_port >= p_nat->pub_ip_port_set[i].start_port) &&
9105 (dest_port <= p_nat->pub_ip_port_set[i].end_port)) ||
9106 ((max_dest_port >= p_nat->pub_ip_port_set[i].start_port)
9107 && max_dest_port <= p_nat->pub_ip_port_set[i].end_port)) {
9108 printf("Error - port cannot be in Dynamic port range %d-%d\n",
9109 p_nat->pub_ip_port_set[i].start_port,
9110 p_nat->pub_ip_port_set[i].end_port);
9116 for (uenum = 0; uenum < max_ue; uenum++) {
9117 if (pipeline_cgnapt_msg_req_entry_addm_pair
9118 (p, msg, src_ip, src_port, dest_ip, dest_port, rx_port,
9119 ttl, type, src_ipv6)) {
9120 printf("Error - pipeline_cgnapt_msg_req_entry_addm_handler\n");
9127 if (src_port > max_src_port) {
9128 src_port = src_port_start;
9130 if (req->data.type == CGNAPT_ENTRY_IPV6) {
9131 src_ip_temp = rte_bswap32(src_ip);
9132 memcpy(&src_ipv6[12], &src_ip_temp, 4);
9136 if (dest_port > max_dest_port) {
9137 dest_port = dest_port_start;
9142 #ifdef CGNAPT_DBG_PRNT
9143 printf("\nSuccess - pipeline_cgnapt_msg_req_entry_addm_handler added");
9144 printf("%d rule pairs.\n", count);
9150 * Function for deleting NAPT entry
9153 * A void pointer to pipeline
9155 * void pointer for incoming data
9158 * void pointer of response
9160 void *pipeline_cgnapt_msg_req_entry_del_handler(struct pipeline *p, void *msg)
9162 struct pipeline_cgnapt_entry_delete_msg_req *req = msg;
9163 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9164 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9167 uint8_t *KeyP = (void *)(&req->key);
9170 printf("pipeline_cgnapt_msg_req_entry_del_handler - Key: ");
9171 for (i = 0; i < (int)sizeof(struct pipeline_cgnapt_entry_key);
9173 printf(" %02x", KeyP[i]);
9174 printf(" ,KeySize %u\n",
9175 (int)sizeof(struct pipeline_cgnapt_entry_key));
9178 struct cgnapt_table_entry entry;
9180 /* If ingress key */
9181 if (!is_phy_port_privte(req->key.pid))
9182 req->key.pid = 0xffff;
9184 #ifdef NAT_ONLY_CONFIG_REQ
9185 if (nat_only_config_flag)
9186 req->key.port = 0xffff;
9190 position = rte_hash_lookup(napt_common_table, &req->key);
9191 if (position == -ENOENT) {
9192 printf("Entry not found\n");
9195 memcpy(&entry, &napt_hash_tbl_entries[position],
9196 sizeof(struct cgnapt_table_entry));
9197 position = rte_hash_del_key(napt_common_table, &req->key);
9198 p_nat->n_cgnapt_entry_deleted++;
9200 struct pipeline_cgnapt_entry_key second_key;
9202 if (is_phy_port_privte(req->key.pid)) {
9203 /* key is for egress - make second key for ingress */
9204 second_key.ip = entry.data.pub_ip;
9205 second_key.port = entry.data.pub_port;
9206 second_key.pid = 0xffff;
9209 /* key is for ingress - make second key for egress */
9210 second_key.ip = entry.data.u.prv_ip;
9211 second_key.port = entry.data.prv_port;
9212 second_key.pid = entry.data.prv_phy_port;
9215 #ifdef NAT_ONLY_CONFIG_REQ
9216 if (nat_only_config_flag)
9217 second_key.port = 0xffff;
9220 position = rte_hash_del_key(napt_common_table, &second_key);
9221 p_nat->n_cgnapt_entry_deleted++;
9226 void *pipeline_cgnapt_msg_req_entry_sync_handler(struct pipeline *p, void *msg)
9228 struct pipeline_cgnapt_entry_delete_msg_req *req = msg;
9229 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9231 rsp->status = rte_pipeline_table_entry_delete(
9235 &rsp->key_found, NULL);
9241 * Function to print the NAPT key
9244 * A pointer to struct pipeline_cgnapt_entry_key
9246 void print_key(struct pipeline_cgnapt_entry_key *key)
9248 uint8_t *KeyP = (void *)(key);
9252 for (i = 0; i < (int)sizeof(struct pipeline_cgnapt_entry_key); i++)
9253 printf(" %02x", KeyP[i]);
9257 * Function to print the table entry
9260 * A pointer to struct rte_pipeline_table_entry
9262 void print_entry1(struct rte_pipeline_table_entry *entry)
9264 uint8_t *entryP = (void *)(entry);
9268 for (i = 0; i < (int)sizeof(struct rte_pipeline_table_entry); i++)
9269 printf(" %02x", entryP[i]);
9273 * Function to print the NAPT table entry
9276 * A pointer to struct cgnapt_table_entry
9278 void print_cgnapt_entry(struct cgnapt_table_entry *entry)
9280 uint8_t *entryP = (void *)(entry);
9283 printf("CGNAPT Entry: ");
9284 for (i = 0; i < (int)sizeof(struct cgnapt_table_entry); i++)
9285 printf(" %02x", entryP[i]);
9286 printf(" size:%d\n", (int)sizeof(struct cgnapt_table_entry));
9290 * Function to get a free port
9293 * A pointer to struct pipeline_cgnapt
9295 * A uint32_t pointer to return corresponding ip address
9298 * free port number, 0 if error
9300 int get_free_iport(struct pipeline_cgnapt *p_nat, uint32_t *public_ip)
9303 /* If we don't have a valid napt_port_alloc_elem get one from
9306 if (p_nat->allocated_ports == NULL) {
9310 ret = rte_ring_dequeue(p_nat->port_alloc_ring, &ports);
9312 p_nat->allocated_ports =
9313 (struct napt_port_alloc_elem *)ports;
9315 #ifdef CGNAPT_DEBUGGING
9319 #ifdef CGNAPT_DBG_PRNT
9320 if (CGNAPT_DEBUG > 3)
9321 printf("p_nat->allocated_ports %p\n",
9322 p_nat->allocated_ports);
9325 printf("CGNAPT Err - get_free_iport rte_ring_dequeue "
9327 printf("%d, %d, %d\n", rte_ring_count(
9328 p_nat->port_alloc_ring), rte_ring_free_count(
9329 p_nat->port_alloc_ring), ret);
9331 #ifdef CGNAPT_DEBUGGING
9332 #ifdef CGNAPT_DBG_PRNT
9333 printf("Th%d GFP:: %" PRIu64 ", %" PRIu64 ", "
9334 "%" PRIu64", %" PRIu64 ",\n", p_nat->pipeline_num,
9335 p_nat->gfp_get, p_nat->gfp_ret, p_nat->gfp_suc,
9345 /* get the port from index count-1 and decrease count */
9346 port = p_nat->allocated_ports->ports
9347 [p_nat->allocated_ports->count - 1];
9348 *public_ip = p_nat->allocated_ports->ip_addr
9349 [p_nat->allocated_ports->count - 1];
9351 p_nat->allocated_ports->count -= 1;
9353 /* if count is zero, return buffer to mem pool */
9354 if (p_nat->allocated_ports->count == 0) {
9355 rte_mempool_put(napt_port_pool, p_nat->allocated_ports);
9357 #ifdef CGNAPT_DEBUGGING
9359 #ifdef CGNAPT_DBG_PRNT
9360 printf("Th%d Returned to pool p_nat->allocated_ports %p,",
9361 p_nat->pipeline_num, p_nat->allocated_ports);
9362 printf("%" PRIu64 ", %" PRIu64 ",",
9363 p_nat->gfp_get, p_nat->gfp_ret);
9364 printf("%" PRIu64 ", %" PRIu64 ",\n",
9365 p_nat->gfp_suc, p_nat->gfp_err);
9369 p_nat->allocated_ports = NULL;
9372 #ifdef CGNAPT_DEBUGGING
9380 * Function to free a port
9383 * Port number to free
9385 * Corresponding ip address
9387 * A pointer to struct pipeline_cgnapt
9390 void release_iport(uint16_t port_num, uint32_t public_ip,
9391 struct pipeline_cgnapt *p_nat)
9393 /* If we don't have a valid napt_port_alloc_elem get one
9396 if (p_nat->free_ports == NULL) {
9399 #ifdef CGNAPT_DEBUGGING
9403 if (rte_mempool_get(napt_port_pool, &ports) < 0) {
9404 #ifdef CGNAPT_DEBUGGING
9407 printf("CGNAPT release_iport error in getting "
9408 "port alloc buffer\n");
9412 p_nat->free_ports = (struct napt_port_alloc_elem *)ports;
9413 p_nat->free_ports->count = 0;
9416 /* put the port at index count and increase count */
9417 p_nat->free_ports->ip_addr[p_nat->free_ports->count] = public_ip;
9418 p_nat->free_ports->ports[p_nat->free_ports->count] = port_num;
9419 p_nat->free_ports->count += 1;
9421 /* if napt_port_alloc_elem is full add it to ring */
9424 #ifdef CGNAPT_DEBUGGING
9428 #ifdef CGNAPT_DBG_PRNT
9429 if (CGNAPT_DEBUG >= 2) {
9430 printf("CGNAPT port_alloc_ring before EnQ Cnt %d, Free %d\n",
9431 rte_ring_count(p_nat->port_alloc_ring),
9432 rte_ring_free_count(p_nat->port_alloc_ring));
9436 if (rte_ring_enqueue(p_nat->port_alloc_ring,
9437 (void *)p_nat->free_ports) != 0) {
9438 printf("CGNAPT release_iport Enqueue error %p\n",
9441 #ifdef CGNAPT_DEBUGGING
9446 #ifdef CGNAPT_DBG_PRNT
9447 if (CGNAPT_DEBUG >= 2) {
9448 printf("CGNAPT port_alloc_ring after EnQ Cnt %d",
9449 rte_ring_count(p_nat->port_alloc_ring));
9451 rte_ring_free_count(p_nat->port_alloc_ring));
9455 p_nat->free_ports = NULL;
9458 #ifdef CGNAPT_DEBUGGING
9464 * Function to initialize max ports per client data structures
9465 * Called during dynamic NAPT initialization.
9468 * A pointer to struct pipeline_cgnapt
9471 * 0 if success, negative if error
9473 int init_max_port_per_client(
9474 __rte_unused struct pipeline_cgnapt *p_nat)
9476 if (max_port_per_client_hash)
9479 /*MPPC_ALREADY_EXISTS */
9483 max_port_per_client_hash =
9484 rte_hash_create(&max_port_per_client_hash_params);
9485 if (!max_port_per_client_hash)
9488 /*MPPC_HASH_CREATE_ERROR */
9490 max_port_per_client_array =
9492 sizeof(struct max_port_per_client) * MAX_DYN_ENTRY,
9493 RTE_CACHE_LINE_SIZE);
9494 if (!max_port_per_client_array)
9497 /*MPPC_ARRAY_CREATE_ERROR */
9499 for (i = 0; i < MAX_DYN_ENTRY; i++) {
9500 max_port_per_client_array[i].prv_ip = 0;
9501 max_port_per_client_array[i].prv_phy_port = 0;
9502 max_port_per_client_array[i].max_port_cnt = 0;
9510 * Function to check if max ports for a client is reached
9512 * @param prv_ip_param
9513 * A uint32_t ip address of client
9514 * @param prv_phy_port_param
9515 * A uint32_t physical port id of the client
9517 * A pointer to struct pipeline_cgnapt
9520 * 0 if max port not reached, 1 if reached, -1 if error
9522 int is_max_port_per_client_reached(uint32_t prv_ip_param,
9523 uint32_t prv_phy_port_param,
9524 struct pipeline_cgnapt *p_nat)
9526 int index = MAX_PORT_INVALID_KEY;
9528 struct max_port_per_client_key key = {
9529 .prv_ip = prv_ip_param,
9530 .prv_phy_port = prv_phy_port_param,
9533 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9536 return MAX_PORT_INVALID_KEY;
9538 if (max_port_per_client_array[index].max_port_cnt >=
9539 p_nat->max_port_per_client)
9540 return MAX_PORT_REACHED;
9542 return MAX_PORT_NOT_REACHED;
9546 * Function to increase max ports for a client
9548 * @param prv_ip_param
9549 * A uint32_t ip address of client
9550 * @param prv_phy_port_param
9551 * A uint32_t physical port id of the client
9553 * A pointer to struct pipeline_cgnapt
9556 * 0 if max port reached, 1 if success, 2 if new entry, -1 if error
9558 int increment_max_port_counter(uint32_t prv_ip_param,
9559 uint32_t prv_phy_port_param,
9560 struct pipeline_cgnapt *p_nat)
9562 int index = MAX_PORT_INC_ERROR;
9564 struct max_port_per_client_key key = {
9565 .prv_ip = prv_ip_param,
9566 .prv_phy_port = prv_phy_port_param,
9569 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9571 if (index == -EINVAL)
9572 return MAX_PORT_INC_ERROR;
9574 if (index == -ENOENT) {
9575 if (max_port_per_client_add_entry(prv_ip_param,
9578 return MAX_PORT_INC_ERROR;
9580 return 2; /*return MAX_PORT_NEW_ENTRY; */
9583 if (CGNAPT_DEBUG > 2)
9584 printf("%s: max_port_cnt(%d), p_nat_max(%d)\n", __func__,
9585 max_port_per_client_array[index].max_port_cnt,
9586 p_nat->max_port_per_client);
9588 if (max_port_per_client_array[index].max_port_cnt <
9589 p_nat->max_port_per_client) {
9590 max_port_per_client_array[index].max_port_cnt++;
9591 return MAX_PORT_INC_SUCCESS;
9594 return MAX_PORT_INC_REACHED;
9598 * Function to decrease max ports for a client
9600 * @param prv_ip_param
9601 * A uint32_t ip address of client
9602 * @param prv_phy_port_param
9603 * A uint32_t physical port id of the client
9605 * A pointer to struct pipeline_cgnapt
9608 * 0 if count already 0, 1 if success, -1 if error
9610 int decrement_max_port_counter(uint32_t prv_ip_param,
9611 uint32_t prv_phy_port_param,
9612 struct pipeline_cgnapt *p_nat)
9614 int index = MAX_PORT_DEC_ERROR;
9616 struct max_port_per_client_key key = {
9617 .prv_ip = prv_ip_param,
9618 .prv_phy_port = prv_phy_port_param,
9621 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9624 #ifdef CGNAPT_DEBUGGING
9625 p_nat->max_port_dec_err1++;
9627 return MAX_PORT_DEC_ERROR;
9631 if (max_port_per_client_array[index].max_port_cnt > 0) {
9632 /* If it is the last port,ret this info which is used for
9633 * max_cli_per_pub_ip
9636 max_port_per_client_array[index].max_port_cnt--;
9637 /* Count should be atomic but we are good as we have only
9638 * one task handling this counter at a time (core affinity)
9642 if (max_port_per_client_array[index].max_port_cnt <= 0) {
9643 if (max_port_per_client_del_entry
9644 (prv_ip_param, prv_phy_port_param, p_nat) <= 0) {
9646 #ifdef CGNAPT_DEBUGGING
9647 p_nat->max_port_dec_err2++;
9649 return MAX_PORT_DEC_ERROR;
9652 #ifdef CGNAPT_DEBUGGING
9653 p_nat->max_port_dec_err3++;
9656 return MAX_PORT_DEC_REACHED;
9659 #ifdef CGNAPT_DEBUGGING
9660 p_nat->max_port_dec_success++;
9663 return MAX_PORT_DEC_SUCCESS;
9667 * Function to add a max ports per client entry
9669 * @param prv_ip_param
9670 * A uint32_t ip address of client
9671 * @param prv_phy_port_param
9672 * A uint32_t physical port id of the client
9674 * A pointer to struct pipeline_cgnapt
9677 * 0 no success, 1 if success, -1 if error
9679 int max_port_per_client_add_entry(
9680 uint32_t prv_ip_param,
9681 uint32_t prv_phy_port_param,
9682 __rte_unused struct pipeline_cgnapt *p_nat)
9684 int index = MAX_PORT_ADD_ERROR;
9686 struct max_port_per_client_key key = {
9687 .prv_ip = prv_ip_param,
9688 .prv_phy_port = prv_phy_port_param,
9691 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9692 if (index == -EINVAL)
9693 return MAX_PORT_ADD_ERROR;
9696 return MAX_PORT_ADD_UNSUCCESS;
9698 if (index == -ENOENT) {
9700 #ifdef CGNAPT_DBG_PRNT
9701 if (CGNAPT_DEBUG > 2)
9702 printf("max_port_per_client_add_entry fn: "
9703 "Entry does not exist\n");
9707 rte_hash_add_key(max_port_per_client_hash,
9708 (const void *)&key);
9709 if (index == -ENOSPC)
9710 return MAX_PORT_ADD_UNSUCCESS;
9712 #ifdef CGNAPT_DBG_PRNT
9713 if (CGNAPT_DEBUG > 2)
9714 printf("max_port_per_client_add_entry fn:"
9715 "Add entry index(%d)\n", index);
9718 max_port_per_client_array[index].prv_ip = prv_ip_param;
9719 max_port_per_client_array[index].prv_phy_port =
9723 max_port_per_client_array[index].max_port_cnt++;
9724 return MAX_PORT_ADD_SUCCESS;
9728 * Function to delete a max ports per client entry
9730 * @param prv_ip_param
9731 * A uint32_t ip address of client
9732 * @param prv_phy_port_param
9733 * A uint32_t physical port id of the client
9735 * A pointer to struct pipeline_cgnapt
9738 * 0 no success, 1 if success, -1 if error
9740 int max_port_per_client_del_entry(
9741 uint32_t prv_ip_param,
9742 uint32_t prv_phy_port_param,
9743 __rte_unused struct pipeline_cgnapt *p_nat)
9745 int index = MAX_PORT_DEL_ERROR;
9747 struct max_port_per_client_key key = {
9748 .prv_ip = prv_ip_param,
9749 .prv_phy_port = prv_phy_port_param,
9752 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9754 if (index == -EINVAL)
9755 return MAX_PORT_DEL_ERROR;
9757 if (index == -ENOENT)
9758 return MAX_PORT_DEL_UNSUCCESS;
9760 index = rte_hash_del_key(max_port_per_client_hash, (const void *)&key);
9761 max_port_per_client_array[index].prv_ip = 0;
9762 max_port_per_client_array[index].prv_phy_port = 0;
9763 max_port_per_client_array[index].max_port_cnt = 0;
9765 return MAX_PORT_DEL_SUCCESS;
9769 * Function to execute debug commands
9772 * A pointer to struct pipeline
9774 * void pointer to incoming arguments
9776 void *pipeline_cgnapt_msg_req_entry_dbg_handler(struct pipeline *p, void *msg)
9778 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9780 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9784 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_STATS_SHOW) {
9785 printf("\nCG-NAPT Packet Stats:\n");
9786 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
9787 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
9788 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
9789 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
9790 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
9791 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
9792 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
9794 #ifdef CGNAPT_DEBUGGING
9795 printf("\n Drop detail 1:%" PRIu64 ",",
9796 p_nat->naptDroppedPktCount1);
9797 printf("\n Drop detail 2:%" PRIu64 ",",
9798 p_nat->naptDroppedPktCount2);
9799 printf("\n Drop detail 3:%" PRIu64 ",",
9800 p_nat->naptDroppedPktCount3);
9801 printf("\n Drop detail 4:%" PRIu64 ",",
9802 p_nat->naptDroppedPktCount4);
9803 printf("\n Drop detail 5:%" PRIu64 ",",
9804 p_nat->naptDroppedPktCount5);
9805 printf("\n Drop detail 6:%" PRIu64 "",
9806 p_nat->naptDroppedPktCount6);
9808 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9809 p_nat->missedpktcount1,
9810 p_nat->missedpktcount2);
9811 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9812 p_nat->missedpktcount3,
9813 p_nat->missedpktcount4);
9814 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9815 p_nat->missedpktcount5,
9816 p_nat->missedpktcount6);
9817 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9818 p_nat->missedpktcount7,
9819 p_nat->missedpktcount8);
9820 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9821 p_nat->missedpktcount9,
9822 p_nat->missedpktcount10);
9829 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_STATS_CLEAR) {
9830 printf("\nCG-NAPT Packet Stats:\n");
9831 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
9832 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
9833 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
9834 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
9835 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
9836 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
9837 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
9839 p_nat->naptedPktCount = 0;
9840 p_nat->naptDroppedPktCount = 0;
9841 p_nat->inaptedPktCount = 0;
9842 p_nat->enaptedPktCount = 0;
9843 p_nat->receivedPktCount = 0;
9844 p_nat->missedPktCount = 0;
9845 p_nat->arpicmpPktCount = 0;
9846 printf("CG-NAPT Packet Stats cleared\n");
9850 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DBG_LEVEL) {
9851 CGNAPT_DEBUG = Msg[CGNAPT_DBG_CMD_OFST + 1];
9852 printf("CG-NAPT debug level set to %d\n", CGNAPT_DEBUG);
9856 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DBG_SHOW) {
9858 printf("\nNAPT entries - added %" PRIu64 ",",
9859 p_nat->n_cgnapt_entry_added);
9860 printf("deleted %" PRIu64 ",", p_nat->n_cgnapt_entry_deleted);
9861 printf("current %" PRIu64 "", p_nat->n_cgnapt_entry_added -
9862 p_nat->n_cgnapt_entry_deleted);
9864 printf("\nCG-NAPT Packet Stats:\n");
9865 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
9866 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
9867 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
9868 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
9869 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
9870 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
9871 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
9875 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
9876 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_INSTRUMENTATION) {
9877 if (Msg[CGNAPT_DBG_CMD_OFST1] ==
9878 CGNAPT_CMD_INSTRUMENTATION_SUB0) {
9881 uint32_t diff_sum = 0;
9883 printf("CG-NAPT Instrumentation ...\n");
9884 printf("Instrumentation data collected for fn# %d\n",
9885 cgnapt_num_func_to_inst);
9886 printf("Current collection index %d\n",
9889 if (Msg[CGNAPT_DBG_CMD_OFST + 2] == 2) {
9890 printf("Timer Start:\n");
9892 for (index = 0; index < INST_ARRAY_SIZE; index++) {
9893 if ((index % 5) == 0)
9895 printf(" 0x%jx", inst_start_time[index]);
9897 printf("\n\nTimer End:\n");
9899 for (index = 0; index < INST_ARRAY_SIZE; index++) {
9900 if ((index % 5) == 0)
9902 printf(" 0x%jx", inst_end_time[index]);
9906 for (index = 0; index < INST_ARRAY_SIZE; index++) {
9907 inst_diff_time[index] = (uint32_t) (inst_end_time[index] -
9908 inst_start_time[index]);
9911 if (Msg[CGNAPT_DBG_CMD_OFST + 2] ==
9912 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
9913 printf("\n\nTimer Diff:\n");
9915 for (index = 0; index < INST_ARRAY_SIZE; index++) {
9916 if (Msg[CGNAPT_DBG_CMD_OFST + 2] ==
9917 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
9918 if ((index % 5) == 0)
9920 printf(" 0x%08x", inst_diff_time[index]);
9923 diff_sum += inst_diff_time[index];
9926 printf("\ndiff_sum %u, INST_ARRAY_SIZE %d, Ave Time %u\n",
9927 diff_sum, INST_ARRAY_SIZE, (diff_sum / INST_ARRAY_SIZE));
9928 } else if (Msg[CGNAPT_DBG_CMD_OFST + 1] ==
9929 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
9930 /* p plid entry dbg 7 1 0
9931 * p plid entry dbg 7 1 1 <--- pkt_work_cgnapt
9932 * p plid entry dbg 7 1 2 <--- pkt4_work_cgnapt
9933 * p plid entry dbg 7 1 3 <--- pkt_work_cgnapt_key
9934 * p plid entry dbg 7 1 4 <--- pkt4_work_cgnapt_key
9935 * p plid entry dbg 7 1 5 <--- in port ah to out port ah
9936 * - pkt life in the system
9937 * p plid entry dbg 7 1 6 <--- how long this instrumentation
9940 cgnapt_inst_index = 0;
9941 cgnapt_num_func_to_inst = Msg[CGNAPT_DBG_CMD_OFST + 2];
9942 printf("Instrumentation data collection started for fn# %d\n",
9943 cgnapt_num_func_to_inst);
9944 } else if (Msg[CGNAPT_DBG_CMD_OFST + 1] ==
9945 CGNAPT_CMD_INSTRUMENTATION_SUB2) {
9946 /* p plid entry dbg 7 2 0
9947 * Test all major functions by calling them multiple times
9948 * pkt_work_cgnapt, pkt4_work_cgnapt, pkt_work_cgnapt_key,
9949 * pkt4_work_cgnapt_key
9951 if (cgnapt_test_pktmbuf_pool == NULL) {
9952 cgnapt_test_pktmbuf_pool = rte_pktmbuf_pool_create(
9953 "cgnapt_test_pktmbuf_pool", 63, 32, 0,
9954 RTE_MBUF_DEFAULT_BUF_SIZE,
9958 if (cgnapt_test_pktmbuf_pool == NULL)
9959 printf("CGNAPT test mbuf pool create failed.\n");
9961 struct rte_mbuf *cgnapt_test_pkt0 =
9962 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
9963 if (cgnapt_test_pkt0 == NULL)
9964 printf("CGNAPT test pkt 0 alloc failed.");
9965 struct rte_mbuf *cgnapt_test_pkt1 =
9966 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
9967 if (cgnapt_test_pkt1 == NULL)
9968 printf("CGNAPT test pkt 1 alloc failed.");
9969 struct rte_mbuf *cgnapt_test_pkt2 =
9970 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
9971 if (cgnapt_test_pkt2 == NULL)
9972 printf("CGNAPT test pkt 2 alloc failed.");
9973 struct rte_mbuf *cgnapt_test_pkt3 =
9974 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
9975 if (cgnapt_test_pkt3 == NULL)
9976 printf("CGNAPT test pkt 3 alloc failed.");
9978 struct rte_mbuf *cgnapt_test_pkts[4];
9980 cgnapt_test_pkts[0] = cgnapt_test_pkt0;
9981 cgnapt_test_pkts[1] = cgnapt_test_pkt1;
9982 cgnapt_test_pkts[2] = cgnapt_test_pkt2;
9983 cgnapt_test_pkts[3] = cgnapt_test_pkt3;
9985 uint32_t src_addr_offset =
9986 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_SRC_ADR_OFST;
9987 /* header room + eth hdr size +
9988 * src_aadr offset in ip header
9990 uint32_t dst_addr_offset =
9991 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
9992 /* header room + eth hdr size +
9993 * dst_aadr offset in ip header
9995 uint32_t prot_offset =
9996 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_PROTOCOL_OFST;
9997 /* header room + eth hdr size +
9998 * srprotocol char offset in ip header
10000 int pktCnt = 0, entCnt = 0, exCnt = 0;
10002 for (pktCnt = 0; pktCnt < 4; pktCnt++) {
10003 uint32_t *src_addr =
10004 RTE_MBUF_METADATA_UINT32_PTR
10005 (cgnapt_test_pkts[pktCnt], src_addr_offset);
10006 uint32_t *dst_addr =
10007 RTE_MBUF_METADATA_UINT32_PTR
10008 (cgnapt_test_pkts[pktCnt], dst_addr_offset);
10009 uint8_t *protocol =
10010 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10013 uint8_t *phy_port =
10014 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10016 uint8_t *eth_dest =
10017 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10021 RTE_MBUF_METADATA_UINT8_PTR(
10022 cgnapt_test_pkts[pktCnt],
10025 uint16_t *src_port =
10026 RTE_MBUF_METADATA_UINT16_PTR
10027 (cgnapt_test_pkts[pktCnt],
10028 MBUF_HDR_ROOM + ETH_HDR_SIZE +
10030 uint16_t *dst_port =
10031 RTE_MBUF_METADATA_UINT16_PTR
10032 (cgnapt_test_pkts[pktCnt],
10033 MBUF_HDR_ROOM + ETH_HDR_SIZE +
10035 *src_addr = 0xc0a80001;
10036 *dst_addr = 0x90418634;
10047 eth_dest[0] = 0x90;
10048 eth_dest[1] = 0xE2;
10049 eth_dest[2] = 0xba;
10050 eth_dest[3] = 0x54;
10051 eth_dest[4] = 0x67;
10052 eth_dest[5] = 0xc8;
10054 struct rte_pipeline_table_entry *table_entries[4];
10055 struct cgnapt_table_entry ctable_entries[4];
10056 table_entries[0] = (struct rte_pipeline_table_entry *)
10057 &ctable_entries[0];
10058 table_entries[1] = (struct rte_pipeline_table_entry *)
10059 &ctable_entries[1];
10060 table_entries[2] = (struct rte_pipeline_table_entry *)
10061 &ctable_entries[2];
10062 table_entries[3] = (struct rte_pipeline_table_entry *)
10063 &ctable_entries[3];
10064 for (entCnt = 0; entCnt < 4; entCnt++) {
10065 ctable_entries[entCnt].head.action =
10066 RTE_PIPELINE_ACTION_PORT;
10067 ctable_entries[entCnt].head.port_id = 0;
10069 ctable_entries[entCnt].data.prv_ip = 0x01020304;
10070 ctable_entries[entCnt].data.prv_port = 1234;
10071 ctable_entries[entCnt].data.pub_ip = 0x0a0b0c0d;
10072 ctable_entries[entCnt].data.pub_port = 4000;
10073 ctable_entries[entCnt].data.prv_phy_port = 0;
10074 ctable_entries[entCnt].data.pub_phy_port = 1;
10075 ctable_entries[entCnt].data.ttl = 500;
10078 uint64_t time1 = rte_get_tsc_cycles();
10080 for (exCnt = 0; exCnt < 1000; exCnt++) {
10081 pkt_work_cgnapt_key(cgnapt_test_pkts[0],
10082 instrumentation_port_in_arg);
10084 uint64_t time2 = rte_get_tsc_cycles();
10086 printf("times for %d times execution of "
10087 "pkt_work_cgnapt_key 0x%jx",
10089 printf(", 0x%jx, diff %" PRIu64 "\n", time2,
10092 time1 = rte_get_tsc_cycles();
10093 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10094 pkt_work_cgnapt_key(cgnapt_test_pkts[0],
10095 instrumentation_port_in_arg);
10097 time2 = rte_get_tsc_cycles();
10098 printf("times for %d times execution of "
10099 "pkt_work_cgnapt_key 0x%jx", exCnt, time1);
10100 printf("0x%jx, diff %" PRIu64 "\n", time2,
10103 time1 = rte_get_tsc_cycles();
10104 for (exCnt = 0; exCnt < 1000; exCnt++) {
10105 pkt4_work_cgnapt_key(cgnapt_test_pkts,
10106 instrumentation_port_in_arg);
10108 time2 = rte_get_tsc_cycles();
10109 printf("times for %d times execution of "
10110 "pkt4_work_cgnapt_key 0x%jx",
10112 printf(" 0x%jx, diff %" PRIu64 "\n", time2,
10115 time1 = rte_get_tsc_cycles();
10116 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10117 pkt4_work_cgnapt_key(cgnapt_test_pkts,
10118 instrumentation_port_in_arg);
10120 time2 = rte_get_tsc_cycles();
10121 printf("times for %d times execution of "
10122 "pkt4_work_cgnapt_key 0x%jx",
10124 printf("0x%jx, diff %" PRIu64 "\n", time2,
10127 uint64_t mask = 0xff;
10129 time1 = rte_get_tsc_cycles();
10130 for (exCnt = 0; exCnt < 1000; exCnt++) {
10131 pkt_work_cgnapt(cgnapt_test_pkts[0],
10132 table_entries[0], 3, &mask,
10135 time2 = rte_get_tsc_cycles();
10136 printf("times for %d times execution of "
10137 "pkt_work_cgnapt 0x%jx",
10139 printf("0x%jx, diff %" PRIu64 "\n", time2,
10142 time1 = rte_get_tsc_cycles();
10143 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10144 pkt_work_cgnapt(cgnapt_test_pkts[0],
10145 table_entries[0], 3, &mask,
10148 time2 = rte_get_tsc_cycles();
10149 printf("times for %d times execution of "
10150 "pkt_work_cgnapt 0x%jx",
10152 printf("0x%jx, diff %" PRIu64 "\n", time2,
10155 time1 = rte_get_tsc_cycles();
10156 for (exCnt = 0; exCnt < 1000; exCnt++) {
10157 pkt4_work_cgnapt(cgnapt_test_pkts,
10158 table_entries, 0, &mask, NULL);
10160 time2 = rte_get_tsc_cycles();
10161 printf("times for %d times execution of "
10162 "pkt4_work_cgnapt 0x%jx",
10164 printf("0x%jx, diff % " PRIu64 "\n", time2,
10167 int idummy = ctable_entries[0].data.prv_port;
10177 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_LS_ENTRY) {
10178 printf("CG-NAPT be entries are:\n");
10179 printf("Pipeline pointer %p\n", p);
10183 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DYN) {
10184 printf("Total Number of dynamic napt entries: %" PRIu64 "\n",
10185 p_nat->dynCgnaptCount);
10187 #ifdef CGNAPT_DEBUGGING
10188 printf("MAX PORT PER CLIENT:");
10189 printf("%" PRIu64 ",%" PRIu64 ",%" PRIu64 "\n",
10190 p_nat->max_port_dec_err1, p_nat->max_port_dec_err2,
10191 p_nat->max_port_dec_err3);
10192 printf("MPPC success : %" PRIu64 "\n",
10193 p_nat->max_port_dec_success);
10195 printf("Release port:err:%" PRIu64 ",ret::%" PRIu64 ",get::%"
10196 PRIu64 ",suc::%" PRIu64 "\n", p_nat->pfb_err,
10197 p_nat->pfb_ret, p_nat->pfb_get, p_nat->pfb_suc);
10198 printf("Get port::err:%" PRIu64 ",ret::%" PRIu64 ",get::%"
10199 PRIu64 ",suc::%" PRIu64 "\n", p_nat->gfp_err,
10200 p_nat->gfp_ret, p_nat->gfp_get, p_nat->gfp_suc);
10201 printf("Ring Info:\n");
10202 rte_ring_dump(stdout, p_nat->port_alloc_ring);
10206 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_IPV6) {
10207 dual_stack_enable = Msg[CGNAPT_DBG_CMD_OFST + 1];
10208 printf("Dual Stack option set: %x\n", dual_stack_enable);
10212 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_MAPS_INFO) {
10213 pipelines_port_info();
10214 pipelines_map_info();
10218 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_ITER_COM_TBL) {
10219 uint32_t count = 0;
10227 rte_hash_iterate(napt_common_table, &key, &data,
10230 if ((index != -EINVAL) && (index != -ENOENT)) {
10231 printf("\n%04d ", count);
10232 rte_hexdump(stdout, "KEY", key,
10234 pipeline_cgnapt_entry_key));
10236 //print_key((struct pipeline_cgnapt_entry_key *)
10239 rte_hash_lookup(napt_common_table,
10241 print_cgnapt_entry(&napt_hash_tbl_entries
10246 } while (index != -ENOENT);
10250 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_IF_STATS) {
10252 struct app_params *app =
10253 (struct app_params *)p_nat->app_params_addr;
10256 cmd[0] = Msg[CGNAPT_DBG_CMD_OFST + 1];
10257 cmd[1] = Msg[CGNAPT_DBG_CMD_OFST + 2];
10259 case CGNAPT_IF_STATS_HWQ:
10260 printf("n_pktq_hwq_int :%d\n", app->n_pktq_hwq_in);
10261 printf("n_pktq_hwq_out :%d\n", app->n_pktq_hwq_out);
10265 for (i = 0; i < app->n_pktq_hwq_in; i++) {
10266 struct rte_eth_stats stats;
10268 rte_eth_stats_get(p_nat->links_map[i], &stats);
10270 if (is_phy_port_privte(i))
10271 printf("Private Port Stats %d\n", i);
10273 printf("Public Port Stats %d\n", i);
10275 printf("\n\tipackets : %" PRIu64 "",
10277 printf("\n\topackets : %" PRIu64 "",
10279 printf("\n\tierrors : %" PRIu64 "",
10281 printf("\n\toerrors : %" PRIu64 "",
10283 printf("\n\trx_nombuf: %" PRIu64 "",
10286 if (is_phy_port_privte(i))
10287 printf("Private Q:");
10289 printf("Public Q:");
10290 for (j = 0; j < RTE_ETHDEV_QUEUE_STAT_CNTRS;
10292 printf(" %" PRIu64 ", %" PRIu64 "|",
10293 stats.q_ipackets[j],
10294 stats.q_opackets[j]);
10302 case CGNAPT_IF_STATS_SWQ:
10304 printf("n_pktq_swq :%d\n", app->n_pktq_swq);
10306 if (cmd[1] < app->n_pktq_swq) {
10307 rte_ring_dump(stdout, app->swq[cmd[1]]);
10310 printf("SWQ number is invalid\n");
10313 case CGNAPT_IF_STATS_OTH:
10315 printf("config_file:%s\n", app->config_file);
10316 printf("script_file:%s\n", app->script_file);
10317 printf("parser_file:%s\n", app->parser_file);
10318 printf("output_file:%s\n", app->output_file);
10319 printf("n_msgq :%d\n", app->n_msgq);
10320 printf("n_pktq_tm :%d\n", app->n_pktq_tm);
10321 printf("n_pktq_source :%d\n", app->n_pktq_source);
10322 printf("n_pktq_sink :%d\n", app->n_pktq_sink);
10323 printf("n_pipelines :%d\n", app->n_pipelines);
10327 printf("Command does not match\n\n");
10335 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_MAX_CLI_PER_PUB_IP) {
10336 if (nat_only_config_flag) {
10337 printf("Command not supported for NAT only config.\n");
10342 printf("\tPublic IP: Num Clients\n");
10343 for (ii = 0; ii < CGNAPT_MAX_PUB_IP; ii++)
10344 printf("\t%x : %7d\n", all_public_ip[ii].ip,
10345 rte_atomic16_read(&all_public_ip[ii].count));
10349 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_PUB_IP_LIST) {
10352 for (i = 0; i < p_nat->pub_ip_count; i++)
10353 printf("%x : (%d,%d)\n", p_nat->pub_ip_port_set[i].ip,
10354 p_nat->pub_ip_port_set[i].start_port,
10355 p_nat->pub_ip_port_set[i].end_port);
10359 #ifdef CGNAPT_TIMING_INST
10360 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_TIMING_INST) {
10361 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 0) {
10362 p_nat->time_measurements_on = 1;
10363 p_nat->time_measurements = 0;
10364 printf("CGNAPT timing instrumentation turned on.\n");
10365 printf("Max samples %d\n", p_nat->max_time_mesurements);
10367 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 1) {
10368 p_nat->time_measurements_on = 0;
10369 printf("CGNAPT timing instrumentation turned off.\n");
10370 printf("Cur Samples %d\n", p_nat->time_measurements);
10372 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 2) {
10373 uint64_t sum = p_nat->external_time_sum +
10374 p_nat->internal_time_sum;
10375 uint64_t isump = (p_nat->internal_time_sum * 100) / sum;
10376 uint64_t esump = (p_nat->external_time_sum * 100) / sum;
10377 printf("CGNAPT timing instrumentation status ...\n");
10378 printf("Max Count %d, Cur Count %d, Status %d (1=ON)\n",
10379 p_nat->max_time_mesurements,
10380 p_nat->time_measurements,
10381 p_nat->time_measurements_on);
10382 printf("Internal Time Sum %" PRIu64 " , Ave %" PRIu64
10383 ", percent %" PRIu64 "\n",
10384 p_nat->internal_time_sum,
10385 (p_nat->internal_time_sum /
10386 p_nat->time_measurements), isump);
10387 printf("External Time Sum %" PRIu64 " , Ave %" PRIu64
10388 ", percent %" PRIu64 "\n",
10389 p_nat->external_time_sum,
10390 (p_nat->external_time_sum /
10391 p_nat->time_measurements), esump);
10398 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_PRINT_NSP) {
10399 struct cgnapt_nsp_node *ll = nsp_ll;
10401 while (ll != NULL) {
10402 fprintf(stderr, "NSP Prefix/Depth=>%x%x:%x%x:%x%x: "
10403 "%x%x:%x%x:%x%x:%x%x:%x%x/%d",
10404 ll->nsp.prefix[0], ll->nsp.prefix[1],
10405 ll->nsp.prefix[2], ll->nsp.prefix[3],
10406 ll->nsp.prefix[4], ll->nsp.prefix[5],
10407 ll->nsp.prefix[6], ll->nsp.prefix[7],
10408 ll->nsp.prefix[8], ll->nsp.prefix[9],
10409 ll->nsp.prefix[10], ll->nsp.prefix[11],
10410 ll->nsp.prefix[12], ll->nsp.prefix[13],
10411 ll->nsp.prefix[14], ll->nsp.prefix[15],
10420 printf("CG-NAPT debug handler called with wrong args %x %x\n", Msg[0],
10424 for (i = 0; i < 20; i++)
10425 printf("%02x ", Msg[i]);
10431 * Function to print num of clients per IP address
10434 void print_num_ip_clients(void)
10436 if (nat_only_config_flag) {
10437 printf("Command not supported for NAT only config.\n");
10442 printf("\tPublic IP: Num Clients\n");
10443 for (ii = 0; ii < CGNAPT_MAX_PUB_IP; ii++)
10444 printf("\t%08x : %7d\n", all_public_ip[ii].ip,
10445 rte_atomic16_read(&all_public_ip[ii].count));
10449 * Function to print CGNAPT version info
10452 * An unused pointer to struct pipeline
10454 * void pointer to incoming arguments
10456 void *pipeline_cgnapt_msg_req_ver_handler(__rte_unused struct pipeline *p,
10459 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
10460 uint8_t *Msg = msg;
10464 printf("CG-NAPT debug handler called with args %x %x, offset %d\n",
10465 Msg[CGNAPT_VER_CMD_OFST], Msg[CGNAPT_VER_CMD_OFST + 1],
10466 CGNAPT_VER_CMD_OFST);
10468 if (Msg[CGNAPT_VER_CMD_OFST] == CGNAPT_VER_CMD_VER) {
10469 printf("CGNAPT Version %s\n", CGNAPT_VERSION);
10472 printf("CG-NAPT Version handler called with wrong args %x %x\n",
10476 for (i = 0; i < 20; i++)
10477 printf("%02x ", Msg[i]);
10483 * Function to show CGNAPT stats
10486 void all_cgnapt_stats(char *buf)
10489 struct pipeline_cgnapt *p_nat;
10490 uint64_t receivedPktCount = 0;
10491 uint64_t missedPktCount = 0;
10492 uint64_t naptDroppedPktCount = 0;
10493 uint64_t naptedPktCount = 0;
10494 uint64_t inaptedPktCount = 0;
10495 uint64_t enaptedPktCount = 0;
10496 uint64_t arpicmpPktCount = 0;
10498 len += sprintf(buf + len, "\nCG-NAPT Packet Stats:\n");
10499 for (i = 0; i < n_cgnapt_pipeline; i++) {
10500 p_nat = all_pipeline_cgnapt[i];
10502 receivedPktCount += p_nat->receivedPktCount;
10503 missedPktCount += p_nat->missedPktCount;
10504 naptDroppedPktCount += p_nat->naptDroppedPktCount;
10505 naptedPktCount += p_nat->naptedPktCount;
10506 inaptedPktCount += p_nat->inaptedPktCount;
10507 enaptedPktCount += p_nat->enaptedPktCount;
10508 arpicmpPktCount += p_nat->arpicmpPktCount;
10510 len += sprintf(buf + len, "pipeline %d stats:\n", p_nat->pipeline_num);
10511 len += sprintf(buf + len, "Received %" PRIu64 ",", p_nat->receivedPktCount);
10512 len += sprintf(buf + len, "Missed %" PRIu64 ",", p_nat->missedPktCount);
10513 len += sprintf(buf + len, "Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10514 len += sprintf(buf + len, "Translated %" PRIu64 ",", p_nat->naptedPktCount);
10515 len += sprintf(buf + len, "ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10516 len += sprintf(buf + len, "egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10517 len += sprintf(buf + len, "arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10519 printf("\nCG-NAPT Packet Stats:\n");
10520 printf("pipeline %d stats:\n", p_nat->pipeline_num);
10521 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10522 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10523 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10524 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10525 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10526 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10527 printf("arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10531 #ifdef CGNAPT_DEBUGGING
10532 len += sprintf(buf + len, "\n Drop detail 1:%" PRIu64 ",",
10533 p_nat->naptDroppedPktCount1);
10534 len += sprintf(buf + len, "\n Drop detail 2:%" PRIu64 ",",
10535 p_nat->naptDroppedPktCount2);
10536 len += sprintf(buf + len, "\n Drop detail 3:%" PRIu64 ",",
10537 p_nat->naptDroppedPktCount3);
10538 len += sprintf(buf + len, "\n Drop detail 4:%" PRIu64 ",",
10539 p_nat->naptDroppedPktCount4);
10540 len += sprintf(buf + len, "\n Drop detail 5:%" PRIu64 ",",
10541 p_nat->naptDroppedPktCount5);
10542 len += sprintf(buf + len, "\n Drop detail 6:%" PRIu64 "",
10543 p_nat->naptDroppedPktCount6);
10545 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10546 p_nat->missedpktcount1,
10547 p_nat->missedpktcount2);
10548 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10549 p_nat->missedpktcount3,
10550 p_nat->missedpktcount4);
10551 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10552 p_nat->missedpktcount5,
10553 p_nat->missedpktcount6);
10554 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10555 p_nat->missedpktcount7,
10556 p_nat->missedpktcount8);
10557 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10558 p_nat->missedpktcount9,
10559 p_nat->missedpktcount10);
10565 len += sprintf(buf + len, "\nTotal pipeline stats:\n");
10566 len += sprintf(buf + len, "Received %" PRIu64 ",", receivedPktCount);
10567 len += sprintf(buf + len, "Missed %" PRIu64 ",", missedPktCount);
10568 len += sprintf(buf + len, "Dropped %" PRIu64 ",", naptDroppedPktCount);
10569 len += sprintf(buf + len, "Translated %" PRIu64 ",", naptedPktCount);
10570 len += sprintf(buf + len, "ingress %" PRIu64 ",", inaptedPktCount);
10571 len += sprintf(buf + len, "egress %" PRIu64 "\n", enaptedPktCount);
10572 len += sprintf(buf + len, "arpicmp pkts %" PRIu64 "\n", arpicmpPktCount);
10574 printf("\nTotal pipeline stats:\n");
10575 printf("Received %" PRIu64 ",", receivedPktCount);
10576 printf("Missed %" PRIu64 ",", missedPktCount);
10577 printf("Dropped %" PRIu64 ",", naptDroppedPktCount);
10578 printf("Translated %" PRIu64 ",", naptedPktCount);
10579 printf("ingress %" PRIu64 ",", inaptedPktCount);
10580 printf("egress %" PRIu64 "\n", enaptedPktCount);
10581 printf("arpicmp pkts %" PRIu64 "\n", arpicmpPktCount);
10583 if (!rest_api_supported())
10584 printf("%s\n", buf);
10587 void all_cgnapt_clear_stats(char *buf)
10590 struct pipeline_cgnapt *p_nat;
10591 len += sprintf(buf + len, "\nCG-NAPT Packet Stats:\n");
10592 for (i = 0; i < n_cgnapt_pipeline; i++) {
10593 p_nat = all_pipeline_cgnapt[i];
10595 len += sprintf(buf + len, "pipeline %d stats:\n", p_nat->pipeline_num);
10596 len += sprintf(buf + len, "Received %" PRIu64 ",", p_nat->receivedPktCount);
10597 len += sprintf(buf + len, "Missed %" PRIu64 ",", p_nat->missedPktCount);
10598 len += sprintf(buf + len, "Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10599 len += sprintf(buf + len, "Translated %" PRIu64 ",", p_nat->naptedPktCount);
10600 len += sprintf(buf + len, "ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10601 len += sprintf(buf + len, "egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10602 len += sprintf(buf + len, "arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10604 p_nat->receivedPktCount = 0;
10605 p_nat->missedPktCount = 0;
10606 p_nat->naptDroppedPktCount = 0;
10607 p_nat->naptedPktCount = 0;
10608 p_nat->inaptedPktCount = 0;
10609 p_nat->enaptedPktCount = 0;
10610 p_nat->arpicmpPktCount = 0;
10612 #ifdef CGNAPT_DEBUGGING
10613 len += sprintf(buf + len, "\n Drop detail 1:%" PRIu64 ",",
10614 p_nat->naptDroppedPktCount1);
10615 len += sprintf(buf + len, "\n Drop detail 2:%" PRIu64 ",",
10616 p_nat->naptDroppedPktCount2);
10617 len += sprintf(buf + len, "\n Drop detail 3:%" PRIu64 ",",
10618 p_nat->naptDroppedPktCount3);
10619 len += sprintf(buf + len, "\n Drop detail 4:%" PRIu64 ",",
10620 p_nat->naptDroppedPktCount4);
10621 len += sprintf(buf + len, "\n Drop detail 5:%" PRIu64 ",",
10622 p_nat->naptDroppedPktCount5);
10623 len += sprintf(buf + len, "\n Drop detail 6:%" PRIu64 "",
10624 p_nat->naptDroppedPktCount6);
10626 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10627 p_nat->missedpktcount1,
10628 p_nat->missedpktcount2);
10629 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10630 p_nat->missedpktcount3,
10631 p_nat->missedpktcount4);
10632 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10633 p_nat->missedpktcount5,
10634 p_nat->missedpktcount6);
10635 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10636 p_nat->missedpktcount7,
10637 p_nat->missedpktcount8);
10638 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10639 p_nat->missedpktcount9,
10640 p_nat->missedpktcount10);
10646 if (!rest_api_supported())
10647 printf("%s\n", buf);
10651 * Function to print common CGNAPT table entries
10654 void print_static_cgnapt_entries(void)
10656 uint32_t count = 0;
10661 struct cgnapt_table_entry *entry;
10663 index = rte_hash_iterate(napt_common_table,
10664 &key, &data, &next);
10666 if ((index != -EINVAL) && (index != -ENOENT)) {
10667 printf("\n%04d ", count);
10668 rte_hexdump(stdout, "KEY", key,
10669 sizeof(struct pipeline_cgnapt_entry_key));
10670 int32_t position = rte_hash_lookup(
10671 napt_common_table, key);
10672 entry = &napt_hash_tbl_entries[position];
10674 if (entry->data.timeout == STATIC_CGNAPT_TIMEOUT)
10675 rte_hexdump(stdout, "Entry",
10676 (const void *)entry,
10677 sizeof(struct cgnapt_table_entry));
10681 } while (index != -ENOENT);
10685 * Function to show CGNAPT stats
10689 struct pipeline_be_ops pipeline_cgnapt_be_ops = {
10690 .f_init = pipeline_cgnapt_init,
10691 .f_free = pipeline_cgnapt_free,
10693 .f_timer = pipeline_cgnapt_timer,
10694 .f_track = pipeline_cgnapt_track,