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 = pkts[pkt_index]->port;
1974 dest_if = prv_to_pub_map[src_phy_port];
1975 gw_get_route_nh_port_ipv4(dest_address,
1976 &dest_if, &nhip, dest_if);
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 = pkts[pkt_index]->port;
2221 dest_if = pub_to_prv_map[src_phy_port];
2222 gw_get_route_nh_port_ipv4(dest_address,
2223 &dest_if, &nhip, dest_if);
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 = pkt->port;
3731 dest_if = prv_to_pub_map[src_phy_port];
3732 gw_get_route_nh_port_ipv4(dest_address,
3733 &dest_if, &nhip, dest_if);
3735 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if,
3736 (struct ether_addr *)eth_dest);
3738 *outport_id = p_nat->outport_id[dest_if];
3740 if (arp_cache_dest_mac_present(dest_if)) {
3741 ether_addr_copy(get_link_hw_addr(dest_if),(struct ether_addr *)eth_src);
3742 update_nhip_access(dest_if);
3743 if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) {
3744 p_nat->naptedPktCount += ret_arp_data->num_pkts;
3745 arp_send_buffered_pkts(ret_arp_data,
3746 (struct ether_addr *)eth_dest, *outport_id);
3751 if (unlikely(ret_arp_data == NULL)) {
3753 #ifdef CGNAPT_DEBUGGING
3754 printf("%s: NHIP Not Found, nhip:%x , "
3755 "outport_id: %d\n", __func__, nhip,
3760 p_nat->invalid_packets |= pkt_mask;
3761 p_nat->naptDroppedPktCount++;
3763 #ifdef CGNAPT_DEBUGGING
3764 p_nat->naptDroppedPktCount4++;
3769 if (ret_arp_data->status == INCOMPLETE ||
3770 ret_arp_data->status == PROBE) {
3771 if (ret_arp_data->num_pkts >= NUM_DESC) {
3773 p_nat->invalid_packets |= pkt_mask;
3774 p_nat->naptDroppedPktCount++;
3776 #ifdef CGNAPT_DEBUGGING
3777 p_nat->naptDroppedPktCount4++;
3781 arp_pkts_mask |= pkt_mask;
3782 arp_queue_unresolved_packet(ret_arp_data, pkt);
3791 *src_addr = rte_bswap32(entry->data.pub_ip);
3794 #ifdef NAT_ONLY_CONFIG_REQ
3795 if (!nat_only_config_flag) {
3797 *src_port = rte_bswap16(entry->data.pub_port);
3798 #ifdef NAT_ONLY_CONFIG_REQ
3803 uint16_t rtp_port = 0, rtcp_port = 0;
3804 struct cgnapt_table_entry *entry_ptr1 = NULL,
3805 *entry_ptr2 = NULL, *entry_ptr3 = NULL,
3808 if (unlikely(protocol == IP_PROTOCOL_UDP
3809 && (rte_be_to_cpu_16(*dst_port) == 5060
3810 || rte_be_to_cpu_16(*src_port) == 5060))) {
3812 int ret = natSipAlgGetAudioPorts(pkt, &rtp_port,
3814 /* Commented code may be required for debug
3815 * and future use, Please keep it*/
3818 printf("%s: Wrong SIP ALG packet1\n",
3820 p_nat->invalid_packets |= pkt_mask;
3822 p_nat->naptDroppedPktCount++;
3824 #ifdef CGNAPT_DEBUGGING
3825 p_nat->naptDroppedPktCount4++;
3831 if (ret >= 0 && rtp_port != 0) {
3832 struct pipeline_cgnapt_entry_key rtp_key;
3833 rtp_key.ip = entry->data.u.prv_ip;
3834 rtp_key.port = rtp_port;
3835 rtp_key.pid = entry->data.prv_phy_port;
3837 if (add_dynamic_cgnapt_entry_alg(
3838 (struct pipeline *)p_nat, &rtp_key,
3839 &entry_ptr1, &entry_ptr2) == 0) {
3840 printf("%s: Wrong SIP ALG packet2\n",
3842 p_nat->invalid_packets |= pkt_mask;
3844 p_nat->naptDroppedPktCount++;
3846 #ifdef CGNAPT_DEBUGGING
3847 p_nat->naptDroppedPktCount4++;
3853 if (ret >= 0 && rtcp_port != 0) {
3854 struct pipeline_cgnapt_entry_key rtcp_key;
3855 rtcp_key.ip = entry->data.u.prv_ip;
3856 rtcp_key.port = rtcp_port;
3857 rtcp_key.pid = entry->data.prv_phy_port;
3859 if (add_dynamic_cgnapt_entry_alg(
3860 (struct pipeline *)p_nat, &rtcp_key,
3861 &entry_ptr3, &entry_ptr4) == 0) {
3862 printf("%s: Wrong SIP ALG packet3\n",
3864 p_nat->invalid_packets |= pkt_mask;
3866 p_nat->naptDroppedPktCount++;
3868 #ifdef CGNAPT_DEBUGGING
3869 p_nat->naptDroppedPktCount4++;
3875 //if(entry_ptr1 != NULL && entry_ptr3 != NULL)
3876 if (sip_alg_dpi(pkt, PRIVATE, entry->data.pub_ip,
3877 entry->data.pub_port, entry->data.u.prv_ip,
3878 entry->data.prv_port, (rtp_port == 0) ? 0 :
3879 entry_ptr1->data.pub_port,
3880 (rtcp_port == 0) ? 0 :
3881 entry_ptr3->data.pub_port) == 0) {
3883 printf("%s: Wrong SIP ALG packet4\n",
3885 p_nat->invalid_packets |= pkt_mask;
3887 p_nat->naptDroppedPktCount++;
3889 #ifdef CGNAPT_DEBUGGING
3890 p_nat->naptDroppedPktCount4++;
3895 #endif /* SIP_ALG */
3900 printf("@CGNAT-pktwork ct_position :%d, pkt_num %d pkt_mask= "
3901 "%" PRIu64 "\n", ct_position, pkt_num, pkt_mask);
3904 if ((rte_be_to_cpu_16(*src_port) == 21) ||
3905 rte_be_to_cpu_16(*dst_port) == 21) {
3907 int32_t ct_position = cgnat_cnxn_tracker->positions[pkt_num];
3908 if (ct_position < 0){
3909 p_nat->invalid_packets |= pkt_mask;
3910 p_nat->naptDroppedPktCount++;
3913 /* Commented code may be required for future usage,
3916 //if (cgnat_cnxn_tracker->hash_table_entries
3917 // [ct_position].alg_bypass_flag != BYPASS)
3919 struct pipeline_cgnapt_entry_key data_channel_entry_key;
3921 data_channel_entry_key.ip = entry->data.pub_ip;
3922 data_channel_entry_key.port = entry->data.pub_port;
3923 data_channel_entry_key.pid = pkt->port;
3924 ftp_alg_dpi(p_nat, &data_channel_entry_key, pkt,
3925 cgnat_cnxn_tracker, ct_position, PRIVATE);
3928 #endif /* FTP_ALG */
3930 p_nat->enaptedPktCount++;
3933 p_nat->naptedPktCount++;
3936 if (p_nat->hw_checksum_reqd)
3937 hw_checksum(pkt, pkt_type);
3939 sw_checksum(pkt, pkt_type);
3946 * NAPT function for IPv4 public traffic which handles 1 pkt
3949 * A pointer to array of packet mbuf
3955 * A pointer to main CGNAPT structure
3959 pkt_work_cgnapt_ipv4_pub(
3960 struct rte_mbuf **pkts,
3962 __rte_unused void *arg,
3963 struct pipeline_cgnapt *p_nat)
3967 struct rte_CT_helper ct_helper;
3968 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
3971 /* index into hash table entries */
3972 int hash_table_entry = p_nat->lkup_indx[pkt_num];
3973 /*bitmask representing only this packet */
3974 uint64_t pkt_mask = 1LLU << pkt_num;
3975 struct rte_mbuf *pkt = pkts[pkt_num];
3977 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3979 uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */
3980 uint16_t *outport_id =
3981 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
3983 struct cgnapt_table_entry *entry = NULL;
3985 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
3987 if (hash_table_entry < 0) {
3989 /* try to add new entry */
3990 struct rte_pipeline_table_entry *table_entry = NULL;
3992 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
3994 &p_nat->valid_packets, pkt_num,
3998 /* ICMP Error message generation for
3999 * Destination Host unreachable
4001 if (protocol == IP_PROTOCOL_ICMP) {
4002 cgnapt_icmp_pkt = pkt;
4003 send_icmp_dest_unreachable_msg();
4006 /* Drop packet by adding to invalid pkt mask */
4008 p_nat->invalid_packets |= dropmask;
4009 #ifdef CGNAPT_DEBUGGING
4010 if (p_nat->kpc2++ < 5) {
4011 printf("in_ah Th: %d", p_nat->pipeline_num);
4012 print_key(p_nat->key_ptrs[pkt_num]);
4016 p_nat->naptDroppedPktCount++;
4018 #ifdef CGNAPT_DEBUGGING
4019 p_nat->naptDroppedPktCount3++;
4024 entry = (struct cgnapt_table_entry *)table_entry;
4026 /* entry found for this packet */
4027 entry = &napt_hash_tbl_entries[hash_table_entry];
4030 /* apply napt and mac changes */
4032 p_nat->entries[pkt_num] = &(entry->head);
4034 uint32_t *dst_addr =
4035 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4036 uint16_t src_port_offset = 0;
4037 uint16_t dst_port_offset = 0;
4039 if ((protocol == IP_PROTOCOL_TCP) || (protocol == IP_PROTOCOL_UDP)) {
4040 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4041 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4042 } else if (protocol == IP_PROTOCOL_ICMP) {
4044 src_port_offset = MBUF_HDR_ROOM +
4047 /*Sequence number */
4048 dst_port_offset = MBUF_HDR_ROOM +
4053 uint16_t *src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
4054 uint16_t *dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
4056 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4057 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4059 if (entry->data.ttl == NAPT_ENTRY_STALE)
4060 entry->data.ttl = NAPT_ENTRY_VALID;
4062 uint32_t dest_address = 0;
4064 /* Multiport Changes */
4070 if (unlikely(protocol == IP_PROTOCOL_UDP
4071 && rte_be_to_cpu_16(*src_port) == 53)) {
4072 p_nat->invalid_packets |= pkt_mask;
4073 p_nat->naptDroppedPktCount++;
4074 #ifdef CGNAPT_DEBUGGING
4075 p_nat->naptDroppedPktCount6++;
4081 dest_address = entry->data.u.prv_ip;
4082 struct arp_entry_data *ret_arp_data = NULL;
4084 uint32_t src_phy_port = pkt->port;
4086 dest_if = pub_to_prv_map[src_phy_port];
4087 gw_get_route_nh_port_ipv4(dest_address,
4088 &dest_if, &nhip, dest_if);
4090 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if,
4091 (struct ether_addr *)eth_dest);
4092 *outport_id = p_nat->outport_id[dest_if];
4094 if (arp_cache_dest_mac_present(dest_if)) {
4095 ether_addr_copy(get_link_hw_addr(dest_if), (struct ether_addr *)eth_src);
4096 update_nhip_access(dest_if);
4098 if (ret_arp_data && ret_arp_data->num_pkts) {
4099 p_nat->naptedPktCount += ret_arp_data->num_pkts;
4100 arp_send_buffered_pkts(ret_arp_data,
4101 (struct ether_addr *)eth_dest, *outport_id);
4106 if (unlikely(ret_arp_data == NULL)) {
4108 /* Commented code may be required for debug
4109 * and future use, Please keep it */
4111 #ifdef CGNAPT_DEBUGGING
4112 printf("%s: NHIP Not Found, nhip: %x, "
4113 "outport_id: %d\n", __func__, nhip,
4118 p_nat->invalid_packets |= pkt_mask;
4119 p_nat->naptDroppedPktCount++;
4121 #ifdef CGNAPT_DEBUGGING
4122 p_nat->naptDroppedPktCount4++;
4128 if (ret_arp_data->status == INCOMPLETE ||
4129 ret_arp_data->status == PROBE) {
4130 if (ret_arp_data->num_pkts >= NUM_DESC) {
4132 p_nat->invalid_packets |= pkt_mask;
4133 p_nat->naptDroppedPktCount++;
4135 #ifdef CGNAPT_DEBUGGING
4136 p_nat->naptDroppedPktCount4++;
4140 arp_pkts_mask |= pkt_mask;
4141 arp_queue_unresolved_packet(ret_arp_data, pkt);
4150 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
4151 if (protocol == IP_PROTOCOL_ICMP) {
4152 /* Query ID reverse translation done here */
4153 /* dont care sequence num */
4154 *src_port = rte_bswap16(entry->data.prv_port);
4157 #ifdef NAT_ONLY_CONFIG_REQ
4158 if (!nat_only_config_flag) {
4160 *dst_port = rte_bswap16(entry->data.prv_port);
4162 #ifdef NAT_ONLY_CONFIG_REQ
4166 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4167 rte_be_to_cpu_16(*dst_port) == 21) {
4168 pkt_mask = cgnapt_ct_process(cgnat_cnxn_tracker, pkts,
4169 pkt_mask, &ct_helper);
4175 uint16_t rtp_port = 0, rtcp_port = 0;
4176 struct cgnapt_table_entry *entry_ptr1 = NULL,
4179 /* Commented code may be required for debug
4180 * and future use, Please keep it */
4182 struct cgnapt_table_entry *entry_ptr2 = NULL,
4186 if (unlikely(protocol == IP_PROTOCOL_UDP
4187 && (rte_be_to_cpu_16(*dst_port) == 5060
4188 || rte_be_to_cpu_16(*src_port) == 5060))) {
4189 /* Commented code may be required for future usage,
4193 int ret = natSipAlgGetAudioPorts(pkt, &rtp_port,
4196 printf("%s: Wrong SIP ALG packet1\n",
4198 p_nat->invalid_packets |= pkt_mask;
4200 p_nat->naptDroppedPktCount++;
4202 #ifdef CGNAPT_DEBUGGING
4203 p_nat->naptDroppedPktCount4++;
4207 if (rtp_port != 0) {
4208 struct pipeline_cgnapt_entry_key rtp_key;
4209 rtp_key.ip = entry->data.pub_ip;
4210 rtp_key.port = rtp_port;
4211 rtp_key.pid = 0xffff;
4213 if (retrieve_cgnapt_entry_alg(&rtp_key,
4214 &entry_ptr1, &entry_ptr2) == 0) {
4215 printf("%s: Wrong SIP ALG packet2\n",
4217 p_nat->invalid_packets |= pkt_mask;
4219 p_nat->naptDroppedPktCount++;
4221 #ifdef CGNAPT_DEBUGGING
4222 p_nat->naptDroppedPktCount4++;
4228 if (rtcp_port != 0) {
4229 struct pipeline_cgnapt_entry_key rtcp_key;
4230 rtcp_key.ip = entry->data.pub_ip;
4231 rtcp_key.port = rtcp_port;
4232 rtcp_key.pid = 0xffff;
4234 if (retrieve_cgnapt_entry_alg(&rtcp_key,
4235 &entry_ptr3, &entry_ptr4) == 0) {
4236 printf("%s: Wrong SIP ALG packet3\n",
4238 p_nat->invalid_packets |= pkt_mask;
4240 p_nat->naptDroppedPktCount++;
4242 #ifdef CGNAPT_DEBUGGING
4243 p_nat->naptDroppedPktCount4++;
4251 if (sip_alg_dpi(pkt, PUBLIC, entry->data.u.prv_ip,
4252 entry->data.prv_port, entry->data.pub_ip,
4253 entry->data.pub_port, (rtp_port == 0) ? 0 :
4254 entry_ptr1->data.prv_port,
4255 (rtcp_port == 0) ? 0 :
4256 entry_ptr3->data.prv_port) == 0) {
4258 printf("%s: Wrong SIP ALG packet4\n",
4260 p_nat->invalid_packets |= pkt_mask;
4262 p_nat->naptDroppedPktCount++;
4264 #ifdef CGNAPT_DEBUGGING
4265 p_nat->naptDroppedPktCount4++;
4271 #endif /* SIP_ALG */
4274 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4275 rte_be_to_cpu_16(*dst_port) == 21) {
4276 int32_t ct_position = cgnat_cnxn_tracker->
4278 if (ct_position < 0){
4279 p_nat->invalid_packets |= pkt_mask;
4281 p_nat->naptDroppedPktCount++;
4285 rte_hexdump(stdout, "CT Entry", &cgnat_cnxn_tracker->
4286 hash_table_entries[ct_position].key, 40);
4289 /* Commented code may be required for debug
4290 * and future use, Please keep it*/
4291 //if (cgnat_cnxn_tracker->hash_table_entries
4292 // [ct_position].alg_bypass_flag != BYPASS)
4295 struct pipeline_cgnapt_entry_key
4296 data_channel_entry_key;
4298 data_channel_entry_key.ip = entry->data.pub_ip;
4299 data_channel_entry_key.port = entry->data.pub_port;
4300 data_channel_entry_key.pid = 0xffff;
4301 //printf("pkt_work_pub ftp_alg_dpi\n");
4302 ftp_alg_dpi(p_nat, &data_channel_entry_key, pkt,
4303 cgnat_cnxn_tracker, ct_position, PUBLIC);
4309 p_nat->inaptedPktCount++;
4312 p_nat->naptedPktCount++;
4315 if (p_nat->hw_checksum_reqd)
4316 hw_checksum(pkt, pkt_type);
4318 sw_checksum(pkt, pkt_type);
4324 * NAPT function for IPv4 private traffic which handles 4 pkts
4327 * A pointer to array of packets mbuf
4329 * Starting pkt number of pkts
4333 * A pointer to main CGNAPT structure
4337 pkt4_work_cgnapt_ipv4_prv(
4338 struct rte_mbuf **pkts,
4339 uint32_t in_pkt_num,
4340 __rte_unused void *arg,
4341 struct pipeline_cgnapt *p_nat)
4343 uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */
4344 struct rte_mbuf *pkt;
4347 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4350 struct rte_CT_helper ct_helper;
4351 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4354 for (i = 0; i < 4; i++) {
4355 pkt_num = in_pkt_num + i;
4356 pkt = pkts[pkt_num];
4358 /* index into hash table entries */
4359 int hash_table_entry = p_nat->lkup_indx[pkt_num];
4360 /*bitmask representing only this packet */
4361 uint64_t pkt_mask = 1LLU << pkt_num;
4363 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
4365 uint16_t *outport_id =
4366 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
4368 struct cgnapt_table_entry *entry = NULL;
4370 if (hash_table_entry < 0) {
4372 /* try to add new entry */
4373 struct rte_pipeline_table_entry *table_entry = NULL;
4376 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
4378 &p_nat->valid_packets, pkt_num,
4382 /* ICMP Error message generation for
4383 * Destination Host unreachable
4385 if (protocol == IP_PROTOCOL_ICMP) {
4386 cgnapt_icmp_pkt = pkt;
4387 send_icmp_dest_unreachable_msg();
4390 /* Drop packet by adding to invalid pkt mask */
4392 p_nat->invalid_packets |= dropmask;
4394 #ifdef CGNAPT_DEBUGGING
4395 if (p_nat->kpc2++ < 5) {
4396 printf("in_ah Th: %d",
4397 p_nat->pipeline_num);
4398 print_key(p_nat->key_ptrs[pkt_num]);
4402 p_nat->naptDroppedPktCount++;
4404 #ifdef CGNAPT_DEBUGGING
4405 p_nat->naptDroppedPktCount3++;
4410 entry = (struct cgnapt_table_entry *)table_entry;
4412 /* entry found for this packet */
4413 entry = &napt_hash_tbl_entries[hash_table_entry];
4416 /* apply napt and mac changes */
4418 p_nat->entries[pkt_num] = &(entry->head);
4420 uint32_t *src_addr =
4421 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP4);
4422 uint32_t *dst_addr =
4423 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4424 uint16_t src_port_offset = 0;
4425 uint16_t dst_port_offset = 0;
4430 if ((protocol == IP_PROTOCOL_TCP)
4431 || (protocol == IP_PROTOCOL_UDP)) {
4432 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4433 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4434 } else if (protocol == IP_PROTOCOL_ICMP) {
4436 src_port_offset = MBUF_HDR_ROOM +
4439 /*Sequence number */
4440 dst_port_offset = MBUF_HDR_ROOM +
4447 case IP_PROTOCOL_TCP:
4448 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4449 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4450 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4452 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4456 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4457 rte_be_to_cpu_16(*dst_port) == 21) {
4459 //To process CT , pkt_mask does it need
4460 //to be complemented ??
4462 printf("cgnapt_ct_process: pkt_mask: "
4463 "% "PRIu64", pkt_num: %d\n",
4467 pkt_mask = cgnapt_ct_process(
4468 cgnat_cnxn_tracker, pkts,
4469 pkt_mask, &ct_helper);
4473 case IP_PROTOCOL_UDP:
4474 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4475 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4476 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4478 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4481 case IP_PROTOCOL_ICMP:
4483 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
4485 /*Sequence number */
4486 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
4488 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4490 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4493 default: /* KW fix: unknown is treated as TCP/UDP */
4494 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4495 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4496 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4498 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4505 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4507 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4509 if (entry->data.ttl == NAPT_ENTRY_STALE)
4510 entry->data.ttl = NAPT_ENTRY_VALID;
4512 uint32_t dest_address = 0;
4513 /*Multiport Changes */
4520 if (unlikely(protocol == IP_PROTOCOL_UDP
4521 && rte_be_to_cpu_16(*dst_port) == 53)) {
4522 p_nat->invalid_packets |= pkt_mask;
4523 p_nat->naptDroppedPktCount++;
4525 #ifdef CGNAPT_DEBUGGING
4526 p_nat->naptDroppedPktCount6++;
4532 dest_address = rte_bswap32(*dst_addr);
4533 struct arp_entry_data *ret_arp_data = NULL;
4534 uint64_t start, end;
4535 uint32_t src_phy_port = pkt->port;
4536 dest_if = prv_to_pub_map[src_phy_port];
4537 gw_get_route_nh_port_ipv4(dest_address,
4538 &dest_if, &nhip, dest_if);
4540 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if,
4541 (struct ether_addr *)eth_dest);
4543 *outport_id = p_nat->outport_id[dest_if];
4545 if (arp_cache_dest_mac_present(dest_if)) {
4546 ether_addr_copy(get_link_hw_addr(dest_if),
4547 (struct ether_addr *)eth_src);
4548 update_nhip_access(dest_if);
4550 if (ret_arp_data && ret_arp_data->num_pkts) {
4551 p_nat->naptedPktCount += ret_arp_data->num_pkts;
4552 arp_send_buffered_pkts(ret_arp_data,
4553 (struct ether_addr *)eth_dest, *outport_id);
4558 if (unlikely(ret_arp_data == NULL)) {
4560 #ifdef CGNAPT_DEBUGGING
4561 printf("%s: ARP Not Found, nhip: %x, "
4562 "outport_id: %d\n", __func__, nhip,
4567 p_nat->invalid_packets |= pkt_mask;
4568 p_nat->naptDroppedPktCount++;
4570 #ifdef CGNAPT_DEBUGGING
4571 p_nat->naptDroppedPktCount4++;
4577 if (ret_arp_data->status == INCOMPLETE ||
4578 ret_arp_data->status == PROBE) {
4579 if (ret_arp_data->num_pkts >= NUM_DESC) {
4581 p_nat->invalid_packets |= pkt_mask;
4582 p_nat->naptDroppedPktCount++;
4584 #ifdef CGNAPT_DEBUGGING
4585 p_nat->naptDroppedPktCount4++;
4589 arp_pkts_mask |= pkt_mask;
4590 arp_queue_unresolved_packet(ret_arp_data, pkt);
4598 *src_addr = rte_bswap32(entry->data.pub_ip);
4600 #ifdef NAT_ONLY_CONFIG_REQ
4601 if (!nat_only_config_flag) {
4603 *src_port = rte_bswap16(entry->data.pub_port);
4604 #ifdef NAT_ONLY_CONFIG_REQ
4609 uint16_t rtp_port = 0, rtcp_port = 0;
4610 struct cgnapt_table_entry *entry_ptr1 = NULL,
4611 *entry_ptr2 = NULL, *entry_ptr3 = NULL,
4614 if (unlikely(protocol == IP_PROTOCOL_UDP
4615 && (rte_be_to_cpu_16(*dst_port) == 5060
4616 || rte_be_to_cpu_16(*src_port) == 5060))) {
4618 int ret = natSipAlgGetAudioPorts(pkt,
4619 &rtp_port, &rtcp_port);
4620 /* Commented code may be required for future usage,
4625 printf("%s: Wrong SIP ALG packet1\n",
4627 p_nat->invalid_packets |= pkt_mask;
4629 p_nat->naptDroppedPktCount++;
4631 #ifdef CGNAPT_DEBUGGING
4632 p_nat->naptDroppedPktCount4++;
4638 if (ret >= 0 && rtp_port != 0) {
4639 struct pipeline_cgnapt_entry_key rtp_key;
4640 rtp_key.ip = entry->data.u.prv_ip;
4641 rtp_key.port = rtp_port;
4642 rtp_key.pid = entry->data.prv_phy_port;
4644 if (add_dynamic_cgnapt_entry_alg(
4645 (struct pipeline *)p_nat, &rtp_key,
4646 &entry_ptr1, &entry_ptr2) == 0) {
4647 printf("%s: Wrong SIP ALG packet2\n",
4649 p_nat->invalid_packets |= pkt_mask;
4651 p_nat->naptDroppedPktCount++;
4653 #ifdef CGNAPT_DEBUGGING
4654 p_nat->naptDroppedPktCount4++;
4660 if (ret >= 0 && rtcp_port != 0) {
4661 struct pipeline_cgnapt_entry_key rtcp_key;
4662 rtcp_key.ip = entry->data.u.prv_ip;
4663 rtcp_key.port = rtcp_port;
4664 rtcp_key.pid = entry->data.prv_phy_port;
4666 if (add_dynamic_cgnapt_entry_alg(
4667 (struct pipeline *)p_nat, &rtcp_key,
4668 &entry_ptr3, &entry_ptr4) == 0) {
4670 printf("%s: Wrong SIP ALG packet3\n",
4672 p_nat->invalid_packets |= pkt_mask;
4674 p_nat->naptDroppedPktCount++;
4676 #ifdef CGNAPT_DEBUGGING
4677 p_nat->naptDroppedPktCount4++;
4683 //if(entry_ptr1 != NULL && entry_ptr3 != NULL)
4684 if (sip_alg_dpi(pkt, PRIVATE,
4686 entry->data.pub_port,
4687 entry->data.u.prv_ip,
4688 entry->data.prv_port,
4689 (rtp_port == 0) ? 0 :
4690 entry_ptr1->data.pub_port,
4691 (rtcp_port == 0) ? 0 :
4692 entry_ptr3->data.pub_port) == 0) {
4694 printf("%s: Wrong SIP ALG packet4\n",
4696 p_nat->invalid_packets |= pkt_mask;
4698 p_nat->naptDroppedPktCount++;
4700 #ifdef CGNAPT_DEBUGGING
4701 p_nat->naptDroppedPktCount4++;
4706 #endif /* SIP_ALG */
4709 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4710 rte_be_to_cpu_16(*dst_port) == 21) {
4712 int32_t ct_position =
4713 cgnat_cnxn_tracker->positions[pkt_num];
4715 printf("@CGNAT-pkt4work ct_position :%d, pkt_num %d "
4716 "pkt_mask = %" PRIu64 "\n", ct_position,
4720 if (ct_position < 0){
4721 p_nat->invalid_packets |= pkt_mask;
4722 p_nat->naptDroppedPktCount++;
4725 if (cgnat_cnxn_tracker->hash_table_entries[ct_position].
4726 alg_bypass_flag != BYPASS){
4728 struct pipeline_cgnapt_entry_key
4729 data_channel_entry_key;
4731 data_channel_entry_key.ip =
4733 data_channel_entry_key.port =
4734 entry->data.pub_port;
4735 data_channel_entry_key.pid = 0xffff;
4737 ftp_alg_dpi(p_nat, &data_channel_entry_key,
4738 pkt, cgnat_cnxn_tracker, ct_position,
4744 p_nat->enaptedPktCount++;
4747 p_nat->naptedPktCount++;
4750 if (p_nat->hw_checksum_reqd)
4751 hw_checksum(pkt, pkt_type);
4753 sw_checksum(pkt, pkt_type);
4759 * NAPT function for IPv4 public traffic which handles 4 pkts
4762 * A pointer to array of packets mbuf
4764 * Starting pkt number of pkts
4768 * A pointer to main CGNAPT structure
4772 pkt4_work_cgnapt_ipv4_pub(
4773 struct rte_mbuf **pkts,
4774 uint32_t in_pkt_num,
4775 __rte_unused void *arg,
4776 struct pipeline_cgnapt *p_nat)
4779 struct rte_CT_helper ct_helper;
4780 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4782 struct rte_mbuf *pkt;
4785 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4787 for (i = 0; i < 4; i++) {
4788 pkt_num = in_pkt_num + i;
4789 pkt = pkts[pkt_num];
4791 /* index into hash table entries */
4792 int hash_table_entry = p_nat->lkup_indx[pkt_num];
4793 /*bitmask representing only this packet */
4794 uint64_t pkt_mask = 1LLU << pkt_num;
4796 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
4798 uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */
4799 uint16_t *outport_id =
4800 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
4802 struct cgnapt_table_entry *entry = NULL;
4804 if (hash_table_entry < 0) {
4806 /* try to add new entry */
4807 struct rte_pipeline_table_entry *table_entry = NULL;
4810 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
4812 &p_nat->valid_packets, pkt_num,
4816 /* ICMP Error message generation for
4817 * Destination Host unreachable
4819 if (protocol == IP_PROTOCOL_ICMP) {
4820 cgnapt_icmp_pkt = pkt;
4821 send_icmp_dest_unreachable_msg();
4824 /* Drop packet by adding to invalid pkt mask */
4826 p_nat->invalid_packets |= dropmask;
4828 #ifdef CGNAPT_DEBUGGING
4829 if (p_nat->kpc2++ < 5) {
4830 printf("in_ah Th: %d",
4831 p_nat->pipeline_num);
4832 print_key(p_nat->key_ptrs[pkt_num]);
4836 p_nat->naptDroppedPktCount++;
4838 #ifdef CGNAPT_DEBUGGING
4839 p_nat->naptDroppedPktCount3++;
4844 entry = (struct cgnapt_table_entry *)table_entry;
4846 /* entry found for this packet */
4847 entry = &napt_hash_tbl_entries[hash_table_entry];
4850 /* apply napt and mac changes */
4852 p_nat->entries[pkt_num] = &(entry->head);
4854 uint32_t *dst_addr =
4855 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4856 uint16_t src_port_offset = 0;
4857 uint16_t dst_port_offset = 0;
4859 if ((protocol == IP_PROTOCOL_TCP)
4860 || (protocol == IP_PROTOCOL_UDP)) {
4861 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4862 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4863 } else if (protocol == IP_PROTOCOL_ICMP) {
4865 src_port_offset = MBUF_HDR_ROOM +
4868 /*Sequence number */
4869 dst_port_offset = MBUF_HDR_ROOM +
4874 uint16_t *src_port =
4875 RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
4876 uint16_t *dst_port =
4877 RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
4880 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4882 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4884 if (entry->data.ttl == NAPT_ENTRY_STALE)
4885 entry->data.ttl = NAPT_ENTRY_VALID;
4887 uint32_t dest_address = 0;
4888 /* Multiport Changes */
4894 if (unlikely(protocol == IP_PROTOCOL_UDP
4895 && rte_be_to_cpu_16(*src_port) == 53)) {
4896 p_nat->invalid_packets |= pkt_mask;
4897 p_nat->naptDroppedPktCount++;
4898 #ifdef CGNAPT_DEBUGGING
4899 p_nat->naptDroppedPktCount6++;
4904 dest_address = entry->data.u.prv_ip;
4905 struct arp_entry_data *ret_arp_data = NULL;
4906 uint32_t src_phy_port = pkt->port;
4907 dest_if = pub_to_prv_map[src_phy_port];
4908 gw_get_route_nh_port_ipv4(dest_address,
4909 &dest_if, &nhip, dest_if);
4911 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if,
4912 (struct ether_addr *)eth_dest);
4914 *outport_id = p_nat->outport_id[dest_if];
4916 if (arp_cache_dest_mac_present(dest_if)) {
4917 ether_addr_copy(get_link_hw_addr(dest_if),
4918 (struct ether_addr *)eth_src);
4919 update_nhip_access(dest_if);
4921 if (ret_arp_data && ret_arp_data->num_pkts) {
4922 p_nat->naptedPktCount += ret_arp_data->num_pkts;
4923 arp_send_buffered_pkts(ret_arp_data,
4924 (struct ether_addr *)eth_dest, *outport_id);
4929 if (unlikely(ret_arp_data == NULL)) {
4931 #ifdef CGNAPT_DEBUGGING
4932 printf("%s: NHIP Not Found, nhip: %x, "
4933 "outport_id: %d\n", __func__, nhip,
4938 p_nat->invalid_packets |= pkt_mask;
4939 p_nat->naptDroppedPktCount++;
4941 #ifdef CGNAPT_DEBUGGING
4942 p_nat->naptDroppedPktCount4++;
4947 if (ret_arp_data->status == INCOMPLETE ||
4948 ret_arp_data->status == PROBE) {
4949 if (ret_arp_data->num_pkts >= NUM_DESC) {
4951 p_nat->invalid_packets |= pkt_mask;
4952 p_nat->naptDroppedPktCount++;
4954 #ifdef CGNAPT_DEBUGGING
4955 p_nat->naptDroppedPktCount4++;
4959 arp_pkts_mask |= pkt_mask;
4960 arp_queue_unresolved_packet(ret_arp_data, pkt);
4969 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
4970 if (protocol == IP_PROTOCOL_ICMP) {
4971 /* Query ID reverse translation done here */
4972 *src_port = rte_bswap16(entry->data.prv_port);
4973 /* dont care sequence num */
4975 #ifdef NAT_ONLY_CONFIG_REQ
4976 if (!nat_only_config_flag) {
4979 rte_bswap16(entry->data.prv_port);
4980 #ifdef NAT_ONLY_CONFIG_REQ
4985 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4986 rte_be_to_cpu_16(*dst_port) == 21) {
4987 pkt_mask = cgnapt_ct_process(
4988 cgnat_cnxn_tracker, pkts,
4989 pkt_mask, &ct_helper);
4995 uint16_t rtp_port = 0, rtcp_port = 0;
4996 struct cgnapt_table_entry *entry_ptr1 = NULL,
4998 /* Commented code may be required for future usage,
5002 struct cgnapt_table_entry *entry_ptr2 = NULL,
5006 if (unlikely(protocol == IP_PROTOCOL_UDP
5007 && (rte_be_to_cpu_16(*dst_port) == 5060
5008 || rte_be_to_cpu_16(*src_port) == 5060))) {
5009 /* Commented code may be required for future usage,
5013 int ret = natSipAlgGetAudioPorts(pkt,
5014 &rtp_port, &rtcp_port);
5016 printf("%s: Wrong SIP ALG packet1\n",
5018 p_nat->invalid_packets |= pkt_mask;
5020 p_nat->naptDroppedPktCount++;
5022 #ifdef CGNAPT_DEBUGGING
5023 p_nat->naptDroppedPktCount4++;
5028 if (rtp_port != 0) {
5029 struct pipeline_cgnapt_entry_key rtp_key;
5030 rtp_key.ip = entry->data.pub_ip;
5031 rtp_key.port = rtp_port;
5032 rtp_key.pid = 0xffff;
5034 if (retrieve_cgnapt_entry_alg(&rtp_key,
5035 &entry_ptr1, &entry_ptr2) == 0) {
5036 printf("%s: Wrong SIP ALG packet2\n",
5038 p_nat->invalid_packets |= pkt_mask;
5040 p_nat->naptDroppedPktCount++;
5042 #ifdef CGNAPT_DEBUGGING
5043 p_nat->naptDroppedPktCount4++;
5049 if (rtcp_port != 0) {
5050 struct pipeline_cgnapt_entry_key rtcp_key;
5051 rtcp_key.ip = entry->data.pub_ip;
5052 rtcp_key.port = rtcp_port;
5053 rtcp_key.pid = 0xffff;
5055 if (retrieve_cgnapt_entry_alg(&rtcp_key,
5056 &entry_ptr3, &entry_ptr4) == 0) {
5057 printf("%s: Wrong SIP ALG packet3\n",
5059 p_nat->invalid_packets |= pkt_mask;
5060 p_nat->naptDroppedPktCount++;
5062 #ifdef CGNAPT_DEBUGGING
5063 p_nat->naptDroppedPktCount4++;
5070 if (sip_alg_dpi(pkt, PUBLIC,
5071 entry->data.u.prv_ip,
5072 entry->data.prv_port,
5074 entry->data.pub_port,
5075 (rtp_port == 0) ? 0 :
5076 entry_ptr1->data.prv_port,
5077 (rtcp_port == 0) ? 0 :
5078 entry_ptr3->data.prv_port) == 0) {
5080 printf("%s: Wrong SIP ALG packet4\n",
5082 p_nat->invalid_packets |= pkt_mask;
5084 p_nat->naptDroppedPktCount++;
5086 #ifdef CGNAPT_DEBUGGING
5087 p_nat->naptDroppedPktCount4++;
5092 #endif /* SIP_ALG */
5095 if ((rte_be_to_cpu_16(*src_port) == 21) ||
5096 rte_be_to_cpu_16(*dst_port) == 21) {
5098 int32_t ct_position =
5099 cgnat_cnxn_tracker->positions[pkt_num];
5100 if (ct_position < 0){
5101 p_nat->invalid_packets |= pkt_mask;
5103 p_nat->naptDroppedPktCount++;
5106 if (cgnat_cnxn_tracker->hash_table_entries
5107 [ct_position].alg_bypass_flag != BYPASS){
5109 struct pipeline_cgnapt_entry_key
5110 data_channel_entry_key;
5113 data_channel_entry_key.ip =
5115 data_channel_entry_key.port =
5116 entry->data.pub_port;
5117 data_channel_entry_key.pid = 0xffff;
5119 ftp_alg_dpi(p_nat, &data_channel_entry_key,
5120 pkt, cgnat_cnxn_tracker,
5121 ct_position, PUBLIC);
5126 p_nat->inaptedPktCount++;
5129 p_nat->naptedPktCount++;
5132 if (p_nat->hw_checksum_reqd)
5133 hw_checksum(pkt, pkt_type);
5135 sw_checksum(pkt, pkt_type);
5141 * NAPT key calculation function for IPv6 private traffic
5142 * which handles 1 pkt
5145 * A pointer to array of packets mbuf
5147 * Pkt number of pkts
5151 * A pointer to main CGNAPT structure
5155 pkt_work_cgnapt_key_ipv6_prv(
5156 struct rte_mbuf *pkt,
5158 __rte_unused void *arg,
5159 struct pipeline_cgnapt *p_nat)
5162 p_nat->receivedPktCount++;
5164 /* bitmask representing only this packet */
5165 uint64_t pkt_mask = 1LLU << pkt_num;
5167 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
5168 uint32_t *src_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
5170 uint16_t src_port = RTE_MBUF_METADATA_UINT16(pkt, SRC_PRT_OFST_IP6);
5172 uint16_t phy_port = pkt->port;
5173 struct pipeline_cgnapt_entry_key key;
5175 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
5177 #ifdef CGNAPT_DBG_PRNT
5178 if (CGNAPT_DEBUG > 4)
5183 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
5188 case IP_PROTOCOL_UDP:
5192 struct udp_hdr *udp;
5194 udp = (struct udp_hdr *)
5195 RTE_MBUF_METADATA_UINT8_PTR(pkt,
5198 if (rte_bswap16(udp->dst_port) ==
5200 handle_pcp_req(pkt, IPV6_SZ, p_nat);
5201 p_nat->invalid_packets |= pkt_mask;
5207 case IP_PROTOCOL_TCP:
5208 case IP_PROTOCOL_ICMP:
5209 /*we don't need icmp check in ipv6 */
5213 printf("wrong protocol: %d\n", protocol);
5214 /* remember invalid packets to be dropped */
5215 p_nat->invalid_packets |= pkt_mask;
5216 p_nat->naptDroppedPktCount++;
5218 #ifdef CGNAPT_DEBUGGING
5219 p_nat->naptDroppedPktCount2++;
5225 key.ip = rte_bswap32(src_addr[3]);
5226 key.port = rte_bswap16(src_port);
5228 #ifdef NAT_ONLY_CONFIG_REQ
5229 if (nat_only_config_flag)
5233 memcpy(&p_nat->keys[pkt_num], &key,
5234 sizeof(struct pipeline_cgnapt_entry_key));
5235 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5239 * NAPT key calculation function for IPv6 public traffic
5240 * which handles 1 pkt
5243 * A pointer to array of packets mbuf
5245 * Pkt number of pkts
5249 * A pointer to main CGNAPT structure
5253 pkt_work_cgnapt_key_ipv6_pub(
5254 struct rte_mbuf *pkt,
5256 __rte_unused void *arg,
5257 struct pipeline_cgnapt *p_nat)
5261 p_nat->receivedPktCount++;
5263 /* bitmask representing only this packet */
5264 uint64_t pkt_mask = 1LLU << pkt_num;
5266 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
5268 uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
5270 uint16_t dst_port = RTE_MBUF_METADATA_UINT16(pkt,
5271 DST_PRT_OFST_IP4_TCP);
5273 struct pipeline_cgnapt_entry_key key;
5275 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
5277 #ifdef CGNAPT_DBG_PRNT
5278 if (CGNAPT_DEBUG > 4)
5283 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
5289 case IP_PROTOCOL_UDP:
5290 case IP_PROTOCOL_TCP:
5291 case IP_PROTOCOL_ICMP:
5292 /*we don't need icmp check in ipv6 */
5296 /* remember invalid packets to be dropped */
5297 p_nat->invalid_packets |= pkt_mask;
5298 p_nat->naptDroppedPktCount++;
5300 #ifdef CGNAPT_DEBUGGING
5301 p_nat->naptDroppedPktCount2++;
5307 key.ip = rte_bswap32(dst_addr[0]);
5308 key.port = rte_bswap16(dst_port);
5310 #ifdef NAT_ONLY_CONFIG_REQ
5311 if (nat_only_config_flag)
5315 memcpy(&p_nat->keys[pkt_num], &key,
5316 sizeof(struct pipeline_cgnapt_entry_key));
5317 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5321 * NAPT key calculation function for IPv6 private traffic
5322 * which handles 4 pkts
5325 * A pointer to array of packets mbuf
5327 * Starting pkt number of pkts
5331 * A pointer to main CGNAPT structure
5335 pkt4_work_cgnapt_key_ipv6_prv(
5336 struct rte_mbuf **pkt,
5338 __rte_unused void *arg,
5339 struct pipeline_cgnapt *p_nat)
5341 p_nat->receivedPktCount += 4;
5343 /* bitmask representing only this packet */
5344 uint64_t pkt_mask0 = 1LLU << pkt_num;
5345 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
5346 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
5347 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
5349 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
5351 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
5353 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
5355 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
5358 uint32_t *src_addr0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0],
5360 uint32_t *src_addr1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1],
5362 uint32_t *src_addr2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2],
5364 uint32_t *src_addr3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3],
5367 uint16_t src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
5369 uint16_t src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
5371 uint16_t src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
5373 uint16_t src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
5376 uint16_t phy_port0 = pkt[0]->port;
5377 uint16_t phy_port1 = pkt[1]->port;
5378 uint16_t phy_port2 = pkt[2]->port;
5379 uint16_t phy_port3 = pkt[3]->port;
5381 struct pipeline_cgnapt_entry_key key0;
5382 struct pipeline_cgnapt_entry_key key1;
5383 struct pipeline_cgnapt_entry_key key2;
5384 struct pipeline_cgnapt_entry_key key3;
5386 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
5387 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
5388 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
5389 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
5393 #ifdef CGNAPT_DBG_PRNT
5394 if (CGNAPT_DEBUG > 4)
5399 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
5403 switch (protocol0) {
5405 case IP_PROTOCOL_UDP:
5409 struct udp_hdr *udp;
5411 udp = (struct udp_hdr *)
5412 RTE_MBUF_METADATA_UINT8_PTR(pkt[0],
5415 if (rte_bswap16(udp->dst_port) ==
5417 handle_pcp_req(pkt[0], IPV6_SZ, p_nat);
5418 p_nat->invalid_packets |= pkt_mask0;
5424 case IP_PROTOCOL_TCP:
5425 case IP_PROTOCOL_ICMP:
5426 /*we don't need icmp check in ipv6 */
5430 /* remember invalid packets to be dropped */
5431 p_nat->invalid_packets |= pkt_mask0;
5432 p_nat->naptDroppedPktCount++;
5434 #ifdef CGNAPT_DEBUGGING
5435 p_nat->naptDroppedPktCount2++;
5442 key0.pid = phy_port0;
5443 key0.ip = rte_bswap32(src_addr0[3]);
5444 key0.port = rte_bswap16(src_port0);
5446 #ifdef NAT_ONLY_CONFIG_REQ
5447 if (nat_only_config_flag)
5451 memcpy(&p_nat->keys[pkt_num], &key0,
5452 sizeof(struct pipeline_cgnapt_entry_key));
5453 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5456 #ifdef CGNAPT_DBG_PRNT
5457 if (CGNAPT_DEBUG > 4)
5462 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
5466 switch (protocol1) {
5467 case IP_PROTOCOL_UDP:
5471 struct udp_hdr *udp;
5473 udp = (struct udp_hdr *)
5474 RTE_MBUF_METADATA_UINT8_PTR(pkt[1],
5477 if (rte_bswap16(udp->dst_port) ==
5479 handle_pcp_req(pkt[1], IPV6_SZ, p_nat);
5480 p_nat->invalid_packets |= pkt_mask1;
5486 case IP_PROTOCOL_TCP:
5487 case IP_PROTOCOL_ICMP:
5488 /*we don't need icmp check in ipv6 */
5492 /* remember invalid packets to be dropped */
5493 p_nat->invalid_packets |= pkt_mask1;
5494 p_nat->naptDroppedPktCount++;
5496 #ifdef CGNAPT_DEBUGGING
5497 p_nat->naptDroppedPktCount2++;
5503 key1.pid = phy_port1;
5504 key1.ip = rte_bswap32(src_addr1[3]);
5505 key1.port = rte_bswap16(src_port1);
5507 #ifdef NAT_ONLY_CONFIG_REQ
5508 if (nat_only_config_flag)
5512 memcpy(&p_nat->keys[pkt_num + 1], &key1,
5513 sizeof(struct pipeline_cgnapt_entry_key));
5514 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
5517 #ifdef CGNAPT_DBG_PRNT
5518 if (CGNAPT_DEBUG > 4)
5523 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
5527 switch (protocol2) {
5528 case IP_PROTOCOL_UDP:
5532 struct udp_hdr *udp;
5534 udp = (struct udp_hdr *)
5535 RTE_MBUF_METADATA_UINT8_PTR(pkt[2],
5538 if (rte_bswap16(udp->dst_port) ==
5540 handle_pcp_req(pkt[2], IPV6_SZ, p_nat);
5541 p_nat->invalid_packets |= pkt_mask2;
5547 case IP_PROTOCOL_TCP:
5548 case IP_PROTOCOL_ICMP:
5549 /*we don't need icmp check in ipv6 */
5553 /* remember invalid packets to be dropped */
5554 p_nat->invalid_packets |= pkt_mask2;
5555 p_nat->naptDroppedPktCount++;
5557 #ifdef CGNAPT_DEBUGGING
5558 p_nat->naptDroppedPktCount2++;
5564 key2.pid = phy_port2;
5565 key2.ip = rte_bswap32(src_addr2[3]);
5566 key2.port = rte_bswap16(src_port2);
5568 #ifdef NAT_ONLY_CONFIG_REQ
5569 if (nat_only_config_flag)
5573 memcpy(&p_nat->keys[pkt_num + 2], &key2,
5574 sizeof(struct pipeline_cgnapt_entry_key));
5575 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
5578 #ifdef CGNAPT_DBG_PRNT
5579 if (CGNAPT_DEBUG > 4)
5584 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
5588 switch (protocol3) {
5589 case IP_PROTOCOL_UDP:
5593 struct udp_hdr *udp;
5595 udp = (struct udp_hdr *)
5596 RTE_MBUF_METADATA_UINT8_PTR(pkt[3],
5599 if (rte_bswap16(udp->dst_port) ==
5601 handle_pcp_req(pkt[3], IPV6_SZ, p_nat);
5602 p_nat->invalid_packets |= pkt_mask3;
5608 case IP_PROTOCOL_TCP:
5609 case IP_PROTOCOL_ICMP:
5610 /*we don't need icmp check in ipv6 */
5614 /* remember invalid packets to be dropped */
5615 p_nat->invalid_packets |= pkt_mask2;
5616 p_nat->naptDroppedPktCount++;
5618 #ifdef CGNAPT_DEBUGGING
5619 p_nat->naptDroppedPktCount2++;
5625 key3.pid = phy_port3;
5626 key3.ip = rte_bswap32(src_addr3[3]);
5627 key3.port = rte_bswap16(src_port3);
5629 #ifdef NAT_ONLY_CONFIG_REQ
5630 if (nat_only_config_flag)
5634 memcpy(&p_nat->keys[pkt_num + 3], &key3,
5635 sizeof(struct pipeline_cgnapt_entry_key));
5636 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
5642 * NAPT key calculation function for IPv4 public traffic
5643 * which handles 4 pkts
5646 * A pointer to array of packets mbuf
5648 * Starting pkt number of pkts
5652 * A pointer to main CGNAPT structure
5656 pkt4_work_cgnapt_key_ipv6_pub(
5657 struct rte_mbuf **pkt,
5659 __rte_unused void *arg,
5660 struct pipeline_cgnapt *p_nat)
5662 p_nat->receivedPktCount += 4;
5664 /* bitmask representing only this packet */
5665 uint64_t pkt_mask0 = 1LLU << pkt_num;
5666 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
5667 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
5668 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
5670 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
5672 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
5674 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
5676 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
5679 uint32_t *dst_addr0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0],
5681 uint32_t *dst_addr1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1],
5683 uint32_t *dst_addr2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2],
5685 uint32_t *dst_addr3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3],
5688 uint16_t dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
5689 DST_PRT_OFST_IP4_TCP);
5690 uint16_t dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
5691 DST_PRT_OFST_IP4_TCP);
5692 uint16_t dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
5693 DST_PRT_OFST_IP4_TCP);
5694 uint16_t dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
5695 DST_PRT_OFST_IP4_TCP);
5697 struct pipeline_cgnapt_entry_key key0;
5698 struct pipeline_cgnapt_entry_key key1;
5699 struct pipeline_cgnapt_entry_key key2;
5700 struct pipeline_cgnapt_entry_key key3;
5702 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
5703 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
5704 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
5705 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
5709 #ifdef CGNAPT_DBG_PRNT
5710 if (CGNAPT_DEBUG > 4)
5715 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
5719 switch (protocol0) {
5721 case IP_PROTOCOL_TCP:
5722 case IP_PROTOCOL_UDP:
5723 case IP_PROTOCOL_ICMP:
5724 /*we don't need icmp check in ipv6 */
5728 /* remember invalid packets to be dropped */
5729 p_nat->invalid_packets |= pkt_mask0;
5730 p_nat->naptDroppedPktCount++;
5732 #ifdef CGNAPT_DEBUGGING
5733 p_nat->naptDroppedPktCount2++;
5739 key0.ip = rte_bswap32(dst_addr0[0]);
5740 key0.port = rte_bswap16(dst_port0);
5742 #ifdef NAT_ONLY_CONFIG_REQ
5743 if (nat_only_config_flag)
5747 memcpy(&p_nat->keys[pkt_num], &key0,
5748 sizeof(struct pipeline_cgnapt_entry_key));
5749 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5755 #ifdef CGNAPT_DBG_PRNT
5756 if (CGNAPT_DEBUG > 4)
5761 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
5765 switch (protocol1) {
5767 case IP_PROTOCOL_TCP:
5768 case IP_PROTOCOL_UDP:
5769 case IP_PROTOCOL_ICMP:
5770 /*we don't need icmp check in ipv6 */
5774 /* remember invalid packets to be dropped */
5775 p_nat->invalid_packets |= pkt_mask1;
5776 p_nat->naptDroppedPktCount++;
5778 #ifdef CGNAPT_DEBUGGING
5779 p_nat->naptDroppedPktCount2++;
5785 key1.ip = rte_bswap32(dst_addr1[0]);
5786 key1.port = rte_bswap16(dst_port1);
5788 #ifdef NAT_ONLY_CONFIG_REQ
5789 if (nat_only_config_flag)
5793 memcpy(&p_nat->keys[pkt_num + 1], &key1,
5794 sizeof(struct pipeline_cgnapt_entry_key));
5795 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
5801 #ifdef CGNAPT_DBG_PRNT
5802 if (CGNAPT_DEBUG > 4)
5807 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
5811 switch (protocol2) {
5813 case IP_PROTOCOL_TCP:
5814 case IP_PROTOCOL_UDP:
5815 case IP_PROTOCOL_ICMP:
5816 /*we don't need icmp check in ipv6 */
5820 /* remember invalid packets to be dropped */
5821 p_nat->invalid_packets |= pkt_mask2;
5822 p_nat->naptDroppedPktCount++;
5824 #ifdef CGNAPT_DEBUGGING
5825 p_nat->naptDroppedPktCount2++;
5831 key2.ip = rte_bswap32(dst_addr2[0]);
5832 key2.port = rte_bswap16(dst_port2);
5834 #ifdef NAT_ONLY_CONFIG_REQ
5835 if (nat_only_config_flag)
5839 memcpy(&p_nat->keys[pkt_num + 2], &key2,
5840 sizeof(struct pipeline_cgnapt_entry_key));
5842 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
5848 #ifdef CGNAPT_DBG_PRNT
5849 if (CGNAPT_DEBUG > 4)
5854 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
5858 switch (protocol3) {
5860 case IP_PROTOCOL_TCP:
5861 case IP_PROTOCOL_UDP:
5862 case IP_PROTOCOL_ICMP:
5863 /*we don't need icmp check in ipv6 */
5867 /* remember invalid packets to be dropped */
5868 p_nat->invalid_packets |= pkt_mask3;
5869 p_nat->naptDroppedPktCount++;
5871 #ifdef CGNAPT_DEBUGGING
5872 p_nat->naptDroppedPktCount2++;
5878 key3.ip = rte_bswap32(dst_addr3[0]);
5879 key3.port = rte_bswap16(dst_port3);
5881 #ifdef NAT_ONLY_CONFIG_REQ
5882 if (nat_only_config_flag)
5886 memcpy(&p_nat->keys[pkt_num + 3], &key3,
5887 sizeof(struct pipeline_cgnapt_entry_key));
5889 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
5893 * NAPT function for IPv6 private traffic which handles 1 pkt
5896 * A pointer to array of packet mbuf
5902 * A pointer to main CGNAPT structure
5906 pkt_work_cgnapt_ipv6_prv(
5907 struct rte_mbuf *pkt,
5909 __rte_unused void *arg,
5910 struct pipeline_cgnapt *p_nat)
5912 /* index into hash table entries */
5913 int hash_table_entry = p_nat->lkup_indx[pkt_num];
5915 /*bitmask representing only this packet */
5916 uint64_t pkt_mask = 1LLU << pkt_num;
5918 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
5920 /* Added for Multiport */
5921 uint32_t dest_if = INVALID_DESTIF;
5922 uint16_t *outport_id = RTE_MBUF_METADATA_UINT16_PTR(pkt,
5923 cgnapt_meta_offset);
5925 struct cgnapt_table_entry *entry = NULL;
5926 enum PKT_TYPE pkt_type = PKT_TYPE_IPV6to4;
5928 if (hash_table_entry < 0) {
5930 /* try to add new entry */
5931 struct rte_pipeline_table_entry *table_entry = NULL;
5933 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
5935 &p_nat->valid_packets, pkt_num,
5939 /* ICMP Error message generation for
5940 * Destination Host unreachable
5942 /* Do we need this check for ipv6? */
5943 if (protocol == IP_PROTOCOL_ICMP) {
5944 cgnapt_icmp_pkt = pkt;
5945 send_icmp_dest_unreachable_msg();
5948 /* Drop packet by adding to invalid pkt mask */
5950 p_nat->invalid_packets |= dropmask;
5952 #ifdef CGNAPT_DEBUGGING
5953 if (p_nat->kpc2++ < 5) {
5954 printf("in_ah Th: %d", p_nat->pipeline_num);
5955 print_key(p_nat->key_ptrs[pkt_num]);
5959 p_nat->naptDroppedPktCount++;
5961 #ifdef CGNAPT_DEBUGGING
5962 p_nat->naptDroppedPktCount3++;
5968 entry = (struct cgnapt_table_entry *)table_entry;
5970 /* entry found for this packet */
5971 entry = &napt_hash_tbl_entries[hash_table_entry];
5974 /* apply napt and mac changes */
5976 p_nat->entries[pkt_num] = &(entry->head);
5978 struct ipv6_hdr ipv6_hdr;
5980 uint32_t dest_address = 0;
5985 convert_ipv6_to_ipv4(pkt, &ipv6_hdr);
5987 #ifdef CGNAPT_DBG_PRNT
5988 if (CGNAPT_DEBUG == 1)
5989 printf("pkt_work_cganpt: convert_ipv6_to_ipv4\n");
5992 struct cgnapt_nsp_node *ll = nsp_ll;
5995 while (ll != NULL) {
5997 (&ipv6_hdr.dst_addr[0], &ll->nsp.prefix[0],
5998 ll->nsp.depth / 8)) {
6006 && !memcmp(&ipv6_hdr.dst_addr[0], &well_known_prefix[0],
6012 p_nat->invalid_packets |= pkt_mask;
6013 p_nat->naptDroppedPktCount++;
6015 #ifdef CGNAPT_DEBUGGING
6016 p_nat->naptDroppedPktCount5++;
6024 /* As packet is already converted into IPv4 we must not
6025 * operate IPv6 offsets on packet
6026 * Only perform IPv4 operations
6029 uint32_t *src_addr =
6030 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP6t4);
6031 uint32_t *dst_addr =
6032 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP6t4);
6033 uint16_t *src_port =
6034 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP6t4);
6035 uint16_t *dst_port =
6036 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP6t4);
6038 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt,
6040 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt,
6041 ETH_OFST_IP6t4 + 6);
6043 if (entry->data.ttl == NAPT_ENTRY_STALE)
6044 entry->data.ttl = NAPT_ENTRY_VALID;
6047 if (unlikely(protocol == IP_PROTOCOL_UDP
6048 && rte_be_to_cpu_16(*dst_port) == 53)) {
6049 p_nat->invalid_packets |= pkt_mask;
6050 p_nat->naptDroppedPktCount++;
6052 #ifdef CGNAPT_DEBUGGING
6053 p_nat->naptDroppedPktCount6++;
6059 dest_address = rte_bswap32(*dst_addr);
6060 /*Multiport Changes */
6063 #ifdef CGNAPT_DBG_PRNT
6064 if (CGNAPT_DEBUG > 2)
6065 printf("Egress: \tphy_port:%d\t get_prv_to_pub():%d "
6066 "\tout_port:%d\n", pkt->port,
6067 dest_if, *outport_id);
6071 #ifdef CGNAPT_DBG_PRNT
6072 static int static_count;
6074 if (static_count++ < 10) {
6076 my_print_entry(entry);
6077 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6078 printf("dest_add:%x\n", entry->data.u.prv_ip);
6079 printf("dest_add:%x\n", *dst_addr);
6080 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6084 struct arp_entry_data *ret_arp_data;
6086 uint32_t src_phy_port = pkt->port;
6087 dest_if = prv_to_pub_map[src_phy_port];
6088 gw_get_route_nh_port_ipv4(dest_address,
6089 &dest_if, &nhip, dest_if);
6091 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if,
6092 (struct ether_addr *)eth_dest);
6094 *outport_id = p_nat->outport_id[dest_if];
6096 if (arp_cache_dest_mac_present(dest_if)) {
6097 ether_addr_copy(get_link_hw_addr(dest_if),
6098 (struct ether_addr *)eth_src);
6099 update_nhip_access(dest_if);
6101 if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) {
6102 p_nat->naptedPktCount += ret_arp_data->num_pkts;
6103 arp_send_buffered_pkts(ret_arp_data,
6104 (struct ether_addr *)eth_dest, *outport_id);
6109 if (unlikely(ret_arp_data == NULL)) {
6111 #ifdef CGNAPT_DEBUGGING
6112 printf("%s: NHIP Not Found, nhip:%x , "
6113 "outport_id: %d\n", __func__, nhip,
6118 p_nat->invalid_packets |= pkt_mask;
6119 p_nat->naptDroppedPktCount++;
6121 #ifdef CGNAPT_DEBUGGING
6122 p_nat->naptDroppedPktCount4++;
6127 if (ret_arp_data->status == INCOMPLETE ||
6128 ret_arp_data->status == PROBE) {
6129 if (ret_arp_data->num_pkts >= NUM_DESC) {
6131 p_nat->invalid_packets |= pkt_mask;
6132 p_nat->naptDroppedPktCount++;
6134 #ifdef CGNAPT_DEBUGGING
6135 p_nat->naptDroppedPktCount4++;
6139 arp_pkts_mask |= pkt_mask;
6140 arp_queue_unresolved_packet(ret_arp_data, pkt);
6148 *src_addr = rte_bswap32(entry->data.pub_ip);
6150 #ifdef NAT_ONLY_CONFIG_REQ
6151 if (!nat_only_config_flag) {
6153 *src_port = rte_bswap16(entry->data.pub_port);
6155 #ifdef NAT_ONLY_CONFIG_REQ
6159 p_nat->enaptedPktCount++;
6162 p_nat->naptedPktCount++;
6165 if (p_nat->hw_checksum_reqd)
6166 hw_checksum(pkt, pkt_type);
6168 sw_checksum(pkt, pkt_type);
6174 * NAPT function for IPv6 public traffic which handles 1 pkt
6177 * A pointer to array of packet mbuf
6183 * A pointer to main CGNAPT structure
6187 pkt_work_cgnapt_ipv6_pub(
6188 struct rte_mbuf *pkt,
6190 __rte_unused void *arg,
6191 struct pipeline_cgnapt *p_nat)
6194 /* index into hash table entries */
6195 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6196 /*bitmask representing only this packet */
6197 uint64_t pkt_mask = 1LLU << pkt_num;
6199 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
6201 uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */
6202 uint16_t *outport_id =
6203 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6204 struct cgnapt_table_entry *entry = NULL;
6206 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4to6;
6208 if (hash_table_entry < 0) {
6210 /* Drop ingress initial traffic */
6212 p_nat->invalid_packets |= pkt_mask;
6213 p_nat->naptDroppedPktCount++;
6215 #ifdef CGNAPT_DEBUGGING
6216 p_nat->naptDroppedPktCount3++;
6217 if (p_nat->kpc2++ < 5) {
6218 printf("in_ah Th: %d", p_nat->pipeline_num);
6219 print_key(p_nat->key_ptrs[pkt_num]);
6226 /* entry found for this packet */
6227 entry = &napt_hash_tbl_entries[hash_table_entry];
6230 /* apply napt and mac changes */
6232 p_nat->entries[pkt_num] = &(entry->head);
6233 if (entry->data.type != CGNAPT_ENTRY_IPV6) {
6234 p_nat->invalid_packets |= pkt_mask;
6235 p_nat->naptDroppedPktCount++;
6239 struct ipv4_hdr ipv4_hdr;
6240 uint16_t *src_port =
6241 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP4_TCP);
6243 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
6244 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
6246 if (entry->data.ttl == NAPT_ENTRY_STALE)
6247 entry->data.ttl = NAPT_ENTRY_VALID;
6249 struct ether_addr hw_addr;
6250 uint8_t dest_addr_ipv6[16];
6251 uint8_t nh_ipv6[16];
6256 if (unlikely(protocol == IP_PROTOCOL_UDP
6257 && rte_be_to_cpu_16(*src_port) == 53)) {
6258 p_nat->invalid_packets |= pkt_mask;
6259 p_nat->naptDroppedPktCount++;
6260 #ifdef CGNAPT_DEBUGGING
6261 p_nat->naptDroppedPktCount6++;
6266 memcpy(&dest_addr_ipv6[0], &entry->data.u.prv_ipv6[0], 16);
6269 memset(nh_ipv6, 0, 16);
6270 struct nd_entry_data *ret_nd_data = NULL;
6272 dest_if = INVALID_DESTIF;
6274 uint32_t src_phy_port = pkt->port;
6276 gw_get_nh_port_ipv6((uint8_t *) &dest_addr_ipv6[0],
6277 &dest_if, &nh_ipv6[0]);
6279 ret_nd_data = get_dest_mac_addr_ipv6(&nh_ipv6[0],
6280 dest_if, (struct ether_addr *)eth_dest);
6282 *outport_id = p_nat->outport_id[dest_if];
6284 if (nd_cache_dest_mac_present(dest_if)) {
6285 ether_addr_copy(get_link_hw_addr(dest_if),
6286 (struct ether_addr *)eth_src);
6287 update_nhip_access(dest_if);
6289 if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) {
6290 p_nat->naptedPktCount += ret_nd_data->num_pkts;
6291 nd_send_buffered_pkts(ret_nd_data,
6292 (struct ether_addr *)eth_dest, *outport_id);
6296 if (unlikely(ret_nd_data == NULL)) {
6298 #ifdef CGNAPT_DEBUGGING
6299 printf("%s: NHIP Not Found, "
6300 "outport_id: %d\n", __func__,
6305 p_nat->invalid_packets |= pkt_mask;
6306 p_nat->naptDroppedPktCount++;
6308 #ifdef CGNAPT_DEBUGGING
6309 p_nat->naptDroppedPktCount4++;
6314 if (ret_nd_data->status == INCOMPLETE ||
6315 ret_nd_data->status == PROBE) {
6316 if (ret_nd_data->num_pkts >= NUM_DESC) {
6318 p_nat->invalid_packets |= pkt_mask;
6319 p_nat->naptDroppedPktCount++;
6321 #ifdef CGNAPT_DEBUGGING
6322 p_nat->naptDroppedPktCount4++;
6326 arp_pkts_mask |= pkt_mask;
6327 nd_queue_unresolved_packet(ret_nd_data, pkt);
6337 convert_ipv4_to_ipv6(pkt, &ipv4_hdr);
6339 /* Ethernet MTU check */
6340 if ((rte_pktmbuf_data_len(pkt) - 14) > 1500) {
6341 p_nat->invalid_packets |= pkt_mask;
6342 p_nat->naptDroppedPktCount++;
6345 uint32_t *dst_addr =
6346 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4t6);
6347 uint16_t *dst_port =
6348 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP4t6);
6350 memcpy((uint8_t *) &dst_addr[0], &entry->data.u.prv_ipv6[0],
6353 #ifdef NAT_ONLY_CONFIG_REQ
6354 if (!nat_only_config_flag) {
6356 *dst_port = rte_bswap16(entry->data.prv_port);
6358 #ifdef NAT_ONLY_CONFIG_REQ
6362 p_nat->inaptedPktCount++;
6365 p_nat->naptedPktCount++;
6368 if (p_nat->hw_checksum_reqd)
6369 hw_checksum(pkt, pkt_type);
6371 sw_checksum(pkt, pkt_type);
6377 * NAPT function for IPv6 private traffic which handles 4 pkts
6380 * A pointer to array of packets mbuf
6382 * Starting pkt number of pkts
6386 * A pointer to main CGNAPT structure
6390 pkt4_work_cgnapt_ipv6_prv(
6391 struct rte_mbuf **pkts,
6392 uint32_t in_pkt_num,
6393 __rte_unused void *arg,
6394 struct pipeline_cgnapt *p_nat)
6396 struct rte_mbuf *pkt;
6400 enum PKT_TYPE pkt_type = PKT_TYPE_IPV6to4;
6402 for (i = 0; i < 4; i++) {
6403 pkt_num = in_pkt_num + i;
6406 /* index into hash table entries */
6407 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6408 /*bitmask representing only this packet */
6409 uint64_t pkt_mask = 1LLU << pkt_num;
6411 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
6412 uint32_t dest_if = INVALID_DESTIF;
6413 uint16_t *outport_id =
6414 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6415 struct cgnapt_table_entry *entry = NULL;
6417 if (hash_table_entry < 0) {
6419 /* try to add new entry */
6420 struct rte_pipeline_table_entry *table_entry = NULL;
6423 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
6425 &p_nat->valid_packets, pkt_num,
6429 /* ICMP Error message generation for
6430 * Destination Host unreachable
6432 /* Do we need this check for ipv6? */
6433 if (protocol == IP_PROTOCOL_ICMP) {
6434 cgnapt_icmp_pkt = pkt;
6435 send_icmp_dest_unreachable_msg();
6438 /* Drop packet by adding to invalid pkt mask */
6440 p_nat->invalid_packets |= dropmask;
6442 #ifdef CGNAPT_DEBUGGING
6443 if (p_nat->kpc2++ < 5) {
6444 printf("in_ah Th: %d",
6445 p_nat->pipeline_num);
6446 print_key(p_nat->key_ptrs[pkt_num]);
6450 p_nat->naptDroppedPktCount++;
6452 #ifdef CGNAPT_DEBUGGING
6453 p_nat->naptDroppedPktCount3++;
6459 entry = (struct cgnapt_table_entry *)table_entry;
6461 /* entry found for this packet */
6462 entry = &napt_hash_tbl_entries[hash_table_entry];
6465 /* apply napt and mac changes */
6467 p_nat->entries[pkt_num] = &(entry->head);
6469 struct ipv6_hdr ipv6_hdr;
6470 uint32_t dest_address = 0;
6471 uint8_t nh_ipv6[16];
6476 convert_ipv6_to_ipv4(pkt, &ipv6_hdr);
6478 #ifdef CGNAPT_DBG_PRNT
6479 if (CGNAPT_DEBUG >= 1)
6480 printf("pkt_work_cganpt: "
6481 "convert_ipv6_to_ipv4\n");
6484 struct cgnapt_nsp_node *ll = nsp_ll;
6487 while (ll != NULL) {
6488 if (!memcmp(&ipv6_hdr.dst_addr[0],
6490 ll->nsp.depth / 8)) {
6498 && !memcmp(&ipv6_hdr.dst_addr[0],
6499 &well_known_prefix[0], 12)) {
6504 p_nat->invalid_packets |= pkt_mask;
6505 p_nat->naptDroppedPktCount++;
6507 #ifdef CGNAPT_DEBUGGING
6508 p_nat->naptDroppedPktCount5++;
6515 /* As packet is already converted into IPv4 we must not
6516 * operate IPv6 offsets on packet only perform IPv4 operations
6519 uint32_t *src_addr =
6520 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP6t4);
6521 uint32_t *dst_addr =
6522 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP6t4);
6523 uint16_t *src_port =
6524 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP6t4);
6525 uint16_t *dst_port =
6526 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP6t4);
6529 RTE_MBUF_METADATA_UINT8_PTR(pkt, ETH_OFST_IP6t4);
6531 RTE_MBUF_METADATA_UINT8_PTR(pkt, ETH_OFST_IP6t4 + 6);
6533 if (entry->data.ttl == NAPT_ENTRY_STALE)
6534 entry->data.ttl = NAPT_ENTRY_VALID;
6539 if (unlikely(protocol == IP_PROTOCOL_UDP
6540 && rte_be_to_cpu_16(*dst_port) == 53)) {
6541 p_nat->invalid_packets |= pkt_mask;
6542 p_nat->naptDroppedPktCount++;
6544 #ifdef CGNAPT_DEBUGGING
6545 p_nat->naptDroppedPktCount6++;
6550 dest_address = rte_bswap32(*dst_addr);
6553 #ifdef CGNAPT_DBG_PRNT
6554 if (CGNAPT_DEBUG > 2)
6555 printf("Egress: \tphy_port:%d\t"
6556 "get_prv_to_pub():%d \tout_port:%d\n",
6557 pkt->port, dest_if, *outport_id);
6561 #ifdef CGNAPT_DEBUGGING
6562 static int static_count;
6564 if (static_count++ < 10) {
6566 my_print_entry(entry);
6567 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6568 printf("dest_add:%x\n", entry->data.u.prv_ip);
6569 printf("dest_add:%x\n", *dst_addr);
6570 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6574 memset(nh_ipv6, 0, 16);
6577 struct arp_entry_data *ret_arp_data;
6578 uint32_t src_phy_port = pkt->port;
6579 dest_if = prv_to_pub_map[src_phy_port];
6580 gw_get_route_nh_port_ipv4(dest_address,
6581 &dest_if, &nhip, dest_if);
6583 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if,
6584 (struct ether_addr *)eth_dest);
6585 *outport_id = p_nat->outport_id[dest_if];
6587 if (arp_cache_dest_mac_present(dest_if)) {
6588 ether_addr_copy(get_link_hw_addr(dest_if),
6589 (struct ether_addr *)eth_src);
6590 update_nhip_access(dest_if);
6591 if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) {
6592 p_nat->naptedPktCount += ret_arp_data->num_pkts;
6593 arp_send_buffered_pkts(ret_arp_data,
6594 (struct ether_addr *)eth_dest, *outport_id);
6599 if (unlikely(ret_arp_data == NULL)) {
6601 #ifdef CGNAPT_DEBUGGING
6602 printf("%s: NHIP Not Found, nhip:%x , "
6603 "outport_id: %d\n", __func__, nhip,
6608 p_nat->invalid_packets |= pkt_mask;
6609 p_nat->naptDroppedPktCount++;
6611 #ifdef CGNAPT_DEBUGGING
6612 p_nat->naptDroppedPktCount4++;
6617 if (ret_arp_data->status == INCOMPLETE ||
6618 ret_arp_data->status == PROBE) {
6619 if (ret_arp_data->num_pkts >= NUM_DESC) {
6621 p_nat->invalid_packets |= pkt_mask;
6622 p_nat->naptDroppedPktCount++;
6624 #ifdef CGNAPT_DEBUGGING
6625 p_nat->naptDroppedPktCount4++;
6629 arp_pkts_mask |= pkt_mask;
6630 arp_queue_unresolved_packet(ret_arp_data, pkt);
6640 *src_addr = rte_bswap32(entry->data.pub_ip);
6642 #ifdef NAT_ONLY_CONFIG_REQ
6643 if (!nat_only_config_flag) {
6645 *src_port = rte_bswap16(entry->data.pub_port);
6647 #ifdef NAT_ONLY_CONFIG_REQ
6651 p_nat->enaptedPktCount++;
6654 p_nat->naptedPktCount++;
6657 if (p_nat->hw_checksum_reqd)
6658 hw_checksum(pkt, pkt_type);
6660 sw_checksum(pkt, pkt_type);
6666 * NAPT function for IPv6 public traffic which handles 4 pkts
6669 * A pointer to array of packets mbuf
6671 * Starting pkt number of pkts
6675 * A pointer to main CGNAPT structure
6679 pkt4_work_cgnapt_ipv6_pub(
6680 struct rte_mbuf **pkts,
6681 uint32_t in_pkt_num,
6682 __rte_unused void *arg,
6683 struct pipeline_cgnapt *p_nat)
6685 struct rte_mbuf *pkt;
6689 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4to6;
6691 for (i = 0; i < 4; i++) {
6692 pkt_num = in_pkt_num + i;
6695 /* index into hash table entries */
6696 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6697 /*bitmask representing only this packet */
6698 uint64_t pkt_mask = 1LLU << pkt_num;
6700 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
6701 uint16_t *outport_id =
6702 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6703 struct cgnapt_table_entry *entry = NULL;
6705 if (hash_table_entry < 0) {
6707 /* Drop ingress initial traffic */
6709 p_nat->invalid_packets |= pkt_mask;
6710 p_nat->naptDroppedPktCount++;
6711 #ifdef CGNAPT_DEBUGGING
6712 p_nat->naptDroppedPktCount3++;
6713 if (p_nat->kpc2++ < 5) {
6714 printf("in_ah Th: %d", p_nat->pipeline_num);
6715 print_key(p_nat->key_ptrs[pkt_num]);
6722 /* entry found for this packet */
6723 entry = &napt_hash_tbl_entries[hash_table_entry];
6726 /* apply napt and mac changes */
6728 p_nat->entries[pkt_num] = &(entry->head);
6729 if (entry->data.type != CGNAPT_ENTRY_IPV6) {
6730 p_nat->invalid_packets |= pkt_mask;
6731 p_nat->naptDroppedPktCount++;
6735 struct ipv4_hdr ipv4_hdr;
6737 uint16_t *src_port =
6738 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP4_TCP);
6741 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
6743 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
6745 if (entry->data.ttl == NAPT_ENTRY_STALE)
6746 entry->data.ttl = NAPT_ENTRY_VALID;
6748 struct ether_addr hw_addr;
6749 uint8_t dest_addr_ipv6[16];
6750 uint8_t nh_ipv6[16];
6751 uint32_t dest_if = INVALID_DESTIF;
6752 { /*start of Ingress */
6754 if (unlikely(protocol == IP_PROTOCOL_UDP
6755 && rte_be_to_cpu_16(*src_port) == 53)) {
6756 p_nat->invalid_packets |= pkt_mask;
6757 p_nat->naptDroppedPktCount++;
6758 #ifdef CGNAPT_DEBUGGING
6759 p_nat->naptDroppedPktCount6++;
6764 memcpy(&dest_addr_ipv6[0], &entry->data.u.prv_ipv6[0],
6767 }/* end of ingress */
6769 #ifdef CGNAPT_DEBUGGING
6770 static int static_count;
6772 if (static_count++ < 10) {
6774 my_print_entry(entry);
6775 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6776 printf("dest_add:%x\n", entry->data.u.prv_ip);
6777 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6781 memset(nh_ipv6, 0, 16);
6782 struct nd_entry_data *ret_nd_data = NULL;
6783 dest_if = INVALID_DESTIF;
6785 uint32_t src_phy_port = pkt->port;
6787 gw_get_nh_port_ipv6((uint8_t *) &dest_addr_ipv6[0],
6788 &dest_if, &nh_ipv6[0]);
6790 ret_nd_data = get_dest_mac_addr_ipv6(&nh_ipv6[0],
6791 dest_if, (struct ether_addr *)eth_dest);
6792 *outport_id = p_nat->outport_id[dest_if];
6794 if (nd_cache_dest_mac_present(dest_if)) {
6795 ether_addr_copy(get_link_hw_addr(dest_if),
6796 (struct ether_addr *)eth_src);
6797 update_nhip_access(dest_if);
6799 if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) {
6800 p_nat->naptedPktCount += ret_nd_data->num_pkts;
6801 nd_send_buffered_pkts(ret_nd_data,
6802 (struct ether_addr *)eth_dest, *outport_id);
6805 if (unlikely(ret_nd_data == NULL)) {
6807 #ifdef CGNAPT_DEBUGGING
6808 printf("%s: NHIP Not Found "
6809 "outport_id: %d\n", __func__,
6814 p_nat->invalid_packets |= pkt_mask;
6815 p_nat->naptDroppedPktCount++;
6817 #ifdef CGNAPT_DEBUGGING
6818 p_nat->naptDroppedPktCount4++;
6823 if (ret_nd_data->status == INCOMPLETE ||
6824 ret_nd_data->status == PROBE) {
6826 if (ret_nd_data->num_pkts >= NUM_DESC) {
6828 p_nat->invalid_packets |= pkt_mask;
6829 p_nat->naptDroppedPktCount++;
6831 #ifdef CGNAPT_DEBUGGING
6832 p_nat->naptDroppedPktCount4++;
6836 arp_pkts_mask |= pkt_mask;
6837 nd_queue_unresolved_packet(ret_nd_data, pkt);
6845 /* start of Ingress */
6847 convert_ipv4_to_ipv6(pkt, &ipv4_hdr);
6849 /* Ethernet MTU check */
6850 if ((rte_pktmbuf_data_len(pkt) - 14) > 1500) {
6851 p_nat->invalid_packets |= pkt_mask;
6852 p_nat->naptDroppedPktCount++;
6855 uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
6856 DST_ADR_OFST_IP4t6);
6857 uint16_t *dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
6858 DST_PRT_OFST_IP4t6);
6860 memcpy((uint8_t *) &dst_addr[0],
6861 &entry->data.u.prv_ipv6[0], 16);
6863 #ifdef NAT_ONLY_CONFIG_REQ
6864 if (!nat_only_config_flag) {
6866 *dst_port = rte_bswap16(entry->data.prv_port);
6868 #ifdef NAT_ONLY_CONFIG_REQ
6872 p_nat->inaptedPktCount++;
6873 } /* end of ingress */
6875 p_nat->naptedPktCount++;
6878 if (p_nat->hw_checksum_reqd)
6879 hw_checksum(pkt, pkt_type);
6881 sw_checksum(pkt, pkt_type);
6883 } /* end of for loop */
6887 * Input port handler for IPv6 private traffic
6888 * Starting from the packet burst it filters unwanted packets,
6889 * calculates keys, does lookup and then based on the lookup
6890 * updates NAPT table and does packet NAPT translation.
6893 * A pointer to struct rte_pipeline
6895 * A pointer to array of packets mbuf
6897 * Number of packets in the burst
6902 * int that is not checked by caller
6904 static int cgnapt_in_port_ah_ipv6_prv(struct rte_pipeline *rte_p,
6905 struct rte_mbuf **pkts,
6906 uint32_t n_pkts, void *arg)
6909 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
6910 struct pipeline_cgnapt *p_nat = ap->p;
6912 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
6913 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
6914 p_nat->invalid_packets = 0;
6917 #ifdef CGNAPT_DBG_PRNT
6918 if (CGNAPT_DEBUG > 1)
6919 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
6922 /* prefetching for mbufs should be done here */
6923 for (j = 0; j < n_pkts; j++)
6924 rte_prefetch0(pkts[j]);
6926 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
6927 pkt4_work_cgnapt_key_ipv6_prv(&pkts[i], i, arg, p_nat);
6929 for (; i < n_pkts; i++)
6930 pkt_work_cgnapt_key_ipv6_prv(pkts[i], i, arg, p_nat);
6932 p_nat->valid_packets &= ~(p_nat->invalid_packets);
6934 if (arp_pkts_mask) {
6935 p_nat->valid_packets &= ~(arp_pkts_mask);
6936 rte_pipeline_ah_packet_hijack(rte_p, arp_pkts_mask);
6939 if (unlikely(p_nat->valid_packets == 0)) {
6940 /* no suitable packet for lookup */
6941 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
6942 return p_nat->valid_packets;
6945 /* lookup entries in the common napt table */
6947 int lookup_result = rte_hash_lookup_bulk(
6949 (const void **) &p_nat->key_ptrs,
6950 /* should be minus num invalid pkts */
6952 /*new pipeline data member */
6953 &p_nat->lkup_indx[0]);
6955 if (unlikely(lookup_result < 0)) {
6956 /* unknown error, just discard all packets */
6957 printf("Unexpected hash lookup error %d, "
6958 "discarding all packets",
6960 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
6964 /* Now call second stage of pipeline to one by one
6965 * check the result of our bulk lookup
6968 /* prefetching for table entries should be done here */
6969 for (j = 0; j < n_pkts; j++) {
6970 if (p_nat->lkup_indx[j] >= 0)
6971 rte_prefetch0(&napt_hash_tbl_entries
6972 [p_nat->lkup_indx[j]]);
6975 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
6976 pkt4_work_cgnapt_ipv6_prv(&pkts[i], i, arg, p_nat);
6978 for (; i < n_pkts; i++)
6979 pkt_work_cgnapt_ipv6_prv(pkts[i], i, arg, p_nat);
6981 if (p_nat->invalid_packets) {
6982 /* get rid of invalid packets */
6983 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
6985 p_nat->valid_packets &= ~(p_nat->invalid_packets);
6987 #ifdef CGNAPT_DBG_PRNT
6988 if (CGNAPT_DEBUG > 1) {
6989 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
6990 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
6991 printf("invalid_packets:0x%jx\n",
6992 p_nat->invalid_packets);
6993 printf("rte_invalid_packets :0x%jx\n",
6994 rte_p->pkts_drop_mask);
6995 printf("Total pkts dropped :0x%jx\n",
6996 rte_p->n_pkts_ah_drop);
7001 return p_nat->valid_packets;
7006 * Input port handler for IPv6 public traffic
7007 * Starting from the packet burst it filters unwanted packets,
7008 * calculates keys, does lookup and then based on the lookup
7009 * updates NAPT table and does packet NAPT translation.
7012 * A pointer to struct rte_pipeline
7014 * A pointer to array of packets mbuf
7016 * Number of packets in the burst
7021 * int that is not checked by caller
7023 static int cgnapt_in_port_ah_ipv6_pub(struct rte_pipeline *rte_p,
7024 struct rte_mbuf **pkts,
7025 uint32_t n_pkts, void *arg)
7028 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
7029 struct pipeline_cgnapt *p_nat = ap->p;
7031 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
7032 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
7033 p_nat->invalid_packets = 0;
7036 #ifdef CGNAPT_DBG_PRNT
7037 if (CGNAPT_DEBUG > 1)
7038 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
7041 /* prefetching for mbufs should be done here */
7042 for (j = 0; j < n_pkts; j++)
7043 rte_prefetch0(pkts[j]);
7045 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7046 pkt4_work_cgnapt_key_ipv6_pub(&pkts[i], i, arg, p_nat);
7048 for (; i < n_pkts; i++)
7049 pkt_work_cgnapt_key_ipv6_pub(pkts[i], i, arg, p_nat);
7051 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7053 if (arp_pkts_mask) {
7054 p_nat->valid_packets &= ~(arp_pkts_mask);
7055 rte_pipeline_ah_packet_hijack(rte_p, arp_pkts_mask);
7058 if (unlikely(p_nat->valid_packets == 0)) {
7059 /* no suitable packet for lookup */
7060 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7061 return p_nat->valid_packets;
7064 /* lookup entries in the common napt table */
7066 int lookup_result = rte_hash_lookup_bulk(
7068 (const void **) &p_nat->key_ptrs,
7069 /* should be minus num invalid pkts */
7071 /*new pipeline data member */
7072 &p_nat->lkup_indx[0]);
7074 if (unlikely(lookup_result < 0)) {
7075 /* unknown error, just discard all packets */
7076 printf("Unexpected hash lookup error %d, "
7077 "discarding all packets",
7079 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
7083 /* Now call second stage of pipeline to one by one
7084 * check the result of our bulk lookup
7087 /* prefetching for table entries should be done here */
7088 for (j = 0; j < n_pkts; j++) {
7089 if (p_nat->lkup_indx[j] >= 0)
7090 rte_prefetch0(&napt_hash_tbl_entries
7091 [p_nat->lkup_indx[j]]);
7094 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7095 pkt4_work_cgnapt_ipv6_pub(&pkts[i], i, arg, p_nat);
7097 for (; i < n_pkts; i++)
7098 pkt_work_cgnapt_ipv6_pub(pkts[i], i, arg, p_nat);
7100 if (p_nat->invalid_packets) {
7101 /* get rid of invalid packets */
7102 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7104 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7106 #ifdef CGNAPT_DBG_PRNT
7107 if (CGNAPT_DEBUG > 1) {
7108 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
7109 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
7110 printf("invalid_packets:0x%jx\n",
7111 p_nat->invalid_packets);
7112 printf("rte_invalid_packets :0x%jx\n",
7113 rte_p->pkts_drop_mask);
7114 printf("Total pkts dropped :0x%jx\n",
7115 rte_p->n_pkts_ah_drop);
7120 return p_nat->valid_packets;
7124 * Function to send ICMP dest unreachable msg
7127 void send_icmp_dest_unreachable_msg(void)
7130 struct ether_hdr *eth_h;
7131 struct ipv4_hdr *ip_h;
7132 struct icmp_hdr *icmp_h;
7133 struct rte_mbuf *icmp_pkt = cgnapt_icmp_pkt;
7135 if (icmp_pkt == NULL) {
7137 printf("Error allocating icmp_pkt rte_mbuf\n");
7141 port_id = icmp_pkt->port;
7143 struct app_link_params *link;
7144 link = &mylink[port_id];
7145 eth_h = rte_pktmbuf_mtod(icmp_pkt, struct ether_hdr *);
7146 ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
7147 icmp_h = (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
7149 struct ether_addr gw_addr;
7150 struct ether_addr dst_addr;
7151 ether_addr_copy(ð_h->s_addr, &dst_addr);
7152 rte_eth_macaddr_get(port_id, &gw_addr);
7153 ether_addr_copy(&gw_addr, ð_h->s_addr);
7154 ether_addr_copy(&dst_addr, ð_h->d_addr);
7156 eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
7157 ip_h->version_ihl = IP_VHL_DEF;
7158 ip_h->type_of_service = 0;
7159 ip_h->total_length = rte_cpu_to_be_16(sizeof(struct ipv4_hdr) +
7160 sizeof(struct icmp_hdr));
7161 ip_h->packet_id = 0xaabb;
7162 ip_h->fragment_offset = 0x0000;
7163 ip_h->time_to_live = 64;
7164 ip_h->next_proto_id = 1;
7167 uint32_t src_addr_offset =
7168 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_SRC_ADR_OFST;
7170 RTE_MBUF_METADATA_UINT32_PTR(cgnapt_icmp_pkt, src_addr_offset);
7172 ip_h->dst_addr = *src_addr;
7173 ip_h->src_addr = rte_bswap32(link->ip);
7175 ip_h->dst_addr = *src_addr;
7176 ip_h->src_addr = rte_bswap32(link->ip);
7178 ip_h->hdr_checksum = 0;
7179 ip_h->hdr_checksum = rte_ipv4_cksum(ip_h);
7180 icmp_h->icmp_type = 3; /* Destination Unreachable */
7181 icmp_h->icmp_code = 13; /* Communication administratively prohibited */
7183 icmp_h->icmp_cksum = ~rte_raw_cksum(icmp_h, sizeof(struct icmp_hdr));
7185 icmp_pkt->pkt_len = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
7186 sizeof(struct icmp_hdr);
7187 icmp_pkt->data_len = icmp_pkt->pkt_len;
7188 if (ARPICMP_DEBUG) {
7189 printf("Sending ICMP error message - "
7190 "Destination Unreachable\n");
7192 rte_pipeline_port_out_packet_insert(myP, port_id, icmp_pkt);
7196 * Function to add a dynamic NAPT entry pair
7199 * A pointer to struct pipeline
7201 * A pointer to struct pipeline_cgnapt_entry_key
7203 * expairy time of an dynamic or PCP req entry
7205 * uint8_t pointer of source address
7208 * A pointer to struct cgnapt_table_entry for added entry
7211 struct cgnapt_table_entry *add_dynamic_cgnapt_entry(
7213 struct pipeline_cgnapt_entry_key *key,
7220 void *entry_ptr, *ret_ptr;
7223 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
7225 #ifdef CGNAPT_DBG_PRNT
7226 if (CGNAPT_DEBUG >= 1) {
7227 printf("Th%d add_dynamic_cgnapt_entry key detail Entry:"
7228 "0x%x, %d, %d\n", p_nat->pipeline_num, key->ip, key->port,
7233 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX && i < p_nat->pkt_burst_cnt;
7235 if (p_nat->cgnapt_dyn_ent_table[i].ip == key->ip
7236 && p_nat->cgnapt_dyn_ent_table[i].port == key->port
7237 && p_nat->cgnapt_dyn_ent_table[i].pid == key->pid) {
7239 #ifdef CGNAPT_DBG_PRNT
7240 if (CGNAPT_DEBUG > 1)
7241 printf("add_dynamic_cgnapt_entry:pkt_burst "
7242 "array key matched!!!\n");
7245 return &napt_hash_tbl_entries
7246 [p_nat->cgnapt_dyn_ent_index[i]];
7250 #ifdef NAT_ONLY_CONFIG_REQ
7251 if (!nat_only_config_flag) {
7254 ret = increment_max_port_counter(key->ip, key->pid, p_nat);
7255 if (ret == MAX_PORT_INC_ERROR) {
7257 #ifdef CGNAPT_DEBUGGING
7258 p_nat->missedpktcount5++;
7261 #ifdef CGNAPT_DBG_PRNT
7262 if (CGNAPT_DEBUG > 1)
7263 printf("add_dynamic_cgnapt_entry:"
7264 "increment_max_port_counter-1 failed\n");
7271 if (ret == MAX_PORT_INC_REACHED) {
7273 #ifdef CGNAPT_DEBUGGING
7274 p_nat->missedpktcount6++;
7277 #ifdef CGNAPT_DBG_PRNT
7278 if (CGNAPT_DEBUG > 1)
7279 printf("add_dynamic_cgnapt_entry:"
7280 "increment_max_port_counter-2 failed\n");
7287 #ifdef NAT_ONLY_CONFIG_REQ
7292 port_num = get_free_iport(p_nat, &public_ip);
7294 if (port_num == -1) {
7296 #ifdef CGNAPT_DBG_PRNT
7297 if (CGNAPT_DEBUG > 2) {
7298 printf("add_dynamic_cgnapt_entry: %d\n", port_num);
7299 printf("add_dynamic_cgnapt_entry key detail:0x%x, "
7300 "%d, %d\n", key->ip, key->port, key->pid);
7304 #ifdef CGNAPT_DEBUGGING
7305 p_nat->missedpktcount7++;
7312 #ifdef NAT_ONLY_CONFIG_REQ
7313 if (!nat_only_config_flag) {
7316 if (ret == 2) { //MPPC_NEW_ENTRY
7318 /* check for max_clients_per_ip */
7319 if (rte_atomic16_read
7321 [rte_jhash(&public_ip, 4, 0) %
7322 CGNAPT_MAX_PUB_IP].count) ==
7323 p_nat->max_clients_per_ip) {
7325 /* For now just bail out
7326 * In future we can think about
7327 * retrying getting a new iport
7330 release_iport(port_num, public_ip, p_nat);
7332 #ifdef CGNAPT_DEBUGGING
7333 p_nat->missedpktcount10++;
7339 rte_atomic16_inc(&all_public_ip
7340 [rte_jhash(&public_ip, 4, 0) %
7341 CGNAPT_MAX_PUB_IP].count);
7343 #ifdef CGNAPT_DBG_PRNT
7344 if ((rte_jhash(&public_ip, 4, 0) %
7345 CGNAPT_MAX_PUB_IP) == 8)
7346 printf("pub ip:%x coutn:%d\n", public_ip,
7347 rte_atomic16_read(&all_public_ip
7348 [rte_jhash(&public_ip, 4, 0) %
7349 CGNAPT_MAX_PUB_IP].count));
7353 #ifdef NAT_ONLY_CONFIG_REQ
7357 #ifdef CGNAPT_DBG_PRNT
7358 if (CGNAPT_DEBUG > 0) {
7359 printf("add_dynamic_cgnapt_entry: %d\n",
7361 printf("add_dynamic_cgnapt_entry key detail: "
7362 "0x%x, %d, %d\n", key->ip, key->port, key->pid);
7366 struct cgnapt_table_entry entry = {
7368 .action = RTE_PIPELINE_ACTION_PORT,
7369 /* made it configurable below */
7370 {.port_id = p->port_out_id[0]},
7374 .prv_port = key->port,
7375 .pub_ip = public_ip,
7376 .pub_port = port_num,
7377 .prv_phy_port = key->pid,
7378 .pub_phy_port = get_pub_to_prv_port(
7382 /* if(timeout == -1) : static entry
7383 * if(timeout == 0 ) : dynamic entry
7384 * if(timeout > 0 ) : PCP requested entry
7386 .timeout = timeout > 0 ? timeout : 0,
7393 #ifdef NAT_ONLY_CONFIG_REQ
7394 if (nat_only_config_flag) {
7395 entry.data.prv_port = 0xffff;
7396 entry.data.pub_port = 0xffff;
7400 if (pkt_type == CGNAPT_ENTRY_IPV6) {
7401 entry.data.type = CGNAPT_ENTRY_IPV6;
7402 memcpy(&entry.data.u.prv_ipv6[0], src_addr, 16);
7404 entry.data.u.prv_ip = key->ip;
7405 entry.data.type = CGNAPT_ENTRY_IPV4;
7408 //entry.head.port_id = CGNAPT_PUB_PORT_ID; /* outgoing port info */
7409 entry.head.port_id = entry.data.pub_phy_port; /* outgoing port info */
7411 struct pipeline_cgnapt_entry_key second_key;
7412 /* Need to add a second ingress entry */
7413 second_key.ip = public_ip;
7414 second_key.port = port_num;
7415 second_key.pid = 0xffff;
7417 #ifdef NAT_ONLY_CONFIG_REQ
7418 if (nat_only_config_flag)
7419 second_key.port = 0xffff;
7422 #ifdef CGNAPT_DBG_PRNT
7423 if (CGNAPT_DEBUG > 2)
7424 printf("add_dynamic_cgnapt_entry second key detail:"
7425 "0x%x, %d, %d\n", second_key.ip, second_key.port,
7429 int32_t position = rte_hash_add_key(napt_common_table, (void *)key);
7432 #ifdef CGNAPT_DEBUGGING
7433 p_nat->missedpktcount8++;
7436 printf("CG-NAPT entry add failed ...returning "
7437 "without adding ... %d\n", position);
7442 #ifdef CGNAPT_DBG_PRNT
7444 printf("add_dynamic_cgnapt_entry\n");
7446 print_cgnapt_entry(&entry);
7450 memcpy(&napt_hash_tbl_entries[position], &entry,
7451 sizeof(struct cgnapt_table_entry));
7453 /* this pointer is returned to pkt miss function */
7454 ret_ptr = &napt_hash_tbl_entries[position];
7456 p_nat->n_cgnapt_entry_added++;
7457 p_nat->dynCgnaptCount++;
7459 /* Now modify the forward port for reverse entry */
7461 /* outgoing port info */
7462 //entry.head.port_id = CGNAPT_PRV_PORT_ID;
7463 /* outgoing port info */
7464 entry.head.port_id = entry.data.prv_phy_port;
7466 int32_t position2 = rte_hash_add_key(napt_common_table, &second_key);
7468 if (position2 < 0) {
7469 #ifdef CGNAPT_DEBUGGING
7470 p_nat->missedpktcount9++;
7472 printf("CG-NAPT entry reverse bulk add failed ..."
7473 "returning with fwd add ...%d\n",
7479 memcpy(&napt_hash_tbl_entries[position2], &entry,
7480 sizeof(struct cgnapt_table_entry));
7482 entry_ptr = &napt_hash_tbl_entries[position2];
7484 timer_thread_enqueue(key, &second_key, ret_ptr,
7485 entry_ptr, (struct pipeline *)p_nat);
7487 p_nat->n_cgnapt_entry_added++;
7488 p_nat->dynCgnaptCount++;
7490 if (p_nat->pkt_burst_cnt < RTE_PORT_IN_BURST_SIZE_MAX) {
7491 memcpy(&p_nat->cgnapt_dyn_ent_table[p_nat->pkt_burst_cnt], key,
7492 sizeof(struct pipeline_cgnapt_entry_key));
7493 p_nat->cgnapt_dyn_ent_index[p_nat->pkt_burst_cnt] = position;
7494 p_nat->pkt_burst_cnt++;
7499 int pkt_miss_cgnapt_count;
7501 * Function handle a missed NAPT entry lookup
7502 * Will attempt to add a dynamic entry pair.
7505 * A pointer to struct pipeline
7507 * A pointer to struct pipeline_cgnapt_entry_key
7509 * A pointer to pkt struct rte_mbuf
7511 * uint64_t pointer to pkt mask
7512 * @param table_entry
7513 * A pointer to struct rte_pipeline_table_entry to be created and returned
7515 * number of this pkt in current burst
7518 * A uint64_t mask for drop packets
7521 pkt_miss_cgnapt(struct pipeline_cgnapt_entry_key *key,
7522 struct rte_mbuf *pkt,
7523 struct rte_pipeline_table_entry **table_entry,
7524 __rte_unused uint64_t *pkts_mask,
7525 uint32_t pkt_num, void *arg)
7528 #ifdef CGNAPT_DBG_PRNT
7529 if (CGNAPT_DEBUG > 0)
7530 printf("\n pkt_miss_cgnapt\n");
7534 * see if get_port passes for this src address
7535 * if passed add a new egress entry and a
7536 * corresponding new ingress entry
7537 * return the fwd entry to calling function using input pointer
7538 * else if get_port fails drop packet
7541 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)arg;
7543 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
7544 uint32_t src_addr_offset_ipv6 =
7545 MBUF_HDR_ROOM + ETH_HDR_SIZE + IPV6_HDR_SRC_ADR_OFST;
7546 uint16_t phy_port = pkt->port;
7548 uint16_t *eth_proto =
7549 RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
7551 uint8_t *src_addr = NULL;
7552 uint8_t src_addr_ipv6[16];
7553 uint8_t pkt_type = CGNAPT_ENTRY_IPV4;
7554 /* To drop the packet */
7555 uint64_t drop_mask = 0;
7557 if (p_nat->is_static_cgnapt) {
7558 drop_mask |= 1LLU << pkt_num;
7559 p_nat->missedPktCount++;
7561 #ifdef CGNAPT_DEBUGGING
7562 p_nat->missedpktcount1++;
7567 if (rte_be_to_cpu_16(*eth_proto) == ETHER_TYPE_IPv6) {
7569 RTE_MBUF_METADATA_UINT8_PTR(pkt, src_addr_offset_ipv6);
7570 pkt_type = CGNAPT_ENTRY_IPV6;
7571 memcpy(src_addr_ipv6, src_addr, 16);
7576 /* some validation first */
7577 if (is_phy_port_privte(phy_port)) {
7578 /* dynamic NAPT entry creation */
7579 *table_entry = (struct rte_pipeline_table_entry *)
7580 add_dynamic_cgnapt_entry(
7581 (struct pipeline *)&p_nat->p,
7583 DYNAMIC_CGNAPT_TIMEOUT,
7585 src_addr_ipv6, &err);
7587 if (!(*table_entry)) {
7589 drop_mask |= 1LLU << pkt_num;
7590 p_nat->missedPktCount++;
7592 #ifdef CGNAPT_DEBUGGING
7593 p_nat->missedpktcount2++;
7596 #ifdef CGNAPT_DBG_PRNT
7597 if (CGNAPT_DEBUG > 1)
7598 printf("Add Dynamic NAT entry failed "
7602 #ifdef CGNAPT_DEBUGGING
7603 p_nat->missedpktcount11++;
7608 } else if (!is_phy_port_privte(phy_port)) {
7610 #ifdef CGNAPT_DBG_PRNT
7611 if (CGNAPT_DEBUG >= 2) {
7612 printf("Initial Ingress entry creation NOT ALLOWED "
7617 drop_mask |= 1LLU << pkt_num;
7618 p_nat->missedPktCount++;
7620 #ifdef CGNAPT_DEBUGGING
7621 p_nat->missedpktcount3++;
7625 #ifdef CGNAPT_DBG_PRNT
7626 if (CGNAPT_DEBUG > 1)
7627 printf("NOT a PRIVATE or PUBLIC port!!!!!\n");
7630 drop_mask |= 1LLU << pkt_num;
7631 p_nat->missedPktCount++;
7633 #ifdef CGNAPT_DEBUGGING
7634 p_nat->missedpktcount4++;
7638 #ifdef CGNAPT_DBG_PRNT
7639 if (CGNAPT_DEBUG > 5)
7649 * Function to print the contents of a packet
7652 * A pointer to pkt struct rte_mbuf
7654 void print_pkt(struct rte_mbuf *pkt)
7658 printf("\nPacket Contents:\n");
7660 uint8_t *rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
7662 for (i = 0; i < 20; i++) {
7663 for (j = 0; j < 20; j++)
7664 printf("%02x ", rd[(20 * i) + j]);
7670 rte_table_hash_op_hash cgnapt_hash_func[] = {
7682 * Function to parse incoming pipeline arguments
7683 * Called during pipeline initialization
7686 * A pointer to struct pipeline_cgnapt
7688 * A pointer to struct pipeline_params
7691 * 0 if success, negative if failure
7694 pipeline_cgnapt_parse_args(struct pipeline_cgnapt *p,
7695 struct pipeline_params *params)
7697 uint32_t n_flows_present = 0;
7698 uint32_t key_offset_present = 0;
7699 uint32_t key_size_present = 0;
7700 uint32_t hash_offset_present = 0;
7701 uint32_t n_entries_present = 0;
7702 uint32_t max_port_present = 0;
7703 uint32_t max_client_present = 0;
7704 uint32_t public_ip_range_present = 0;
7705 uint32_t public_ip_port_range_present = 0;
7707 uint8_t public_ip_count = 0;
7708 uint8_t public_ip_range_count = 0;
7709 uint8_t dest_if_offset_present = 0;
7710 uint8_t cgnapt_meta_offset_present = 0;
7711 uint8_t prv_que_handler_present = 0;
7712 uint8_t n_prv_in_port = 0;
7714 if (CGNAPT_DEBUG > 2) {
7715 printf("CGNAPT pipeline_cgnapt_parse_args params->n_args: %d\n",
7718 for (i = 0; i < params->n_args; i++) {
7719 char *arg_name = params->args_name[i];
7720 char *arg_value = params->args_value[i];
7722 if (CGNAPT_DEBUG > 2) {
7723 printf("CGNAPT args[%d]: %s %d, %s\n", i, arg_name,
7724 atoi(arg_value), arg_value);
7726 if (strcmp(arg_name, "prv_que_handler") == 0) {
7728 if (prv_que_handler_present) {
7729 printf("Duplicate pktq_in_prv ..\n\n");
7732 prv_que_handler_present = 1;
7737 /* get the first token */
7738 token = strtok(arg_value, "(");
7739 token = strtok(token, ")");
7740 token = strtok(token, ",");
7741 printf("***** prv_que_handler *****\n");
7743 if (token == NULL) {
7744 printf("string is null\n");
7745 printf("invalid prv_que_handler value/n");
7748 printf("string is :%s\n", token);
7750 /* walk through other tokens */
7751 while (token != NULL) {
7752 printf(" %s\n", token);
7753 rxport = atoi(token);
7754 cgnapt_prv_que_port_index[n_prv_in_port++] =
7756 if (rxport < PIPELINE_MAX_PORT_IN)
7757 cgnapt_in_port_egress_prv[rxport] = 1;
7758 token = strtok(NULL, ",");
7761 if (n_prv_in_port == 0) {
7762 printf("VNF common parse err - "
7763 "no prv RX phy port\n");
7769 if (strcmp(arg_name, "cgnapt_meta_offset") == 0) {
7770 if (cgnapt_meta_offset_present) {
7771 printf("CG-NAPT parse error:");
7772 printf("cgnapt_meta_offset initizlized "
7773 "mulitple times\n");
7776 cgnapt_meta_offset_present = 1;
7778 temp = atoi(arg_value);
7781 printf("cgnapt_meta_offset is invalid :");
7782 printf("Not be more than metadata size\n");
7785 cgnapt_meta_offset = (uint16_t) temp;
7787 if (strcmp(arg_name, "vnf_set") == 0)
7790 if (strcmp(arg_name, "public_ip_range") == 0) {
7791 public_ip_range_present = 1;
7792 if (public_ip_port_range_present) {
7793 printf("CG-NAPT parse error:");
7794 printf("public_ip_range with "
7795 "public_ip_port_range_present\n");
7799 p->pub_ip_range = rte_realloc(p->pub_ip_range,
7802 RTE_CACHE_LINE_SIZE);
7804 if (!p->pub_ip_range) {
7805 printf("Memory allocation failed for "
7810 uint32_t sip = 0, eip = 0;
7812 if (sscanf(arg_value, "(%x,%x)", &sip, &eip) != 2) {
7813 printf("public_ip_range is invalid\n");
7817 if (sip <= 0 || eip <= 0 || sip >= eip) {
7818 printf("public_ip_range is invalid %x-%x\n",
7823 printf("public_ip_range: %d-%d\n",
7824 p->pub_ip_range[public_ip_range_count].
7826 p->pub_ip_range[public_ip_range_count].
7829 p->pub_ip_range_count = ++public_ip_range_count;
7833 if (strcmp(arg_name, "public_ip_port_range") == 0) {
7834 public_ip_port_range_present = 1;
7835 if (nat_only_config_flag || public_ip_range_present) {
7837 printf("CG-NAPT parse error:");
7838 printf("nat_only_config_flag OR ");
7839 printf("public_ip_range_present with "
7840 "public_ip_port_range_present\n");
7844 p->pub_ip_port_set = rte_realloc(
7846 sizeof(struct pub_ip_port_set),
7847 RTE_CACHE_LINE_SIZE);
7849 if (!p->pub_ip_port_set) {
7850 printf("Memory allocation failed for "
7858 if (sscanf(arg_value, "%x:(%d,%d)",
7859 &ip, &sp, &ep) != 3) {
7860 printf("Public IP or Port-range is invalid\n");
7864 if (ip <= 0 || sp <= 0 || ep <= 0 || sp > ep) {
7865 printf("Public IP or Port-range is invalid "
7866 "%x:%d-%d\n", ip, sp, ep);
7870 printf("public_ip: 0x%x Range:%d-%d\n",
7871 p->pub_ip_port_set[public_ip_count].ip = ip,
7872 p->pub_ip_port_set[public_ip_count].start_port = sp,
7873 p->pub_ip_port_set[public_ip_count].end_port = ep);
7875 napt_port_alloc_elem_count += (ep - sp + 1);
7876 printf("parse - napt_port_alloc_elem_count :%d\n",
7877 napt_port_alloc_elem_count);
7879 /* Store all public IPs of all CGNAPT threads
7880 * in the global variable
7882 /* to revisit indexing */
7883 all_public_ip[rte_jhash(&ip, 4, 0) %
7884 CGNAPT_MAX_PUB_IP].ip = ip;
7885 p->pub_ip_count = ++public_ip_count;
7886 printf("public_ip_count:%d hash:%d\n", public_ip_count,
7887 rte_jhash(&ip, 4, 0) % CGNAPT_MAX_PUB_IP);
7891 /* hw_checksum_reqd */
7892 if (strcmp(arg_name, "hw_checksum_reqd") == 0) {
7894 temp = atoi(arg_value);
7895 if ((temp != 0) && (temp != 1)) {
7896 printf("hw_checksum_reqd is invalid\n");
7899 p->hw_checksum_reqd = temp;
7903 /* nat_only_config_flag */
7904 if (strcmp(arg_name, "nat_only_config_flag") == 0) {
7905 nat_only_config_flag = 1;
7906 if (public_ip_port_range_present) {
7908 printf("CG-NAPT parse error:");
7909 printf("nat_only_config_flag with "
7910 "public_ip_port_range_present\n");
7916 /* max_port_per_client */
7917 if (strcmp(arg_name, "max_port_per_client") == 0) {
7918 if (max_port_present) {
7919 printf("CG-NAPT Parse Error: "
7920 "duplicate max_port_per_client\n");
7923 max_port_present = 1;
7926 max = atoi(arg_value);
7928 printf("max_port_per_client is invalid !!!\n");
7932 p->max_port_per_client = (uint16_t) max;
7934 if (p->max_port_per_client <= 0) {
7935 printf("max port per client is invalid\n");
7939 printf("max_port_per_client comp: %d\n",
7940 p->max_port_per_client);
7944 /* max_clients_per_ip */
7945 if (strcmp(arg_name, "max_clients_per_ip") == 0) {
7946 if (max_client_present) {
7947 printf("CG-NAPT parse Error: duplicate "
7948 "max_clients_per_ip\n");
7951 max_client_present = 1;
7953 if (nat_only_config_flag) {
7954 printf("CG-NAPT parse error:");
7955 printf("nat_only_config_flag with "
7956 "max_clients_per_ip\n");
7961 max = atoi(arg_value);
7963 printf("max_clients_per_ip is invalid !!!\n");
7967 p->max_clients_per_ip = (uint16_t) max;
7969 if (p->max_clients_per_ip <= 0) {
7970 printf("max_clients_per_ip is invalid\n");
7974 printf("max_clients_per_ip: %d\n",
7975 p->max_clients_per_ip);
7980 if (strcmp(arg_name, "n_entries") == 0) {
7981 if (n_entries_present)
7983 n_entries_present = 1;
7985 p->n_entries = atoi(arg_value);
7986 if (p->n_entries == 0)
7993 if (strcmp(arg_name, "n_flows") == 0) {
7994 if (n_flows_present)
7996 n_flows_present = 1;
7998 p->n_flows = atoi(arg_value);
7999 if (p->n_flows == 0)
8002 napt_common_table_hash_params.entries = p->n_flows;
8005 /* dest_if_offset Multiport Changes */
8006 if (strcmp(arg_name, "dest_if_offset") == 0) {
8007 if (dest_if_offset_present)
8009 //dest_if_offset_present = 1;
8011 dest_if_offset = atoi(arg_value);
8017 if (strcmp(arg_name, "key_offset") == 0) {
8018 if (key_offset_present)
8020 key_offset_present = 1;
8022 p->key_offset = atoi(arg_value);
8028 if (strcmp(arg_name, "key_size") == 0) {
8029 if (key_size_present)
8031 key_size_present = 1;
8033 p->key_size = atoi(arg_value);
8034 if ((p->key_size == 0) ||
8035 (p->key_size > PIPELINE_CGNAPT_KEY_MAX_SIZE) ||
8043 if (strcmp(arg_name, "hash_offset") == 0) {
8044 if (hash_offset_present)
8046 hash_offset_present = 1;
8048 p->hash_offset = atoi(arg_value);
8054 if (strcmp(arg_name, "pkt_type") == 0) {
8055 if (strcmp(arg_value, "ipv4") == 0) {
8056 p->traffic_type = TRAFFIC_TYPE_IPV4;
8057 printf("Traffic is set to IPv4\n");
8058 } else if (strcmp(arg_value, "ipv6") == 0) {
8059 p->traffic_type = TRAFFIC_TYPE_IPV6;
8060 printf("Traffic is set to IPv6\n");
8066 if (strcmp(arg_name, "cgnapt_debug") == 0) {
8067 CGNAPT_DEBUG = atoi(arg_value);
8072 /* any other Unknown argument return -1 */
8075 #ifdef NAT_ONLY_CONFIG_REQ
8076 if (nat_only_config_flag) {
8077 if (!public_ip_range_count) {
8078 printf("No public_ip_range %d for NAT only config.\n",
8079 public_ip_range_count);
8080 printf("Running static NAT only configuration\n");
8081 p->is_static_cgnapt = 1;
8086 if (!p->max_port_per_client)
8087 p->is_static_cgnapt = 1;
8090 /* Check that mandatory arguments are present */
8091 if ((n_flows_present == 0) ||
8092 (cgnapt_meta_offset_present == 0))
8099 * Function to initialize the pipeline
8102 * A pointer to struct pipeline_params
8104 * Void pointer - points to app params
8107 * void pointer to the pipeline, NULL 0 if failure
8109 static void *pipeline_cgnapt_init(struct pipeline_params *params, void *arg)
8110 /* (struct app_params *app) save it for use in port in handler */
8113 struct pipeline_cgnapt *p_nat;
8114 uint32_t size, i, in_ports_arg_size;
8116 /* Check input arguments */
8117 if ((params == NULL) ||
8118 (params->n_ports_in == 0) || (params->n_ports_out == 0))
8121 /* Memory allocation */
8122 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_cgnapt));
8123 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8124 p_nat = (struct pipeline_cgnapt *)p;
8125 global_pnat = p_nat;
8129 all_pipeline_cgnapt[n_cgnapt_pipeline++] = p_nat;
8131 strncpy(p->name, params->name,PIPELINE_NAME_SIZE);
8132 p->log_level = params->log_level;
8134 PLOG(p, HIGH, "CG-NAPT");
8135 /* Initialize all counters and arrays */
8137 p_nat->n_cgnapt_entry_deleted = 0;
8138 p_nat->n_cgnapt_entry_added = 0;
8139 p_nat->naptedPktCount = 0;
8140 p_nat->naptDroppedPktCount = 0;
8141 p_nat->inaptedPktCount = 0;
8142 p_nat->enaptedPktCount = 0;
8143 p_nat->receivedPktCount = 0;
8144 p_nat->missedPktCount = 0;
8145 p_nat->dynCgnaptCount = 0;
8146 p_nat->arpicmpPktCount = 0;
8148 p_nat->app_params_addr = (uint64_t) arg;
8149 for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
8150 p_nat->links_map[i] = 0xff;
8151 p_nat->outport_id[i] = 0xff;
8152 cgnapt_in_port_egress_prv[i] = 0;
8153 cgnapt_prv_que_port_index[i] = 0;
8155 p_nat->pipeline_num = 0xff;
8156 p_nat->hw_checksum_reqd = 0;
8157 p_nat->pub_ip_port_set = NULL;
8158 p_nat->pub_ip_count = 0;
8159 p_nat->traffic_type = TRAFFIC_TYPE_IPV4;
8160 p_nat->vnf_set = 0xff;
8162 /* For every init it should be reset */
8163 napt_port_alloc_elem_count = 0;
8165 #ifdef CGNAPT_TIMING_INST
8166 p_nat->in_port_exit_timestamp = 0;
8167 p_nat->external_time_sum = 0;
8168 p_nat->internal_time_sum = 0;
8169 p_nat->time_measurements = 0;
8170 p_nat->max_time_mesurements = 10000;
8171 p_nat->time_measurements_on = 0;
8174 #ifdef CGNAPT_DEBUGGING
8176 p_nat->naptDebugCount = 0;
8178 p_nat->naptDroppedPktCount1 = 0;
8179 p_nat->naptDroppedPktCount2 = 0;
8180 p_nat->naptDroppedPktCount3 = 0;
8181 p_nat->naptDroppedPktCount4 = 0;
8182 p_nat->naptDroppedPktCount5 = 0;
8183 p_nat->naptDroppedPktCount6 = 0;
8185 p_nat->missedpktcount1 = 0;
8186 p_nat->missedpktcount2 = 0;
8187 p_nat->missedpktcount3 = 0;
8188 p_nat->missedpktcount4 = 0;
8189 p_nat->missedpktcount5 = 0;
8190 p_nat->missedpktcount6 = 0;
8191 p_nat->missedpktcount7 = 0;
8192 p_nat->missedpktcount8 = 0;
8193 p_nat->missedpktcount9 = 0;
8194 p_nat->missedpktcount10 = 0;
8195 p_nat->missedpktcount11 = 0;
8196 p_nat->missedpktcount12 = 0;
8198 p_nat->max_port_dec_err1 = 0;
8199 p_nat->max_port_dec_err2 = 0;
8200 p_nat->max_port_dec_err3 = 0;
8201 p_nat->max_port_dec_success = 0;
8217 static int sip_enabled;
8221 #endif /* SIP_ALG */
8223 /*struct rte_pipeline_table_entry *entries[RTE_HASH_LOOKUP_BULK_MAX];*/
8224 /* bitmap of valid packets */
8225 p_nat->valid_packets = 0;
8226 /* bitmap of invalid packets to be dropped */
8227 p_nat->invalid_packets = 0;
8229 for (i = 0; i < RTE_HASH_LOOKUP_BULK_MAX; i++)
8230 p_nat->key_ptrs[i] = &(p_nat->keys[i]);
8232 p_nat->port_alloc_ring = NULL;
8234 /* Parse arguments */
8235 if (pipeline_cgnapt_parse_args(p_nat, params))
8238 p_nat->vnf_set = vnf_set_count;
8242 struct rte_pipeline_params pipeline_params = {
8243 .name = params->name,
8244 .socket_id = params->socket_id,
8245 .offset_port_id = cgnapt_meta_offset,
8248 p->p = rte_pipeline_create(&pipeline_params);
8256 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8258 uint32_t instr_size =
8259 RTE_CACHE_LINE_ROUNDUP((sizeof(uint64_t)) *
8262 (uint64_t *) rte_zmalloc(NULL, instr_size,
8263 RTE_CACHE_LINE_SIZE);
8265 (uint64_t *) rte_zmalloc(NULL, instr_size,
8266 RTE_CACHE_LINE_SIZE);
8268 (uint32_t *) rte_zmalloc(NULL, instr_size / 2,
8269 RTE_CACHE_LINE_SIZE);
8270 if ((inst_start_time == NULL) || (inst_end_time == NULL)
8271 || (inst_diff_time == NULL)) {
8272 printf("Inst array alloc failed .... ");
8277 /* Memory allocation for in_port_h_arg */
8278 in_ports_arg_size = RTE_CACHE_LINE_ROUNDUP(
8279 (sizeof(struct pipeline_cgnapt_in_port_h_arg)) *
8280 (params->n_ports_in));
8281 struct pipeline_cgnapt_in_port_h_arg *ap =
8282 (struct pipeline_cgnapt_in_port_h_arg *)
8285 RTE_CACHE_LINE_SIZE);
8289 myApp = (struct app_params *) arg;
8292 p->n_ports_in = params->n_ports_in;
8293 for (i = 0; i < p->n_ports_in; i++) {
8294 /* passing our cgnapt pipeline in call back arg */
8296 (ap[i]).in_port_id = i;
8298 struct rte_pipeline_port_in_params port_params = {
8300 pipeline_port_in_params_get_ops(¶ms->port_in
8303 pipeline_port_in_params_convert(¶ms->port_in
8305 .f_action = cgnapt_in_port_ah_mix,
8307 .burst_size = params->port_in[i].burst_size,
8310 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8312 instrumentation_port_in_arg = &(ap[i]);
8315 if (p_nat->traffic_type == TRAFFIC_TYPE_IPV4) {
8316 /* Private in-port handler */
8317 /* Multiport changes */
8318 if (cgnapt_in_port_egress_prv[i]) {
8319 port_params.f_action =
8320 cgnapt_in_port_ah_ipv4_prv;
8321 printf("CGNAPT port %d is IPv4 Prv\n", i);
8323 port_params.f_action =
8324 cgnapt_in_port_ah_ipv4_pub;
8325 printf("CGNAPT port %d is IPv4 Pub\n", i);
8329 if (p_nat->traffic_type == TRAFFIC_TYPE_IPV6) {
8330 if (cgnapt_in_port_egress_prv[i]) {
8331 port_params.f_action =
8332 cgnapt_in_port_ah_ipv6_prv;
8333 printf("CGNAPT port %d is IPv6 Prv\n", i);
8335 port_params.f_action =
8336 cgnapt_in_port_ah_ipv6_pub;
8337 printf("CGNAPT port %d is IPv6 Pub\n", i);
8341 int status = rte_pipeline_port_in_create(p->p,
8346 rte_pipeline_free(p->p);
8354 p->n_ports_out = params->n_ports_out;
8355 for (i = 0; i < p->n_ports_out; i++) {
8356 struct rte_pipeline_port_out_params port_params = {
8357 .ops = pipeline_port_out_params_get_ops(
8358 ¶ms->port_out[i]),
8359 .arg_create = pipeline_port_out_params_convert(
8360 ¶ms->port_out[i]),
8361 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8362 .f_action = port_out_ah_cgnapt,
8369 int status = rte_pipeline_port_out_create(p->p,
8371 &p->port_out_id[i]);
8374 rte_pipeline_free(p->p);
8380 int pipeline_num = 0;
8382 ignore = sscanf(params->name, "PIPELINE%d", &pipeline_num);
8384 printf("Not able to read pipeline number\n");
8387 p_nat->pipeline_num = (uint8_t) pipeline_num;
8388 register_pipeline_Qs(p_nat->pipeline_num, p);
8389 set_link_map(p_nat->pipeline_num, p, p_nat->links_map);
8390 set_outport_id(p_nat->pipeline_num, p, p_nat->outport_id);
8396 if (napt_common_table == NULL) {
8397 if (create_napt_common_table(p_nat->n_flows)) {
8399 "CG-NAPT create_napt_common_table failed.");
8404 struct rte_pipeline_table_params table_params = {
8405 .ops = &rte_table_stub_ops,
8407 .f_action_hit = NULL,
8408 .f_action_miss = NULL,
8410 .action_data_size = 0,
8413 int status = rte_pipeline_table_create(p->p,
8418 rte_pipeline_free(p->p);
8422 struct rte_pipeline_table_entry default_entry = {
8423 .action = RTE_PIPELINE_ACTION_PORT_META
8425 struct rte_pipeline_table_entry *default_entry_ptr;
8426 status = rte_pipeline_table_default_entry_add(
8430 &default_entry_ptr);
8432 rte_pipeline_free(p->p);
8438 /* Connecting input ports to tables */
8439 for (i = 0; i < p->n_ports_in; i++) {
8440 int status = rte_pipeline_port_in_connect_to_table(p->p,
8447 rte_pipeline_free(p->p);
8453 /* Enable input ports */
8454 for (i = 0; i < p->n_ports_in; i++) {
8455 int status = rte_pipeline_port_in_enable(p->p,
8459 rte_pipeline_free(p->p);
8465 /* Check pipeline consistency */
8466 if (rte_pipeline_check(p->p) < 0) {
8467 rte_pipeline_free(p->p);
8472 /* Message queues */
8473 p->n_msgq = params->n_msgq;
8474 for (i = 0; i < p->n_msgq; i++)
8475 p->msgq_in[i] = params->msgq_in[i];
8476 for (i = 0; i < p->n_msgq; i++)
8477 p->msgq_out[i] = params->msgq_out[i];
8479 /* Message handlers */
8480 memcpy(p->handlers, handlers, sizeof(p->handlers));
8481 memcpy(p_nat->custom_handlers,
8482 custom_handlers, sizeof(p_nat->custom_handlers));
8484 if (!p_nat->is_static_cgnapt) {
8485 printf("Initializing dyn napt components ... %d\n",
8486 p_nat->pipeline_num);
8487 if (napt_port_alloc_init(p_nat) == -1) {
8488 printf("Error - napt_port_alloc_init failed - %d\n",
8489 p_nat->pipeline_num);
8494 if (max_port_per_client_hash == NULL) {
8495 rc = init_max_port_per_client(p_nat);
8497 printf("CGNAPT Error - "
8498 "init_max_port_per_client failed %d", rc);
8505 if (!icmp_pool_init) {
8507 /* create the arp_icmp mbuf rx pool */
8508 cgnapt_icmp_pktmbuf_tx_pool =
8509 rte_pktmbuf_pool_create("icmp_mbuf_tx_pool", 63, 32, 0,
8510 RTE_MBUF_DEFAULT_BUF_SIZE,
8512 if (cgnapt_icmp_pktmbuf_tx_pool == NULL) {
8513 PLOG(p, HIGH, "ICMP mbuf pool create failed.");
8518 rte_pktmbuf_alloc(cgnapt_icmp_pktmbuf_tx_pool);
8520 if (cgnapt_icmp_pkt == NULL) {
8521 printf("Failed to allocate cgnapt_icmp_pkt\n");
8528 cgnat_cnxn_tracker = rte_zmalloc(NULL, rte_ct_get_cnxn_tracker_size(),
8529 RTE_CACHE_LINE_SIZE);
8531 if (cgnat_cnxn_tracker == NULL) {
8532 printf("CGNAPT CT memory not allocated\n");
8535 rte_ct_initialize_default_timeouts(cgnat_cnxn_tracker);
8537 printf("CGNAPT CT Flows %d\n", p_nat->n_flows);
8539 ret = rte_ct_initialize_cnxn_tracker(cgnat_cnxn_tracker,
8541 "CGNAT_CT_COMMON_TABLE");
8551 if (pcp_init() == PCP_INIT_SUCCESS)
8552 printf("PCP contents are initialized successfully\n");
8554 printf("Error in initializing PCP contents\n");
8561 * Function for pipeline cleanup
8564 * A void pointer to pipeline
8569 static int pipeline_cgnapt_free(void *pipeline)
8571 struct pipeline *p = (struct pipeline *)pipeline;
8573 /* Check input arguments */
8577 /* Free resources */
8578 rte_pipeline_free(p->p);
8584 pipeline_cgnapt_track(void *pipeline, __rte_unused uint32_t port_in,
8587 struct pipeline *p = (struct pipeline *)pipeline;
8589 /* Check input arguments */
8590 if ((p == NULL) || (port_in >= p->n_ports_in) || (port_out == NULL))
8593 if (p->n_ports_in == 1) {
8602 * Function for pipeline timers
8605 * A void pointer to pipeline
8610 static int pipeline_cgnapt_timer(void *pipeline)
8612 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)pipeline;
8614 pipeline_msg_req_handle(&p_nat->p);
8616 rte_pipeline_flush(((struct pipeline *)p_nat)->p);
8622 * Function for pipeline custom handlers
8625 * A void pointer to pipeline
8627 * void pointer for incoming data
8630 * void pointer of response
8632 void *pipeline_cgnapt_msg_req_custom_handler(struct pipeline *p, void *msg)
8634 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
8635 struct pipeline_custom_msg_req *req = msg;
8636 pipeline_msg_req_handler f_handle;
8638 f_handle = (req->subtype < PIPELINE_CGNAPT_MSG_REQS) ?
8639 p_nat->custom_handlers[req->subtype] :
8640 pipeline_msg_req_invalid_handler;
8642 if (f_handle == NULL)
8643 f_handle = pipeline_msg_req_invalid_handler;
8645 return f_handle(p, req);
8649 * Function for adding NSP data
8652 * A void pointer to pipeline
8654 * void pointer for incoming data
8657 * void pointer of response
8659 void *pipeline_cgnapt_msg_req_nsp_add_handler(
8660 __rte_unused struct pipeline *p,
8663 struct pipeline_cgnapt_nsp_add_msg_req *req = msg;
8664 struct pipeline_cgnapt_nsp_add_msg_rsp *rsp = msg;
8666 struct cgnapt_nsp_node *node = NULL, *ll = nsp_ll;
8669 (req->nsp.depth == 32 || req->nsp.depth == 40
8670 || req->nsp.depth == 48 || req->nsp.depth == 56
8671 || req->nsp.depth == 64 || req->nsp.depth == 96)) {
8677 printf("be initial cond\n");
8678 if (nsp_ll == NULL) {
8679 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_nsp_node));
8680 node = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8682 printf("be 1st cond\n");
8688 memcpy(&node->nsp, &req->nsp,
8689 sizeof(struct pipeline_cgnapt_nsp_t));
8693 while (ll != NULL) {
8694 if (!memcmp(ll->nsp.prefix, req->nsp.prefix, 16)
8695 && ll->nsp.depth == req->nsp.depth) {
8696 printf("be 2st cond\n");
8704 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_nsp_node));
8705 node = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8707 printf("be 3st cond\n");
8713 memcpy(&node->nsp, &req->nsp,
8714 sizeof(struct pipeline_cgnapt_nsp_t));
8715 node->next = nsp_ll;
8722 printf("be 4st cond\n");
8727 * Function for deleting NSP data
8730 * A void pointer to pipeline
8732 * void pointer for incoming data
8735 * void pointer of response
8737 void *pipeline_cgnapt_msg_req_nsp_del_handler(
8738 __rte_unused struct pipeline *p,
8741 struct pipeline_cgnapt_nsp_del_msg_req *req = msg;
8742 struct pipeline_cgnapt_nsp_del_msg_rsp *rsp = msg;
8743 struct cgnapt_nsp_node *prev = NULL, *ll = nsp_ll;
8745 while (ll != NULL) {
8746 if (!memcmp(ll->nsp.prefix, req->nsp.prefix, 16)
8747 && ll->nsp.depth == req->nsp.depth) {
8749 prev->next = ll->next;
8772 * Function for adding NAPT entry
8775 * A void pointer to pipeline
8777 * void pointer for incoming data
8780 * void pointer of response
8782 void *pipeline_cgnapt_msg_req_entry_add_handler(struct pipeline *p, void *msg)
8784 struct pipeline_cgnapt_entry_add_msg_req *req = msg;
8785 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
8786 uint8_t type = req->data.type;
8787 uint32_t src_ip = (type == CGNAPT_ENTRY_IPV4) ?
8788 req->data.u.prv_ip :
8789 rte_bswap32(req->data.u.u32_prv_ipv6[3]);
8791 uint8_t src_ipv6[16];
8793 uint32_t dest_ip = req->data.pub_ip;
8794 uint16_t src_port = req->data.prv_port;
8795 uint16_t dest_port = req->data.pub_port;
8796 uint16_t rx_port = req->data.prv_phy_port;
8797 uint32_t ttl = req->data.ttl;
8799 if (type == CGNAPT_ENTRY_IPV6)
8800 memcpy(src_ipv6, req->data.u.prv_ipv6, 16);
8802 printf("CG-NAPT addm - PrvIP %x, PrvPort %d,", src_ip, src_port);
8803 printf("PubIP %x, PubPort %d,", dest_ip, dest_port);
8805 printf("PhyPort %d, ttl %u,", rx_port, ttl);
8806 printf("entry_type %d\n", type);
8807 #ifdef NAT_ONLY_CONFIG_REQ
8808 if (nat_only_config_flag) {
8809 if (!p_nat->is_static_cgnapt) {
8812 for (i = 0; i < p_nat->pub_ip_range_count; i++) {
8813 if (((dest_ip >= p_nat->pub_ip_range[i].start_ip)
8814 && (dest_ip <= p_nat->pub_ip_range[i].end_ip))) {
8815 printf("Error - static port cannot be in Dynamic "
8817 printf("%x-%x\n", p_nat->pub_ip_range[i].start_ip,
8818 p_nat->pub_ip_range[i].end_ip);
8824 if (pipeline_cgnapt_msg_req_entry_addm_pair(p, msg,
8830 printf("pipeline_cgnapt_msg_req_entry_addm_handler\n");
8834 #ifdef CGNAPT_DBG_PRNT
8835 printf("Success - pipeline_cgnapt_msg_req_entry_addm_handler");
8836 printf("added %d rule pairs.\n", count);
8842 if (!p_nat->is_static_cgnapt) {
8845 for (i = 0; i < p_nat->pub_ip_count; i++) {
8846 /* Check port range if same Public-IP */
8847 if (dest_ip != p_nat->pub_ip_port_set[i].ip)
8849 if (((dest_port >= p_nat->pub_ip_port_set[i].start_port) &&
8850 (dest_port <= p_nat->pub_ip_port_set[i].end_port))) {
8851 printf("Error - port cannot be in Dynamic "
8852 "port range %d-%d\n",
8853 p_nat->pub_ip_port_set[i].start_port,
8854 p_nat->pub_ip_port_set[i].end_port);
8860 if (pipeline_cgnapt_msg_req_entry_addm_pair
8861 (p, msg, src_ip, src_port, dest_ip, dest_port, rx_port,
8862 ttl, type, src_ipv6)) {
8863 printf("Error - pipeline_cgnapt_msg_req_entry_add_handler\n");
8868 #ifdef CGNAPT_DBG_PRNT
8869 printf("\nSuccess - pipeline_cgnapt_msg_req_entry_add_handler "
8876 * Function for adding a NAPT entry pair
8879 * A void pointer to pipeline
8881 * void pointer for incoming data
8887 * destination ip address
8891 * Physical receive port
8893 * time to live value
8895 * type of entry IPv4 vs IPv6
8897 * uint8_t array of IPv6 address
8900 * 0 if success, negative if fails
8903 pipeline_cgnapt_msg_req_entry_addm_pair(
8904 struct pipeline *p, __rte_unused void *msg,
8905 uint32_t src_ip, uint16_t src_port,
8906 uint32_t dest_ip, uint16_t dest_port,
8907 uint16_t rx_port, uint32_t ttl,
8908 uint8_t type, uint8_t src_ipv6[16])
8911 struct pipeline_cgnapt_entry_key key;
8912 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
8915 key.port = src_port;
8918 struct cgnapt_table_entry entry = {
8920 .action = RTE_PIPELINE_ACTION_PORT,
8921 .port_id = CGNAPT_PUB_PORT_ID,
8925 /*.prv_ip = src_ip, */
8926 .prv_port = src_port,
8928 .pub_port = dest_port,
8929 .prv_phy_port = rx_port,
8930 .pub_phy_port = get_prv_to_pub_port(&dest_ip,
8933 .timeout = STATIC_CGNAPT_TIMEOUT,
8940 if (type == CGNAPT_ENTRY_IPV4) {
8941 entry.data.type = CGNAPT_ENTRY_IPV4;
8942 entry.data.u.prv_ip = src_ip;
8944 entry.data.type = CGNAPT_ENTRY_IPV6;
8945 memcpy(entry.data.u.prv_ipv6, src_ipv6, 16);
8948 /* Also need to add a paired entry on our own */
8950 * Need to change key
8951 * Need to change entry header
8952 * Will keep the same entry and take care
8953 * of translation in table hit handler
8955 struct pipeline_cgnapt_entry_key second_key;
8957 /* Need to add a second ingress entry */
8958 second_key.ip = dest_ip;
8959 second_key.port = dest_port;
8960 second_key.pid = 0xffff;
8962 #ifdef NAT_ONLY_CONFIG_REQ
8963 if (nat_only_config_flag) {
8965 entry.data.pub_port = 0xffff;
8966 second_key.port = 0xffff;
8970 int32_t position = rte_hash_add_key(napt_common_table, &key);
8973 printf("CG-NAPT entry bulk add failed");
8974 printf(" ... returning without adding ...\n");
8978 memcpy(&napt_hash_tbl_entries[position], &entry,
8979 sizeof(struct cgnapt_table_entry));
8981 #ifdef CGNAPT_DEBUGGING
8982 if (p_nat->kpc1++ < 5)
8986 p_nat->n_cgnapt_entry_added++;
8988 /* Now modify the forward port for reverse entry */
8989 entry.head.port_id = CGNAPT_PRV_PORT_ID;
8991 position = rte_hash_add_key(napt_common_table, &second_key);
8994 printf("CG-NAPT entry reverse bulk add failed");
8995 printf(" ... returning with fwd add ...%d\n", position);
8999 memcpy(&napt_hash_tbl_entries[position], &entry,
9000 sizeof(struct cgnapt_table_entry));
9002 #ifdef CGNAPT_DEBUGGING
9003 if (p_nat->kpc1 < 5)
9004 print_key(&second_key);
9007 p_nat->n_cgnapt_entry_added++;
9012 * Function for adding multiple NAPT entries
9015 * A void pointer to pipeline
9017 * void pointer for incoming data
9020 * void pointer of response
9022 void *pipeline_cgnapt_msg_req_entry_addm_handler(struct pipeline *p, void *msg)
9024 struct pipeline_cgnapt_entry_addm_msg_req *req = msg;
9025 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9027 uint32_t max_ue = req->data.num_ue;
9028 uint8_t type = req->data.type;
9029 uint32_t src_ip = (type == CGNAPT_ENTRY_IPV4) ?
9030 req->data.u.prv_ip :
9031 rte_bswap32(req->data.u.u32_prv_ipv6[3]);
9033 uint8_t src_ipv6[16];
9035 uint32_t dest_ip = req->data.pub_ip;
9036 uint16_t src_port = req->data.prv_port;
9037 uint16_t dest_port = req->data.pub_port;
9038 uint16_t rx_port = req->data.prv_phy_port;
9039 uint32_t ttl = req->data.ttl;
9040 uint16_t max_src_port = req->data.prv_port_max;
9041 uint16_t max_dest_port = req->data.pub_port_max;
9043 uint16_t src_port_start = src_port;
9044 uint16_t dest_port_start = dest_port;
9045 uint32_t src_ip_temp;
9047 if (type == CGNAPT_ENTRY_IPV6)
9048 memcpy(src_ipv6, req->data.u.prv_ipv6, 16);
9050 printf("CG-NAPT addm - PrvIP %x, PrvPort %d,", src_ip, src_port);
9051 printf("PubIP %x, PubPort %d,", dest_ip, dest_port);
9052 printf("PhyPort %d, ttl %u, NumUe %d,", rx_port, ttl, max_ue);
9053 printf("mPrvPort %d, mPubPort %d,", max_src_port, max_dest_port);
9054 printf("entry_type %d\n", type);
9055 #ifdef NAT_ONLY_CONFIG_REQ
9056 if (nat_only_config_flag) {
9057 if (!p_nat->is_static_cgnapt) {
9060 for (i = 0; i < p_nat->pub_ip_range_count; i++) {
9061 if (((dest_ip >= p_nat->pub_ip_range[i].start_ip)
9062 && (dest_ip <= p_nat->pub_ip_range[i].end_ip)) ||
9063 (((dest_ip + max_ue) >=
9064 p_nat->pub_ip_range[i].start_ip) &&
9065 ((dest_ip + max_ue) <=
9066 p_nat->pub_ip_range[i].end_ip))) {
9067 printf("Error - static port cannot be in Dynamic "
9069 printf("%x-%x\n", p_nat->pub_ip_range[i].start_ip,
9070 p_nat->pub_ip_range[i].end_ip);
9077 for (uenum = 0; uenum < max_ue; uenum++) {
9079 if (pipeline_cgnapt_msg_req_entry_addm_pair(p, msg,
9085 printf("pipeline_cgnapt_msg_req_entry_addm_handler\n");
9095 #ifdef CGNAPT_DBG_PRNT
9096 printf("Success - pipeline_cgnapt_msg_req_entry_addm_handler");
9097 printf("added %d rule pairs.\n", count);
9104 if (!p_nat->is_static_cgnapt) {
9107 for (i = 0; i < p_nat->pub_ip_count; i++) {
9108 /* Check port range if same Public-IP */
9109 if (dest_ip != p_nat->pub_ip_port_set[i].ip)
9111 if (((dest_port >= p_nat->pub_ip_port_set[i].start_port) &&
9112 (dest_port <= p_nat->pub_ip_port_set[i].end_port)) ||
9113 ((max_dest_port >= p_nat->pub_ip_port_set[i].start_port)
9114 && max_dest_port <= p_nat->pub_ip_port_set[i].end_port)) {
9115 printf("Error - port cannot be in Dynamic port range %d-%d\n",
9116 p_nat->pub_ip_port_set[i].start_port,
9117 p_nat->pub_ip_port_set[i].end_port);
9123 for (uenum = 0; uenum < max_ue; uenum++) {
9124 if (pipeline_cgnapt_msg_req_entry_addm_pair
9125 (p, msg, src_ip, src_port, dest_ip, dest_port, rx_port,
9126 ttl, type, src_ipv6)) {
9127 printf("Error - pipeline_cgnapt_msg_req_entry_addm_handler\n");
9134 if (src_port > max_src_port) {
9135 src_port = src_port_start;
9137 if (req->data.type == CGNAPT_ENTRY_IPV6) {
9138 src_ip_temp = rte_bswap32(src_ip);
9139 memcpy(&src_ipv6[12], &src_ip_temp, 4);
9143 if (dest_port > max_dest_port) {
9144 dest_port = dest_port_start;
9149 #ifdef CGNAPT_DBG_PRNT
9150 printf("\nSuccess - pipeline_cgnapt_msg_req_entry_addm_handler added");
9151 printf("%d rule pairs.\n", count);
9157 * Function for deleting NAPT entry
9160 * A void pointer to pipeline
9162 * void pointer for incoming data
9165 * void pointer of response
9167 void *pipeline_cgnapt_msg_req_entry_del_handler(struct pipeline *p, void *msg)
9169 struct pipeline_cgnapt_entry_delete_msg_req *req = msg;
9170 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9171 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9174 uint8_t *KeyP = (void *)(&req->key);
9177 printf("pipeline_cgnapt_msg_req_entry_del_handler - Key: ");
9178 for (i = 0; i < (int)sizeof(struct pipeline_cgnapt_entry_key);
9180 printf(" %02x", KeyP[i]);
9181 printf(" ,KeySize %u\n",
9182 (int)sizeof(struct pipeline_cgnapt_entry_key));
9185 struct cgnapt_table_entry entry;
9187 /* If ingress key */
9188 if (!is_phy_port_privte(req->key.pid))
9189 req->key.pid = 0xffff;
9191 #ifdef NAT_ONLY_CONFIG_REQ
9192 if (nat_only_config_flag)
9193 req->key.port = 0xffff;
9197 position = rte_hash_lookup(napt_common_table, &req->key);
9198 if (position == -ENOENT) {
9199 printf("Entry not found\n");
9202 memcpy(&entry, &napt_hash_tbl_entries[position],
9203 sizeof(struct cgnapt_table_entry));
9204 position = rte_hash_del_key(napt_common_table, &req->key);
9205 p_nat->n_cgnapt_entry_deleted++;
9207 struct pipeline_cgnapt_entry_key second_key;
9209 if (is_phy_port_privte(req->key.pid)) {
9210 /* key is for egress - make second key for ingress */
9211 second_key.ip = entry.data.pub_ip;
9212 second_key.port = entry.data.pub_port;
9213 second_key.pid = 0xffff;
9216 /* key is for ingress - make second key for egress */
9217 second_key.ip = entry.data.u.prv_ip;
9218 second_key.port = entry.data.prv_port;
9219 second_key.pid = entry.data.prv_phy_port;
9222 #ifdef NAT_ONLY_CONFIG_REQ
9223 if (nat_only_config_flag)
9224 second_key.port = 0xffff;
9227 position = rte_hash_del_key(napt_common_table, &second_key);
9228 p_nat->n_cgnapt_entry_deleted++;
9233 void *pipeline_cgnapt_msg_req_entry_sync_handler(struct pipeline *p, void *msg)
9235 struct pipeline_cgnapt_entry_delete_msg_req *req = msg;
9236 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9238 rsp->status = rte_pipeline_table_entry_delete(
9242 &rsp->key_found, NULL);
9248 * Function to print the NAPT key
9251 * A pointer to struct pipeline_cgnapt_entry_key
9253 void print_key(struct pipeline_cgnapt_entry_key *key)
9255 uint8_t *KeyP = (void *)(key);
9259 for (i = 0; i < (int)sizeof(struct pipeline_cgnapt_entry_key); i++)
9260 printf(" %02x", KeyP[i]);
9264 * Function to print the table entry
9267 * A pointer to struct rte_pipeline_table_entry
9269 void print_entry1(struct rte_pipeline_table_entry *entry)
9271 uint8_t *entryP = (void *)(entry);
9275 for (i = 0; i < (int)sizeof(struct rte_pipeline_table_entry); i++)
9276 printf(" %02x", entryP[i]);
9280 * Function to print the NAPT table entry
9283 * A pointer to struct cgnapt_table_entry
9285 void print_cgnapt_entry(struct cgnapt_table_entry *entry)
9287 uint8_t *entryP = (void *)(entry);
9290 printf("CGNAPT Entry: ");
9291 for (i = 0; i < (int)sizeof(struct cgnapt_table_entry); i++)
9292 printf(" %02x", entryP[i]);
9293 printf(" size:%d\n", (int)sizeof(struct cgnapt_table_entry));
9297 * Function to get a free port
9300 * A pointer to struct pipeline_cgnapt
9302 * A uint32_t pointer to return corresponding ip address
9305 * free port number, 0 if error
9307 int get_free_iport(struct pipeline_cgnapt *p_nat, uint32_t *public_ip)
9310 /* If we don't have a valid napt_port_alloc_elem get one from
9313 if (p_nat->allocated_ports == NULL) {
9317 ret = rte_ring_dequeue(p_nat->port_alloc_ring, &ports);
9319 p_nat->allocated_ports =
9320 (struct napt_port_alloc_elem *)ports;
9322 #ifdef CGNAPT_DEBUGGING
9326 #ifdef CGNAPT_DBG_PRNT
9327 if (CGNAPT_DEBUG > 3)
9328 printf("p_nat->allocated_ports %p\n",
9329 p_nat->allocated_ports);
9332 printf("CGNAPT Err - get_free_iport rte_ring_dequeue "
9334 printf("%d, %d, %d\n", rte_ring_count(
9335 p_nat->port_alloc_ring), rte_ring_free_count(
9336 p_nat->port_alloc_ring), ret);
9338 #ifdef CGNAPT_DEBUGGING
9339 #ifdef CGNAPT_DBG_PRNT
9340 printf("Th%d GFP:: %" PRIu64 ", %" PRIu64 ", "
9341 "%" PRIu64", %" PRIu64 ",\n", p_nat->pipeline_num,
9342 p_nat->gfp_get, p_nat->gfp_ret, p_nat->gfp_suc,
9352 /* get the port from index count-1 and decrease count */
9353 port = p_nat->allocated_ports->ports
9354 [p_nat->allocated_ports->count - 1];
9355 *public_ip = p_nat->allocated_ports->ip_addr
9356 [p_nat->allocated_ports->count - 1];
9358 p_nat->allocated_ports->count -= 1;
9360 /* if count is zero, return buffer to mem pool */
9361 if (p_nat->allocated_ports->count == 0) {
9362 rte_mempool_put(napt_port_pool, p_nat->allocated_ports);
9364 #ifdef CGNAPT_DEBUGGING
9366 #ifdef CGNAPT_DBG_PRNT
9367 printf("Th%d Returned to pool p_nat->allocated_ports %p,",
9368 p_nat->pipeline_num, p_nat->allocated_ports);
9369 printf("%" PRIu64 ", %" PRIu64 ",",
9370 p_nat->gfp_get, p_nat->gfp_ret);
9371 printf("%" PRIu64 ", %" PRIu64 ",\n",
9372 p_nat->gfp_suc, p_nat->gfp_err);
9376 p_nat->allocated_ports = NULL;
9379 #ifdef CGNAPT_DEBUGGING
9387 * Function to free a port
9390 * Port number to free
9392 * Corresponding ip address
9394 * A pointer to struct pipeline_cgnapt
9397 void release_iport(uint16_t port_num, uint32_t public_ip,
9398 struct pipeline_cgnapt *p_nat)
9400 /* If we don't have a valid napt_port_alloc_elem get one
9403 if (p_nat->free_ports == NULL) {
9406 #ifdef CGNAPT_DEBUGGING
9410 if (rte_mempool_get(napt_port_pool, &ports) < 0) {
9411 #ifdef CGNAPT_DEBUGGING
9414 printf("CGNAPT release_iport error in getting "
9415 "port alloc buffer\n");
9419 p_nat->free_ports = (struct napt_port_alloc_elem *)ports;
9420 p_nat->free_ports->count = 0;
9423 /* put the port at index count and increase count */
9424 p_nat->free_ports->ip_addr[p_nat->free_ports->count] = public_ip;
9425 p_nat->free_ports->ports[p_nat->free_ports->count] = port_num;
9426 p_nat->free_ports->count += 1;
9428 /* if napt_port_alloc_elem is full add it to ring */
9431 #ifdef CGNAPT_DEBUGGING
9435 #ifdef CGNAPT_DBG_PRNT
9436 if (CGNAPT_DEBUG >= 2) {
9437 printf("CGNAPT port_alloc_ring before EnQ Cnt %d, Free %d\n",
9438 rte_ring_count(p_nat->port_alloc_ring),
9439 rte_ring_free_count(p_nat->port_alloc_ring));
9443 if (rte_ring_enqueue(p_nat->port_alloc_ring,
9444 (void *)p_nat->free_ports) != 0) {
9445 printf("CGNAPT release_iport Enqueue error %p\n",
9448 #ifdef CGNAPT_DEBUGGING
9453 #ifdef CGNAPT_DBG_PRNT
9454 if (CGNAPT_DEBUG >= 2) {
9455 printf("CGNAPT port_alloc_ring after EnQ Cnt %d",
9456 rte_ring_count(p_nat->port_alloc_ring));
9458 rte_ring_free_count(p_nat->port_alloc_ring));
9462 p_nat->free_ports = NULL;
9465 #ifdef CGNAPT_DEBUGGING
9471 * Function to initialize max ports per client data structures
9472 * Called during dynamic NAPT initialization.
9475 * A pointer to struct pipeline_cgnapt
9478 * 0 if success, negative if error
9480 int init_max_port_per_client(
9481 __rte_unused struct pipeline_cgnapt *p_nat)
9483 if (max_port_per_client_hash)
9486 /*MPPC_ALREADY_EXISTS */
9490 max_port_per_client_hash =
9491 rte_hash_create(&max_port_per_client_hash_params);
9492 if (!max_port_per_client_hash)
9495 /*MPPC_HASH_CREATE_ERROR */
9497 max_port_per_client_array =
9499 sizeof(struct max_port_per_client) * MAX_DYN_ENTRY,
9500 RTE_CACHE_LINE_SIZE);
9501 if (!max_port_per_client_array)
9504 /*MPPC_ARRAY_CREATE_ERROR */
9506 for (i = 0; i < MAX_DYN_ENTRY; i++) {
9507 max_port_per_client_array[i].prv_ip = 0;
9508 max_port_per_client_array[i].prv_phy_port = 0;
9509 max_port_per_client_array[i].max_port_cnt = 0;
9517 * Function to check if max ports for a client is reached
9519 * @param prv_ip_param
9520 * A uint32_t ip address of client
9521 * @param prv_phy_port_param
9522 * A uint32_t physical port id of the client
9524 * A pointer to struct pipeline_cgnapt
9527 * 0 if max port not reached, 1 if reached, -1 if error
9529 int is_max_port_per_client_reached(uint32_t prv_ip_param,
9530 uint32_t prv_phy_port_param,
9531 struct pipeline_cgnapt *p_nat)
9533 int index = MAX_PORT_INVALID_KEY;
9535 struct max_port_per_client_key key = {
9536 .prv_ip = prv_ip_param,
9537 .prv_phy_port = prv_phy_port_param,
9540 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9543 return MAX_PORT_INVALID_KEY;
9545 if (max_port_per_client_array[index].max_port_cnt >=
9546 p_nat->max_port_per_client)
9547 return MAX_PORT_REACHED;
9549 return MAX_PORT_NOT_REACHED;
9553 * Function to increase max ports for a client
9555 * @param prv_ip_param
9556 * A uint32_t ip address of client
9557 * @param prv_phy_port_param
9558 * A uint32_t physical port id of the client
9560 * A pointer to struct pipeline_cgnapt
9563 * 0 if max port reached, 1 if success, 2 if new entry, -1 if error
9565 int increment_max_port_counter(uint32_t prv_ip_param,
9566 uint32_t prv_phy_port_param,
9567 struct pipeline_cgnapt *p_nat)
9569 int index = MAX_PORT_INC_ERROR;
9571 struct max_port_per_client_key key = {
9572 .prv_ip = prv_ip_param,
9573 .prv_phy_port = prv_phy_port_param,
9576 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9578 if (index == -EINVAL)
9579 return MAX_PORT_INC_ERROR;
9581 if (index == -ENOENT) {
9582 if (max_port_per_client_add_entry(prv_ip_param,
9585 return MAX_PORT_INC_ERROR;
9587 return 2; /*return MAX_PORT_NEW_ENTRY; */
9590 if (CGNAPT_DEBUG > 2)
9591 printf("%s: max_port_cnt(%d), p_nat_max(%d)\n", __func__,
9592 max_port_per_client_array[index].max_port_cnt,
9593 p_nat->max_port_per_client);
9595 if (max_port_per_client_array[index].max_port_cnt <
9596 p_nat->max_port_per_client) {
9597 max_port_per_client_array[index].max_port_cnt++;
9598 return MAX_PORT_INC_SUCCESS;
9601 return MAX_PORT_INC_REACHED;
9605 * Function to decrease max ports for a client
9607 * @param prv_ip_param
9608 * A uint32_t ip address of client
9609 * @param prv_phy_port_param
9610 * A uint32_t physical port id of the client
9612 * A pointer to struct pipeline_cgnapt
9615 * 0 if count already 0, 1 if success, -1 if error
9617 int decrement_max_port_counter(uint32_t prv_ip_param,
9618 uint32_t prv_phy_port_param,
9619 struct pipeline_cgnapt *p_nat)
9621 int index = MAX_PORT_DEC_ERROR;
9623 struct max_port_per_client_key key = {
9624 .prv_ip = prv_ip_param,
9625 .prv_phy_port = prv_phy_port_param,
9628 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9631 #ifdef CGNAPT_DEBUGGING
9632 p_nat->max_port_dec_err1++;
9634 return MAX_PORT_DEC_ERROR;
9638 if (max_port_per_client_array[index].max_port_cnt > 0) {
9639 /* If it is the last port,ret this info which is used for
9640 * max_cli_per_pub_ip
9643 max_port_per_client_array[index].max_port_cnt--;
9644 /* Count should be atomic but we are good as we have only
9645 * one task handling this counter at a time (core affinity)
9649 if (max_port_per_client_array[index].max_port_cnt <= 0) {
9650 if (max_port_per_client_del_entry
9651 (prv_ip_param, prv_phy_port_param, p_nat) <= 0) {
9653 #ifdef CGNAPT_DEBUGGING
9654 p_nat->max_port_dec_err2++;
9656 return MAX_PORT_DEC_ERROR;
9659 #ifdef CGNAPT_DEBUGGING
9660 p_nat->max_port_dec_err3++;
9663 return MAX_PORT_DEC_REACHED;
9666 #ifdef CGNAPT_DEBUGGING
9667 p_nat->max_port_dec_success++;
9670 return MAX_PORT_DEC_SUCCESS;
9674 * Function to add a max ports per client entry
9676 * @param prv_ip_param
9677 * A uint32_t ip address of client
9678 * @param prv_phy_port_param
9679 * A uint32_t physical port id of the client
9681 * A pointer to struct pipeline_cgnapt
9684 * 0 no success, 1 if success, -1 if error
9686 int max_port_per_client_add_entry(
9687 uint32_t prv_ip_param,
9688 uint32_t prv_phy_port_param,
9689 __rte_unused struct pipeline_cgnapt *p_nat)
9691 int index = MAX_PORT_ADD_ERROR;
9693 struct max_port_per_client_key key = {
9694 .prv_ip = prv_ip_param,
9695 .prv_phy_port = prv_phy_port_param,
9698 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9699 if (index == -EINVAL)
9700 return MAX_PORT_ADD_ERROR;
9703 return MAX_PORT_ADD_UNSUCCESS;
9705 if (index == -ENOENT) {
9707 #ifdef CGNAPT_DBG_PRNT
9708 if (CGNAPT_DEBUG > 2)
9709 printf("max_port_per_client_add_entry fn: "
9710 "Entry does not exist\n");
9714 rte_hash_add_key(max_port_per_client_hash,
9715 (const void *)&key);
9716 if (index == -ENOSPC)
9717 return MAX_PORT_ADD_UNSUCCESS;
9719 #ifdef CGNAPT_DBG_PRNT
9720 if (CGNAPT_DEBUG > 2)
9721 printf("max_port_per_client_add_entry fn:"
9722 "Add entry index(%d)\n", index);
9725 max_port_per_client_array[index].prv_ip = prv_ip_param;
9726 max_port_per_client_array[index].prv_phy_port =
9730 max_port_per_client_array[index].max_port_cnt++;
9731 return MAX_PORT_ADD_SUCCESS;
9735 * Function to delete a max ports per client entry
9737 * @param prv_ip_param
9738 * A uint32_t ip address of client
9739 * @param prv_phy_port_param
9740 * A uint32_t physical port id of the client
9742 * A pointer to struct pipeline_cgnapt
9745 * 0 no success, 1 if success, -1 if error
9747 int max_port_per_client_del_entry(
9748 uint32_t prv_ip_param,
9749 uint32_t prv_phy_port_param,
9750 __rte_unused struct pipeline_cgnapt *p_nat)
9752 int index = MAX_PORT_DEL_ERROR;
9754 struct max_port_per_client_key key = {
9755 .prv_ip = prv_ip_param,
9756 .prv_phy_port = prv_phy_port_param,
9759 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9761 if (index == -EINVAL)
9762 return MAX_PORT_DEL_ERROR;
9764 if (index == -ENOENT)
9765 return MAX_PORT_DEL_UNSUCCESS;
9767 index = rte_hash_del_key(max_port_per_client_hash, (const void *)&key);
9768 max_port_per_client_array[index].prv_ip = 0;
9769 max_port_per_client_array[index].prv_phy_port = 0;
9770 max_port_per_client_array[index].max_port_cnt = 0;
9772 return MAX_PORT_DEL_SUCCESS;
9776 * Function to execute debug commands
9779 * A pointer to struct pipeline
9781 * void pointer to incoming arguments
9783 void *pipeline_cgnapt_msg_req_entry_dbg_handler(struct pipeline *p, void *msg)
9785 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9787 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9791 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_STATS_SHOW) {
9792 printf("\nCG-NAPT Packet Stats:\n");
9793 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
9794 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
9795 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
9796 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
9797 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
9798 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
9799 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
9801 #ifdef CGNAPT_DEBUGGING
9802 printf("\n Drop detail 1:%" PRIu64 ",",
9803 p_nat->naptDroppedPktCount1);
9804 printf("\n Drop detail 2:%" PRIu64 ",",
9805 p_nat->naptDroppedPktCount2);
9806 printf("\n Drop detail 3:%" PRIu64 ",",
9807 p_nat->naptDroppedPktCount3);
9808 printf("\n Drop detail 4:%" PRIu64 ",",
9809 p_nat->naptDroppedPktCount4);
9810 printf("\n Drop detail 5:%" PRIu64 ",",
9811 p_nat->naptDroppedPktCount5);
9812 printf("\n Drop detail 6:%" PRIu64 "",
9813 p_nat->naptDroppedPktCount6);
9815 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9816 p_nat->missedpktcount1,
9817 p_nat->missedpktcount2);
9818 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9819 p_nat->missedpktcount3,
9820 p_nat->missedpktcount4);
9821 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9822 p_nat->missedpktcount5,
9823 p_nat->missedpktcount6);
9824 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9825 p_nat->missedpktcount7,
9826 p_nat->missedpktcount8);
9827 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9828 p_nat->missedpktcount9,
9829 p_nat->missedpktcount10);
9836 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_STATS_CLEAR) {
9837 printf("\nCG-NAPT Packet Stats:\n");
9838 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
9839 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
9840 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
9841 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
9842 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
9843 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
9844 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
9846 p_nat->naptedPktCount = 0;
9847 p_nat->naptDroppedPktCount = 0;
9848 p_nat->inaptedPktCount = 0;
9849 p_nat->enaptedPktCount = 0;
9850 p_nat->receivedPktCount = 0;
9851 p_nat->missedPktCount = 0;
9852 p_nat->arpicmpPktCount = 0;
9853 printf("CG-NAPT Packet Stats cleared\n");
9857 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DBG_LEVEL) {
9858 CGNAPT_DEBUG = Msg[CGNAPT_DBG_CMD_OFST + 1];
9859 printf("CG-NAPT debug level set to %d\n", CGNAPT_DEBUG);
9863 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DBG_SHOW) {
9865 printf("\nNAPT entries - added %" PRIu64 ",",
9866 p_nat->n_cgnapt_entry_added);
9867 printf("deleted %" PRIu64 ",", p_nat->n_cgnapt_entry_deleted);
9868 printf("current %" PRIu64 "", p_nat->n_cgnapt_entry_added -
9869 p_nat->n_cgnapt_entry_deleted);
9871 printf("\nCG-NAPT Packet Stats:\n");
9872 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
9873 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
9874 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
9875 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
9876 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
9877 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
9878 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
9882 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
9883 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_INSTRUMENTATION) {
9884 if (Msg[CGNAPT_DBG_CMD_OFST1] ==
9885 CGNAPT_CMD_INSTRUMENTATION_SUB0) {
9888 uint32_t diff_sum = 0;
9890 printf("CG-NAPT Instrumentation ...\n");
9891 printf("Instrumentation data collected for fn# %d\n",
9892 cgnapt_num_func_to_inst);
9893 printf("Current collection index %d\n",
9896 if (Msg[CGNAPT_DBG_CMD_OFST + 2] == 2) {
9897 printf("Timer Start:\n");
9899 for (index = 0; index < INST_ARRAY_SIZE; index++) {
9900 if ((index % 5) == 0)
9902 printf(" 0x%jx", inst_start_time[index]);
9904 printf("\n\nTimer End:\n");
9906 for (index = 0; index < INST_ARRAY_SIZE; index++) {
9907 if ((index % 5) == 0)
9909 printf(" 0x%jx", inst_end_time[index]);
9913 for (index = 0; index < INST_ARRAY_SIZE; index++) {
9914 inst_diff_time[index] = (uint32_t) (inst_end_time[index] -
9915 inst_start_time[index]);
9918 if (Msg[CGNAPT_DBG_CMD_OFST + 2] ==
9919 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
9920 printf("\n\nTimer Diff:\n");
9922 for (index = 0; index < INST_ARRAY_SIZE; index++) {
9923 if (Msg[CGNAPT_DBG_CMD_OFST + 2] ==
9924 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
9925 if ((index % 5) == 0)
9927 printf(" 0x%08x", inst_diff_time[index]);
9930 diff_sum += inst_diff_time[index];
9933 printf("\ndiff_sum %u, INST_ARRAY_SIZE %d, Ave Time %u\n",
9934 diff_sum, INST_ARRAY_SIZE, (diff_sum / INST_ARRAY_SIZE));
9935 } else if (Msg[CGNAPT_DBG_CMD_OFST + 1] ==
9936 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
9937 /* p plid entry dbg 7 1 0
9938 * p plid entry dbg 7 1 1 <--- pkt_work_cgnapt
9939 * p plid entry dbg 7 1 2 <--- pkt4_work_cgnapt
9940 * p plid entry dbg 7 1 3 <--- pkt_work_cgnapt_key
9941 * p plid entry dbg 7 1 4 <--- pkt4_work_cgnapt_key
9942 * p plid entry dbg 7 1 5 <--- in port ah to out port ah
9943 * - pkt life in the system
9944 * p plid entry dbg 7 1 6 <--- how long this instrumentation
9947 cgnapt_inst_index = 0;
9948 cgnapt_num_func_to_inst = Msg[CGNAPT_DBG_CMD_OFST + 2];
9949 printf("Instrumentation data collection started for fn# %d\n",
9950 cgnapt_num_func_to_inst);
9951 } else if (Msg[CGNAPT_DBG_CMD_OFST + 1] ==
9952 CGNAPT_CMD_INSTRUMENTATION_SUB2) {
9953 /* p plid entry dbg 7 2 0
9954 * Test all major functions by calling them multiple times
9955 * pkt_work_cgnapt, pkt4_work_cgnapt, pkt_work_cgnapt_key,
9956 * pkt4_work_cgnapt_key
9958 if (cgnapt_test_pktmbuf_pool == NULL) {
9959 cgnapt_test_pktmbuf_pool = rte_pktmbuf_pool_create(
9960 "cgnapt_test_pktmbuf_pool", 63, 32, 0,
9961 RTE_MBUF_DEFAULT_BUF_SIZE,
9965 if (cgnapt_test_pktmbuf_pool == NULL)
9966 printf("CGNAPT test mbuf pool create failed.\n");
9968 struct rte_mbuf *cgnapt_test_pkt0 =
9969 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
9970 if (cgnapt_test_pkt0 == NULL)
9971 printf("CGNAPT test pkt 0 alloc failed.");
9972 struct rte_mbuf *cgnapt_test_pkt1 =
9973 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
9974 if (cgnapt_test_pkt1 == NULL)
9975 printf("CGNAPT test pkt 1 alloc failed.");
9976 struct rte_mbuf *cgnapt_test_pkt2 =
9977 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
9978 if (cgnapt_test_pkt2 == NULL)
9979 printf("CGNAPT test pkt 2 alloc failed.");
9980 struct rte_mbuf *cgnapt_test_pkt3 =
9981 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
9982 if (cgnapt_test_pkt3 == NULL)
9983 printf("CGNAPT test pkt 3 alloc failed.");
9985 struct rte_mbuf *cgnapt_test_pkts[4];
9987 cgnapt_test_pkts[0] = cgnapt_test_pkt0;
9988 cgnapt_test_pkts[1] = cgnapt_test_pkt1;
9989 cgnapt_test_pkts[2] = cgnapt_test_pkt2;
9990 cgnapt_test_pkts[3] = cgnapt_test_pkt3;
9992 uint32_t src_addr_offset =
9993 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_SRC_ADR_OFST;
9994 /* header room + eth hdr size +
9995 * src_aadr offset in ip header
9997 uint32_t dst_addr_offset =
9998 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
9999 /* header room + eth hdr size +
10000 * dst_aadr offset in ip header
10002 uint32_t prot_offset =
10003 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_PROTOCOL_OFST;
10004 /* header room + eth hdr size +
10005 * srprotocol char offset in ip header
10007 int pktCnt = 0, entCnt = 0, exCnt = 0;
10009 for (pktCnt = 0; pktCnt < 4; pktCnt++) {
10010 uint32_t *src_addr =
10011 RTE_MBUF_METADATA_UINT32_PTR
10012 (cgnapt_test_pkts[pktCnt], src_addr_offset);
10013 uint32_t *dst_addr =
10014 RTE_MBUF_METADATA_UINT32_PTR
10015 (cgnapt_test_pkts[pktCnt], dst_addr_offset);
10016 uint8_t *protocol =
10017 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10020 uint8_t *phy_port =
10021 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10023 uint8_t *eth_dest =
10024 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10028 RTE_MBUF_METADATA_UINT8_PTR(
10029 cgnapt_test_pkts[pktCnt],
10032 uint16_t *src_port =
10033 RTE_MBUF_METADATA_UINT16_PTR
10034 (cgnapt_test_pkts[pktCnt],
10035 MBUF_HDR_ROOM + ETH_HDR_SIZE +
10037 uint16_t *dst_port =
10038 RTE_MBUF_METADATA_UINT16_PTR
10039 (cgnapt_test_pkts[pktCnt],
10040 MBUF_HDR_ROOM + ETH_HDR_SIZE +
10042 *src_addr = 0xc0a80001;
10043 *dst_addr = 0x90418634;
10054 eth_dest[0] = 0x90;
10055 eth_dest[1] = 0xE2;
10056 eth_dest[2] = 0xba;
10057 eth_dest[3] = 0x54;
10058 eth_dest[4] = 0x67;
10059 eth_dest[5] = 0xc8;
10061 struct rte_pipeline_table_entry *table_entries[4];
10062 struct cgnapt_table_entry ctable_entries[4];
10063 table_entries[0] = (struct rte_pipeline_table_entry *)
10064 &ctable_entries[0];
10065 table_entries[1] = (struct rte_pipeline_table_entry *)
10066 &ctable_entries[1];
10067 table_entries[2] = (struct rte_pipeline_table_entry *)
10068 &ctable_entries[2];
10069 table_entries[3] = (struct rte_pipeline_table_entry *)
10070 &ctable_entries[3];
10071 for (entCnt = 0; entCnt < 4; entCnt++) {
10072 ctable_entries[entCnt].head.action =
10073 RTE_PIPELINE_ACTION_PORT;
10074 ctable_entries[entCnt].head.port_id = 0;
10076 ctable_entries[entCnt].data.prv_ip = 0x01020304;
10077 ctable_entries[entCnt].data.prv_port = 1234;
10078 ctable_entries[entCnt].data.pub_ip = 0x0a0b0c0d;
10079 ctable_entries[entCnt].data.pub_port = 4000;
10080 ctable_entries[entCnt].data.prv_phy_port = 0;
10081 ctable_entries[entCnt].data.pub_phy_port = 1;
10082 ctable_entries[entCnt].data.ttl = 500;
10085 uint64_t time1 = rte_get_tsc_cycles();
10087 for (exCnt = 0; exCnt < 1000; exCnt++) {
10088 pkt_work_cgnapt_key(cgnapt_test_pkts[0],
10089 instrumentation_port_in_arg);
10091 uint64_t time2 = rte_get_tsc_cycles();
10093 printf("times for %d times execution of "
10094 "pkt_work_cgnapt_key 0x%jx",
10096 printf(", 0x%jx, diff %" PRIu64 "\n", time2,
10099 time1 = rte_get_tsc_cycles();
10100 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10101 pkt_work_cgnapt_key(cgnapt_test_pkts[0],
10102 instrumentation_port_in_arg);
10104 time2 = rte_get_tsc_cycles();
10105 printf("times for %d times execution of "
10106 "pkt_work_cgnapt_key 0x%jx", exCnt, time1);
10107 printf("0x%jx, diff %" PRIu64 "\n", time2,
10110 time1 = rte_get_tsc_cycles();
10111 for (exCnt = 0; exCnt < 1000; exCnt++) {
10112 pkt4_work_cgnapt_key(cgnapt_test_pkts,
10113 instrumentation_port_in_arg);
10115 time2 = rte_get_tsc_cycles();
10116 printf("times for %d times execution of "
10117 "pkt4_work_cgnapt_key 0x%jx",
10119 printf(" 0x%jx, diff %" PRIu64 "\n", time2,
10122 time1 = rte_get_tsc_cycles();
10123 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10124 pkt4_work_cgnapt_key(cgnapt_test_pkts,
10125 instrumentation_port_in_arg);
10127 time2 = rte_get_tsc_cycles();
10128 printf("times for %d times execution of "
10129 "pkt4_work_cgnapt_key 0x%jx",
10131 printf("0x%jx, diff %" PRIu64 "\n", time2,
10134 uint64_t mask = 0xff;
10136 time1 = rte_get_tsc_cycles();
10137 for (exCnt = 0; exCnt < 1000; exCnt++) {
10138 pkt_work_cgnapt(cgnapt_test_pkts[0],
10139 table_entries[0], 3, &mask,
10142 time2 = rte_get_tsc_cycles();
10143 printf("times for %d times execution of "
10144 "pkt_work_cgnapt 0x%jx",
10146 printf("0x%jx, diff %" PRIu64 "\n", time2,
10149 time1 = rte_get_tsc_cycles();
10150 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10151 pkt_work_cgnapt(cgnapt_test_pkts[0],
10152 table_entries[0], 3, &mask,
10155 time2 = rte_get_tsc_cycles();
10156 printf("times for %d times execution of "
10157 "pkt_work_cgnapt 0x%jx",
10159 printf("0x%jx, diff %" PRIu64 "\n", time2,
10162 time1 = rte_get_tsc_cycles();
10163 for (exCnt = 0; exCnt < 1000; exCnt++) {
10164 pkt4_work_cgnapt(cgnapt_test_pkts,
10165 table_entries, 0, &mask, NULL);
10167 time2 = rte_get_tsc_cycles();
10168 printf("times for %d times execution of "
10169 "pkt4_work_cgnapt 0x%jx",
10171 printf("0x%jx, diff % " PRIu64 "\n", time2,
10174 int idummy = ctable_entries[0].data.prv_port;
10184 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_LS_ENTRY) {
10185 printf("CG-NAPT be entries are:\n");
10186 printf("Pipeline pointer %p\n", p);
10190 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DYN) {
10191 printf("Total Number of dynamic napt entries: %" PRIu64 "\n",
10192 p_nat->dynCgnaptCount);
10194 #ifdef CGNAPT_DEBUGGING
10195 printf("MAX PORT PER CLIENT:");
10196 printf("%" PRIu64 ",%" PRIu64 ",%" PRIu64 "\n",
10197 p_nat->max_port_dec_err1, p_nat->max_port_dec_err2,
10198 p_nat->max_port_dec_err3);
10199 printf("MPPC success : %" PRIu64 "\n",
10200 p_nat->max_port_dec_success);
10202 printf("Release port:err:%" PRIu64 ",ret::%" PRIu64 ",get::%"
10203 PRIu64 ",suc::%" PRIu64 "\n", p_nat->pfb_err,
10204 p_nat->pfb_ret, p_nat->pfb_get, p_nat->pfb_suc);
10205 printf("Get port::err:%" PRIu64 ",ret::%" PRIu64 ",get::%"
10206 PRIu64 ",suc::%" PRIu64 "\n", p_nat->gfp_err,
10207 p_nat->gfp_ret, p_nat->gfp_get, p_nat->gfp_suc);
10208 printf("Ring Info:\n");
10209 rte_ring_dump(stdout, p_nat->port_alloc_ring);
10213 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_IPV6) {
10214 dual_stack_enable = Msg[CGNAPT_DBG_CMD_OFST + 1];
10215 printf("Dual Stack option set: %x\n", dual_stack_enable);
10219 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_MAPS_INFO) {
10220 pipelines_port_info();
10221 pipelines_map_info();
10225 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_ITER_COM_TBL) {
10226 uint32_t count = 0;
10234 rte_hash_iterate(napt_common_table, &key, &data,
10237 if ((index != -EINVAL) && (index != -ENOENT)) {
10238 printf("\n%04d ", count);
10239 rte_hexdump(stdout, "KEY", key,
10241 pipeline_cgnapt_entry_key));
10243 //print_key((struct pipeline_cgnapt_entry_key *)
10246 rte_hash_lookup(napt_common_table,
10248 print_cgnapt_entry(&napt_hash_tbl_entries
10253 } while (index != -ENOENT);
10257 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_IF_STATS) {
10259 struct app_params *app =
10260 (struct app_params *)p_nat->app_params_addr;
10263 cmd[0] = Msg[CGNAPT_DBG_CMD_OFST + 1];
10264 cmd[1] = Msg[CGNAPT_DBG_CMD_OFST + 2];
10266 case CGNAPT_IF_STATS_HWQ:
10267 printf("n_pktq_hwq_int :%d\n", app->n_pktq_hwq_in);
10268 printf("n_pktq_hwq_out :%d\n", app->n_pktq_hwq_out);
10272 for (i = 0; i < app->n_pktq_hwq_in; i++) {
10273 struct rte_eth_stats stats;
10275 rte_eth_stats_get(p_nat->links_map[i], &stats);
10277 if (is_phy_port_privte(i))
10278 printf("Private Port Stats %d\n", i);
10280 printf("Public Port Stats %d\n", i);
10282 printf("\n\tipackets : %" PRIu64 "",
10284 printf("\n\topackets : %" PRIu64 "",
10286 printf("\n\tierrors : %" PRIu64 "",
10288 printf("\n\toerrors : %" PRIu64 "",
10290 printf("\n\trx_nombuf: %" PRIu64 "",
10293 if (is_phy_port_privte(i))
10294 printf("Private Q:");
10296 printf("Public Q:");
10297 for (j = 0; j < RTE_ETHDEV_QUEUE_STAT_CNTRS;
10299 printf(" %" PRIu64 ", %" PRIu64 "|",
10300 stats.q_ipackets[j],
10301 stats.q_opackets[j]);
10309 case CGNAPT_IF_STATS_SWQ:
10311 printf("n_pktq_swq :%d\n", app->n_pktq_swq);
10313 if (cmd[1] < app->n_pktq_swq) {
10314 rte_ring_dump(stdout, app->swq[cmd[1]]);
10317 printf("SWQ number is invalid\n");
10320 case CGNAPT_IF_STATS_OTH:
10322 printf("config_file:%s\n", app->config_file);
10323 printf("script_file:%s\n", app->script_file);
10324 printf("parser_file:%s\n", app->parser_file);
10325 printf("output_file:%s\n", app->output_file);
10326 printf("n_msgq :%d\n", app->n_msgq);
10327 printf("n_pktq_tm :%d\n", app->n_pktq_tm);
10328 printf("n_pktq_source :%d\n", app->n_pktq_source);
10329 printf("n_pktq_sink :%d\n", app->n_pktq_sink);
10330 printf("n_pipelines :%d\n", app->n_pipelines);
10334 printf("Command does not match\n\n");
10342 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_MAX_CLI_PER_PUB_IP) {
10343 if (nat_only_config_flag) {
10344 printf("Command not supported for NAT only config.\n");
10349 printf("\tPublic IP: Num Clients\n");
10350 for (ii = 0; ii < CGNAPT_MAX_PUB_IP; ii++)
10351 printf("\t%x : %7d\n", all_public_ip[ii].ip,
10352 rte_atomic16_read(&all_public_ip[ii].count));
10356 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_PUB_IP_LIST) {
10359 for (i = 0; i < p_nat->pub_ip_count; i++)
10360 printf("%x : (%d,%d)\n", p_nat->pub_ip_port_set[i].ip,
10361 p_nat->pub_ip_port_set[i].start_port,
10362 p_nat->pub_ip_port_set[i].end_port);
10366 #ifdef CGNAPT_TIMING_INST
10367 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_TIMING_INST) {
10368 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 0) {
10369 p_nat->time_measurements_on = 1;
10370 p_nat->time_measurements = 0;
10371 printf("CGNAPT timing instrumentation turned on.\n");
10372 printf("Max samples %d\n", p_nat->max_time_mesurements);
10374 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 1) {
10375 p_nat->time_measurements_on = 0;
10376 printf("CGNAPT timing instrumentation turned off.\n");
10377 printf("Cur Samples %d\n", p_nat->time_measurements);
10379 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 2) {
10380 uint64_t sum = p_nat->external_time_sum +
10381 p_nat->internal_time_sum;
10382 uint64_t isump = (p_nat->internal_time_sum * 100) / sum;
10383 uint64_t esump = (p_nat->external_time_sum * 100) / sum;
10384 printf("CGNAPT timing instrumentation status ...\n");
10385 printf("Max Count %d, Cur Count %d, Status %d (1=ON)\n",
10386 p_nat->max_time_mesurements,
10387 p_nat->time_measurements,
10388 p_nat->time_measurements_on);
10389 printf("Internal Time Sum %" PRIu64 " , Ave %" PRIu64
10390 ", percent %" PRIu64 "\n",
10391 p_nat->internal_time_sum,
10392 (p_nat->internal_time_sum /
10393 p_nat->time_measurements), isump);
10394 printf("External Time Sum %" PRIu64 " , Ave %" PRIu64
10395 ", percent %" PRIu64 "\n",
10396 p_nat->external_time_sum,
10397 (p_nat->external_time_sum /
10398 p_nat->time_measurements), esump);
10405 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_PRINT_NSP) {
10406 struct cgnapt_nsp_node *ll = nsp_ll;
10408 while (ll != NULL) {
10409 fprintf(stderr, "NSP Prefix/Depth=>%x%x:%x%x:%x%x: "
10410 "%x%x:%x%x:%x%x:%x%x:%x%x/%d",
10411 ll->nsp.prefix[0], ll->nsp.prefix[1],
10412 ll->nsp.prefix[2], ll->nsp.prefix[3],
10413 ll->nsp.prefix[4], ll->nsp.prefix[5],
10414 ll->nsp.prefix[6], ll->nsp.prefix[7],
10415 ll->nsp.prefix[8], ll->nsp.prefix[9],
10416 ll->nsp.prefix[10], ll->nsp.prefix[11],
10417 ll->nsp.prefix[12], ll->nsp.prefix[13],
10418 ll->nsp.prefix[14], ll->nsp.prefix[15],
10427 printf("CG-NAPT debug handler called with wrong args %x %x\n", Msg[0],
10431 for (i = 0; i < 20; i++)
10432 printf("%02x ", Msg[i]);
10438 * Function to print num of clients per IP address
10441 void print_num_ip_clients(void)
10443 if (nat_only_config_flag) {
10444 printf("Command not supported for NAT only config.\n");
10449 printf("\tPublic IP: Num Clients\n");
10450 for (ii = 0; ii < CGNAPT_MAX_PUB_IP; ii++)
10451 printf("\t%08x : %7d\n", all_public_ip[ii].ip,
10452 rte_atomic16_read(&all_public_ip[ii].count));
10456 * Function to print CGNAPT version info
10459 * An unused pointer to struct pipeline
10461 * void pointer to incoming arguments
10463 void *pipeline_cgnapt_msg_req_ver_handler(__rte_unused struct pipeline *p,
10466 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
10467 uint8_t *Msg = msg;
10471 printf("CG-NAPT debug handler called with args %x %x, offset %d\n",
10472 Msg[CGNAPT_VER_CMD_OFST], Msg[CGNAPT_VER_CMD_OFST + 1],
10473 CGNAPT_VER_CMD_OFST);
10475 if (Msg[CGNAPT_VER_CMD_OFST] == CGNAPT_VER_CMD_VER) {
10476 printf("CGNAPT Version %s\n", CGNAPT_VERSION);
10479 printf("CG-NAPT Version handler called with wrong args %x %x\n",
10483 for (i = 0; i < 20; i++)
10484 printf("%02x ", Msg[i]);
10490 * Function to show CGNAPT stats
10493 void all_cgnapt_stats(char *buf)
10496 struct pipeline_cgnapt *p_nat;
10497 uint64_t receivedPktCount = 0;
10498 uint64_t missedPktCount = 0;
10499 uint64_t naptDroppedPktCount = 0;
10500 uint64_t naptedPktCount = 0;
10501 uint64_t inaptedPktCount = 0;
10502 uint64_t enaptedPktCount = 0;
10503 uint64_t arpicmpPktCount = 0;
10505 len += sprintf(buf + len, "\nCG-NAPT Packet Stats:\n");
10506 for (i = 0; i < n_cgnapt_pipeline; i++) {
10507 p_nat = all_pipeline_cgnapt[i];
10509 receivedPktCount += p_nat->receivedPktCount;
10510 missedPktCount += p_nat->missedPktCount;
10511 naptDroppedPktCount += p_nat->naptDroppedPktCount;
10512 naptedPktCount += p_nat->naptedPktCount;
10513 inaptedPktCount += p_nat->inaptedPktCount;
10514 enaptedPktCount += p_nat->enaptedPktCount;
10515 arpicmpPktCount += p_nat->arpicmpPktCount;
10517 len += sprintf(buf + len, "pipeline %d stats:\n", p_nat->pipeline_num);
10518 len += sprintf(buf + len, "Received %" PRIu64 ",", p_nat->receivedPktCount);
10519 len += sprintf(buf + len, "Missed %" PRIu64 ",", p_nat->missedPktCount);
10520 len += sprintf(buf + len, "Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10521 len += sprintf(buf + len, "Translated %" PRIu64 ",", p_nat->naptedPktCount);
10522 len += sprintf(buf + len, "ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10523 len += sprintf(buf + len, "egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10524 len += sprintf(buf + len, "arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10526 printf("\nCG-NAPT Packet Stats:\n");
10527 printf("pipeline %d stats:\n", p_nat->pipeline_num);
10528 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10529 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10530 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10531 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10532 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10533 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10534 printf("arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10538 #ifdef CGNAPT_DEBUGGING
10539 len += sprintf(buf + len, "\n Drop detail 1:%" PRIu64 ",",
10540 p_nat->naptDroppedPktCount1);
10541 len += sprintf(buf + len, "\n Drop detail 2:%" PRIu64 ",",
10542 p_nat->naptDroppedPktCount2);
10543 len += sprintf(buf + len, "\n Drop detail 3:%" PRIu64 ",",
10544 p_nat->naptDroppedPktCount3);
10545 len += sprintf(buf + len, "\n Drop detail 4:%" PRIu64 ",",
10546 p_nat->naptDroppedPktCount4);
10547 len += sprintf(buf + len, "\n Drop detail 5:%" PRIu64 ",",
10548 p_nat->naptDroppedPktCount5);
10549 len += sprintf(buf + len, "\n Drop detail 6:%" PRIu64 "",
10550 p_nat->naptDroppedPktCount6);
10552 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10553 p_nat->missedpktcount1,
10554 p_nat->missedpktcount2);
10555 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10556 p_nat->missedpktcount3,
10557 p_nat->missedpktcount4);
10558 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10559 p_nat->missedpktcount5,
10560 p_nat->missedpktcount6);
10561 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10562 p_nat->missedpktcount7,
10563 p_nat->missedpktcount8);
10564 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10565 p_nat->missedpktcount9,
10566 p_nat->missedpktcount10);
10572 len += sprintf(buf + len, "\nTotal pipeline stats:\n");
10573 len += sprintf(buf + len, "Received %" PRIu64 ",", receivedPktCount);
10574 len += sprintf(buf + len, "Missed %" PRIu64 ",", missedPktCount);
10575 len += sprintf(buf + len, "Dropped %" PRIu64 ",", naptDroppedPktCount);
10576 len += sprintf(buf + len, "Translated %" PRIu64 ",", naptedPktCount);
10577 len += sprintf(buf + len, "ingress %" PRIu64 ",", inaptedPktCount);
10578 len += sprintf(buf + len, "egress %" PRIu64 "\n", enaptedPktCount);
10579 len += sprintf(buf + len, "arpicmp pkts %" PRIu64 "\n", arpicmpPktCount);
10581 printf("\nTotal pipeline stats:\n");
10582 printf("Received %" PRIu64 ",", receivedPktCount);
10583 printf("Missed %" PRIu64 ",", missedPktCount);
10584 printf("Dropped %" PRIu64 ",", naptDroppedPktCount);
10585 printf("Translated %" PRIu64 ",", naptedPktCount);
10586 printf("ingress %" PRIu64 ",", inaptedPktCount);
10587 printf("egress %" PRIu64 "\n", enaptedPktCount);
10588 printf("arpicmp pkts %" PRIu64 "\n", arpicmpPktCount);
10590 if (!rest_api_supported())
10591 printf("%s\n", buf);
10594 void all_cgnapt_clear_stats(char *buf)
10597 struct pipeline_cgnapt *p_nat;
10598 len += sprintf(buf + len, "\nCG-NAPT Packet Stats:\n");
10599 for (i = 0; i < n_cgnapt_pipeline; i++) {
10600 p_nat = all_pipeline_cgnapt[i];
10602 len += sprintf(buf + len, "pipeline %d stats:\n", p_nat->pipeline_num);
10603 len += sprintf(buf + len, "Received %" PRIu64 ",", p_nat->receivedPktCount);
10604 len += sprintf(buf + len, "Missed %" PRIu64 ",", p_nat->missedPktCount);
10605 len += sprintf(buf + len, "Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10606 len += sprintf(buf + len, "Translated %" PRIu64 ",", p_nat->naptedPktCount);
10607 len += sprintf(buf + len, "ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10608 len += sprintf(buf + len, "egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10609 len += sprintf(buf + len, "arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10611 p_nat->receivedPktCount = 0;
10612 p_nat->missedPktCount = 0;
10613 p_nat->naptDroppedPktCount = 0;
10614 p_nat->naptedPktCount = 0;
10615 p_nat->inaptedPktCount = 0;
10616 p_nat->enaptedPktCount = 0;
10617 p_nat->arpicmpPktCount = 0;
10619 #ifdef CGNAPT_DEBUGGING
10620 len += sprintf(buf + len, "\n Drop detail 1:%" PRIu64 ",",
10621 p_nat->naptDroppedPktCount1);
10622 len += sprintf(buf + len, "\n Drop detail 2:%" PRIu64 ",",
10623 p_nat->naptDroppedPktCount2);
10624 len += sprintf(buf + len, "\n Drop detail 3:%" PRIu64 ",",
10625 p_nat->naptDroppedPktCount3);
10626 len += sprintf(buf + len, "\n Drop detail 4:%" PRIu64 ",",
10627 p_nat->naptDroppedPktCount4);
10628 len += sprintf(buf + len, "\n Drop detail 5:%" PRIu64 ",",
10629 p_nat->naptDroppedPktCount5);
10630 len += sprintf(buf + len, "\n Drop detail 6:%" PRIu64 "",
10631 p_nat->naptDroppedPktCount6);
10633 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10634 p_nat->missedpktcount1,
10635 p_nat->missedpktcount2);
10636 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10637 p_nat->missedpktcount3,
10638 p_nat->missedpktcount4);
10639 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10640 p_nat->missedpktcount5,
10641 p_nat->missedpktcount6);
10642 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10643 p_nat->missedpktcount7,
10644 p_nat->missedpktcount8);
10645 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10646 p_nat->missedpktcount9,
10647 p_nat->missedpktcount10);
10653 if (!rest_api_supported())
10654 printf("%s\n", buf);
10658 * Function to print common CGNAPT table entries
10661 void print_static_cgnapt_entries(void)
10663 uint32_t count = 0;
10668 struct cgnapt_table_entry *entry;
10670 index = rte_hash_iterate(napt_common_table,
10671 &key, &data, &next);
10673 if ((index != -EINVAL) && (index != -ENOENT)) {
10674 printf("\n%04d ", count);
10675 rte_hexdump(stdout, "KEY", key,
10676 sizeof(struct pipeline_cgnapt_entry_key));
10677 int32_t position = rte_hash_lookup(
10678 napt_common_table, key);
10679 entry = &napt_hash_tbl_entries[position];
10681 if (entry->data.timeout == STATIC_CGNAPT_TIMEOUT)
10682 rte_hexdump(stdout, "Entry",
10683 (const void *)entry,
10684 sizeof(struct cgnapt_table_entry));
10688 } while (index != -ENOENT);
10692 * Function to show CGNAPT stats
10696 struct pipeline_be_ops pipeline_cgnapt_be_ops = {
10697 .f_init = pipeline_cgnapt_init,
10698 .f_free = pipeline_cgnapt_free,
10700 .f_timer = pipeline_cgnapt_timer,
10701 .f_track = pipeline_cgnapt_track,