2 // Copyright (c) 2017 Intel Corporation
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
19 * Pipeline CG-NAPT BE Implementation.
21 * Implementation of Pipeline CG-NAPT Back End (BE).
22 * Provides NAPT service on dataplane packets.
23 * Runs on a core as defined in the config file.
33 #include <rte_common.h>
34 #include <rte_malloc.h>
40 #include <rte_byteorder.h>
41 #include <rte_table_lpm.h>
42 #include <rte_table_hash.h>
43 #include <rte_table_stub.h>
45 #include <rte_mempool.h>
47 #include <rte_jhash.h>
48 #include <rte_cycles.h>
49 #include <rte_ethdev.h>
50 #include <rte_pipeline.h>
51 #include <rte_timer.h>
52 #include <rte_config.h>
53 #include <rte_prefetch.h>
54 #include <rte_hexdump.h>
56 #include "pipeline_cgnapt_be.h"
57 #include "pipeline_cgnapt_common.h"
58 #include "pipeline_actions_common.h"
59 #include "hash_func.h"
60 #include "pipeline_arpicmp_be.h"
61 #include "vnf_common.h"
63 #include "pipeline_common_be.h"
64 #include "vnf_common.h"
65 #include "lib_sip_alg.h"
66 #include "lib_icmpv6.h"
69 #include "pipeline_common_fe.h"
71 #include "rte_ct_tcp.h"
72 #include "rte_cnxn_tracking.h"
75 #include "lib_ftp_alg.h"
78 #include "cgnapt_pcp_be.h"
81 /* To maintain all cgnapt pipeline pointers used for all stats */
82 struct pipeline_cgnapt *all_pipeline_cgnapt[128];
83 uint8_t n_cgnapt_pipeline;
84 struct pipeline_cgnapt *global_pnat;
86 uint64_t arp_pkts_mask;
88 /* To know egress or ingress port */
89 static uint8_t cgnapt_in_port_egress_prv[PIPELINE_MAX_PORT_IN];
90 static uint8_t cgnapt_prv_que_port_index[PIPELINE_MAX_PORT_IN];
92 /* Max port per client declarations */
94 struct rte_hash_parameters max_port_per_client_hash_params = {
95 .name = "MAX_PORT_PER_CLIENT",
96 .entries = MAX_DYN_ENTRY,
97 .key_len = sizeof(struct max_port_per_client_key),
98 .hash_func = rte_jhash,
99 .hash_func_init_val = 0,
102 struct rte_ct_cnxn_tracker *cgnat_cnxn_tracker;
105 /***** Common Port Allocation declarations *****/
107 struct rte_ring *port_alloc_ring[MAX_CGNAPT_SETS] = { NULL, NULL, NULL, NULL,
108 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
109 NULL, NULL, NULL, NULL};
110 const char *napt_port_alloc_ring_name[MAX_CGNAPT_SETS] = {
111 "NAPT_PORT_ALLOC_0 ",
112 "NAPT_PORT_ALLOC_1 ",
113 "NAPT_PORT_ALLOC_2 ",
114 "NAPT_PORT_ALLOC_3 ",
115 "NAPT_PORT_ALLOC_4 ",
116 "NAPT_PORT_ALLOC_5 ",
117 "NAPT_PORT_ALLOC_6 ",
118 "NAPT_PORT_ALLOC_7 ",
119 "NAPT_PORT_ALLOC_8 ",
120 "NAPT_PORT_ALLOC_9 ",
121 "NAPT_PORT_ALLOC_10 ",
122 "NAPT_PORT_ALLOC_11 ",
123 "NAPT_PORT_ALLOC_12 ",
124 "NAPT_PORT_ALLOC_13 ",
125 "NAPT_PORT_ALLOC_14 ",
126 "NAPT_PORT_ALLOC_16 "
129 int vnf_set_count = -1;
131 struct app_params *myApp;
133 /***** Common Port Allocation declarations *****/
134 int napt_port_alloc_elem_count;
136 /***** Common Table declarations *****/
137 struct rte_hash_parameters napt_common_table_hash_params = {
138 .name = "NAPT_COM_TBL",
139 .entries = MAX_NAPT_ENTRIES,
140 .key_len = sizeof(struct pipeline_cgnapt_entry_key),
141 .hash_func = rte_jhash,
142 .hash_func_init_val = 0,
146 /***** ARP local cache *****/
148 uint8_t link_hw_laddr_valid[MAX_NUM_LOCAL_MAC_ADDRESS] = {
149 0, 0, 0, 0, 0, 0, 0, 0,
150 0, 0, 0, 0, 0, 0, 0, 0
153 struct ether_addr link_hw_laddr[MAX_NUM_LOCAL_MAC_ADDRESS] = {
154 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
155 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
156 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
157 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
158 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
159 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
160 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
161 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
162 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
163 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
164 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
165 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
166 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
167 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
168 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
169 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }
172 /****** NAT64 declarations *****/
174 uint8_t well_known_prefix[16] = {
175 0x00, 0x64, 0xff, 0x9b,
176 0x00, 0x00, 0x00, 0x00,
177 0x00, 0x00, 0x00, 0x00,
178 0x00, 0x00, 0x00, 0x00
181 static uint8_t check_arp_icmp(
182 struct rte_mbuf *pkt,
184 struct pipeline_cgnapt *p_nat);
186 /* Finds next power of two for n. If n itself
187 * is a power of two then returns n
190 * Value usually 32-bit value
193 * Value after roundup to power of 2
195 uint64_t nextPowerOf2(uint64_t n)
209 /* Commented code may be required for future usage, Please keep it*/
211 static int retrieve_cgnapt_entry_alg(
212 struct pipeline_cgnapt_entry_key *key,
213 struct cgnapt_table_entry **entry_ptr1,
214 struct cgnapt_table_entry **entry_ptr2)
216 #ifdef CGNAPT_DBG_PRNT
217 printf("retrieve_cgnapt_entry key detail Entry:"
218 "0x%x, %d, %d\n", key->ip, key->port,
222 int position = rte_hash_lookup(napt_common_table, key);
224 printf("Invalid cgnapt entry position(first_key): %d\n",
229 *entry_ptr1 = &napt_hash_tbl_entries[position];
231 uint32_t prv_ip = (*entry_ptr1)->data.prv_ip;
232 uint32_t prv_port = (*entry_ptr1)->data.prv_port;
233 uint32_t prv_phy_port = (*entry_ptr1)->data.prv_phy_port;
235 struct pipeline_cgnapt_entry_key second_key;
236 second_key.ip = prv_ip;
237 second_key.port = prv_port;
238 second_key.pid = prv_phy_port;
240 position = rte_hash_lookup(napt_common_table, &second_key);
242 printf("Invalid cgnapt entry position(second_key): %d\n",
247 *entry_ptr2 = &napt_hash_tbl_entries[position];
253 int add_dynamic_cgnapt_entry_alg(
255 struct pipeline_cgnapt_entry_key *key,
256 struct cgnapt_table_entry **entry_ptr1,
257 struct cgnapt_table_entry **entry_ptr2)
259 int port_num = 0, ret;
261 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
263 #ifdef CGNAPT_DBG_PRNT
264 if (CGNAPT_DEBUG >= 1) {
265 printf("Th%d add_dynamic_cgnapt_entry key detail Entry:"
266 "0x%x, %d, %d\n", p_nat->pipeline_num, key->ip, key->port,
271 int32_t position = rte_hash_lookup(napt_common_table, key);
273 #ifdef CGNAPT_DBG_PRNT
274 if (CGNAPT_DEBUG >= 1) {
275 printf("%s: cgnapt entry exists in "
276 "position(first_key): %d\n", __func__, position);
279 *entry_ptr1 = &napt_hash_tbl_entries[position];
280 /* not required, as it is not used in the caller */
286 ret = increment_max_port_counter(key->ip, key->pid, p_nat);
287 if (ret == MAX_PORT_INC_ERROR) {
289 #ifdef CGNAPT_DBG_PRNT
290 if (CGNAPT_DEBUG > 1)
291 printf("add_dynamic_cgnapt_entry:"
292 "increment_max_port_counter-1 failed\n");
298 if (ret == MAX_PORT_INC_REACHED) {
300 #ifdef CGNAPT_DBG_PRNT
301 if (CGNAPT_DEBUG > 1)
302 printf("add_dynamic_cgnapt_entry:"
303 "increment_max_port_counter-2 failed\n");
310 port_num = get_free_iport(p_nat, &public_ip);
312 if (port_num == -1) {
314 #ifdef CGNAPT_DBG_PRNT
315 if (CGNAPT_DEBUG > 2) {
316 printf("add_dynamic_cgnapt_entry: %d\n", port_num);
317 printf("add_dynamic_cgnapt_entry key detail:0x%x, "
318 "%d, %d\n", key->ip, key->port, key->pid);
325 /* check for max_clients_per_ip */
326 if (rte_atomic16_read
328 [rte_jhash(&public_ip, 4, 0) % 16].count) ==
329 p_nat->max_clients_per_ip) {
330 /* For now just bail out
331 * In future we can think about
332 * retrying getting a new iport
334 release_iport(port_num, public_ip, p_nat);
339 rte_atomic16_inc(&all_public_ip
340 [rte_jhash(&public_ip, 4, 0) %
343 #ifdef CGNAPT_DBG_PRNT
344 if ((rte_jhash(&public_ip, 4, 0) % 16) == 8)
345 printf("pub ip:%x coutn:%d\n", public_ip,
346 rte_atomic16_read(&all_public_ip
347 [rte_jhash(&public_ip, 4, 0) % 16].count));
350 #ifdef CGNAPT_DBG_PRNT
351 if (CGNAPT_DEBUG > 0) {
352 printf("add_dynamic_cgnapt_entry: %d\n",
354 printf("add_dynamic_cgnapt_entry key detail: "
355 "0x%x, %d, %d\n", key->ip, key->port, key->pid);
359 struct cgnapt_table_entry entry = {
361 .action = RTE_PIPELINE_ACTION_PORT,
362 /* made it configurable below */
363 {.port_id = p->port_out_id[0]},
367 .prv_port = key->port,
369 .pub_port = port_num,
370 .prv_phy_port = key->pid,
371 .pub_phy_port = get_pub_to_prv_port(
375 /* if(timeout == -1) : static entry
376 * if(timeout == 0 ) : dynamic entry
377 * if(timeout > 0 ) : PCP requested entry
386 entry.data.u.prv_ip = key->ip;
387 entry.data.type = CGNAPT_ENTRY_IPV4;
389 entry.head.port_id = entry.data.pub_phy_port; /* outgoing port info */
391 struct pipeline_cgnapt_entry_key second_key;
392 /* Need to add a second ingress entry */
393 second_key.ip = public_ip;
394 second_key.port = port_num;
395 second_key.pid = 0xffff;
397 #ifdef CGNAPT_DBG_PRNT
398 if (CGNAPT_DEBUG > 2)
399 printf("add_dynamic_cgnapt_entry second key detail:"
400 "0x%x, %d, %d\n", second_key.ip, second_key.port,
404 int32_t position1 = rte_hash_add_key(napt_common_table, (void *)key);
407 printf("CG-NAPT entry add failed ...returning "
408 "without adding ... %d\n", position1);
413 #ifdef CGNAPT_DBG_PRNT
415 printf("add_dynamic_cgnapt_entry:");
417 print_cgnapt_entry(&entry);
421 memcpy(&napt_hash_tbl_entries[position1], &entry,
422 sizeof(struct cgnapt_table_entry));
424 /* this pointer is returned to pkt miss function */
425 *entry_ptr1 = &napt_hash_tbl_entries[position1];
427 p_nat->n_cgnapt_entry_added++;
428 p_nat->dynCgnaptCount++;
430 /* Now modify the forward port for reverse entry */
432 /* outgoing port info */
433 entry.head.port_id = entry.data.prv_phy_port;
435 int32_t position2 = rte_hash_add_key(napt_common_table, &second_key);
438 printf("CG-NAPT entry reverse bulk add failed ..."
439 "returning with fwd add ...%d\n",
444 memcpy(&napt_hash_tbl_entries[position2], &entry,
445 sizeof(struct cgnapt_table_entry));
447 *entry_ptr2 = &napt_hash_tbl_entries[position2];
449 #ifdef CGNAPT_DBG_PRNT
450 if (CGNAPT_DEBUG >= 1) {
451 printf("add_dynamic_cgnapt_entry position: %d, %d\n",
452 position1, position2);
453 printf("add_dynamic_cgnapt_entry: entry_ptr1: %p, "
454 "entry_ptr2: %p\n", *entry_ptr1, *entry_ptr2);
458 timer_thread_enqueue(key, &second_key, *entry_ptr1,
459 *entry_ptr2, (struct pipeline *)p_nat);
461 p_nat->n_cgnapt_entry_added++;
462 p_nat->dynCgnaptCount++;
469 void hw_checksum(struct rte_mbuf *pkt, enum PKT_TYPE ver)
471 struct tcp_hdr *tcp = NULL;
472 struct udp_hdr *udp = NULL;
473 struct icmp_hdr *icmp = NULL;
475 void *ip_header = NULL;
476 uint16_t prot_offset = 0;
477 uint32_t pkt_type_is_ipv4 = 1;
479 pkt->ol_flags |= PKT_TX_IP_CKSUM;
480 pkt->l2_len = ETH_HDR_SIZE;
485 case PKT_TYPE_IPV4to6:
489 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
490 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
492 pkt_type_is_ipv4 = 0;
493 pkt->ol_flags |= PKT_TX_IPV6;
495 sizeof(struct ipv6_hdr);
496 tcp = (struct tcp_hdr *)
497 ((unsigned char *)ip_header +
498 sizeof(struct ipv6_hdr));
499 udp = (struct udp_hdr *)
500 ((unsigned char *)ip_header +
501 sizeof(struct ipv6_hdr));
502 icmp = (struct icmp_hdr *)
503 ((unsigned char *)ip_header +
504 sizeof(struct ipv6_hdr));
506 prot_offset = PROT_OFST_IP6 + temp;
508 case PKT_TYPE_IPV6to4:
512 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
513 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
515 pkt->ol_flags |= PKT_TX_IPV4;
517 sizeof(struct ipv4_hdr);
518 tcp = (struct tcp_hdr *)
519 ((unsigned char *)ip_header +
520 sizeof(struct ipv4_hdr));
521 udp = (struct udp_hdr *)
522 ((unsigned char *)ip_header +
523 sizeof(struct ipv4_hdr));
524 icmp = (struct icmp_hdr *)
525 ((unsigned char *)ip_header +
526 sizeof(struct ipv4_hdr));
527 struct ipv4_hdr *ip_hdr =
528 (struct ipv4_hdr *)ip_header;
529 ip_hdr->hdr_checksum = 0;
531 prot_offset = PROT_OFST_IP4 + temp;
534 printf("hw_checksum: pkt version is invalid\n");
536 protocol = (uint8_t *) RTE_MBUF_METADATA_UINT8_PTR(pkt,
540 case IP_PROTOCOL_TCP: /* 6 */
542 pkt->ol_flags |= PKT_TX_TCP_CKSUM;
543 if (pkt_type_is_ipv4) {
544 tcp->cksum = rte_ipv4_phdr_cksum(
545 (struct ipv4_hdr *)ip_header,
548 tcp->cksum = rte_ipv6_phdr_cksum(
549 (struct ipv6_hdr *)ip_header,
553 case IP_PROTOCOL_UDP: /* 17 */
554 udp->dgram_cksum = 0;
555 pkt->ol_flags |= PKT_TX_UDP_CKSUM;
556 if (pkt_type_is_ipv4) {
559 (struct ipv4_hdr *)ip_header,
564 (struct ipv6_hdr *)ip_header,
568 case IP_PROTOCOL_ICMP: /* 1 */
569 if (pkt_type_is_ipv4) {
570 /* ICMP checksum code */
571 struct ipv4_hdr *ip_hdr =
572 (struct ipv4_hdr *)ip_header;
573 int size = rte_bswap16(ip_hdr->total_length) - 20;
574 icmp->icmp_cksum = 0;
582 #ifdef CGNAPT_DEBUGGING
583 printf("hw_checksum() : Neither TCP or UDP pkt\n");
590 void sw_checksum(struct rte_mbuf *pkt, enum PKT_TYPE ver)
592 struct tcp_hdr *tcp = NULL;
593 struct udp_hdr *udp = NULL;
594 struct icmp_hdr *icmp = NULL;
596 void *ip_header = NULL;
597 uint16_t prot_offset = 0;
598 uint32_t pkt_type_is_ipv4 = 1;
602 case PKT_TYPE_IPV4to6:
606 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
607 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
609 pkt_type_is_ipv4 = 0;
610 tcp = (struct tcp_hdr *)
611 ((unsigned char *)ip_header +
612 sizeof(struct ipv6_hdr));
613 udp = (struct udp_hdr *)
614 ((unsigned char *)ip_header +
615 sizeof(struct ipv6_hdr));
616 icmp = (struct icmp_hdr *)
617 ((unsigned char *)ip_header +
618 sizeof(struct ipv6_hdr));
620 prot_offset = PROT_OFST_IP6 + temp;
622 case PKT_TYPE_IPV6to4:
626 ip_header = RTE_MBUF_METADATA_UINT32_PTR(pkt,
627 MBUF_HDR_ROOM + ETH_HDR_SIZE + temp);
629 tcp = (struct tcp_hdr *)
630 ((unsigned char *)ip_header +
631 sizeof(struct ipv4_hdr));
632 udp = (struct udp_hdr *)
633 ((unsigned char *)ip_header +
634 sizeof(struct ipv4_hdr));
635 icmp = (struct icmp_hdr *)
636 ((unsigned char *)ip_header +
637 sizeof(struct ipv4_hdr));
639 prot_offset = PROT_OFST_IP4 + temp;
642 printf("sw_checksum: pkt version is invalid\n");
644 protocol = (uint8_t *) RTE_MBUF_METADATA_UINT8_PTR(pkt,
648 case IP_PROTOCOL_TCP: /* 6 */
650 if (pkt_type_is_ipv4) {
651 struct ipv4_hdr *ip_hdr =
652 (struct ipv4_hdr *)ip_header;
653 tcp->cksum = rte_ipv4_udptcp_cksum(ip_hdr,
655 ip_hdr->hdr_checksum = 0;
656 ip_hdr->hdr_checksum = rte_ipv4_cksum(
657 (struct ipv4_hdr *)ip_hdr);
659 tcp->cksum = rte_ipv6_udptcp_cksum(
661 ip_header, (void *)tcp);
664 case IP_PROTOCOL_UDP: /* 17 */
665 udp->dgram_cksum = 0;
666 if (pkt_type_is_ipv4) {
667 struct ipv4_hdr *ip_hdr =
668 (struct ipv4_hdr *)ip_header;
669 udp->dgram_cksum = rte_ipv4_udptcp_cksum(
670 ip_hdr, (void *)udp);
671 ip_hdr->hdr_checksum = 0;
672 ip_hdr->hdr_checksum = rte_ipv4_cksum(ip_hdr);
674 udp->dgram_cksum = rte_ipv6_udptcp_cksum(
676 ip_header, (void *)udp);
679 case IP_PROTOCOL_ICMP: /* 1 */
680 if (pkt_type_is_ipv4) {
681 /* ICMP checksum code */
682 struct ipv4_hdr *ip_hdr =
683 (struct ipv4_hdr *)ip_header;
684 int size = rte_bswap16(ip_hdr->total_length) - 20;
685 icmp->icmp_cksum = 0;
689 ip_hdr->hdr_checksum = 0;
690 ip_hdr->hdr_checksum = rte_ipv4_cksum(ip_hdr);
695 #ifdef CGNAPT_DEBUGGING
696 printf("sw_checksum() : Neither TCP or UDP pkt\n");
702 void print_pkt_info(uint8_t *eth_dest, struct ether_addr *hw_addr,
703 uint32_t dest_address, uint32_t port_id, struct rte_mbuf *pkt)
706 if (CGNAPT_DEBUG > 2) {
707 printf("MAC Found ip 0x%x, port %d - %02x:%02x:%02x:%02x:%02x:%02x \n",
708 dest_address, port_id, hw_addr->addr_bytes[0], hw_addr->addr_bytes[1],
709 hw_addr->addr_bytes[2], hw_addr->addr_bytes[3], hw_addr->addr_bytes[4],
710 hw_addr->addr_bytes[5]);
712 printf("Dest MAC before - %02x:%02x:%02x:%02x:%02x:%02x \n",
713 eth_dest[0], eth_dest[1], eth_dest[2], eth_dest[3], eth_dest[4],
717 if (CGNAPT_DEBUG > 2) {
718 printf("Dest MAC after - "
719 "%02x:%02x:%02x:%02x:%02x:%02x \n",
720 eth_dest[0], eth_dest[1],
721 eth_dest[2], eth_dest[3],
722 eth_dest[4], eth_dest[5]);
725 if (CGNAPT_DEBUG > 4)
729 static uint8_t check_arp_icmp(
730 struct rte_mbuf *pkt,
732 struct pipeline_cgnapt *p_nat)
734 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
735 uint16_t *eth_proto = RTE_MBUF_METADATA_UINT16_PTR(
736 pkt, eth_proto_offset);
737 struct app_link_params *link;
738 uint8_t solicited_node_multicast_addr[16] = {
739 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
740 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00};
742 /* ARP outport number */
743 uint16_t out_port = p_nat->p.n_ports_out - 1;
745 uint32_t prot_offset;
747 link = &myApp->link_params[pkt->port];
750 switch (rte_be_to_cpu_16(*eth_proto)) {
754 rte_pipeline_port_out_packet_insert(
760 * Pkt mask should be changed, and not changing the
763 p_nat->invalid_packets |= pkt_mask;
764 p_nat->arpicmpPktCount++;
768 case ETH_TYPE_IPV4: {
769 /* header room + eth hdr size +
770 * src_aadr offset in ip header
772 uint32_t dst_addr_offset = MBUF_HDR_ROOM +
773 ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
775 RTE_MBUF_METADATA_UINT32_PTR(pkt,
777 prot_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
778 IP_HDR_PROTOCOL_OFST;
779 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt,
781 if ((*protocol == IP_PROTOCOL_ICMP) &&
782 link->ip == rte_be_to_cpu_32(*dst_addr)) {
784 if (is_phy_port_privte(pkt->port)) {
786 rte_pipeline_port_out_packet_insert(
787 p_nat->p.p, out_port, pkt);
790 * Pkt mask should be changed,
791 * and not changing the drop mask
794 p_nat->invalid_packets |= pkt_mask;
795 p_nat->arpicmpPktCount++;
806 if (dual_stack_enable) {
808 /* Commented code may be required for future usage,
811 //uint32_t dst_addr_offset = MBUF_HDR_ROOM +
812 // ETH_HDR_SIZE + IPV6_HDR_DST_ADR_OFST;
813 //uint32_t *dst_addr =
814 // RTE_MBUF_METADATA_UINT32_PTR(pkt,
816 uint32_t prot_offset_ipv6 = MBUF_HDR_ROOM +
817 ETH_HDR_SIZE + IPV6_HDR_PROTOCOL_OFST;
818 struct ipv6_hdr *ipv6_h;
820 ipv6_h = (struct ipv6_hdr *) MBUF_HDR_ROOM +
822 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt,
825 if (ipv6_h->proto == ICMPV6_PROTOCOL_ID) {
826 if (!memcmp(ipv6_h->dst_addr, link->ipv6, 16)
827 || !memcmp(ipv6_h->dst_addr,
828 solicited_node_multicast_addr, 13)) {
829 rte_pipeline_port_out_packet_insert(
830 p_nat->p.p, out_port, pkt);
832 * Pkt mask should be changed,
833 * and not changing the drop mask
835 p_nat->invalid_packets |= pkt_mask;
836 p_nat->arpicmpPktCount++;
838 p_nat->invalid_packets |= pkt_mask;
839 p_nat->naptDroppedPktCount++;
841 #ifdef CGNAPT_DEBUGGING
842 p_nat->naptDroppedPktCount1++;
857 * Function to create common NAPT table
858 * Called during pipeline initialization
859 * Creates the common NAPT table
860 * If it is not already created and stores its pointer
861 * in global napt_common_table pointer.
864 * Max number of NAPT flows. This parameter is configurable via config file.
867 * 0 on success, negative on error.
869 int create_napt_common_table(uint32_t nFlows)
871 if (napt_common_table != NULL) {
872 printf("napt_common_table already exists.\n");
876 napt_common_table = rte_hash_create(&napt_common_table_hash_params);
878 if (napt_common_table == NULL) {
879 printf("napt_common_table creation failed.\n");
883 uint32_t number_of_entries = nFlows;
886 RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_table_entry) *
888 napt_hash_tbl_entries = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
890 if (napt_hash_tbl_entries == NULL) {
891 printf("napt_hash_tbl_entries creation failed. %d, %d\n",
892 nFlows, (int)sizeof(struct cgnapt_table_entry));
900 * Function to initialize bulk port allocation data structures
901 * Called during pipeline initialization.
903 * Creates the port alloc ring for the VNF_set this pipeline belongs
905 * Creates global port allocation buffer pool
907 * Initializes the port alloc ring according to config data
910 * A pointer to struct pipeline_cgnapt
913 * 0 on success, negative on error.
915 int napt_port_alloc_init(struct pipeline_cgnapt *p_nat)
917 p_nat->allocated_ports = NULL;
918 p_nat->free_ports = NULL;
920 uint32_t vnf_set_num = p_nat->vnf_set;
921 /*uint32_t vnf_set_num = get_vnf_set_num(p_nat->pipeline_num); */
923 #ifdef CGNAPT_DBG_PRNT
924 printf("VNF set number for CGNAPT %d is %d.\n", p_nat->pipeline_num,
927 if (vnf_set_num == 0xFF) {
928 printf("VNF set number for CGNAPT %d is invalid %d.\n",
929 p_nat->pipeline_num, vnf_set_num);
933 p_nat->port_alloc_ring = port_alloc_ring[vnf_set_num];
934 if (p_nat->port_alloc_ring != NULL) {
935 printf("CGNAPT%d port_alloc_ring already exists.\n",
936 p_nat->pipeline_num);
940 printf("napt_port_alloc_elem_count :%d\n",
941 napt_port_alloc_elem_count);
942 napt_port_alloc_elem_count += 1;
943 napt_port_alloc_elem_count =
944 nextPowerOf2(napt_port_alloc_elem_count);
945 printf("Next power of napt_port_alloc_elem_count: %d\n",
946 napt_port_alloc_elem_count);
948 port_alloc_ring[vnf_set_num] =
949 rte_ring_create(napt_port_alloc_ring_name[vnf_set_num],
950 napt_port_alloc_elem_count, rte_socket_id(), 0);
951 p_nat->port_alloc_ring = port_alloc_ring[vnf_set_num];
952 if (p_nat->port_alloc_ring == NULL) {
953 printf("CGNAPT%d - Failed to create port_alloc_ring\n",
954 p_nat->pipeline_num);
958 /* Create port alloc buffer */
959 /* Only one pool is enough for all vnf sets */
960 if (napt_port_pool == NULL) {
962 napt_port_pool = rte_mempool_create(
964 napt_port_alloc_elem_count,
965 sizeof(struct napt_port_alloc_elem),
966 0, 0, NULL, NULL, NULL,
967 NULL, rte_socket_id(), 0);
970 if (napt_port_pool == NULL) {
971 printf("CGNAPT - Create port pool failed\n");
975 /* Add all available public IP addresses and ports to the ring */
978 #ifdef NAT_ONLY_CONFIG_REQ
979 if (nat_only_config_flag) {
980 printf("******* pub_ip_range_count:%d ***********\n",
981 p_nat->pub_ip_range_count);
982 /* Initialize all public IP's addresses */
984 uint32_t max_ips_remain;
986 for (if_addrs = 0; if_addrs < p_nat->pub_ip_range_count;
988 /* Add all available addresses to the ring */
990 for (i = p_nat->pub_ip_range[if_addrs].start_ip;
991 i <= p_nat->pub_ip_range[if_addrs].end_ip;) {
992 /* 1. Get a port alloc buffer from napt_port_pool */
996 /* get new napt_port_alloc_elem from pool */
997 if (rte_mempool_get(napt_port_pool,
999 printf("CGNAPT - Error in getting port "
1005 /* 2. Populate it with available ports and ip addr */
1006 struct napt_port_alloc_elem *pb =
1007 (struct napt_port_alloc_elem *)portsBuf;
1010 temp = p_nat->pub_ip_range[if_addrs].end_ip -
1013 /* Check if remaining port count is greater
1014 * than or equals to bulk count, if not give
1015 * remaining count ports than giving bulk count
1017 if (temp < NUM_NAPT_PORT_BULK_ALLOC)
1018 max_ips_remain = temp;
1021 NUM_NAPT_PORT_BULK_ALLOC;
1023 for (j = 0; j < max_ips_remain; j++) {
1025 pb->ip_addr[j] = i + j;
1028 p_nat->pub_ip_range[if_addrs].
1033 /* 3. add the port alloc buffer to ring */
1034 if (rte_ring_enqueue(p_nat->port_alloc_ring,
1036 printf("CGNAPT%d - Enqueue error - i %d,",
1037 p_nat->pipeline_num, i);
1038 printf("j %d, if_addrs %d, pb %p\n",
1040 rte_ring_dump(stdout,
1041 p_nat->port_alloc_ring);
1042 rte_mempool_put(napt_port_pool,
1047 /* reset j and advance i */
1049 i += max_ips_remain;
1057 printf("******* p_nat->pub_ip_count:%d ***********\n",
1058 p_nat->pub_ip_count);
1059 /* Initialize all public IP's ports */
1061 uint32_t max_ports_remain;
1063 for (if_ports = 0; if_ports < p_nat->pub_ip_count; if_ports++) {
1064 /* Add all available ports to the ring */
1066 for (i = p_nat->pub_ip_port_set[if_ports].start_port;
1067 i <= p_nat->pub_ip_port_set[if_ports].end_port;) {
1068 /* 1. Get a port alloc buffer from napt_port_pool */
1072 /* get new napt_port_alloc_elem from pool */
1073 if (rte_mempool_get(napt_port_pool, &portsBuf) <
1075 printf("CGNAPT - Error in getting "
1076 "port alloc buffer\n");
1081 /* 2. Populate it with available ports and ip addr */
1082 struct napt_port_alloc_elem *pb =
1083 (struct napt_port_alloc_elem *)portsBuf;
1086 temp = p_nat->pub_ip_port_set[if_ports].end_port -
1088 /* Check if remaining port count is greater
1089 * than or equals to bulk count, if not give
1090 * remaining count ports than giving bulk count
1092 if (temp < NUM_NAPT_PORT_BULK_ALLOC)
1093 max_ports_remain = temp;
1096 NUM_NAPT_PORT_BULK_ALLOC;
1098 for (j = 0; j < max_ports_remain; j++) {
1101 p_nat->pub_ip_port_set[if_ports].ip;
1102 pb->ports[j] = i + j;
1103 if ((i + j) == p_nat->pub_ip_port_set
1104 [if_ports].end_port)
1108 /* 3. add the port alloc buffer to ring */
1109 if (rte_ring_enqueue(p_nat->port_alloc_ring,
1111 printf("CGNAPT%d - Enqueue error - i %d, j %d, "
1112 " if_ports %d, pb %p\n", p_nat->pipeline_num,
1113 i, j, if_ports, pb);
1115 rte_ring_dump(stdout, p_nat->port_alloc_ring);
1116 rte_mempool_put(napt_port_pool, portsBuf);
1120 /* reset j and advance i */
1122 i += max_ports_remain;
1129 static pipeline_msg_req_handler handlers[] = {
1130 [PIPELINE_MSG_REQ_PING] =
1131 pipeline_msg_req_ping_handler,
1132 [PIPELINE_MSG_REQ_STATS_PORT_IN] =
1133 pipeline_msg_req_stats_port_in_handler,
1134 [PIPELINE_MSG_REQ_STATS_PORT_OUT] =
1135 pipeline_msg_req_stats_port_out_handler,
1136 [PIPELINE_MSG_REQ_STATS_TABLE] = pipeline_msg_req_stats_table_handler,
1137 [PIPELINE_MSG_REQ_PORT_IN_ENABLE] =
1138 pipeline_msg_req_port_in_enable_handler,
1139 [PIPELINE_MSG_REQ_PORT_IN_DISABLE] =
1140 pipeline_msg_req_port_in_disable_handler,
1141 [PIPELINE_MSG_REQ_CUSTOM] =
1142 pipeline_cgnapt_msg_req_custom_handler,
1145 static pipeline_msg_req_handler custom_handlers[] = {
1146 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_ADD] =
1147 pipeline_cgnapt_msg_req_entry_add_handler,
1148 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_DEL] =
1149 pipeline_cgnapt_msg_req_entry_del_handler,
1150 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_SYNC] =
1151 pipeline_cgnapt_msg_req_entry_sync_handler,
1152 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_DBG] =
1153 pipeline_cgnapt_msg_req_entry_dbg_handler,
1154 [PIPELINE_CGNAPT_MSG_REQ_ENTRY_ADDM] =
1155 pipeline_cgnapt_msg_req_entry_addm_handler,
1156 [PIPELINE_CGNAPT_MSG_REQ_VER] =
1157 pipeline_cgnapt_msg_req_ver_handler,
1158 [PIPELINE_CGNAPT_MSG_REQ_NSP_ADD] =
1159 pipeline_cgnapt_msg_req_nsp_add_handler,
1160 [PIPELINE_CGNAPT_MSG_REQ_NSP_DEL] =
1161 pipeline_cgnapt_msg_req_nsp_del_handler,
1164 [PIPELINE_CGNAPT_MSG_REQ_PCP] =
1165 pipeline_cgnapt_msg_req_pcp_handler,
1170 * Function to convert an IPv6 packet to IPv4 packet
1173 * A pointer to packet mbuf
1174 * @param in_ipv6_hdr
1175 * A pointer to IPv6 header in the given pkt
1179 convert_ipv6_to_ipv4(struct rte_mbuf *pkt, struct ipv6_hdr *in_ipv6_hdr)
1181 uint32_t ip_hdr_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE;
1183 uint8_t *eth_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1184 uint8_t *ipv6_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, ip_hdr_offset);
1186 struct ether_hdr eth_hdr;
1187 struct ipv4_hdr *ipv4_hdr_p;
1188 uint16_t frag_off = 0x4000;
1189 struct cgnapt_nsp_node *ll = nsp_ll;
1190 uint8_t ipv4_dest[4];
1193 memcpy(ð_hdr, eth_hdr_p, sizeof(struct ether_hdr));
1194 memcpy(in_ipv6_hdr, ipv6_hdr_p, sizeof(struct ipv6_hdr));
1196 eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
1198 char *data_area_p = rte_pktmbuf_adj(pkt, 20);
1199 if (data_area_p == NULL) {
1200 printf("convert_ipv6_to_ipv4:data_area_p is NULL\n");
1203 ipv4_hdr_p = (struct ipv4_hdr *)(data_area_p + ETH_HDR_SIZE);
1204 memset(ipv4_hdr_p, 0, sizeof(struct ipv4_hdr));
1206 memcpy(data_area_p, ð_hdr, sizeof(struct ether_hdr));
1208 #ifdef CGNAPT_DBG_PRNT
1209 if (CGNAPT_DEBUG == 1)
1210 printf("convert_ipv6_to_ipv4: eth_hdr_p(%p), data_area_p(%p), "
1211 "ipv4_hdr_p(%p)\n", eth_hdr_p, data_area_p, ipv4_hdr_p);
1214 ipv4_hdr_p->version_ihl = 0x4 << 4 | 0x5;
1215 ipv4_hdr_p->type_of_service =
1216 rte_be_to_cpu_32(in_ipv6_hdr->vtc_flow) & 0x0ff00000 >> 20;
1217 ipv4_hdr_p->total_length =
1218 rte_cpu_to_be_16(rte_be_to_cpu_16(
1219 in_ipv6_hdr->payload_len) + 20);
1220 ipv4_hdr_p->packet_id = 0;
1221 ipv4_hdr_p->fragment_offset = rte_cpu_to_be_16(frag_off);
1222 ipv4_hdr_p->time_to_live = in_ipv6_hdr->hop_limits;
1223 ipv4_hdr_p->next_proto_id = in_ipv6_hdr->proto;
1224 ipv4_hdr_p->hdr_checksum = 0;
1225 ipv4_hdr_p->src_addr = 0;
1227 while (ll != NULL) {
1229 (&in_ipv6_hdr->dst_addr[0], &ll->nsp.prefix[0],
1230 ll->nsp.depth / 8)) {
1231 if (ll->nsp.depth == 32)
1232 memcpy(&ipv4_dest[0], &in_ipv6_hdr->dst_addr[4],
1234 else if (ll->nsp.depth == 40) {
1235 ipv4_dest[0] = in_ipv6_hdr->dst_addr[5];
1236 ipv4_dest[1] = in_ipv6_hdr->dst_addr[6];
1237 ipv4_dest[2] = in_ipv6_hdr->dst_addr[7];
1238 ipv4_dest[3] = in_ipv6_hdr->dst_addr[9];
1239 } else if (ll->nsp.depth == 48) {
1240 ipv4_dest[0] = in_ipv6_hdr->dst_addr[6];
1241 ipv4_dest[1] = in_ipv6_hdr->dst_addr[7];
1242 ipv4_dest[2] = in_ipv6_hdr->dst_addr[9];
1243 ipv4_dest[3] = in_ipv6_hdr->dst_addr[10];
1244 } else if (ll->nsp.depth == 56) {
1245 ipv4_dest[0] = in_ipv6_hdr->dst_addr[7];
1246 ipv4_dest[1] = in_ipv6_hdr->dst_addr[9];
1247 ipv4_dest[2] = in_ipv6_hdr->dst_addr[10];
1248 ipv4_dest[3] = in_ipv6_hdr->dst_addr[11];
1249 } else if (ll->nsp.depth == 64) {
1250 ipv4_dest[0] = in_ipv6_hdr->dst_addr[9];
1251 ipv4_dest[1] = in_ipv6_hdr->dst_addr[10];
1252 ipv4_dest[2] = in_ipv6_hdr->dst_addr[11];
1253 ipv4_dest[3] = in_ipv6_hdr->dst_addr[12];
1254 } else if (ll->nsp.depth == 96) {
1255 ipv4_dest[0] = in_ipv6_hdr->dst_addr[12];
1256 ipv4_dest[1] = in_ipv6_hdr->dst_addr[13];
1257 ipv4_dest[2] = in_ipv6_hdr->dst_addr[14];
1258 ipv4_dest[3] = in_ipv6_hdr->dst_addr[15];
1269 memcpy(&ipv4_hdr_p->dst_addr, &ipv4_dest[0], 4);
1271 memcpy(&ipv4_hdr_p->dst_addr, &in_ipv6_hdr->dst_addr[12], 4);
1276 * Function to convert an IPv4 packet to IPv6 packet
1279 * A pointer to packet mbuf
1280 * @param in_ipv4_hdr
1281 * A pointer to IPv4 header in the given pkt
1285 convert_ipv4_to_ipv6(struct rte_mbuf *pkt, struct ipv4_hdr *in_ipv4_hdr)
1287 uint32_t ip_hdr_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE;
1289 uint8_t *eth_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1290 uint8_t *ipv4_hdr_p = RTE_MBUF_METADATA_UINT8_PTR(pkt, ip_hdr_offset);
1292 struct ether_hdr eth_hdr;
1293 struct ipv6_hdr *ipv6_hdr_p;
1295 memcpy(ð_hdr, eth_hdr_p, sizeof(struct ether_hdr));
1296 memcpy(in_ipv4_hdr, ipv4_hdr_p, sizeof(struct ipv4_hdr));
1298 eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
1300 char *data_area_p = rte_pktmbuf_prepend(pkt, 20);
1301 if (data_area_p == NULL) {
1302 printf("convert_ipv4_to_ipv6:data_area_p is NULL\n");
1305 ipv6_hdr_p = (struct ipv6_hdr *)(data_area_p + ETH_HDR_SIZE);
1306 memset(ipv6_hdr_p, 0, sizeof(struct ipv6_hdr));
1308 memcpy(data_area_p, ð_hdr, sizeof(struct ether_hdr));
1310 ipv6_hdr_p->vtc_flow =
1311 rte_cpu_to_be_32((0x6 << 28) |
1312 (in_ipv4_hdr->type_of_service << 20));
1313 ipv6_hdr_p->payload_len =
1314 rte_cpu_to_be_16(rte_be_to_cpu_16(
1315 in_ipv4_hdr->total_length) - 20);
1316 ipv6_hdr_p->proto = in_ipv4_hdr->next_proto_id;
1317 ipv6_hdr_p->hop_limits = in_ipv4_hdr->time_to_live;
1319 ipv6_hdr_p->src_addr[0] = 0x00;
1320 ipv6_hdr_p->src_addr[1] = 0x64;
1321 ipv6_hdr_p->src_addr[2] = 0xff;
1322 ipv6_hdr_p->src_addr[3] = 0x9b;
1323 ipv6_hdr_p->src_addr[4] = 0x00;
1324 ipv6_hdr_p->src_addr[5] = 0x00;
1325 ipv6_hdr_p->src_addr[6] = 0x00;
1326 ipv6_hdr_p->src_addr[7] = 0x00;
1327 ipv6_hdr_p->src_addr[8] = 0x00;
1328 ipv6_hdr_p->src_addr[9] = 0x00;
1329 ipv6_hdr_p->src_addr[10] = 0x00;
1330 ipv6_hdr_p->src_addr[11] = 0x00;
1331 memcpy(&ipv6_hdr_p->src_addr[12], &in_ipv4_hdr->src_addr, 4);
1333 memset(&ipv6_hdr_p->dst_addr, 0, 16);
1340 * Output port handler
1343 * A pointer to packet mbuf
1345 * Unused void pointer
1348 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1350 pkt_work_cgnapt_out(__rte_unused struct rte_mbuf *pkt, __rte_unused void *arg)
1352 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1353 if ((cgnapt_num_func_to_inst == 5)
1354 && (cgnapt_inst_index < INST_ARRAY_SIZE)) {
1355 if (cgnapt_inst5_flag == 0) {
1356 uint8_t *inst5_sig =
1357 RTE_MBUF_METADATA_UINT8_PTR(pkt,
1359 if (*inst5_sig == CGNAPT_INST5_SIG) {
1360 cgnapt_inst5_flag = 1;
1361 inst_end_time[cgnapt_inst_index] =
1362 rte_get_tsc_cycles();
1363 cgnapt_inst_index++;
1369 /* cgnapt_pkt_out_count++; */
1370 #ifdef CGNAPT_DBG_PRNT
1378 * Output port handler to handle 4 pkts
1381 * A pointer to packet mbuf
1383 * Inport handler argument pointer
1386 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1387 static void pkt4_work_cgnapt_out(struct rte_mbuf **pkt, void *arg)
1391 /* TO BE IMPLEMENTED IF REQUIRED */
1395 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
1396 PIPELINE_CGNAPT_PORT_OUT_AH(port_out_ah_cgnapt,
1397 pkt_work_cgnapt_out, pkt4_work_cgnapt_out);
1399 PIPELINE_CGNAPT_PORT_OUT_BAH(port_out_ah_cgnapt_bulk,
1400 pkt_work_cgnapt_out, pkt4_work_cgnapt_out);
1404 * Function to validate the packet and return version
1407 * A pointer to packet mbuf
1410 * IP version of the valid pkt, -1 if invalid pkt
1412 int rte_get_pkt_ver(struct rte_mbuf *pkt)
1414 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
1415 uint16_t *eth_proto =
1416 RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
1418 if (*eth_proto == rte_be_to_cpu_16(ETHER_TYPE_IPv4))
1419 return IP_VERSION_4;
1421 if (dual_stack_enable
1422 && (*eth_proto == rte_be_to_cpu_16(ETHER_TYPE_IPv6)))
1423 return IP_VERSION_6;
1425 /* Check the protocol first, if not UDP or TCP return */
1431 * A method to print the NAPT entry
1434 * A pointer to struct cgnapt_table_entry
1436 void my_print_entry(struct cgnapt_table_entry *ent)
1438 printf("CGNAPT key:\n");
1439 printf("entry_type :%d\n", ent->data.type);
1440 printf("prv_ip: %x %x %x %x\n", ent->data.u.u32_prv_ipv6[0],
1441 ent->data.u.u32_prv_ipv6[1], ent->data.u.u32_prv_ipv6[2],
1442 ent->data.u.u32_prv_ipv6[3]);
1443 printf("prv_port:%d\n", ent->data.prv_port);
1445 printf("pub_ip:%x\n", ent->data.pub_ip);
1446 printf("prv_phy_port:%d\n", ent->data.prv_phy_port);
1447 printf("pub_phy_port:%d\n", ent->data.pub_phy_port);
1451 * Function to print common CGNAPT table entries
1454 void print_common_table(void)
1462 index = rte_hash_iterate(napt_common_table,
1463 &key, &data, &next);
1465 if ((index != -EINVAL) && (index != -ENOENT)) {
1466 printf("\n%04d ", count);
1467 //print_key((struct pipeline_cgnapt_entry_key *)key);
1468 rte_hexdump(stdout, "KEY", key,
1469 sizeof(struct pipeline_cgnapt_entry_key));
1470 int32_t position = rte_hash_lookup(
1471 napt_common_table, key);
1472 print_cgnapt_entry(&napt_hash_tbl_entries[position]);
1476 } while (index != -ENOENT);
1480 * Input port handler for mixed traffic
1481 * This is the main method in this file when running in mixed traffic mode.
1482 * Starting from the packet burst it filters unwanted packets,
1483 * calculates keys, does lookup and then based on the lookup
1484 * updates NAPT table and does packet NAPT translation.
1487 * A pointer to struct rte_pipeline
1489 * A pointer to array of packets mbuf
1491 * Number of packets in the burst
1496 * int that is not checked by caller
1498 static int cgnapt_in_port_ah_mix(struct rte_pipeline *rte_p,
1499 struct rte_mbuf **pkts,
1500 uint32_t n_pkts, void *arg)
1505 * 1. Read packet version, if invalid drop the packet
1506 * 2. Check protocol, if not UDP or TCP drop the packet
1507 * 3. Bring all valid packets together - useful for bulk lookup
1508 * and calculate key for all packets
1509 * a. If IPv4 : calculate key with full IP
1510 * b. If IPv6 : calculate key with last 32-bit of IP
1511 * 4. Do bulk lookup with rte_hash_lookup_bulk(), if something went wrong
1513 * 5. For lookup hit packets, read entry from table
1514 * 6. For lookup miss packets, add dynamic entry to table
1516 * a. If egress pkt, convert to IPv4 and NAPT it
1517 * b. If ingress, drop the pkt
1519 * a. If egress pkt, NAPT it. Get MAC
1520 * b. If first ingress pkt (with no egress entry), drop the pkt
1521 * If not first ingress pkt
1522 * I. If IPv6 converted packet, convert back to IPv6,
1524 * II. If IPv4 packet, NAPT it & get MAC
1525 * 9. Send all packets out to corresponding ports
1527 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
1528 struct pipeline_cgnapt *p_nat = ap->p;
1529 uint8_t compacting_map[RTE_HASH_LOOKUP_BULK_MAX];
1530 uint32_t packets_for_lookup = 0;
1533 p_nat->valid_packets = 0;
1534 p_nat->invalid_packets = 0;
1536 #ifdef CGNAPT_DBG_PRNT
1537 if (CGNAPT_DEBUG > 1)
1538 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
1541 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
1543 uint16_t phy_port = 0;
1544 uint16_t *src_port = NULL;
1545 uint16_t *dst_port = NULL;
1546 uint32_t *src_addr = NULL;
1547 uint32_t *dst_addr = NULL;
1548 uint8_t *protocol = NULL;
1549 uint8_t *eth_dest = NULL;
1550 uint8_t *eth_src = NULL;
1551 uint16_t src_port_offset = 0;
1552 uint16_t dst_port_offset = 0;
1553 uint16_t src_addr_offset = 0;
1554 uint16_t dst_addr_offset = 0;
1555 uint16_t prot_offset = 0;
1556 uint16_t eth_offset = 0;
1559 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
1561 src_port_offset = SRC_PRT_OFST_IP4_TCP;
1562 dst_port_offset = DST_PRT_OFST_IP4_TCP;
1564 for (i = 0; i < n_pkts; i++) {
1565 p_nat->receivedPktCount++;
1567 /* bitmask representing only this packet */
1568 uint64_t pkt_mask = 1LLU << i;
1570 /* remember this pkt as valid pkt */
1571 p_nat->valid_packets |= pkt_mask;
1573 struct rte_mbuf *pkt = pkts[i];
1576 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
1579 int ver = rte_get_pkt_ver(pkt);
1581 #ifdef CGNAPT_DBG_PRNT
1582 printf("ver no. of the pkt:%d\n", ver);
1585 if (unlikely(ver < 0)) {
1586 /* Not a valid pkt , ignore. */
1587 /* remember invalid packets to be dropped */
1588 p_nat->invalid_packets |= pkt_mask;
1589 p_nat->naptDroppedPktCount++;
1591 #ifdef CGNAPT_DEBUGGING
1592 p_nat->naptDroppedPktCount1++;
1597 prot_offset = PROT_OFST_IP4;
1599 prot_offset = PROT_OFST_IP6;
1601 (uint8_t *) RTE_MBUF_METADATA_UINT32_PTR(pkt,
1604 (*protocol == IP_PROTOCOL_TCP
1605 || *protocol == IP_PROTOCOL_UDP
1606 || *protocol == IP_PROTOCOL_ICMP)) {
1607 /* remember invalid packets to be dropped */
1608 p_nat->invalid_packets |= pkt_mask;
1609 p_nat->naptDroppedPktCount++;
1611 #ifdef CGNAPT_DEBUGGING
1612 p_nat->naptDroppedPktCount2++;
1617 #ifdef CGNAPT_DBG_PRNT
1618 if (CGNAPT_DEBUG > 4)
1624 * 1. Handel PCP for egress traffic
1625 * 2. If PCP, then give response (send pkt) from the same port
1626 * 3. Drop the PCP packet, should not be added in the NAPT table
1629 if (*protocol == IP_PROTOCOL_UDP) {
1630 struct udp_hdr *udp;
1632 udp = (struct udp_hdr *)
1633 RTE_MBUF_METADATA_UINT8_PTR(pkt,
1636 udp = (struct udp_hdr *)
1637 RTE_MBUF_METADATA_UINT8_PTR(pkt,
1640 if (rte_bswap16(udp->dst_port) ==
1642 handle_pcp_req(pkt, ver, p_nat);
1643 p_nat->invalid_packets |= pkt_mask;
1653 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1656 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1659 if ((*protocol == IP_PROTOCOL_TCP)
1660 || (*protocol == IP_PROTOCOL_UDP)) {
1662 src_port_offset = SRC_PRT_OFST_IP4_TCP;
1663 dst_port_offset = DST_PRT_OFST_IP4_TCP;
1665 } else if (*protocol == IP_PROTOCOL_ICMP) {
1667 src_port_offset = IDEN_OFST_IP4_ICMP;
1668 /* Sequence number */
1669 dst_port_offset = SEQN_OFST_IP4_ICMP;
1673 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1676 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1681 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1684 RTE_MBUF_METADATA_UINT32_PTR(pkt,
1687 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1690 RTE_MBUF_METADATA_UINT16_PTR(pkt,
1693 /* need to create compacted table of pointers to
1694 * pass to bulk lookup
1697 compacting_map[packets_for_lookup] = i;
1699 //phy_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, phyport_offset);
1700 phy_port = pkt->port;
1702 struct pipeline_cgnapt_entry_key key;
1704 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
1707 if (get_in_port_dir(phy_port)) {
1710 key.ip = rte_bswap32(*src_addr);
1712 key.ip = rte_bswap32(src_addr[3]);
1713 key.port = rte_bswap16(*src_port);
1715 #ifdef NAT_ONLY_CONFIG_REQ
1716 if (nat_only_config_flag)
1721 key.ip = rte_bswap32(*dst_addr);
1723 if (*protocol == IP_PROTOCOL_ICMP) {
1724 /* common table lookupkey preparation from
1725 * incoming ICMP Packet- Indentifier field
1727 key.port = rte_bswap16(*src_port);
1729 key.port = rte_bswap16(*dst_port);
1732 #ifdef NAT_ONLY_CONFIG_REQ
1733 if (nat_only_config_flag)
1740 memcpy(&(p_nat->keys[packets_for_lookup]), &key,
1741 sizeof(struct pipeline_cgnapt_entry_key));
1742 p_nat->key_ptrs[packets_for_lookup] =
1743 &(p_nat->keys[packets_for_lookup]);
1744 packets_for_lookup++;
1747 if (unlikely(packets_for_lookup == 0)) {
1748 /* no suitable packet for lookup */
1749 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
1750 return p_nat->valid_packets;
1753 /* lookup entries in the common napt table */
1755 int lookup_result = rte_hash_lookup_bulk(napt_common_table,
1759 &p_nat->lkup_indx[0]);
1761 if (unlikely(lookup_result < 0)) {
1762 /* unknown error, just discard all packets */
1763 printf("Unexpected hash lookup error %d, discarding all "
1764 "packets", lookup_result);
1765 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
1768 //struct rte_pipeline_table_entry *entries[64];
1769 /* Now one by one check the result of our bulk lookup */
1771 for (i = 0; i < packets_for_lookup; i++) {
1772 /* index into hash table entries */
1773 int hash_table_entry = p_nat->lkup_indx[i];
1774 /* index into packet table of this packet */
1775 uint8_t pkt_index = compacting_map[i];
1776 /*bitmask representing only this packet */
1777 uint64_t pkt_mask = 1LLU << pkt_index;
1779 struct cgnapt_table_entry *entry = NULL;
1780 if (hash_table_entry < 0) {
1782 /* try to add new entry */
1783 struct rte_pipeline_table_entry *table_entry = NULL;
1786 pkt_miss_cgnapt(p_nat->key_ptrs[i],
1789 &p_nat->valid_packets,
1794 /* ICMP Error message generation for
1795 * Destination Host unreachable
1797 if (*protocol == IP_PROTOCOL_ICMP) {
1798 cgnapt_icmp_pkt = pkts[pkt_index];
1799 send_icmp_dest_unreachable_msg();
1802 /* Drop packet by adding to invalid pkt mask */
1804 p_nat->invalid_packets |= dropmask;
1805 #ifdef CGNAPT_DEBUGGING
1806 if (p_nat->kpc2++ < 5) {
1807 printf("in_ah Th: %d",
1808 p_nat->pipeline_num);
1809 print_key(p_nat->key_ptrs[i]);
1813 p_nat->naptDroppedPktCount++;
1815 #ifdef CGNAPT_DEBUGGING
1816 p_nat->naptDroppedPktCount3++;
1821 entry = (struct cgnapt_table_entry *)table_entry;
1823 /* entry found for this packet */
1824 entry = &napt_hash_tbl_entries[hash_table_entry];
1827 /* apply napt and mac changes */
1829 p_nat->entries[pkt_index] = &(entry->head);
1831 phy_port = pkts[pkt_index]->port;
1833 struct ipv6_hdr ipv6_hdr;
1834 struct ipv4_hdr ipv4_hdr;
1836 ver = rte_get_pkt_ver(pkts[pkt_index]);
1837 #ifdef CGNAPT_DEBUGGING
1838 if (CGNAPT_DEBUG >= 1) {
1839 printf("ver:%d\n", ver);
1840 printf("entry->data.type:%d\n", entry->data.type);
1843 if ((ver == 6) && (entry->data.type == CGNAPT_ENTRY_IPV6)
1844 && is_phy_port_privte(phy_port)) {
1845 convert_ipv6_to_ipv4(pkts[pkt_index], &ipv6_hdr);
1847 pkt_type = PKT_TYPE_IPV6to4;
1849 #ifdef CGNAPT_DBG_PRNT
1850 if (CGNAPT_DEBUG >= 1)
1851 printf("pkt_work_cganpt: "
1852 "convert_ipv6_to_ipv4\n");
1855 struct cgnapt_nsp_node *ll = nsp_ll;
1857 while (ll != NULL) {
1858 if (!memcmp(&ipv6_hdr.dst_addr[0],
1860 ll->nsp.depth / 8)) {
1868 && !memcmp(&ipv6_hdr.dst_addr[0],
1869 &well_known_prefix[0], 12)) {
1874 p_nat->invalid_packets |= 1LLU << pkt_index;
1875 p_nat->naptDroppedPktCount++;
1877 #ifdef CGNAPT_DEBUGGING
1878 p_nat->naptDroppedPktCount5++;
1885 /* As packet is already converted into IPv4 we must not operate
1886 * IPv6 offsets on packet
1887 * Only perform IPv4 operations
1892 src_port_offset = SRC_PRT_OFST_IP6t4;
1893 dst_port_offset = DST_PRT_OFST_IP6t4;
1894 src_addr_offset = SRC_ADR_OFST_IP6t4;
1895 dst_addr_offset = DST_ADR_OFST_IP6t4;
1896 prot_offset = PROT_OFST_IP6t4;
1897 eth_offset = ETH_OFST_IP6t4;
1901 if ((*protocol == IP_PROTOCOL_TCP)
1902 || (*protocol == IP_PROTOCOL_UDP)) {
1903 src_port_offset = SRC_PRT_OFST_IP4_TCP;
1904 dst_port_offset = DST_PRT_OFST_IP4_TCP;
1905 } else if (*protocol == IP_PROTOCOL_ICMP) {
1907 src_port_offset = IDEN_OFST_IP4_ICMP;
1908 /* Sequence number */
1909 dst_port_offset = SEQN_OFST_IP4_ICMP;
1912 src_addr_offset = SRC_ADR_OFST_IP4;
1913 dst_addr_offset = DST_ADR_OFST_IP4;
1914 prot_offset = PROT_OFST_IP4;
1915 eth_offset = MBUF_HDR_ROOM;
1920 RTE_MBUF_METADATA_UINT32_PTR(pkts[pkt_index],
1923 RTE_MBUF_METADATA_UINT32_PTR(pkts[pkt_index],
1926 RTE_MBUF_METADATA_UINT16_PTR(pkts[pkt_index],
1929 RTE_MBUF_METADATA_UINT16_PTR(pkts[pkt_index],
1932 RTE_MBUF_METADATA_UINT8_PTR(pkts[pkt_index],
1936 RTE_MBUF_METADATA_UINT8_PTR(pkts[pkt_index],
1939 RTE_MBUF_METADATA_UINT8_PTR(pkts[pkt_index],
1942 if (entry->data.ttl == NAPT_ENTRY_STALE)
1943 entry->data.ttl = NAPT_ENTRY_VALID;
1945 struct ether_addr hw_addr;
1946 uint32_t dest_address = 0;
1947 uint8_t nh_ipv6[16];
1950 uint32_t dest_if = INVALID_DESTIF;
1953 uint16_t *outport_id =
1954 RTE_MBUF_METADATA_UINT16_PTR(pkts[pkt_index],
1955 cgnapt_meta_offset);
1957 if (is_phy_port_privte(phy_port)) {
1959 if (*protocol == IP_PROTOCOL_UDP
1960 && rte_be_to_cpu_16(*dst_port) == 53) {
1961 p_nat->invalid_packets |= 1LLU << pkt_index;
1962 p_nat->naptDroppedPktCount++;
1963 #ifdef CGNAPT_DEBUGGING
1964 p_nat->naptDroppedPktCount6++;
1969 dest_address = rte_bswap32(*dst_addr);
1970 /* Gateway Proc Starts */
1972 struct arp_entry_data *ret_arp_data = NULL;
1973 uint32_t src_phy_port = *src_port;
1975 gw_get_nh_port_ipv4(dest_address,
1978 if (dest_if == INVALID_DESTIF) {
1979 p_nat->invalid_packets |=
1981 p_nat->naptDroppedPktCount++;
1982 #ifdef CGNAPT_DEBUGGING
1983 p_nat->naptDroppedPktCount6++;
1988 *outport_id = p_nat->outport_id[dest_if];
1990 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if, &hw_addr);
1992 if (unlikely(ret_arp_data == NULL)) {
1994 #ifdef CGNAPT_DEBUGGING
1995 printf("%s: NHIP Not Found, nhip: %x, "
1996 "outport_id: %d\n", __func__, nhip,
2000 p_nat->invalid_packets |= pkt_mask;
2001 p_nat->naptDroppedPktCount++;
2003 #ifdef CGNAPT_DEBUGGING
2004 p_nat->naptDroppedPktCount4++;
2009 /* Gateway Proc Ends */
2011 if (ret_arp_data->status == COMPLETE) {
2013 if (ret_arp_data->num_pkts) {
2014 p_nat->naptedPktCount += ret_arp_data->num_pkts;
2015 arp_send_buffered_pkts(ret_arp_data,
2016 &hw_addr, *outport_id);
2019 memcpy(eth_dest, &hw_addr,
2020 sizeof(struct ether_addr));
2021 memcpy(eth_src, get_link_hw_addr(dest_if),
2022 sizeof(struct ether_addr));
2023 #ifdef CGNAPT_DBG_PRNT
2024 if (CGNAPT_DEBUG > 2) {
2025 printf("MAC found for ip 0x%x, port %d - "
2026 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2027 dest_address, *outport_id,
2028 hw_addr.addr_bytes[0], hw_addr.addr_bytes[1],
2029 hw_addr.addr_bytes[2], hw_addr.addr_bytes[3],
2030 hw_addr.addr_bytes[4], hw_addr.addr_bytes[5]);
2032 printf("Dest MAC before - "
2033 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2034 eth_dest[0], eth_dest[1], eth_dest[2],
2035 eth_dest[3], eth_dest[4], eth_dest[5]);
2039 #ifdef CGNAPT_DBG_PRNT
2040 if (CGNAPT_DEBUG > 2) {
2041 printf("Dest MAC after - "
2042 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2043 eth_dest[0], eth_dest[1], eth_dest[2],
2044 eth_dest[3], eth_dest[4], eth_dest[5]);
2048 #ifdef CGNAPT_DBG_PRNT
2049 if (CGNAPT_DEBUG > 4)
2050 print_pkt(pkts[pkt_index]);
2053 } else if (ret_arp_data->status == INCOMPLETE ||
2054 ret_arp_data->status == PROBE) {
2055 if (ret_arp_data->num_pkts >= NUM_DESC) {
2057 p_nat->invalid_packets |= pkt_mask;
2058 p_nat->naptDroppedPktCount++;
2060 #ifdef CGNAPT_DEBUGGING
2061 p_nat->naptDroppedPktCount4++;
2065 arp_queue_unresolved_packet(ret_arp_data,
2071 #ifdef CGNAPT_DBG_PRNT
2072 if (CGNAPT_DEBUG > 2)
2073 printf("Egress: \tphy_port:%d\t "
2074 "get_prv_to_pub():%d \tout_port:%d\n",
2080 *src_addr = rte_bswap32(entry->data.pub_ip);
2082 #ifdef NAT_ONLY_CONFIG_REQ
2083 if (!nat_only_config_flag) {
2085 *src_port = rte_bswap16(entry->data.pub_port);
2086 #ifdef NAT_ONLY_CONFIG_REQ
2090 p_nat->enaptedPktCount++;
2093 if (*protocol == IP_PROTOCOL_UDP
2094 && rte_be_to_cpu_16(*src_port) == 53) {
2095 p_nat->invalid_packets |= 1LLU << pkt_index;
2096 p_nat->naptDroppedPktCount++;
2097 #ifdef CGNAPT_DEBUGGING
2098 p_nat->naptDroppedPktCount6++;
2103 #ifdef CGNAPT_DBG_PRNT
2104 if (CGNAPT_DEBUG > 2)
2105 printf("Ingress: \tphy_port:%d\t "
2106 "get_pub_to_prv():%d \tout_port%d\n",
2111 if (entry->data.type == CGNAPT_ENTRY_IPV6) {
2112 convert_ipv4_to_ipv6(pkts[pkt_index],
2114 pkt_type = PKT_TYPE_IPV4to6;
2115 /* Ethernet MTU check */
2116 if ((rte_pktmbuf_data_len(pkts[pkt_index]) -
2118 p_nat->invalid_packets |= pkt_mask;
2119 p_nat->naptDroppedPktCount++;
2123 eth_dest = eth_dest - 20;
2124 eth_src = eth_src - 20;
2126 dst_port_offset = DST_PRT_OFST_IP4t6;
2127 dst_addr_offset = DST_ADR_OFST_IP4t6;
2129 RTE_MBUF_METADATA_UINT32_PTR(
2133 RTE_MBUF_METADATA_UINT16_PTR(
2137 memcpy((uint8_t *) &dst_addr[0],
2138 &entry->data.u.prv_ipv6[0], 16);
2139 memset(nh_ipv6, 0, 16);
2140 struct nd_entry_data *ret_nd_data = NULL;
2142 dest_if = INVALID_DESTIF;
2144 uint32_t src_phy_port = pkts[pkt_index]->port;
2146 gw_get_nh_port_ipv6((uint8_t *) &dst_addr[0],
2147 &dest_if, &nh_ipv6[0]);
2149 ret_nd_data = get_dest_mac_addr_ipv6(&nh_ipv6[0],
2151 *outport_id = p_nat->outport_id[dest_if];
2153 if (nd_cache_dest_mac_present(dest_if)) {
2154 ether_addr_copy(get_link_hw_addr(dest_if),
2155 (struct ether_addr *)eth_src);
2156 update_nhip_access(dest_if);
2158 if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) {
2159 p_nat->naptedPktCount += ret_nd_data->num_pkts;
2160 nd_send_buffered_pkts(ret_nd_data,
2161 (struct ether_addr *)eth_dest,
2165 if (unlikely(ret_nd_data == NULL)) {
2167 #ifdef CGNAPT_DEBUGGING
2168 printf("%s: NHIP Not Found, "
2169 "outport_id: %d\n", __func__,
2174 p_nat->invalid_packets |= pkt_mask;
2175 p_nat->naptDroppedPktCount++;
2177 #ifdef CGNAPT_DEBUGGING
2178 p_nat->naptDroppedPktCount4++;
2183 if (ret_nd_data->status == INCOMPLETE ||
2184 ret_nd_data->status == PROBE) {
2185 if (ret_nd_data->num_pkts >= NUM_DESC) {
2187 p_nat->invalid_packets |= pkt_mask;
2188 p_nat->naptDroppedPktCount++;
2190 #ifdef CGNAPT_DEBUGGING
2191 p_nat->naptDroppedPktCount4++;
2195 arp_pkts_mask |= pkt_mask;
2196 nd_queue_unresolved_packet(ret_nd_data,
2204 #ifdef NAT_ONLY_CONFIG_REQ
2205 if (!nat_only_config_flag) {
2208 rte_bswap16(entry->data.prv_port);
2209 #ifdef NAT_ONLY_CONFIG_REQ
2214 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
2215 dest_address = entry->data.u.prv_ip;
2216 /* Gateway Proc Starts */
2218 struct arp_entry_data *ret_arp_data = NULL;
2219 dest_if = INVALID_DESTIF;
2220 uint32_t src_phy_port = *src_port;
2222 gw_get_nh_port_ipv4(dest_address,
2225 if (dest_if == INVALID_DESTIF) {
2226 p_nat->invalid_packets |=
2228 p_nat->naptDroppedPktCount++;
2229 #ifdef CGNAPT_DEBUGGING
2230 p_nat->naptDroppedPktCount6++;
2235 *outport_id = p_nat->outport_id[dest_if];
2237 ret_arp_data = get_dest_mac_addr_ipv4(nhip,
2238 dest_if, (struct ether_addr *)eth_dest);
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);
3700 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
3701 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
3703 if (entry->data.ttl == NAPT_ENTRY_STALE)
3704 entry->data.ttl = NAPT_ENTRY_VALID;
3706 uint32_t dest_address = 0;
3709 if (unlikely(protocol == IP_PROTOCOL_UDP
3710 && rte_be_to_cpu_16(*dst_port) == 53)) {
3711 p_nat->invalid_packets |= pkt_mask;
3712 p_nat->naptDroppedPktCount++;
3714 #ifdef CGNAPT_DEBUGGING
3715 p_nat->naptDroppedPktCount6++;
3719 last_update = rte_rdtsc();
3720 dest_address = rte_bswap32(*dst_addr);
3722 struct arp_entry_data *ret_arp_data = NULL;
3724 uint32_t src_phy_port = *src_port;
3726 gw_get_nh_port_ipv4(dest_address, &dest_if, &nhip);
3728 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if,
3729 (struct ether_addr *)eth_dest);
3731 *outport_id = p_nat->outport_id[dest_if];
3733 if (arp_cache_dest_mac_present(dest_if)) {
3734 ether_addr_copy(get_link_hw_addr(dest_if),(struct ether_addr *)eth_src);
3735 update_nhip_access(dest_if);
3736 if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) {
3737 p_nat->naptedPktCount += ret_arp_data->num_pkts;
3738 arp_send_buffered_pkts(ret_arp_data,
3739 (struct ether_addr *)eth_dest, *outport_id);
3744 if (unlikely(ret_arp_data == NULL)) {
3746 #ifdef CGNAPT_DEBUGGING
3747 printf("%s: NHIP Not Found, nhip:%x , "
3748 "outport_id: %d\n", __func__, nhip,
3753 p_nat->invalid_packets |= pkt_mask;
3754 p_nat->naptDroppedPktCount++;
3756 #ifdef CGNAPT_DEBUGGING
3757 p_nat->naptDroppedPktCount4++;
3762 if (ret_arp_data->status == INCOMPLETE ||
3763 ret_arp_data->status == PROBE) {
3764 if (ret_arp_data->num_pkts >= NUM_DESC) {
3766 p_nat->invalid_packets |= pkt_mask;
3767 p_nat->naptDroppedPktCount++;
3769 #ifdef CGNAPT_DEBUGGING
3770 p_nat->naptDroppedPktCount4++;
3774 arp_pkts_mask |= pkt_mask;
3775 arp_queue_unresolved_packet(ret_arp_data, pkt);
3784 *src_addr = rte_bswap32(entry->data.pub_ip);
3787 #ifdef NAT_ONLY_CONFIG_REQ
3788 if (!nat_only_config_flag) {
3790 *src_port = rte_bswap16(entry->data.pub_port);
3791 #ifdef NAT_ONLY_CONFIG_REQ
3796 uint16_t rtp_port = 0, rtcp_port = 0;
3797 struct cgnapt_table_entry *entry_ptr1 = NULL,
3798 *entry_ptr2 = NULL, *entry_ptr3 = NULL,
3801 if (unlikely(protocol == IP_PROTOCOL_UDP
3802 && (rte_be_to_cpu_16(*dst_port) == 5060
3803 || rte_be_to_cpu_16(*src_port) == 5060))) {
3805 int ret = natSipAlgGetAudioPorts(pkt, &rtp_port,
3807 /* Commented code may be required for debug
3808 * and future use, Please keep it*/
3811 printf("%s: Wrong SIP ALG packet1\n",
3813 p_nat->invalid_packets |= pkt_mask;
3815 p_nat->naptDroppedPktCount++;
3817 #ifdef CGNAPT_DEBUGGING
3818 p_nat->naptDroppedPktCount4++;
3824 if (ret >= 0 && rtp_port != 0) {
3825 struct pipeline_cgnapt_entry_key rtp_key;
3826 rtp_key.ip = entry->data.u.prv_ip;
3827 rtp_key.port = rtp_port;
3828 rtp_key.pid = entry->data.prv_phy_port;
3830 if (add_dynamic_cgnapt_entry_alg(
3831 (struct pipeline *)p_nat, &rtp_key,
3832 &entry_ptr1, &entry_ptr2) == 0) {
3833 printf("%s: Wrong SIP ALG packet2\n",
3835 p_nat->invalid_packets |= pkt_mask;
3837 p_nat->naptDroppedPktCount++;
3839 #ifdef CGNAPT_DEBUGGING
3840 p_nat->naptDroppedPktCount4++;
3846 if (ret >= 0 && rtcp_port != 0) {
3847 struct pipeline_cgnapt_entry_key rtcp_key;
3848 rtcp_key.ip = entry->data.u.prv_ip;
3849 rtcp_key.port = rtcp_port;
3850 rtcp_key.pid = entry->data.prv_phy_port;
3852 if (add_dynamic_cgnapt_entry_alg(
3853 (struct pipeline *)p_nat, &rtcp_key,
3854 &entry_ptr3, &entry_ptr4) == 0) {
3855 printf("%s: Wrong SIP ALG packet3\n",
3857 p_nat->invalid_packets |= pkt_mask;
3859 p_nat->naptDroppedPktCount++;
3861 #ifdef CGNAPT_DEBUGGING
3862 p_nat->naptDroppedPktCount4++;
3868 //if(entry_ptr1 != NULL && entry_ptr3 != NULL)
3869 if (sip_alg_dpi(pkt, PRIVATE, entry->data.pub_ip,
3870 entry->data.pub_port, entry->data.u.prv_ip,
3871 entry->data.prv_port, (rtp_port == 0) ? 0 :
3872 entry_ptr1->data.pub_port,
3873 (rtcp_port == 0) ? 0 :
3874 entry_ptr3->data.pub_port) == 0) {
3876 printf("%s: Wrong SIP ALG packet4\n",
3878 p_nat->invalid_packets |= pkt_mask;
3880 p_nat->naptDroppedPktCount++;
3882 #ifdef CGNAPT_DEBUGGING
3883 p_nat->naptDroppedPktCount4++;
3888 #endif /* SIP_ALG */
3893 printf("@CGNAT-pktwork ct_position :%d, pkt_num %d pkt_mask= "
3894 "%" PRIu64 "\n", ct_position, pkt_num, pkt_mask);
3897 if ((rte_be_to_cpu_16(*src_port) == 21) ||
3898 rte_be_to_cpu_16(*dst_port) == 21) {
3900 int32_t ct_position = cgnat_cnxn_tracker->positions[pkt_num];
3901 if (ct_position < 0){
3902 p_nat->invalid_packets |= pkt_mask;
3903 p_nat->naptDroppedPktCount++;
3906 /* Commented code may be required for future usage,
3909 //if (cgnat_cnxn_tracker->hash_table_entries
3910 // [ct_position].alg_bypass_flag != BYPASS)
3912 struct pipeline_cgnapt_entry_key data_channel_entry_key;
3914 data_channel_entry_key.ip = entry->data.pub_ip;
3915 data_channel_entry_key.port = entry->data.pub_port;
3916 data_channel_entry_key.pid = pkt->port;
3917 ftp_alg_dpi(p_nat, &data_channel_entry_key, pkt,
3918 cgnat_cnxn_tracker, ct_position, PRIVATE);
3921 #endif /* FTP_ALG */
3923 p_nat->enaptedPktCount++;
3926 p_nat->naptedPktCount++;
3929 if (p_nat->hw_checksum_reqd)
3930 hw_checksum(pkt, pkt_type);
3932 sw_checksum(pkt, pkt_type);
3939 * NAPT function for IPv4 public traffic which handles 1 pkt
3942 * A pointer to array of packet mbuf
3948 * A pointer to main CGNAPT structure
3952 pkt_work_cgnapt_ipv4_pub(
3953 struct rte_mbuf **pkts,
3955 __rte_unused void *arg,
3956 struct pipeline_cgnapt *p_nat)
3960 struct rte_CT_helper ct_helper;
3961 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
3964 /* index into hash table entries */
3965 int hash_table_entry = p_nat->lkup_indx[pkt_num];
3966 /*bitmask representing only this packet */
3967 uint64_t pkt_mask = 1LLU << pkt_num;
3968 struct rte_mbuf *pkt = pkts[pkt_num];
3970 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
3972 uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */
3973 uint16_t *outport_id =
3974 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
3976 struct cgnapt_table_entry *entry = NULL;
3978 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
3980 if (hash_table_entry < 0) {
3982 /* try to add new entry */
3983 struct rte_pipeline_table_entry *table_entry = NULL;
3985 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
3987 &p_nat->valid_packets, pkt_num,
3991 /* ICMP Error message generation for
3992 * Destination Host unreachable
3994 if (protocol == IP_PROTOCOL_ICMP) {
3995 cgnapt_icmp_pkt = pkt;
3996 send_icmp_dest_unreachable_msg();
3999 /* Drop packet by adding to invalid pkt mask */
4001 p_nat->invalid_packets |= dropmask;
4002 #ifdef CGNAPT_DEBUGGING
4003 if (p_nat->kpc2++ < 5) {
4004 printf("in_ah Th: %d", p_nat->pipeline_num);
4005 print_key(p_nat->key_ptrs[pkt_num]);
4009 p_nat->naptDroppedPktCount++;
4011 #ifdef CGNAPT_DEBUGGING
4012 p_nat->naptDroppedPktCount3++;
4017 entry = (struct cgnapt_table_entry *)table_entry;
4019 /* entry found for this packet */
4020 entry = &napt_hash_tbl_entries[hash_table_entry];
4023 /* apply napt and mac changes */
4025 p_nat->entries[pkt_num] = &(entry->head);
4027 uint32_t *dst_addr =
4028 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4029 uint16_t src_port_offset = 0;
4030 uint16_t dst_port_offset = 0;
4032 if ((protocol == IP_PROTOCOL_TCP) || (protocol == IP_PROTOCOL_UDP)) {
4033 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4034 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4035 } else if (protocol == IP_PROTOCOL_ICMP) {
4037 src_port_offset = MBUF_HDR_ROOM +
4040 /*Sequence number */
4041 dst_port_offset = MBUF_HDR_ROOM +
4046 uint16_t *src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
4047 uint16_t *dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
4049 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4050 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4052 if (entry->data.ttl == NAPT_ENTRY_STALE)
4053 entry->data.ttl = NAPT_ENTRY_VALID;
4055 uint32_t dest_address = 0;
4057 /* Multiport Changes */
4063 if (unlikely(protocol == IP_PROTOCOL_UDP
4064 && rte_be_to_cpu_16(*src_port) == 53)) {
4065 p_nat->invalid_packets |= pkt_mask;
4066 p_nat->naptDroppedPktCount++;
4067 #ifdef CGNAPT_DEBUGGING
4068 p_nat->naptDroppedPktCount6++;
4074 dest_address = entry->data.u.prv_ip;
4075 struct arp_entry_data *ret_arp_data = NULL;
4077 uint32_t src_phy_port = *src_port;
4079 gw_get_nh_port_ipv4(dest_address, &dest_if, &nhip);
4081 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if,
4082 (struct ether_addr *)eth_dest);
4083 *outport_id = p_nat->outport_id[dest_if];
4085 if (arp_cache_dest_mac_present(dest_if)) {
4086 ether_addr_copy(get_link_hw_addr(dest_if), (struct ether_addr *)eth_src);
4087 update_nhip_access(dest_if);
4089 if (ret_arp_data && ret_arp_data->num_pkts) {
4090 p_nat->naptedPktCount += ret_arp_data->num_pkts;
4091 arp_send_buffered_pkts(ret_arp_data,
4092 (struct ether_addr *)eth_dest, *outport_id);
4097 if (unlikely(ret_arp_data == NULL)) {
4099 /* Commented code may be required for debug
4100 * and future use, Please keep it */
4102 #ifdef CGNAPT_DEBUGGING
4103 printf("%s: NHIP Not Found, nhip: %x, "
4104 "outport_id: %d\n", __func__, nhip,
4109 p_nat->invalid_packets |= pkt_mask;
4110 p_nat->naptDroppedPktCount++;
4112 #ifdef CGNAPT_DEBUGGING
4113 p_nat->naptDroppedPktCount4++;
4119 if (ret_arp_data->status == INCOMPLETE ||
4120 ret_arp_data->status == PROBE) {
4121 if (ret_arp_data->num_pkts >= NUM_DESC) {
4123 p_nat->invalid_packets |= pkt_mask;
4124 p_nat->naptDroppedPktCount++;
4126 #ifdef CGNAPT_DEBUGGING
4127 p_nat->naptDroppedPktCount4++;
4131 arp_pkts_mask |= pkt_mask;
4132 arp_queue_unresolved_packet(ret_arp_data, pkt);
4141 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
4142 if (protocol == IP_PROTOCOL_ICMP) {
4143 /* Query ID reverse translation done here */
4144 /* dont care sequence num */
4145 *src_port = rte_bswap16(entry->data.prv_port);
4148 #ifdef NAT_ONLY_CONFIG_REQ
4149 if (!nat_only_config_flag) {
4151 *dst_port = rte_bswap16(entry->data.prv_port);
4153 #ifdef NAT_ONLY_CONFIG_REQ
4157 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4158 rte_be_to_cpu_16(*dst_port) == 21) {
4159 pkt_mask = cgnapt_ct_process(cgnat_cnxn_tracker, pkts,
4160 pkt_mask, &ct_helper);
4166 uint16_t rtp_port = 0, rtcp_port = 0;
4167 struct cgnapt_table_entry *entry_ptr1 = NULL,
4170 /* Commented code may be required for debug
4171 * and future use, Please keep it */
4173 struct cgnapt_table_entry *entry_ptr2 = NULL,
4177 if (unlikely(protocol == IP_PROTOCOL_UDP
4178 && (rte_be_to_cpu_16(*dst_port) == 5060
4179 || rte_be_to_cpu_16(*src_port) == 5060))) {
4180 /* Commented code may be required for future usage,
4184 int ret = natSipAlgGetAudioPorts(pkt, &rtp_port,
4187 printf("%s: Wrong SIP ALG packet1\n",
4189 p_nat->invalid_packets |= pkt_mask;
4191 p_nat->naptDroppedPktCount++;
4193 #ifdef CGNAPT_DEBUGGING
4194 p_nat->naptDroppedPktCount4++;
4198 if (rtp_port != 0) {
4199 struct pipeline_cgnapt_entry_key rtp_key;
4200 rtp_key.ip = entry->data.pub_ip;
4201 rtp_key.port = rtp_port;
4202 rtp_key.pid = 0xffff;
4204 if (retrieve_cgnapt_entry_alg(&rtp_key,
4205 &entry_ptr1, &entry_ptr2) == 0) {
4206 printf("%s: Wrong SIP ALG packet2\n",
4208 p_nat->invalid_packets |= pkt_mask;
4210 p_nat->naptDroppedPktCount++;
4212 #ifdef CGNAPT_DEBUGGING
4213 p_nat->naptDroppedPktCount4++;
4219 if (rtcp_port != 0) {
4220 struct pipeline_cgnapt_entry_key rtcp_key;
4221 rtcp_key.ip = entry->data.pub_ip;
4222 rtcp_key.port = rtcp_port;
4223 rtcp_key.pid = 0xffff;
4225 if (retrieve_cgnapt_entry_alg(&rtcp_key,
4226 &entry_ptr3, &entry_ptr4) == 0) {
4227 printf("%s: Wrong SIP ALG packet3\n",
4229 p_nat->invalid_packets |= pkt_mask;
4231 p_nat->naptDroppedPktCount++;
4233 #ifdef CGNAPT_DEBUGGING
4234 p_nat->naptDroppedPktCount4++;
4242 if (sip_alg_dpi(pkt, PUBLIC, entry->data.u.prv_ip,
4243 entry->data.prv_port, entry->data.pub_ip,
4244 entry->data.pub_port, (rtp_port == 0) ? 0 :
4245 entry_ptr1->data.prv_port,
4246 (rtcp_port == 0) ? 0 :
4247 entry_ptr3->data.prv_port) == 0) {
4249 printf("%s: Wrong SIP ALG packet4\n",
4251 p_nat->invalid_packets |= pkt_mask;
4253 p_nat->naptDroppedPktCount++;
4255 #ifdef CGNAPT_DEBUGGING
4256 p_nat->naptDroppedPktCount4++;
4262 #endif /* SIP_ALG */
4265 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4266 rte_be_to_cpu_16(*dst_port) == 21) {
4267 int32_t ct_position = cgnat_cnxn_tracker->
4269 if (ct_position < 0){
4270 p_nat->invalid_packets |= pkt_mask;
4272 p_nat->naptDroppedPktCount++;
4276 rte_hexdump(stdout, "CT Entry", &cgnat_cnxn_tracker->
4277 hash_table_entries[ct_position].key, 40);
4280 /* Commented code may be required for debug
4281 * and future use, Please keep it*/
4282 //if (cgnat_cnxn_tracker->hash_table_entries
4283 // [ct_position].alg_bypass_flag != BYPASS)
4286 struct pipeline_cgnapt_entry_key
4287 data_channel_entry_key;
4289 data_channel_entry_key.ip = entry->data.pub_ip;
4290 data_channel_entry_key.port = entry->data.pub_port;
4291 data_channel_entry_key.pid = 0xffff;
4292 //printf("pkt_work_pub ftp_alg_dpi\n");
4293 ftp_alg_dpi(p_nat, &data_channel_entry_key, pkt,
4294 cgnat_cnxn_tracker, ct_position, PUBLIC);
4300 p_nat->inaptedPktCount++;
4303 p_nat->naptedPktCount++;
4306 if (p_nat->hw_checksum_reqd)
4307 hw_checksum(pkt, pkt_type);
4309 sw_checksum(pkt, pkt_type);
4315 * NAPT function for IPv4 private traffic which handles 4 pkts
4318 * A pointer to array of packets mbuf
4320 * Starting pkt number of pkts
4324 * A pointer to main CGNAPT structure
4328 pkt4_work_cgnapt_ipv4_prv(
4329 struct rte_mbuf **pkts,
4330 uint32_t in_pkt_num,
4331 __rte_unused void *arg,
4332 struct pipeline_cgnapt *p_nat)
4334 uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */
4335 struct rte_mbuf *pkt;
4338 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4341 struct rte_CT_helper ct_helper;
4342 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4345 for (i = 0; i < 4; i++) {
4346 pkt_num = in_pkt_num + i;
4347 pkt = pkts[pkt_num];
4349 /* index into hash table entries */
4350 int hash_table_entry = p_nat->lkup_indx[pkt_num];
4351 /*bitmask representing only this packet */
4352 uint64_t pkt_mask = 1LLU << pkt_num;
4354 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
4356 uint16_t *outport_id =
4357 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
4359 struct cgnapt_table_entry *entry = NULL;
4361 if (hash_table_entry < 0) {
4363 /* try to add new entry */
4364 struct rte_pipeline_table_entry *table_entry = NULL;
4367 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
4369 &p_nat->valid_packets, pkt_num,
4373 /* ICMP Error message generation for
4374 * Destination Host unreachable
4376 if (protocol == IP_PROTOCOL_ICMP) {
4377 cgnapt_icmp_pkt = pkt;
4378 send_icmp_dest_unreachable_msg();
4381 /* Drop packet by adding to invalid pkt mask */
4383 p_nat->invalid_packets |= dropmask;
4385 #ifdef CGNAPT_DEBUGGING
4386 if (p_nat->kpc2++ < 5) {
4387 printf("in_ah Th: %d",
4388 p_nat->pipeline_num);
4389 print_key(p_nat->key_ptrs[pkt_num]);
4393 p_nat->naptDroppedPktCount++;
4395 #ifdef CGNAPT_DEBUGGING
4396 p_nat->naptDroppedPktCount3++;
4401 entry = (struct cgnapt_table_entry *)table_entry;
4403 /* entry found for this packet */
4404 entry = &napt_hash_tbl_entries[hash_table_entry];
4407 /* apply napt and mac changes */
4409 p_nat->entries[pkt_num] = &(entry->head);
4411 uint32_t *src_addr =
4412 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP4);
4413 uint32_t *dst_addr =
4414 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4415 uint16_t src_port_offset = 0;
4416 uint16_t dst_port_offset = 0;
4421 if ((protocol == IP_PROTOCOL_TCP)
4422 || (protocol == IP_PROTOCOL_UDP)) {
4423 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4424 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4425 } else if (protocol == IP_PROTOCOL_ICMP) {
4427 src_port_offset = MBUF_HDR_ROOM +
4430 /*Sequence number */
4431 dst_port_offset = MBUF_HDR_ROOM +
4438 case IP_PROTOCOL_TCP:
4439 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4440 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4441 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4443 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4447 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4448 rte_be_to_cpu_16(*dst_port) == 21) {
4450 //To process CT , pkt_mask does it need
4451 //to be complemented ??
4453 printf("cgnapt_ct_process: pkt_mask: "
4454 "% "PRIu64", pkt_num: %d\n",
4458 pkt_mask = cgnapt_ct_process(
4459 cgnat_cnxn_tracker, pkts,
4460 pkt_mask, &ct_helper);
4464 case IP_PROTOCOL_UDP:
4465 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4466 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4467 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4469 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4472 case IP_PROTOCOL_ICMP:
4474 src_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
4476 /*Sequence number */
4477 dst_port_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
4479 src_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4481 dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
4488 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4490 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4492 if (entry->data.ttl == NAPT_ENTRY_STALE)
4493 entry->data.ttl = NAPT_ENTRY_VALID;
4495 uint32_t dest_address = 0;
4496 /*Multiport Changes */
4503 if (unlikely(protocol == IP_PROTOCOL_UDP
4504 && rte_be_to_cpu_16(*dst_port) == 53)) {
4505 p_nat->invalid_packets |= pkt_mask;
4506 p_nat->naptDroppedPktCount++;
4508 #ifdef CGNAPT_DEBUGGING
4509 p_nat->naptDroppedPktCount6++;
4515 dest_address = rte_bswap32(*dst_addr);
4516 struct arp_entry_data *ret_arp_data = NULL;
4517 uint64_t start, end;
4518 uint32_t src_phy_port = *src_port;
4520 gw_get_nh_port_ipv4(dest_address, &dest_if, &nhip);
4522 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if,
4523 (struct ether_addr *)eth_dest);
4525 *outport_id = p_nat->outport_id[dest_if];
4527 if (arp_cache_dest_mac_present(dest_if)) {
4528 ether_addr_copy(get_link_hw_addr(dest_if),
4529 (struct ether_addr *)eth_src);
4530 update_nhip_access(dest_if);
4532 if (ret_arp_data && ret_arp_data->num_pkts) {
4533 p_nat->naptedPktCount += ret_arp_data->num_pkts;
4534 arp_send_buffered_pkts(ret_arp_data,
4535 (struct ether_addr *)eth_dest, *outport_id);
4540 if (unlikely(ret_arp_data == NULL)) {
4542 #ifdef CGNAPT_DEBUGGING
4543 printf("%s: ARP Not Found, nhip: %x, "
4544 "outport_id: %d\n", __func__, nhip,
4549 p_nat->invalid_packets |= pkt_mask;
4550 p_nat->naptDroppedPktCount++;
4552 #ifdef CGNAPT_DEBUGGING
4553 p_nat->naptDroppedPktCount4++;
4559 if (ret_arp_data->status == INCOMPLETE ||
4560 ret_arp_data->status == PROBE) {
4561 if (ret_arp_data->num_pkts >= NUM_DESC) {
4563 p_nat->invalid_packets |= pkt_mask;
4564 p_nat->naptDroppedPktCount++;
4566 #ifdef CGNAPT_DEBUGGING
4567 p_nat->naptDroppedPktCount4++;
4571 arp_pkts_mask |= pkt_mask;
4572 arp_queue_unresolved_packet(ret_arp_data, pkt);
4580 *src_addr = rte_bswap32(entry->data.pub_ip);
4582 #ifdef NAT_ONLY_CONFIG_REQ
4583 if (!nat_only_config_flag) {
4585 *src_port = rte_bswap16(entry->data.pub_port);
4586 #ifdef NAT_ONLY_CONFIG_REQ
4591 uint16_t rtp_port = 0, rtcp_port = 0;
4592 struct cgnapt_table_entry *entry_ptr1 = NULL,
4593 *entry_ptr2 = NULL, *entry_ptr3 = NULL,
4596 if (unlikely(protocol == IP_PROTOCOL_UDP
4597 && (rte_be_to_cpu_16(*dst_port) == 5060
4598 || rte_be_to_cpu_16(*src_port) == 5060))) {
4600 int ret = natSipAlgGetAudioPorts(pkt,
4601 &rtp_port, &rtcp_port);
4602 /* Commented code may be required for future usage,
4607 printf("%s: Wrong SIP ALG packet1\n",
4609 p_nat->invalid_packets |= pkt_mask;
4611 p_nat->naptDroppedPktCount++;
4613 #ifdef CGNAPT_DEBUGGING
4614 p_nat->naptDroppedPktCount4++;
4620 if (ret >= 0 && rtp_port != 0) {
4621 struct pipeline_cgnapt_entry_key rtp_key;
4622 rtp_key.ip = entry->data.u.prv_ip;
4623 rtp_key.port = rtp_port;
4624 rtp_key.pid = entry->data.prv_phy_port;
4626 if (add_dynamic_cgnapt_entry_alg(
4627 (struct pipeline *)p_nat, &rtp_key,
4628 &entry_ptr1, &entry_ptr2) == 0) {
4629 printf("%s: Wrong SIP ALG packet2\n",
4631 p_nat->invalid_packets |= pkt_mask;
4633 p_nat->naptDroppedPktCount++;
4635 #ifdef CGNAPT_DEBUGGING
4636 p_nat->naptDroppedPktCount4++;
4642 if (ret >= 0 && rtcp_port != 0) {
4643 struct pipeline_cgnapt_entry_key rtcp_key;
4644 rtcp_key.ip = entry->data.u.prv_ip;
4645 rtcp_key.port = rtcp_port;
4646 rtcp_key.pid = entry->data.prv_phy_port;
4648 if (add_dynamic_cgnapt_entry_alg(
4649 (struct pipeline *)p_nat, &rtcp_key,
4650 &entry_ptr3, &entry_ptr4) == 0) {
4652 printf("%s: Wrong SIP ALG packet3\n",
4654 p_nat->invalid_packets |= pkt_mask;
4656 p_nat->naptDroppedPktCount++;
4658 #ifdef CGNAPT_DEBUGGING
4659 p_nat->naptDroppedPktCount4++;
4665 //if(entry_ptr1 != NULL && entry_ptr3 != NULL)
4666 if (sip_alg_dpi(pkt, PRIVATE,
4668 entry->data.pub_port,
4669 entry->data.u.prv_ip,
4670 entry->data.prv_port,
4671 (rtp_port == 0) ? 0 :
4672 entry_ptr1->data.pub_port,
4673 (rtcp_port == 0) ? 0 :
4674 entry_ptr3->data.pub_port) == 0) {
4676 printf("%s: Wrong SIP ALG packet4\n",
4678 p_nat->invalid_packets |= pkt_mask;
4680 p_nat->naptDroppedPktCount++;
4682 #ifdef CGNAPT_DEBUGGING
4683 p_nat->naptDroppedPktCount4++;
4688 #endif /* SIP_ALG */
4691 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4692 rte_be_to_cpu_16(*dst_port) == 21) {
4694 int32_t ct_position =
4695 cgnat_cnxn_tracker->positions[pkt_num];
4697 printf("@CGNAT-pkt4work ct_position :%d, pkt_num %d "
4698 "pkt_mask = %" PRIu64 "\n", ct_position,
4702 if (ct_position < 0){
4703 p_nat->invalid_packets |= pkt_mask;
4704 p_nat->naptDroppedPktCount++;
4707 if (cgnat_cnxn_tracker->hash_table_entries[ct_position].
4708 alg_bypass_flag != BYPASS){
4710 struct pipeline_cgnapt_entry_key
4711 data_channel_entry_key;
4713 data_channel_entry_key.ip =
4715 data_channel_entry_key.port =
4716 entry->data.pub_port;
4717 data_channel_entry_key.pid = 0xffff;
4719 ftp_alg_dpi(p_nat, &data_channel_entry_key,
4720 pkt, cgnat_cnxn_tracker, ct_position,
4726 p_nat->enaptedPktCount++;
4729 p_nat->naptedPktCount++;
4732 if (p_nat->hw_checksum_reqd)
4733 hw_checksum(pkt, pkt_type);
4735 sw_checksum(pkt, pkt_type);
4741 * NAPT function for IPv4 public traffic which handles 4 pkts
4744 * A pointer to array of packets mbuf
4746 * Starting pkt number of pkts
4750 * A pointer to main CGNAPT structure
4754 pkt4_work_cgnapt_ipv4_pub(
4755 struct rte_mbuf **pkts,
4756 uint32_t in_pkt_num,
4757 __rte_unused void *arg,
4758 struct pipeline_cgnapt *p_nat)
4761 struct rte_CT_helper ct_helper;
4762 memset(&ct_helper, 0, sizeof(struct rte_CT_helper));
4764 struct rte_mbuf *pkt;
4767 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4;
4769 for (i = 0; i < 4; i++) {
4770 pkt_num = in_pkt_num + i;
4771 pkt = pkts[pkt_num];
4773 /* index into hash table entries */
4774 int hash_table_entry = p_nat->lkup_indx[pkt_num];
4775 /*bitmask representing only this packet */
4776 uint64_t pkt_mask = 1LLU << pkt_num;
4778 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
4780 uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */
4781 uint16_t *outport_id =
4782 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
4784 struct cgnapt_table_entry *entry = NULL;
4786 if (hash_table_entry < 0) {
4788 /* try to add new entry */
4789 struct rte_pipeline_table_entry *table_entry = NULL;
4792 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
4794 &p_nat->valid_packets, pkt_num,
4798 /* ICMP Error message generation for
4799 * Destination Host unreachable
4801 if (protocol == IP_PROTOCOL_ICMP) {
4802 cgnapt_icmp_pkt = pkt;
4803 send_icmp_dest_unreachable_msg();
4806 /* Drop packet by adding to invalid pkt mask */
4808 p_nat->invalid_packets |= dropmask;
4810 #ifdef CGNAPT_DEBUGGING
4811 if (p_nat->kpc2++ < 5) {
4812 printf("in_ah Th: %d",
4813 p_nat->pipeline_num);
4814 print_key(p_nat->key_ptrs[pkt_num]);
4818 p_nat->naptDroppedPktCount++;
4820 #ifdef CGNAPT_DEBUGGING
4821 p_nat->naptDroppedPktCount3++;
4826 entry = (struct cgnapt_table_entry *)table_entry;
4828 /* entry found for this packet */
4829 entry = &napt_hash_tbl_entries[hash_table_entry];
4832 /* apply napt and mac changes */
4834 p_nat->entries[pkt_num] = &(entry->head);
4836 uint32_t *dst_addr =
4837 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4);
4838 uint16_t src_port_offset = 0;
4839 uint16_t dst_port_offset = 0;
4841 if ((protocol == IP_PROTOCOL_TCP)
4842 || (protocol == IP_PROTOCOL_UDP)) {
4843 src_port_offset = SRC_PRT_OFST_IP4_TCP;
4844 dst_port_offset = DST_PRT_OFST_IP4_TCP;
4845 } else if (protocol == IP_PROTOCOL_ICMP) {
4847 src_port_offset = MBUF_HDR_ROOM +
4850 /*Sequence number */
4851 dst_port_offset = MBUF_HDR_ROOM +
4856 uint16_t *src_port =
4857 RTE_MBUF_METADATA_UINT16_PTR(pkt, src_port_offset);
4858 uint16_t *dst_port =
4859 RTE_MBUF_METADATA_UINT16_PTR(pkt, dst_port_offset);
4862 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
4864 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
4866 if (entry->data.ttl == NAPT_ENTRY_STALE)
4867 entry->data.ttl = NAPT_ENTRY_VALID;
4869 uint32_t dest_address = 0;
4870 /* Multiport Changes */
4876 if (unlikely(protocol == IP_PROTOCOL_UDP
4877 && rte_be_to_cpu_16(*src_port) == 53)) {
4878 p_nat->invalid_packets |= pkt_mask;
4879 p_nat->naptDroppedPktCount++;
4880 #ifdef CGNAPT_DEBUGGING
4881 p_nat->naptDroppedPktCount6++;
4886 dest_address = entry->data.u.prv_ip;
4887 struct arp_entry_data *ret_arp_data = NULL;
4888 uint32_t src_phy_port = *src_port;
4890 gw_get_nh_port_ipv4(dest_address, &dest_if, &nhip);
4892 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if,
4893 (struct ether_addr *)eth_dest);
4895 *outport_id = p_nat->outport_id[dest_if];
4897 if (arp_cache_dest_mac_present(dest_if)) {
4898 ether_addr_copy(get_link_hw_addr(dest_if),
4899 (struct ether_addr *)eth_src);
4900 update_nhip_access(dest_if);
4902 if (ret_arp_data && ret_arp_data->num_pkts) {
4903 p_nat->naptedPktCount += ret_arp_data->num_pkts;
4904 arp_send_buffered_pkts(ret_arp_data,
4905 (struct ether_addr *)eth_dest, *outport_id);
4910 if (unlikely(ret_arp_data == NULL)) {
4912 #ifdef CGNAPT_DEBUGGING
4913 printf("%s: NHIP Not Found, nhip: %x, "
4914 "outport_id: %d\n", __func__, nhip,
4919 p_nat->invalid_packets |= pkt_mask;
4920 p_nat->naptDroppedPktCount++;
4922 #ifdef CGNAPT_DEBUGGING
4923 p_nat->naptDroppedPktCount4++;
4928 if (ret_arp_data->status == INCOMPLETE ||
4929 ret_arp_data->status == PROBE) {
4930 if (ret_arp_data->num_pkts >= NUM_DESC) {
4932 p_nat->invalid_packets |= pkt_mask;
4933 p_nat->naptDroppedPktCount++;
4935 #ifdef CGNAPT_DEBUGGING
4936 p_nat->naptDroppedPktCount4++;
4940 arp_pkts_mask |= pkt_mask;
4941 arp_queue_unresolved_packet(ret_arp_data, pkt);
4950 *dst_addr = rte_bswap32(entry->data.u.prv_ip);
4951 if (protocol == IP_PROTOCOL_ICMP) {
4952 /* Query ID reverse translation done here */
4953 *src_port = rte_bswap16(entry->data.prv_port);
4954 /* dont care sequence num */
4956 #ifdef NAT_ONLY_CONFIG_REQ
4957 if (!nat_only_config_flag) {
4960 rte_bswap16(entry->data.prv_port);
4961 #ifdef NAT_ONLY_CONFIG_REQ
4966 if ((rte_be_to_cpu_16(*src_port) == 21) ||
4967 rte_be_to_cpu_16(*dst_port) == 21) {
4968 pkt_mask = cgnapt_ct_process(
4969 cgnat_cnxn_tracker, pkts,
4970 pkt_mask, &ct_helper);
4976 uint16_t rtp_port = 0, rtcp_port = 0;
4977 struct cgnapt_table_entry *entry_ptr1 = NULL,
4979 /* Commented code may be required for future usage,
4983 struct cgnapt_table_entry *entry_ptr2 = NULL,
4987 if (unlikely(protocol == IP_PROTOCOL_UDP
4988 && (rte_be_to_cpu_16(*dst_port) == 5060
4989 || rte_be_to_cpu_16(*src_port) == 5060))) {
4990 /* Commented code may be required for future usage,
4994 int ret = natSipAlgGetAudioPorts(pkt,
4995 &rtp_port, &rtcp_port);
4997 printf("%s: Wrong SIP ALG packet1\n",
4999 p_nat->invalid_packets |= pkt_mask;
5001 p_nat->naptDroppedPktCount++;
5003 #ifdef CGNAPT_DEBUGGING
5004 p_nat->naptDroppedPktCount4++;
5009 if (rtp_port != 0) {
5010 struct pipeline_cgnapt_entry_key rtp_key;
5011 rtp_key.ip = entry->data.pub_ip;
5012 rtp_key.port = rtp_port;
5013 rtp_key.pid = 0xffff;
5015 if (retrieve_cgnapt_entry_alg(&rtp_key,
5016 &entry_ptr1, &entry_ptr2) == 0) {
5017 printf("%s: Wrong SIP ALG packet2\n",
5019 p_nat->invalid_packets |= pkt_mask;
5021 p_nat->naptDroppedPktCount++;
5023 #ifdef CGNAPT_DEBUGGING
5024 p_nat->naptDroppedPktCount4++;
5030 if (rtcp_port != 0) {
5031 struct pipeline_cgnapt_entry_key rtcp_key;
5032 rtcp_key.ip = entry->data.pub_ip;
5033 rtcp_key.port = rtcp_port;
5034 rtcp_key.pid = 0xffff;
5036 if (retrieve_cgnapt_entry_alg(&rtcp_key,
5037 &entry_ptr3, &entry_ptr4) == 0) {
5038 printf("%s: Wrong SIP ALG packet3\n",
5040 p_nat->invalid_packets |= pkt_mask;
5041 p_nat->naptDroppedPktCount++;
5043 #ifdef CGNAPT_DEBUGGING
5044 p_nat->naptDroppedPktCount4++;
5051 if (sip_alg_dpi(pkt, PUBLIC,
5052 entry->data.u.prv_ip,
5053 entry->data.prv_port,
5055 entry->data.pub_port,
5056 (rtp_port == 0) ? 0 :
5057 entry_ptr1->data.prv_port,
5058 (rtcp_port == 0) ? 0 :
5059 entry_ptr3->data.prv_port) == 0) {
5061 printf("%s: Wrong SIP ALG packet4\n",
5063 p_nat->invalid_packets |= pkt_mask;
5065 p_nat->naptDroppedPktCount++;
5067 #ifdef CGNAPT_DEBUGGING
5068 p_nat->naptDroppedPktCount4++;
5073 #endif /* SIP_ALG */
5076 if ((rte_be_to_cpu_16(*src_port) == 21) ||
5077 rte_be_to_cpu_16(*dst_port) == 21) {
5079 int32_t ct_position =
5080 cgnat_cnxn_tracker->positions[pkt_num];
5081 if (ct_position < 0){
5082 p_nat->invalid_packets |= pkt_mask;
5084 p_nat->naptDroppedPktCount++;
5087 if (cgnat_cnxn_tracker->hash_table_entries
5088 [ct_position].alg_bypass_flag != BYPASS){
5090 struct pipeline_cgnapt_entry_key
5091 data_channel_entry_key;
5094 data_channel_entry_key.ip =
5096 data_channel_entry_key.port =
5097 entry->data.pub_port;
5098 data_channel_entry_key.pid = 0xffff;
5100 ftp_alg_dpi(p_nat, &data_channel_entry_key,
5101 pkt, cgnat_cnxn_tracker,
5102 ct_position, PUBLIC);
5107 p_nat->inaptedPktCount++;
5110 p_nat->naptedPktCount++;
5113 if (p_nat->hw_checksum_reqd)
5114 hw_checksum(pkt, pkt_type);
5116 sw_checksum(pkt, pkt_type);
5122 * NAPT key calculation function for IPv6 private traffic
5123 * which handles 1 pkt
5126 * A pointer to array of packets mbuf
5128 * Pkt number of pkts
5132 * A pointer to main CGNAPT structure
5136 pkt_work_cgnapt_key_ipv6_prv(
5137 struct rte_mbuf *pkt,
5139 __rte_unused void *arg,
5140 struct pipeline_cgnapt *p_nat)
5143 p_nat->receivedPktCount++;
5145 /* bitmask representing only this packet */
5146 uint64_t pkt_mask = 1LLU << pkt_num;
5148 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
5149 uint32_t *src_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
5151 uint16_t src_port = RTE_MBUF_METADATA_UINT16(pkt, SRC_PRT_OFST_IP6);
5153 uint16_t phy_port = pkt->port;
5154 struct pipeline_cgnapt_entry_key key;
5156 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
5158 #ifdef CGNAPT_DBG_PRNT
5159 if (CGNAPT_DEBUG > 4)
5164 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
5169 case IP_PROTOCOL_UDP:
5173 struct udp_hdr *udp;
5175 udp = (struct udp_hdr *)
5176 RTE_MBUF_METADATA_UINT8_PTR(pkt,
5179 if (rte_bswap16(udp->dst_port) ==
5181 handle_pcp_req(pkt, IPV6_SZ, p_nat);
5182 p_nat->invalid_packets |= pkt_mask;
5188 case IP_PROTOCOL_TCP:
5189 case IP_PROTOCOL_ICMP:
5190 /*we don't need icmp check in ipv6 */
5194 printf("wrong protocol: %d\n", protocol);
5195 /* remember invalid packets to be dropped */
5196 p_nat->invalid_packets |= pkt_mask;
5197 p_nat->naptDroppedPktCount++;
5199 #ifdef CGNAPT_DEBUGGING
5200 p_nat->naptDroppedPktCount2++;
5206 key.ip = rte_bswap32(src_addr[3]);
5207 key.port = rte_bswap16(src_port);
5209 #ifdef NAT_ONLY_CONFIG_REQ
5210 if (nat_only_config_flag)
5214 memcpy(&p_nat->keys[pkt_num], &key,
5215 sizeof(struct pipeline_cgnapt_entry_key));
5216 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5220 * NAPT key calculation function for IPv6 public traffic
5221 * which handles 1 pkt
5224 * A pointer to array of packets mbuf
5226 * Pkt number of pkts
5230 * A pointer to main CGNAPT structure
5234 pkt_work_cgnapt_key_ipv6_pub(
5235 struct rte_mbuf *pkt,
5237 __rte_unused void *arg,
5238 struct pipeline_cgnapt *p_nat)
5242 p_nat->receivedPktCount++;
5244 /* bitmask representing only this packet */
5245 uint64_t pkt_mask = 1LLU << pkt_num;
5247 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
5249 uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
5251 uint16_t dst_port = RTE_MBUF_METADATA_UINT16(pkt,
5252 DST_PRT_OFST_IP4_TCP);
5254 struct pipeline_cgnapt_entry_key key;
5256 memset(&key, 0, sizeof(struct pipeline_cgnapt_entry_key));
5258 #ifdef CGNAPT_DBG_PRNT
5259 if (CGNAPT_DEBUG > 4)
5264 if (!check_arp_icmp(pkt, pkt_mask, p_nat))
5270 case IP_PROTOCOL_UDP:
5271 case IP_PROTOCOL_TCP:
5272 case IP_PROTOCOL_ICMP:
5273 /*we don't need icmp check in ipv6 */
5277 /* remember invalid packets to be dropped */
5278 p_nat->invalid_packets |= pkt_mask;
5279 p_nat->naptDroppedPktCount++;
5281 #ifdef CGNAPT_DEBUGGING
5282 p_nat->naptDroppedPktCount2++;
5288 key.ip = rte_bswap32(dst_addr[0]);
5289 key.port = rte_bswap16(dst_port);
5291 #ifdef NAT_ONLY_CONFIG_REQ
5292 if (nat_only_config_flag)
5296 memcpy(&p_nat->keys[pkt_num], &key,
5297 sizeof(struct pipeline_cgnapt_entry_key));
5298 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5302 * NAPT key calculation function for IPv6 private traffic
5303 * which handles 4 pkts
5306 * A pointer to array of packets mbuf
5308 * Starting pkt number of pkts
5312 * A pointer to main CGNAPT structure
5316 pkt4_work_cgnapt_key_ipv6_prv(
5317 struct rte_mbuf **pkt,
5319 __rte_unused void *arg,
5320 struct pipeline_cgnapt *p_nat)
5322 p_nat->receivedPktCount += 4;
5324 /* bitmask representing only this packet */
5325 uint64_t pkt_mask0 = 1LLU << pkt_num;
5326 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
5327 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
5328 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
5330 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
5332 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
5334 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
5336 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
5339 uint32_t *src_addr0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0],
5341 uint32_t *src_addr1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1],
5343 uint32_t *src_addr2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2],
5345 uint32_t *src_addr3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3],
5348 uint16_t src_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
5350 uint16_t src_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
5352 uint16_t src_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
5354 uint16_t src_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
5357 uint16_t phy_port0 = pkt[0]->port;
5358 uint16_t phy_port1 = pkt[1]->port;
5359 uint16_t phy_port2 = pkt[2]->port;
5360 uint16_t phy_port3 = pkt[3]->port;
5362 struct pipeline_cgnapt_entry_key key0;
5363 struct pipeline_cgnapt_entry_key key1;
5364 struct pipeline_cgnapt_entry_key key2;
5365 struct pipeline_cgnapt_entry_key key3;
5367 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
5368 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
5369 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
5370 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
5374 #ifdef CGNAPT_DBG_PRNT
5375 if (CGNAPT_DEBUG > 4)
5380 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
5384 switch (protocol0) {
5386 case IP_PROTOCOL_UDP:
5390 struct udp_hdr *udp;
5392 udp = (struct udp_hdr *)
5393 RTE_MBUF_METADATA_UINT8_PTR(pkt[0],
5396 if (rte_bswap16(udp->dst_port) ==
5398 handle_pcp_req(pkt[0], IPV6_SZ, p_nat);
5399 p_nat->invalid_packets |= pkt_mask0;
5405 case IP_PROTOCOL_TCP:
5406 case IP_PROTOCOL_ICMP:
5407 /*we don't need icmp check in ipv6 */
5411 /* remember invalid packets to be dropped */
5412 p_nat->invalid_packets |= pkt_mask0;
5413 p_nat->naptDroppedPktCount++;
5415 #ifdef CGNAPT_DEBUGGING
5416 p_nat->naptDroppedPktCount2++;
5423 key0.pid = phy_port0;
5424 key0.ip = rte_bswap32(src_addr0[3]);
5425 key0.port = rte_bswap16(src_port0);
5427 #ifdef NAT_ONLY_CONFIG_REQ
5428 if (nat_only_config_flag)
5432 memcpy(&p_nat->keys[pkt_num], &key0,
5433 sizeof(struct pipeline_cgnapt_entry_key));
5434 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5437 #ifdef CGNAPT_DBG_PRNT
5438 if (CGNAPT_DEBUG > 4)
5443 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
5447 switch (protocol1) {
5448 case IP_PROTOCOL_UDP:
5452 struct udp_hdr *udp;
5454 udp = (struct udp_hdr *)
5455 RTE_MBUF_METADATA_UINT8_PTR(pkt[1],
5458 if (rte_bswap16(udp->dst_port) ==
5460 handle_pcp_req(pkt[1], IPV6_SZ, p_nat);
5461 p_nat->invalid_packets |= pkt_mask1;
5467 case IP_PROTOCOL_TCP:
5468 case IP_PROTOCOL_ICMP:
5469 /*we don't need icmp check in ipv6 */
5473 /* remember invalid packets to be dropped */
5474 p_nat->invalid_packets |= pkt_mask1;
5475 p_nat->naptDroppedPktCount++;
5477 #ifdef CGNAPT_DEBUGGING
5478 p_nat->naptDroppedPktCount2++;
5484 key1.pid = phy_port1;
5485 key1.ip = rte_bswap32(src_addr1[3]);
5486 key1.port = rte_bswap16(src_port1);
5488 #ifdef NAT_ONLY_CONFIG_REQ
5489 if (nat_only_config_flag)
5493 memcpy(&p_nat->keys[pkt_num + 1], &key1,
5494 sizeof(struct pipeline_cgnapt_entry_key));
5495 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
5498 #ifdef CGNAPT_DBG_PRNT
5499 if (CGNAPT_DEBUG > 4)
5504 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
5508 switch (protocol2) {
5509 case IP_PROTOCOL_UDP:
5513 struct udp_hdr *udp;
5515 udp = (struct udp_hdr *)
5516 RTE_MBUF_METADATA_UINT8_PTR(pkt[2],
5519 if (rte_bswap16(udp->dst_port) ==
5521 handle_pcp_req(pkt[2], IPV6_SZ, p_nat);
5522 p_nat->invalid_packets |= pkt_mask2;
5528 case IP_PROTOCOL_TCP:
5529 case IP_PROTOCOL_ICMP:
5530 /*we don't need icmp check in ipv6 */
5534 /* remember invalid packets to be dropped */
5535 p_nat->invalid_packets |= pkt_mask2;
5536 p_nat->naptDroppedPktCount++;
5538 #ifdef CGNAPT_DEBUGGING
5539 p_nat->naptDroppedPktCount2++;
5545 key2.pid = phy_port2;
5546 key2.ip = rte_bswap32(src_addr2[3]);
5547 key2.port = rte_bswap16(src_port2);
5549 #ifdef NAT_ONLY_CONFIG_REQ
5550 if (nat_only_config_flag)
5554 memcpy(&p_nat->keys[pkt_num + 2], &key2,
5555 sizeof(struct pipeline_cgnapt_entry_key));
5556 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
5559 #ifdef CGNAPT_DBG_PRNT
5560 if (CGNAPT_DEBUG > 4)
5565 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
5569 switch (protocol3) {
5570 case IP_PROTOCOL_UDP:
5574 struct udp_hdr *udp;
5576 udp = (struct udp_hdr *)
5577 RTE_MBUF_METADATA_UINT8_PTR(pkt[3],
5580 if (rte_bswap16(udp->dst_port) ==
5582 handle_pcp_req(pkt[3], IPV6_SZ, p_nat);
5583 p_nat->invalid_packets |= pkt_mask3;
5589 case IP_PROTOCOL_TCP:
5590 case IP_PROTOCOL_ICMP:
5591 /*we don't need icmp check in ipv6 */
5595 /* remember invalid packets to be dropped */
5596 p_nat->invalid_packets |= pkt_mask2;
5597 p_nat->naptDroppedPktCount++;
5599 #ifdef CGNAPT_DEBUGGING
5600 p_nat->naptDroppedPktCount2++;
5606 key3.pid = phy_port3;
5607 key3.ip = rte_bswap32(src_addr3[3]);
5608 key3.port = rte_bswap16(src_port3);
5610 #ifdef NAT_ONLY_CONFIG_REQ
5611 if (nat_only_config_flag)
5615 memcpy(&p_nat->keys[pkt_num + 3], &key3,
5616 sizeof(struct pipeline_cgnapt_entry_key));
5617 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
5623 * NAPT key calculation function for IPv4 public traffic
5624 * which handles 4 pkts
5627 * A pointer to array of packets mbuf
5629 * Starting pkt number of pkts
5633 * A pointer to main CGNAPT structure
5637 pkt4_work_cgnapt_key_ipv6_pub(
5638 struct rte_mbuf **pkt,
5640 __rte_unused void *arg,
5641 struct pipeline_cgnapt *p_nat)
5643 p_nat->receivedPktCount += 4;
5645 /* bitmask representing only this packet */
5646 uint64_t pkt_mask0 = 1LLU << pkt_num;
5647 uint64_t pkt_mask1 = 1LLU << (pkt_num + 1);
5648 uint64_t pkt_mask2 = 1LLU << (pkt_num + 2);
5649 uint64_t pkt_mask3 = 1LLU << (pkt_num + 3);
5651 uint8_t protocol0 = RTE_MBUF_METADATA_UINT8(pkt[0],
5653 uint8_t protocol1 = RTE_MBUF_METADATA_UINT8(pkt[1],
5655 uint8_t protocol2 = RTE_MBUF_METADATA_UINT8(pkt[2],
5657 uint8_t protocol3 = RTE_MBUF_METADATA_UINT8(pkt[3],
5660 uint32_t *dst_addr0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0],
5662 uint32_t *dst_addr1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1],
5664 uint32_t *dst_addr2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2],
5666 uint32_t *dst_addr3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3],
5669 uint16_t dst_port0 = RTE_MBUF_METADATA_UINT16(pkt[0],
5670 DST_PRT_OFST_IP4_TCP);
5671 uint16_t dst_port1 = RTE_MBUF_METADATA_UINT16(pkt[1],
5672 DST_PRT_OFST_IP4_TCP);
5673 uint16_t dst_port2 = RTE_MBUF_METADATA_UINT16(pkt[2],
5674 DST_PRT_OFST_IP4_TCP);
5675 uint16_t dst_port3 = RTE_MBUF_METADATA_UINT16(pkt[3],
5676 DST_PRT_OFST_IP4_TCP);
5678 struct pipeline_cgnapt_entry_key key0;
5679 struct pipeline_cgnapt_entry_key key1;
5680 struct pipeline_cgnapt_entry_key key2;
5681 struct pipeline_cgnapt_entry_key key3;
5683 memset(&key0, 0, sizeof(struct pipeline_cgnapt_entry_key));
5684 memset(&key1, 0, sizeof(struct pipeline_cgnapt_entry_key));
5685 memset(&key2, 0, sizeof(struct pipeline_cgnapt_entry_key));
5686 memset(&key3, 0, sizeof(struct pipeline_cgnapt_entry_key));
5690 #ifdef CGNAPT_DBG_PRNT
5691 if (CGNAPT_DEBUG > 4)
5696 if (!check_arp_icmp(pkt[0], pkt_mask0, p_nat))
5700 switch (protocol0) {
5702 case IP_PROTOCOL_TCP:
5703 case IP_PROTOCOL_UDP:
5704 case IP_PROTOCOL_ICMP:
5705 /*we don't need icmp check in ipv6 */
5709 /* remember invalid packets to be dropped */
5710 p_nat->invalid_packets |= pkt_mask0;
5711 p_nat->naptDroppedPktCount++;
5713 #ifdef CGNAPT_DEBUGGING
5714 p_nat->naptDroppedPktCount2++;
5720 key0.ip = rte_bswap32(dst_addr0[0]);
5721 key0.port = rte_bswap16(dst_port0);
5723 #ifdef NAT_ONLY_CONFIG_REQ
5724 if (nat_only_config_flag)
5728 memcpy(&p_nat->keys[pkt_num], &key0,
5729 sizeof(struct pipeline_cgnapt_entry_key));
5730 p_nat->key_ptrs[pkt_num] = &p_nat->keys[pkt_num];
5736 #ifdef CGNAPT_DBG_PRNT
5737 if (CGNAPT_DEBUG > 4)
5742 if (!check_arp_icmp(pkt[1], pkt_mask1, p_nat))
5746 switch (protocol1) {
5748 case IP_PROTOCOL_TCP:
5749 case IP_PROTOCOL_UDP:
5750 case IP_PROTOCOL_ICMP:
5751 /*we don't need icmp check in ipv6 */
5755 /* remember invalid packets to be dropped */
5756 p_nat->invalid_packets |= pkt_mask1;
5757 p_nat->naptDroppedPktCount++;
5759 #ifdef CGNAPT_DEBUGGING
5760 p_nat->naptDroppedPktCount2++;
5766 key1.ip = rte_bswap32(dst_addr1[0]);
5767 key1.port = rte_bswap16(dst_port1);
5769 #ifdef NAT_ONLY_CONFIG_REQ
5770 if (nat_only_config_flag)
5774 memcpy(&p_nat->keys[pkt_num + 1], &key1,
5775 sizeof(struct pipeline_cgnapt_entry_key));
5776 p_nat->key_ptrs[pkt_num + 1] = &p_nat->keys[pkt_num + 1];
5782 #ifdef CGNAPT_DBG_PRNT
5783 if (CGNAPT_DEBUG > 4)
5788 if (!check_arp_icmp(pkt[2], pkt_mask2, p_nat))
5792 switch (protocol2) {
5794 case IP_PROTOCOL_TCP:
5795 case IP_PROTOCOL_UDP:
5796 case IP_PROTOCOL_ICMP:
5797 /*we don't need icmp check in ipv6 */
5801 /* remember invalid packets to be dropped */
5802 p_nat->invalid_packets |= pkt_mask2;
5803 p_nat->naptDroppedPktCount++;
5805 #ifdef CGNAPT_DEBUGGING
5806 p_nat->naptDroppedPktCount2++;
5812 key2.ip = rte_bswap32(dst_addr2[0]);
5813 key2.port = rte_bswap16(dst_port2);
5815 #ifdef NAT_ONLY_CONFIG_REQ
5816 if (nat_only_config_flag)
5820 memcpy(&p_nat->keys[pkt_num + 2], &key2,
5821 sizeof(struct pipeline_cgnapt_entry_key));
5823 p_nat->key_ptrs[pkt_num + 2] = &p_nat->keys[pkt_num + 2];
5829 #ifdef CGNAPT_DBG_PRNT
5830 if (CGNAPT_DEBUG > 4)
5835 if (!check_arp_icmp(pkt[3], pkt_mask3, p_nat))
5839 switch (protocol3) {
5841 case IP_PROTOCOL_TCP:
5842 case IP_PROTOCOL_UDP:
5843 case IP_PROTOCOL_ICMP:
5844 /*we don't need icmp check in ipv6 */
5848 /* remember invalid packets to be dropped */
5849 p_nat->invalid_packets |= pkt_mask3;
5850 p_nat->naptDroppedPktCount++;
5852 #ifdef CGNAPT_DEBUGGING
5853 p_nat->naptDroppedPktCount2++;
5859 key3.ip = rte_bswap32(dst_addr3[0]);
5860 key3.port = rte_bswap16(dst_port3);
5862 #ifdef NAT_ONLY_CONFIG_REQ
5863 if (nat_only_config_flag)
5867 memcpy(&p_nat->keys[pkt_num + 3], &key3,
5868 sizeof(struct pipeline_cgnapt_entry_key));
5870 p_nat->key_ptrs[pkt_num + 3] = &p_nat->keys[pkt_num + 3];
5874 * NAPT function for IPv6 private traffic which handles 1 pkt
5877 * A pointer to array of packet mbuf
5883 * A pointer to main CGNAPT structure
5887 pkt_work_cgnapt_ipv6_prv(
5888 struct rte_mbuf *pkt,
5890 __rte_unused void *arg,
5891 struct pipeline_cgnapt *p_nat)
5893 /* index into hash table entries */
5894 int hash_table_entry = p_nat->lkup_indx[pkt_num];
5896 /*bitmask representing only this packet */
5897 uint64_t pkt_mask = 1LLU << pkt_num;
5899 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
5901 /* Added for Multiport */
5902 uint32_t dest_if = INVALID_DESTIF;
5903 uint16_t *outport_id = RTE_MBUF_METADATA_UINT16_PTR(pkt,
5904 cgnapt_meta_offset);
5906 struct cgnapt_table_entry *entry = NULL;
5907 enum PKT_TYPE pkt_type = PKT_TYPE_IPV6to4;
5909 if (hash_table_entry < 0) {
5911 /* try to add new entry */
5912 struct rte_pipeline_table_entry *table_entry = NULL;
5914 uint64_t dropmask = pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num],
5916 &p_nat->valid_packets, pkt_num,
5920 /* ICMP Error message generation for
5921 * Destination Host unreachable
5923 /* Do we need this check for ipv6? */
5924 if (protocol == IP_PROTOCOL_ICMP) {
5925 cgnapt_icmp_pkt = pkt;
5926 send_icmp_dest_unreachable_msg();
5929 /* Drop packet by adding to invalid pkt mask */
5931 p_nat->invalid_packets |= dropmask;
5933 #ifdef CGNAPT_DEBUGGING
5934 if (p_nat->kpc2++ < 5) {
5935 printf("in_ah Th: %d", p_nat->pipeline_num);
5936 print_key(p_nat->key_ptrs[pkt_num]);
5940 p_nat->naptDroppedPktCount++;
5942 #ifdef CGNAPT_DEBUGGING
5943 p_nat->naptDroppedPktCount3++;
5949 entry = (struct cgnapt_table_entry *)table_entry;
5951 /* entry found for this packet */
5952 entry = &napt_hash_tbl_entries[hash_table_entry];
5955 /* apply napt and mac changes */
5957 p_nat->entries[pkt_num] = &(entry->head);
5959 struct ipv6_hdr ipv6_hdr;
5961 uint32_t dest_address = 0;
5966 convert_ipv6_to_ipv4(pkt, &ipv6_hdr);
5968 #ifdef CGNAPT_DBG_PRNT
5969 if (CGNAPT_DEBUG == 1)
5970 printf("pkt_work_cganpt: convert_ipv6_to_ipv4\n");
5973 struct cgnapt_nsp_node *ll = nsp_ll;
5976 while (ll != NULL) {
5978 (&ipv6_hdr.dst_addr[0], &ll->nsp.prefix[0],
5979 ll->nsp.depth / 8)) {
5987 && !memcmp(&ipv6_hdr.dst_addr[0], &well_known_prefix[0],
5993 p_nat->invalid_packets |= pkt_mask;
5994 p_nat->naptDroppedPktCount++;
5996 #ifdef CGNAPT_DEBUGGING
5997 p_nat->naptDroppedPktCount5++;
6005 /* As packet is already converted into IPv4 we must not
6006 * operate IPv6 offsets on packet
6007 * Only perform IPv4 operations
6010 uint32_t *src_addr =
6011 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP6t4);
6012 uint32_t *dst_addr =
6013 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP6t4);
6014 uint16_t *src_port =
6015 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP6t4);
6016 uint16_t *dst_port =
6017 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP6t4);
6019 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt,
6021 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt,
6022 ETH_OFST_IP6t4 + 6);
6024 if (entry->data.ttl == NAPT_ENTRY_STALE)
6025 entry->data.ttl = NAPT_ENTRY_VALID;
6028 if (unlikely(protocol == IP_PROTOCOL_UDP
6029 && rte_be_to_cpu_16(*dst_port) == 53)) {
6030 p_nat->invalid_packets |= pkt_mask;
6031 p_nat->naptDroppedPktCount++;
6033 #ifdef CGNAPT_DEBUGGING
6034 p_nat->naptDroppedPktCount6++;
6040 dest_address = rte_bswap32(*dst_addr);
6041 /*Multiport Changes */
6044 #ifdef CGNAPT_DBG_PRNT
6045 if (CGNAPT_DEBUG > 2)
6046 printf("Egress: \tphy_port:%d\t get_prv_to_pub():%d "
6047 "\tout_port:%d\n", pkt->port,
6048 dest_if, *outport_id);
6052 #ifdef CGNAPT_DBG_PRNT
6053 static int static_count;
6055 if (static_count++ < 10) {
6057 my_print_entry(entry);
6058 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6059 printf("dest_add:%x\n", entry->data.u.prv_ip);
6060 printf("dest_add:%x\n", *dst_addr);
6061 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6065 struct arp_entry_data *ret_arp_data;
6067 uint32_t src_phy_port = *src_port;
6069 gw_get_nh_port_ipv4(dest_address, &dest_if, &nhip);
6071 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if,
6072 (struct ether_addr *)eth_dest);
6074 *outport_id = p_nat->outport_id[dest_if];
6076 if (arp_cache_dest_mac_present(dest_if)) {
6077 ether_addr_copy(get_link_hw_addr(dest_if),
6078 (struct ether_addr *)eth_src);
6079 update_nhip_access(dest_if);
6081 if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) {
6082 p_nat->naptedPktCount += ret_arp_data->num_pkts;
6083 arp_send_buffered_pkts(ret_arp_data,
6084 (struct ether_addr *)eth_dest, *outport_id);
6089 if (unlikely(ret_arp_data == NULL)) {
6091 #ifdef CGNAPT_DEBUGGING
6092 printf("%s: NHIP Not Found, nhip:%x , "
6093 "outport_id: %d\n", __func__, nhip,
6098 p_nat->invalid_packets |= pkt_mask;
6099 p_nat->naptDroppedPktCount++;
6101 #ifdef CGNAPT_DEBUGGING
6102 p_nat->naptDroppedPktCount4++;
6107 if (ret_arp_data->status == INCOMPLETE ||
6108 ret_arp_data->status == PROBE) {
6109 if (ret_arp_data->num_pkts >= NUM_DESC) {
6111 p_nat->invalid_packets |= pkt_mask;
6112 p_nat->naptDroppedPktCount++;
6114 #ifdef CGNAPT_DEBUGGING
6115 p_nat->naptDroppedPktCount4++;
6119 arp_pkts_mask |= pkt_mask;
6120 arp_queue_unresolved_packet(ret_arp_data, pkt);
6128 *src_addr = rte_bswap32(entry->data.pub_ip);
6130 #ifdef NAT_ONLY_CONFIG_REQ
6131 if (!nat_only_config_flag) {
6133 *src_port = rte_bswap16(entry->data.pub_port);
6135 #ifdef NAT_ONLY_CONFIG_REQ
6139 p_nat->enaptedPktCount++;
6142 p_nat->naptedPktCount++;
6145 if (p_nat->hw_checksum_reqd)
6146 hw_checksum(pkt, pkt_type);
6148 sw_checksum(pkt, pkt_type);
6154 * NAPT function for IPv6 public traffic which handles 1 pkt
6157 * A pointer to array of packet mbuf
6163 * A pointer to main CGNAPT structure
6167 pkt_work_cgnapt_ipv6_pub(
6168 struct rte_mbuf *pkt,
6170 __rte_unused void *arg,
6171 struct pipeline_cgnapt *p_nat)
6174 /* index into hash table entries */
6175 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6176 /*bitmask representing only this packet */
6177 uint64_t pkt_mask = 1LLU << pkt_num;
6179 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
6181 uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */
6182 uint16_t *outport_id =
6183 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6184 struct cgnapt_table_entry *entry = NULL;
6186 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4to6;
6188 if (hash_table_entry < 0) {
6190 /* Drop ingress initial traffic */
6192 p_nat->invalid_packets |= pkt_mask;
6193 p_nat->naptDroppedPktCount++;
6195 #ifdef CGNAPT_DEBUGGING
6196 p_nat->naptDroppedPktCount3++;
6197 if (p_nat->kpc2++ < 5) {
6198 printf("in_ah Th: %d", p_nat->pipeline_num);
6199 print_key(p_nat->key_ptrs[pkt_num]);
6206 /* entry found for this packet */
6207 entry = &napt_hash_tbl_entries[hash_table_entry];
6210 /* apply napt and mac changes */
6212 p_nat->entries[pkt_num] = &(entry->head);
6213 if (entry->data.type != CGNAPT_ENTRY_IPV6) {
6214 p_nat->invalid_packets |= pkt_mask;
6215 p_nat->naptDroppedPktCount++;
6219 struct ipv4_hdr ipv4_hdr;
6220 uint16_t *src_port =
6221 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP4_TCP);
6223 uint8_t *eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
6224 uint8_t *eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
6226 if (entry->data.ttl == NAPT_ENTRY_STALE)
6227 entry->data.ttl = NAPT_ENTRY_VALID;
6229 struct ether_addr hw_addr;
6230 uint8_t dest_addr_ipv6[16];
6231 uint8_t nh_ipv6[16];
6236 if (unlikely(protocol == IP_PROTOCOL_UDP
6237 && rte_be_to_cpu_16(*src_port) == 53)) {
6238 p_nat->invalid_packets |= pkt_mask;
6239 p_nat->naptDroppedPktCount++;
6240 #ifdef CGNAPT_DEBUGGING
6241 p_nat->naptDroppedPktCount6++;
6246 memcpy(&dest_addr_ipv6[0], &entry->data.u.prv_ipv6[0], 16);
6249 memset(nh_ipv6, 0, 16);
6250 struct nd_entry_data *ret_nd_data = NULL;
6252 dest_if = INVALID_DESTIF;
6254 uint32_t src_phy_port = pkt->port;
6256 gw_get_nh_port_ipv6((uint8_t *) &dest_addr_ipv6[0],
6257 &dest_if, &nh_ipv6[0]);
6259 ret_nd_data = get_dest_mac_addr_ipv6(&nh_ipv6[0],
6260 dest_if, (struct ether_addr *)eth_dest);
6262 *outport_id = p_nat->outport_id[dest_if];
6264 if (nd_cache_dest_mac_present(dest_if)) {
6265 ether_addr_copy(get_link_hw_addr(dest_if),
6266 (struct ether_addr *)eth_src);
6267 update_nhip_access(dest_if);
6269 if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) {
6270 p_nat->naptedPktCount += ret_nd_data->num_pkts;
6271 nd_send_buffered_pkts(ret_nd_data,
6272 (struct ether_addr *)eth_dest, *outport_id);
6276 if (unlikely(ret_nd_data == NULL)) {
6278 #ifdef CGNAPT_DEBUGGING
6279 printf("%s: NHIP Not Found, "
6280 "outport_id: %d\n", __func__,
6285 p_nat->invalid_packets |= pkt_mask;
6286 p_nat->naptDroppedPktCount++;
6288 #ifdef CGNAPT_DEBUGGING
6289 p_nat->naptDroppedPktCount4++;
6294 if (ret_nd_data->status == INCOMPLETE ||
6295 ret_nd_data->status == PROBE) {
6296 if (ret_nd_data->num_pkts >= NUM_DESC) {
6298 p_nat->invalid_packets |= pkt_mask;
6299 p_nat->naptDroppedPktCount++;
6301 #ifdef CGNAPT_DEBUGGING
6302 p_nat->naptDroppedPktCount4++;
6306 arp_pkts_mask |= pkt_mask;
6307 nd_queue_unresolved_packet(ret_nd_data, pkt);
6317 convert_ipv4_to_ipv6(pkt, &ipv4_hdr);
6319 /* Ethernet MTU check */
6320 if ((rte_pktmbuf_data_len(pkt) - 14) > 1500) {
6321 p_nat->invalid_packets |= pkt_mask;
6322 p_nat->naptDroppedPktCount++;
6325 uint32_t *dst_addr =
6326 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP4t6);
6327 uint16_t *dst_port =
6328 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP4t6);
6330 memcpy((uint8_t *) &dst_addr[0], &entry->data.u.prv_ipv6[0],
6333 #ifdef NAT_ONLY_CONFIG_REQ
6334 if (!nat_only_config_flag) {
6336 *dst_port = rte_bswap16(entry->data.prv_port);
6338 #ifdef NAT_ONLY_CONFIG_REQ
6342 p_nat->inaptedPktCount++;
6345 p_nat->naptedPktCount++;
6348 if (p_nat->hw_checksum_reqd)
6349 hw_checksum(pkt, pkt_type);
6351 sw_checksum(pkt, pkt_type);
6357 * NAPT function for IPv6 private traffic which handles 4 pkts
6360 * A pointer to array of packets mbuf
6362 * Starting pkt number of pkts
6366 * A pointer to main CGNAPT structure
6370 pkt4_work_cgnapt_ipv6_prv(
6371 struct rte_mbuf **pkts,
6372 uint32_t in_pkt_num,
6373 __rte_unused void *arg,
6374 struct pipeline_cgnapt *p_nat)
6376 struct rte_mbuf *pkt;
6380 enum PKT_TYPE pkt_type = PKT_TYPE_IPV6to4;
6382 for (i = 0; i < 4; i++) {
6383 pkt_num = in_pkt_num + i;
6386 /* index into hash table entries */
6387 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6388 /*bitmask representing only this packet */
6389 uint64_t pkt_mask = 1LLU << pkt_num;
6391 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP6);
6392 uint32_t dest_if = INVALID_DESTIF;
6393 uint16_t *outport_id =
6394 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6395 struct cgnapt_table_entry *entry = NULL;
6397 if (hash_table_entry < 0) {
6399 /* try to add new entry */
6400 struct rte_pipeline_table_entry *table_entry = NULL;
6403 pkt_miss_cgnapt(p_nat->key_ptrs[pkt_num], pkt,
6405 &p_nat->valid_packets, pkt_num,
6409 /* ICMP Error message generation for
6410 * Destination Host unreachable
6412 /* Do we need this check for ipv6? */
6413 if (protocol == IP_PROTOCOL_ICMP) {
6414 cgnapt_icmp_pkt = pkt;
6415 send_icmp_dest_unreachable_msg();
6418 /* Drop packet by adding to invalid pkt mask */
6420 p_nat->invalid_packets |= dropmask;
6422 #ifdef CGNAPT_DEBUGGING
6423 if (p_nat->kpc2++ < 5) {
6424 printf("in_ah Th: %d",
6425 p_nat->pipeline_num);
6426 print_key(p_nat->key_ptrs[pkt_num]);
6430 p_nat->naptDroppedPktCount++;
6432 #ifdef CGNAPT_DEBUGGING
6433 p_nat->naptDroppedPktCount3++;
6439 entry = (struct cgnapt_table_entry *)table_entry;
6441 /* entry found for this packet */
6442 entry = &napt_hash_tbl_entries[hash_table_entry];
6445 /* apply napt and mac changes */
6447 p_nat->entries[pkt_num] = &(entry->head);
6449 struct ipv6_hdr ipv6_hdr;
6450 uint32_t dest_address = 0;
6451 uint8_t nh_ipv6[16];
6456 convert_ipv6_to_ipv4(pkt, &ipv6_hdr);
6458 #ifdef CGNAPT_DBG_PRNT
6459 if (CGNAPT_DEBUG >= 1)
6460 printf("pkt_work_cganpt: "
6461 "convert_ipv6_to_ipv4\n");
6464 struct cgnapt_nsp_node *ll = nsp_ll;
6467 while (ll != NULL) {
6468 if (!memcmp(&ipv6_hdr.dst_addr[0],
6470 ll->nsp.depth / 8)) {
6478 && !memcmp(&ipv6_hdr.dst_addr[0],
6479 &well_known_prefix[0], 12)) {
6484 p_nat->invalid_packets |= pkt_mask;
6485 p_nat->naptDroppedPktCount++;
6487 #ifdef CGNAPT_DEBUGGING
6488 p_nat->naptDroppedPktCount5++;
6495 /* As packet is already converted into IPv4 we must not
6496 * operate IPv6 offsets on packet only perform IPv4 operations
6499 uint32_t *src_addr =
6500 RTE_MBUF_METADATA_UINT32_PTR(pkt, SRC_ADR_OFST_IP6t4);
6501 uint32_t *dst_addr =
6502 RTE_MBUF_METADATA_UINT32_PTR(pkt, DST_ADR_OFST_IP6t4);
6503 uint16_t *src_port =
6504 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP6t4);
6505 uint16_t *dst_port =
6506 RTE_MBUF_METADATA_UINT16_PTR(pkt, DST_PRT_OFST_IP6t4);
6509 RTE_MBUF_METADATA_UINT8_PTR(pkt, ETH_OFST_IP6t4);
6511 RTE_MBUF_METADATA_UINT8_PTR(pkt, ETH_OFST_IP6t4 + 6);
6513 if (entry->data.ttl == NAPT_ENTRY_STALE)
6514 entry->data.ttl = NAPT_ENTRY_VALID;
6519 if (unlikely(protocol == IP_PROTOCOL_UDP
6520 && rte_be_to_cpu_16(*dst_port) == 53)) {
6521 p_nat->invalid_packets |= pkt_mask;
6522 p_nat->naptDroppedPktCount++;
6524 #ifdef CGNAPT_DEBUGGING
6525 p_nat->naptDroppedPktCount6++;
6530 dest_address = rte_bswap32(*dst_addr);
6533 #ifdef CGNAPT_DBG_PRNT
6534 if (CGNAPT_DEBUG > 2)
6535 printf("Egress: \tphy_port:%d\t"
6536 "get_prv_to_pub():%d \tout_port:%d\n",
6537 pkt->port, dest_if, *outport_id);
6541 #ifdef CGNAPT_DEBUGGING
6542 static int static_count;
6544 if (static_count++ < 10) {
6546 my_print_entry(entry);
6547 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6548 printf("dest_add:%x\n", entry->data.u.prv_ip);
6549 printf("dest_add:%x\n", *dst_addr);
6550 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6554 memset(nh_ipv6, 0, 16);
6557 struct arp_entry_data *ret_arp_data;
6558 uint32_t src_phy_port = *src_port;
6560 gw_get_nh_port_ipv4(dest_address, &dest_if, &nhip);
6562 ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if,
6563 (struct ether_addr *)eth_dest);
6564 *outport_id = p_nat->outport_id[dest_if];
6566 if (arp_cache_dest_mac_present(dest_if)) {
6567 ether_addr_copy(get_link_hw_addr(dest_if),
6568 (struct ether_addr *)eth_src);
6569 update_nhip_access(dest_if);
6570 if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) {
6571 p_nat->naptedPktCount += ret_arp_data->num_pkts;
6572 arp_send_buffered_pkts(ret_arp_data,
6573 (struct ether_addr *)eth_dest, *outport_id);
6578 if (unlikely(ret_arp_data == NULL)) {
6580 #ifdef CGNAPT_DEBUGGING
6581 printf("%s: NHIP Not Found, nhip:%x , "
6582 "outport_id: %d\n", __func__, nhip,
6587 p_nat->invalid_packets |= pkt_mask;
6588 p_nat->naptDroppedPktCount++;
6590 #ifdef CGNAPT_DEBUGGING
6591 p_nat->naptDroppedPktCount4++;
6596 if (ret_arp_data->status == INCOMPLETE ||
6597 ret_arp_data->status == PROBE) {
6598 if (ret_arp_data->num_pkts >= NUM_DESC) {
6600 p_nat->invalid_packets |= pkt_mask;
6601 p_nat->naptDroppedPktCount++;
6603 #ifdef CGNAPT_DEBUGGING
6604 p_nat->naptDroppedPktCount4++;
6608 arp_pkts_mask |= pkt_mask;
6609 arp_queue_unresolved_packet(ret_arp_data, pkt);
6619 *src_addr = rte_bswap32(entry->data.pub_ip);
6621 #ifdef NAT_ONLY_CONFIG_REQ
6622 if (!nat_only_config_flag) {
6624 *src_port = rte_bswap16(entry->data.pub_port);
6626 #ifdef NAT_ONLY_CONFIG_REQ
6630 p_nat->enaptedPktCount++;
6633 p_nat->naptedPktCount++;
6636 if (p_nat->hw_checksum_reqd)
6637 hw_checksum(pkt, pkt_type);
6639 sw_checksum(pkt, pkt_type);
6645 * NAPT function for IPv6 public traffic which handles 4 pkts
6648 * A pointer to array of packets mbuf
6650 * Starting pkt number of pkts
6654 * A pointer to main CGNAPT structure
6658 pkt4_work_cgnapt_ipv6_pub(
6659 struct rte_mbuf **pkts,
6660 uint32_t in_pkt_num,
6661 __rte_unused void *arg,
6662 struct pipeline_cgnapt *p_nat)
6664 struct rte_mbuf *pkt;
6668 enum PKT_TYPE pkt_type = PKT_TYPE_IPV4to6;
6670 for (i = 0; i < 4; i++) {
6671 pkt_num = in_pkt_num + i;
6674 /* index into hash table entries */
6675 int hash_table_entry = p_nat->lkup_indx[pkt_num];
6676 /*bitmask representing only this packet */
6677 uint64_t pkt_mask = 1LLU << pkt_num;
6679 uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4);
6680 uint16_t *outport_id =
6681 RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset);
6682 struct cgnapt_table_entry *entry = NULL;
6684 if (hash_table_entry < 0) {
6686 /* Drop ingress initial traffic */
6688 p_nat->invalid_packets |= pkt_mask;
6689 p_nat->naptDroppedPktCount++;
6690 #ifdef CGNAPT_DEBUGGING
6691 p_nat->naptDroppedPktCount3++;
6692 if (p_nat->kpc2++ < 5) {
6693 printf("in_ah Th: %d", p_nat->pipeline_num);
6694 print_key(p_nat->key_ptrs[pkt_num]);
6701 /* entry found for this packet */
6702 entry = &napt_hash_tbl_entries[hash_table_entry];
6705 /* apply napt and mac changes */
6707 p_nat->entries[pkt_num] = &(entry->head);
6708 if (entry->data.type != CGNAPT_ENTRY_IPV6) {
6709 p_nat->invalid_packets |= pkt_mask;
6710 p_nat->naptDroppedPktCount++;
6714 struct ipv4_hdr ipv4_hdr;
6716 uint16_t *src_port =
6717 RTE_MBUF_METADATA_UINT16_PTR(pkt, SRC_PRT_OFST_IP4_TCP);
6720 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
6722 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
6724 if (entry->data.ttl == NAPT_ENTRY_STALE)
6725 entry->data.ttl = NAPT_ENTRY_VALID;
6727 struct ether_addr hw_addr;
6728 uint8_t dest_addr_ipv6[16];
6729 uint8_t nh_ipv6[16];
6730 uint32_t dest_if = INVALID_DESTIF;
6731 { /*start of Ingress */
6733 if (unlikely(protocol == IP_PROTOCOL_UDP
6734 && rte_be_to_cpu_16(*src_port) == 53)) {
6735 p_nat->invalid_packets |= pkt_mask;
6736 p_nat->naptDroppedPktCount++;
6737 #ifdef CGNAPT_DEBUGGING
6738 p_nat->naptDroppedPktCount6++;
6743 memcpy(&dest_addr_ipv6[0], &entry->data.u.prv_ipv6[0],
6746 }/* end of ingress */
6748 #ifdef CGNAPT_DEBUGGING
6749 static int static_count;
6751 if (static_count++ < 10) {
6753 my_print_entry(entry);
6754 printf("dest-offset:%d\n", DST_ADR_OFST_IP4);
6755 printf("dest_add:%x\n", entry->data.u.prv_ip);
6756 printf("DST_ADR_OFST_IP6:%d\n", DST_ADR_OFST_IP6);
6760 memset(nh_ipv6, 0, 16);
6761 struct nd_entry_data *ret_nd_data = NULL;
6762 dest_if = INVALID_DESTIF;
6764 uint32_t src_phy_port = pkt->port;
6766 gw_get_nh_port_ipv6((uint8_t *) &dest_addr_ipv6[0],
6767 &dest_if, &nh_ipv6[0]);
6769 ret_nd_data = get_dest_mac_addr_ipv6(&nh_ipv6[0],
6770 dest_if, (struct ether_addr *)eth_dest);
6771 *outport_id = p_nat->outport_id[dest_if];
6773 if (nd_cache_dest_mac_present(dest_if)) {
6774 ether_addr_copy(get_link_hw_addr(dest_if),
6775 (struct ether_addr *)eth_src);
6776 update_nhip_access(dest_if);
6778 if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) {
6779 p_nat->naptedPktCount += ret_nd_data->num_pkts;
6780 nd_send_buffered_pkts(ret_nd_data,
6781 (struct ether_addr *)eth_dest, *outport_id);
6784 if (unlikely(ret_nd_data == NULL)) {
6786 #ifdef CGNAPT_DEBUGGING
6787 printf("%s: NHIP Not Found "
6788 "outport_id: %d\n", __func__,
6793 p_nat->invalid_packets |= pkt_mask;
6794 p_nat->naptDroppedPktCount++;
6796 #ifdef CGNAPT_DEBUGGING
6797 p_nat->naptDroppedPktCount4++;
6802 if (ret_nd_data->status == INCOMPLETE ||
6803 ret_nd_data->status == PROBE) {
6805 if (ret_nd_data->num_pkts >= NUM_DESC) {
6807 p_nat->invalid_packets |= pkt_mask;
6808 p_nat->naptDroppedPktCount++;
6810 #ifdef CGNAPT_DEBUGGING
6811 p_nat->naptDroppedPktCount4++;
6815 arp_pkts_mask |= pkt_mask;
6816 nd_queue_unresolved_packet(ret_nd_data, pkt);
6824 /* start of Ingress */
6826 convert_ipv4_to_ipv6(pkt, &ipv4_hdr);
6828 /* Ethernet MTU check */
6829 if ((rte_pktmbuf_data_len(pkt) - 14) > 1500) {
6830 p_nat->invalid_packets |= pkt_mask;
6831 p_nat->naptDroppedPktCount++;
6834 uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
6835 DST_ADR_OFST_IP4t6);
6836 uint16_t *dst_port = RTE_MBUF_METADATA_UINT16_PTR(pkt,
6837 DST_PRT_OFST_IP4t6);
6839 memcpy((uint8_t *) &dst_addr[0],
6840 &entry->data.u.prv_ipv6[0], 16);
6842 #ifdef NAT_ONLY_CONFIG_REQ
6843 if (!nat_only_config_flag) {
6845 *dst_port = rte_bswap16(entry->data.prv_port);
6847 #ifdef NAT_ONLY_CONFIG_REQ
6851 p_nat->inaptedPktCount++;
6852 } /* end of ingress */
6854 p_nat->naptedPktCount++;
6857 if (p_nat->hw_checksum_reqd)
6858 hw_checksum(pkt, pkt_type);
6860 sw_checksum(pkt, pkt_type);
6862 } /* end of for loop */
6866 * Input port handler for IPv6 private traffic
6867 * Starting from the packet burst it filters unwanted packets,
6868 * calculates keys, does lookup and then based on the lookup
6869 * updates NAPT table and does packet NAPT translation.
6872 * A pointer to struct rte_pipeline
6874 * A pointer to array of packets mbuf
6876 * Number of packets in the burst
6881 * int that is not checked by caller
6883 static int cgnapt_in_port_ah_ipv6_prv(struct rte_pipeline *rte_p,
6884 struct rte_mbuf **pkts,
6885 uint32_t n_pkts, void *arg)
6888 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
6889 struct pipeline_cgnapt *p_nat = ap->p;
6891 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
6892 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
6893 p_nat->invalid_packets = 0;
6896 #ifdef CGNAPT_DBG_PRNT
6897 if (CGNAPT_DEBUG > 1)
6898 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
6901 /* prefetching for mbufs should be done here */
6902 for (j = 0; j < n_pkts; j++)
6903 rte_prefetch0(pkts[j]);
6905 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
6906 pkt4_work_cgnapt_key_ipv6_prv(&pkts[i], i, arg, p_nat);
6908 for (; i < n_pkts; i++)
6909 pkt_work_cgnapt_key_ipv6_prv(pkts[i], i, arg, p_nat);
6911 p_nat->valid_packets &= ~(p_nat->invalid_packets);
6913 if (arp_pkts_mask) {
6914 p_nat->valid_packets &= ~(arp_pkts_mask);
6915 rte_pipeline_ah_packet_hijack(rte_p, arp_pkts_mask);
6918 if (unlikely(p_nat->valid_packets == 0)) {
6919 /* no suitable packet for lookup */
6920 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
6921 return p_nat->valid_packets;
6924 /* lookup entries in the common napt table */
6926 int lookup_result = rte_hash_lookup_bulk(
6928 (const void **) &p_nat->key_ptrs,
6929 /* should be minus num invalid pkts */
6931 /*new pipeline data member */
6932 &p_nat->lkup_indx[0]);
6934 if (unlikely(lookup_result < 0)) {
6935 /* unknown error, just discard all packets */
6936 printf("Unexpected hash lookup error %d, "
6937 "discarding all packets",
6939 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
6943 /* Now call second stage of pipeline to one by one
6944 * check the result of our bulk lookup
6947 /* prefetching for table entries should be done here */
6948 for (j = 0; j < n_pkts; j++) {
6949 if (p_nat->lkup_indx[j] >= 0)
6950 rte_prefetch0(&napt_hash_tbl_entries
6951 [p_nat->lkup_indx[j]]);
6954 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
6955 pkt4_work_cgnapt_ipv6_prv(&pkts[i], i, arg, p_nat);
6957 for (; i < n_pkts; i++)
6958 pkt_work_cgnapt_ipv6_prv(pkts[i], i, arg, p_nat);
6960 if (p_nat->invalid_packets) {
6961 /* get rid of invalid packets */
6962 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
6964 p_nat->valid_packets &= ~(p_nat->invalid_packets);
6966 #ifdef CGNAPT_DBG_PRNT
6967 if (CGNAPT_DEBUG > 1) {
6968 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
6969 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
6970 printf("invalid_packets:0x%jx\n",
6971 p_nat->invalid_packets);
6972 printf("rte_invalid_packets :0x%jx\n",
6973 rte_p->pkts_drop_mask);
6974 printf("Total pkts dropped :0x%jx\n",
6975 rte_p->n_pkts_ah_drop);
6980 return p_nat->valid_packets;
6985 * Input port handler for IPv6 public traffic
6986 * Starting from the packet burst it filters unwanted packets,
6987 * calculates keys, does lookup and then based on the lookup
6988 * updates NAPT table and does packet NAPT translation.
6991 * A pointer to struct rte_pipeline
6993 * A pointer to array of packets mbuf
6995 * Number of packets in the burst
7000 * int that is not checked by caller
7002 static int cgnapt_in_port_ah_ipv6_pub(struct rte_pipeline *rte_p,
7003 struct rte_mbuf **pkts,
7004 uint32_t n_pkts, void *arg)
7007 struct pipeline_cgnapt_in_port_h_arg *ap = arg;
7008 struct pipeline_cgnapt *p_nat = ap->p;
7010 p_nat->pkt_burst_cnt = 0; /* for dynamic napt */
7011 p_nat->valid_packets = rte_p->pkts_mask; /*n_pkts; */
7012 p_nat->invalid_packets = 0;
7015 #ifdef CGNAPT_DBG_PRNT
7016 if (CGNAPT_DEBUG > 1)
7017 printf("cgnapt_key hit fn: %" PRIu32 "\n", n_pkts);
7020 /* prefetching for mbufs should be done here */
7021 for (j = 0; j < n_pkts; j++)
7022 rte_prefetch0(pkts[j]);
7024 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7025 pkt4_work_cgnapt_key_ipv6_pub(&pkts[i], i, arg, p_nat);
7027 for (; i < n_pkts; i++)
7028 pkt_work_cgnapt_key_ipv6_pub(pkts[i], i, arg, p_nat);
7030 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7032 if (arp_pkts_mask) {
7033 p_nat->valid_packets &= ~(arp_pkts_mask);
7034 rte_pipeline_ah_packet_hijack(rte_p, arp_pkts_mask);
7037 if (unlikely(p_nat->valid_packets == 0)) {
7038 /* no suitable packet for lookup */
7039 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7040 return p_nat->valid_packets;
7043 /* lookup entries in the common napt table */
7045 int lookup_result = rte_hash_lookup_bulk(
7047 (const void **) &p_nat->key_ptrs,
7048 /* should be minus num invalid pkts */
7050 /*new pipeline data member */
7051 &p_nat->lkup_indx[0]);
7053 if (unlikely(lookup_result < 0)) {
7054 /* unknown error, just discard all packets */
7055 printf("Unexpected hash lookup error %d, "
7056 "discarding all packets",
7058 rte_pipeline_ah_packet_drop(rte_p, p_nat->valid_packets);
7062 /* Now call second stage of pipeline to one by one
7063 * check the result of our bulk lookup
7066 /* prefetching for table entries should be done here */
7067 for (j = 0; j < n_pkts; j++) {
7068 if (p_nat->lkup_indx[j] >= 0)
7069 rte_prefetch0(&napt_hash_tbl_entries
7070 [p_nat->lkup_indx[j]]);
7073 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4)
7074 pkt4_work_cgnapt_ipv6_pub(&pkts[i], i, arg, p_nat);
7076 for (; i < n_pkts; i++)
7077 pkt_work_cgnapt_ipv6_pub(pkts[i], i, arg, p_nat);
7079 if (p_nat->invalid_packets) {
7080 /* get rid of invalid packets */
7081 rte_pipeline_ah_packet_drop(rte_p, p_nat->invalid_packets);
7083 p_nat->valid_packets &= ~(p_nat->invalid_packets);
7085 #ifdef CGNAPT_DBG_PRNT
7086 if (CGNAPT_DEBUG > 1) {
7087 printf("valid_packets:0x%jx\n", p_nat->valid_packets);
7088 printf("rte_valid_packets :0x%jx\n", rte_p->pkts_mask);
7089 printf("invalid_packets:0x%jx\n",
7090 p_nat->invalid_packets);
7091 printf("rte_invalid_packets :0x%jx\n",
7092 rte_p->pkts_drop_mask);
7093 printf("Total pkts dropped :0x%jx\n",
7094 rte_p->n_pkts_ah_drop);
7099 return p_nat->valid_packets;
7103 * Function to send ICMP dest unreachable msg
7106 void send_icmp_dest_unreachable_msg(void)
7109 struct ether_hdr *eth_h;
7110 struct ipv4_hdr *ip_h;
7111 struct icmp_hdr *icmp_h;
7112 struct rte_mbuf *icmp_pkt = cgnapt_icmp_pkt;
7114 if (icmp_pkt == NULL) {
7116 printf("Error allocating icmp_pkt rte_mbuf\n");
7120 port_id = icmp_pkt->port;
7122 struct app_link_params *link;
7123 link = &mylink[port_id];
7124 eth_h = rte_pktmbuf_mtod(icmp_pkt, struct ether_hdr *);
7125 ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
7126 icmp_h = (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
7128 struct ether_addr gw_addr;
7129 struct ether_addr dst_addr;
7130 ether_addr_copy(ð_h->s_addr, &dst_addr);
7131 rte_eth_macaddr_get(port_id, &gw_addr);
7132 ether_addr_copy(&gw_addr, ð_h->s_addr);
7133 ether_addr_copy(&dst_addr, ð_h->d_addr);
7135 eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
7136 ip_h->version_ihl = IP_VHL_DEF;
7137 ip_h->type_of_service = 0;
7138 ip_h->total_length = rte_cpu_to_be_16(sizeof(struct ipv4_hdr) +
7139 sizeof(struct icmp_hdr));
7140 ip_h->packet_id = 0xaabb;
7141 ip_h->fragment_offset = 0x0000;
7142 ip_h->time_to_live = 64;
7143 ip_h->next_proto_id = 1;
7146 uint32_t src_addr_offset =
7147 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_SRC_ADR_OFST;
7149 RTE_MBUF_METADATA_UINT32_PTR(cgnapt_icmp_pkt, src_addr_offset);
7151 ip_h->dst_addr = *src_addr;
7152 ip_h->src_addr = rte_bswap32(link->ip);
7154 ip_h->dst_addr = *src_addr;
7155 ip_h->src_addr = rte_bswap32(link->ip);
7157 ip_h->hdr_checksum = 0;
7158 ip_h->hdr_checksum = rte_ipv4_cksum(ip_h);
7159 icmp_h->icmp_type = 3; /* Destination Unreachable */
7160 icmp_h->icmp_code = 13; /* Communication administratively prohibited */
7162 icmp_h->icmp_cksum = ~rte_raw_cksum(icmp_h, sizeof(struct icmp_hdr));
7164 icmp_pkt->pkt_len = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
7165 sizeof(struct icmp_hdr);
7166 icmp_pkt->data_len = icmp_pkt->pkt_len;
7167 if (ARPICMP_DEBUG) {
7168 printf("Sending ICMP error message - "
7169 "Destination Unreachable\n");
7171 rte_pipeline_port_out_packet_insert(myP, port_id, icmp_pkt);
7175 * Function to add a dynamic NAPT entry pair
7178 * A pointer to struct pipeline
7180 * A pointer to struct pipeline_cgnapt_entry_key
7182 * expairy time of an dynamic or PCP req entry
7184 * uint8_t pointer of source address
7187 * A pointer to struct cgnapt_table_entry for added entry
7190 struct cgnapt_table_entry *add_dynamic_cgnapt_entry(
7192 struct pipeline_cgnapt_entry_key *key,
7199 void *entry_ptr, *ret_ptr;
7202 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
7204 #ifdef CGNAPT_DBG_PRNT
7205 if (CGNAPT_DEBUG >= 1) {
7206 printf("Th%d add_dynamic_cgnapt_entry key detail Entry:"
7207 "0x%x, %d, %d\n", p_nat->pipeline_num, key->ip, key->port,
7212 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX && i < p_nat->pkt_burst_cnt;
7214 if (p_nat->cgnapt_dyn_ent_table[i].ip == key->ip
7215 && p_nat->cgnapt_dyn_ent_table[i].port == key->port
7216 && p_nat->cgnapt_dyn_ent_table[i].pid == key->pid) {
7218 #ifdef CGNAPT_DBG_PRNT
7219 if (CGNAPT_DEBUG > 1)
7220 printf("add_dynamic_cgnapt_entry:pkt_burst "
7221 "array key matched!!!\n");
7224 return &napt_hash_tbl_entries
7225 [p_nat->cgnapt_dyn_ent_index[i]];
7229 #ifdef NAT_ONLY_CONFIG_REQ
7230 if (!nat_only_config_flag) {
7233 ret = increment_max_port_counter(key->ip, key->pid, p_nat);
7234 if (ret == MAX_PORT_INC_ERROR) {
7236 #ifdef CGNAPT_DEBUGGING
7237 p_nat->missedpktcount5++;
7240 #ifdef CGNAPT_DBG_PRNT
7241 if (CGNAPT_DEBUG > 1)
7242 printf("add_dynamic_cgnapt_entry:"
7243 "increment_max_port_counter-1 failed\n");
7250 if (ret == MAX_PORT_INC_REACHED) {
7252 #ifdef CGNAPT_DEBUGGING
7253 p_nat->missedpktcount6++;
7256 #ifdef CGNAPT_DBG_PRNT
7257 if (CGNAPT_DEBUG > 1)
7258 printf("add_dynamic_cgnapt_entry:"
7259 "increment_max_port_counter-2 failed\n");
7266 #ifdef NAT_ONLY_CONFIG_REQ
7271 port_num = get_free_iport(p_nat, &public_ip);
7273 if (port_num == -1) {
7275 #ifdef CGNAPT_DBG_PRNT
7276 if (CGNAPT_DEBUG > 2) {
7277 printf("add_dynamic_cgnapt_entry: %d\n", port_num);
7278 printf("add_dynamic_cgnapt_entry key detail:0x%x, "
7279 "%d, %d\n", key->ip, key->port, key->pid);
7283 #ifdef CGNAPT_DEBUGGING
7284 p_nat->missedpktcount7++;
7291 #ifdef NAT_ONLY_CONFIG_REQ
7292 if (!nat_only_config_flag) {
7295 if (ret == 2) { //MPPC_NEW_ENTRY
7297 /* check for max_clients_per_ip */
7298 if (rte_atomic16_read
7300 [rte_jhash(&public_ip, 4, 0) %
7301 CGNAPT_MAX_PUB_IP].count) ==
7302 p_nat->max_clients_per_ip) {
7304 /* For now just bail out
7305 * In future we can think about
7306 * retrying getting a new iport
7309 release_iport(port_num, public_ip, p_nat);
7311 #ifdef CGNAPT_DEBUGGING
7312 p_nat->missedpktcount10++;
7318 rte_atomic16_inc(&all_public_ip
7319 [rte_jhash(&public_ip, 4, 0) %
7320 CGNAPT_MAX_PUB_IP].count);
7322 #ifdef CGNAPT_DBG_PRNT
7323 if ((rte_jhash(&public_ip, 4, 0) %
7324 CGNAPT_MAX_PUB_IP) == 8)
7325 printf("pub ip:%x coutn:%d\n", public_ip,
7326 rte_atomic16_read(&all_public_ip
7327 [rte_jhash(&public_ip, 4, 0) %
7328 CGNAPT_MAX_PUB_IP].count));
7332 #ifdef NAT_ONLY_CONFIG_REQ
7336 #ifdef CGNAPT_DBG_PRNT
7337 if (CGNAPT_DEBUG > 0) {
7338 printf("add_dynamic_cgnapt_entry: %d\n",
7340 printf("add_dynamic_cgnapt_entry key detail: "
7341 "0x%x, %d, %d\n", key->ip, key->port, key->pid);
7345 struct cgnapt_table_entry entry = {
7347 .action = RTE_PIPELINE_ACTION_PORT,
7348 /* made it configurable below */
7349 {.port_id = p->port_out_id[0]},
7353 .prv_port = key->port,
7354 .pub_ip = public_ip,
7355 .pub_port = port_num,
7356 .prv_phy_port = key->pid,
7357 .pub_phy_port = get_pub_to_prv_port(
7361 /* if(timeout == -1) : static entry
7362 * if(timeout == 0 ) : dynamic entry
7363 * if(timeout > 0 ) : PCP requested entry
7365 .timeout = timeout > 0 ? timeout : 0,
7372 #ifdef NAT_ONLY_CONFIG_REQ
7373 if (nat_only_config_flag) {
7374 entry.data.prv_port = 0xffff;
7375 entry.data.pub_port = 0xffff;
7379 if (pkt_type == CGNAPT_ENTRY_IPV6) {
7380 entry.data.type = CGNAPT_ENTRY_IPV6;
7381 memcpy(&entry.data.u.prv_ipv6[0], src_addr, 16);
7383 entry.data.u.prv_ip = key->ip;
7384 entry.data.type = CGNAPT_ENTRY_IPV4;
7387 //entry.head.port_id = CGNAPT_PUB_PORT_ID; /* outgoing port info */
7388 entry.head.port_id = entry.data.pub_phy_port; /* outgoing port info */
7390 struct pipeline_cgnapt_entry_key second_key;
7391 /* Need to add a second ingress entry */
7392 second_key.ip = public_ip;
7393 second_key.port = port_num;
7394 second_key.pid = 0xffff;
7396 #ifdef NAT_ONLY_CONFIG_REQ
7397 if (nat_only_config_flag)
7398 second_key.port = 0xffff;
7401 #ifdef CGNAPT_DBG_PRNT
7402 if (CGNAPT_DEBUG > 2)
7403 printf("add_dynamic_cgnapt_entry second key detail:"
7404 "0x%x, %d, %d\n", second_key.ip, second_key.port,
7408 int32_t position = rte_hash_add_key(napt_common_table, (void *)key);
7411 #ifdef CGNAPT_DEBUGGING
7412 p_nat->missedpktcount8++;
7415 printf("CG-NAPT entry add failed ...returning "
7416 "without adding ... %d\n", position);
7421 #ifdef CGNAPT_DBG_PRNT
7423 printf("add_dynamic_cgnapt_entry\n");
7425 print_cgnapt_entry(&entry);
7429 memcpy(&napt_hash_tbl_entries[position], &entry,
7430 sizeof(struct cgnapt_table_entry));
7432 /* this pointer is returned to pkt miss function */
7433 ret_ptr = &napt_hash_tbl_entries[position];
7435 p_nat->n_cgnapt_entry_added++;
7436 p_nat->dynCgnaptCount++;
7438 /* Now modify the forward port for reverse entry */
7440 /* outgoing port info */
7441 //entry.head.port_id = CGNAPT_PRV_PORT_ID;
7442 /* outgoing port info */
7443 entry.head.port_id = entry.data.prv_phy_port;
7445 int32_t position2 = rte_hash_add_key(napt_common_table, &second_key);
7447 if (position2 < 0) {
7448 #ifdef CGNAPT_DEBUGGING
7449 p_nat->missedpktcount9++;
7451 printf("CG-NAPT entry reverse bulk add failed ..."
7452 "returning with fwd add ...%d\n",
7458 memcpy(&napt_hash_tbl_entries[position2], &entry,
7459 sizeof(struct cgnapt_table_entry));
7461 entry_ptr = &napt_hash_tbl_entries[position2];
7463 timer_thread_enqueue(key, &second_key, ret_ptr,
7464 entry_ptr, (struct pipeline *)p_nat);
7466 p_nat->n_cgnapt_entry_added++;
7467 p_nat->dynCgnaptCount++;
7469 if (p_nat->pkt_burst_cnt < RTE_PORT_IN_BURST_SIZE_MAX) {
7470 memcpy(&p_nat->cgnapt_dyn_ent_table[p_nat->pkt_burst_cnt], key,
7471 sizeof(struct pipeline_cgnapt_entry_key));
7472 p_nat->cgnapt_dyn_ent_index[p_nat->pkt_burst_cnt] = position;
7473 p_nat->pkt_burst_cnt++;
7478 int pkt_miss_cgnapt_count;
7480 * Function handle a missed NAPT entry lookup
7481 * Will attempt to add a dynamic entry pair.
7484 * A pointer to struct pipeline
7486 * A pointer to struct pipeline_cgnapt_entry_key
7488 * A pointer to pkt struct rte_mbuf
7490 * uint64_t pointer to pkt mask
7491 * @param table_entry
7492 * A pointer to struct rte_pipeline_table_entry to be created and returned
7494 * number of this pkt in current burst
7497 * A uint64_t mask for drop packets
7500 pkt_miss_cgnapt(struct pipeline_cgnapt_entry_key *key,
7501 struct rte_mbuf *pkt,
7502 struct rte_pipeline_table_entry **table_entry,
7503 __rte_unused uint64_t *pkts_mask,
7504 uint32_t pkt_num, void *arg)
7507 #ifdef CGNAPT_DBG_PRNT
7508 if (CGNAPT_DEBUG > 0)
7509 printf("\n pkt_miss_cgnapt\n");
7513 * see if get_port passes for this src address
7514 * if passed add a new egress entry and a
7515 * corresponding new ingress entry
7516 * return the fwd entry to calling function using input pointer
7517 * else if get_port fails drop packet
7520 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)arg;
7522 uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
7523 uint32_t src_addr_offset_ipv6 =
7524 MBUF_HDR_ROOM + ETH_HDR_SIZE + IPV6_HDR_SRC_ADR_OFST;
7525 uint16_t phy_port = pkt->port;
7527 uint16_t *eth_proto =
7528 RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
7530 uint8_t *src_addr = NULL;
7531 uint8_t src_addr_ipv6[16];
7532 uint8_t pkt_type = CGNAPT_ENTRY_IPV4;
7533 /* To drop the packet */
7534 uint64_t drop_mask = 0;
7536 if (p_nat->is_static_cgnapt) {
7537 drop_mask |= 1LLU << pkt_num;
7538 p_nat->missedPktCount++;
7540 #ifdef CGNAPT_DEBUGGING
7541 p_nat->missedpktcount1++;
7546 if (rte_be_to_cpu_16(*eth_proto) == ETHER_TYPE_IPv6) {
7548 RTE_MBUF_METADATA_UINT8_PTR(pkt, src_addr_offset_ipv6);
7549 pkt_type = CGNAPT_ENTRY_IPV6;
7550 memcpy(src_addr_ipv6, src_addr, 16);
7555 /* some validation first */
7556 if (is_phy_port_privte(phy_port)) {
7557 /* dynamic NAPT entry creation */
7558 *table_entry = (struct rte_pipeline_table_entry *)
7559 add_dynamic_cgnapt_entry(
7560 (struct pipeline *)&p_nat->p,
7562 DYNAMIC_CGNAPT_TIMEOUT,
7564 src_addr_ipv6, &err);
7566 if (!(*table_entry)) {
7568 drop_mask |= 1LLU << pkt_num;
7569 p_nat->missedPktCount++;
7571 #ifdef CGNAPT_DEBUGGING
7572 p_nat->missedpktcount2++;
7575 #ifdef CGNAPT_DBG_PRNT
7576 if (CGNAPT_DEBUG > 1)
7577 printf("Add Dynamic NAT entry failed "
7581 #ifdef CGNAPT_DEBUGGING
7582 p_nat->missedpktcount11++;
7587 } else if (!is_phy_port_privte(phy_port)) {
7589 #ifdef CGNAPT_DBG_PRNT
7590 if (CGNAPT_DEBUG >= 2) {
7591 printf("Initial Ingress entry creation NOT ALLOWED "
7596 drop_mask |= 1LLU << pkt_num;
7597 p_nat->missedPktCount++;
7599 #ifdef CGNAPT_DEBUGGING
7600 p_nat->missedpktcount3++;
7604 #ifdef CGNAPT_DBG_PRNT
7605 if (CGNAPT_DEBUG > 1)
7606 printf("NOT a PRIVATE or PUBLIC port!!!!!\n");
7609 drop_mask |= 1LLU << pkt_num;
7610 p_nat->missedPktCount++;
7612 #ifdef CGNAPT_DEBUGGING
7613 p_nat->missedpktcount4++;
7617 #ifdef CGNAPT_DBG_PRNT
7618 if (CGNAPT_DEBUG > 5)
7628 * Function to print the contents of a packet
7631 * A pointer to pkt struct rte_mbuf
7633 void print_pkt(struct rte_mbuf *pkt)
7637 printf("\nPacket Contents:\n");
7639 uint8_t *rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
7641 for (i = 0; i < 20; i++) {
7642 for (j = 0; j < 20; j++)
7643 printf("%02x ", rd[(20 * i) + j]);
7649 rte_table_hash_op_hash cgnapt_hash_func[] = {
7661 * Function to parse incoming pipeline arguments
7662 * Called during pipeline initialization
7665 * A pointer to struct pipeline_cgnapt
7667 * A pointer to struct pipeline_params
7670 * 0 if success, negative if failure
7673 pipeline_cgnapt_parse_args(struct pipeline_cgnapt *p,
7674 struct pipeline_params *params)
7676 uint32_t n_flows_present = 0;
7677 uint32_t key_offset_present = 0;
7678 uint32_t key_size_present = 0;
7679 uint32_t hash_offset_present = 0;
7680 uint32_t n_entries_present = 0;
7681 uint32_t max_port_present = 0;
7682 uint32_t max_client_present = 0;
7683 uint32_t public_ip_range_present = 0;
7684 uint32_t public_ip_port_range_present = 0;
7686 uint8_t public_ip_count = 0;
7687 uint8_t public_ip_range_count = 0;
7688 uint8_t dest_if_offset_present = 0;
7689 uint8_t cgnapt_meta_offset_present = 0;
7690 uint8_t prv_que_handler_present = 0;
7691 uint8_t n_prv_in_port = 0;
7693 if (CGNAPT_DEBUG > 2) {
7694 printf("CGNAPT pipeline_cgnapt_parse_args params->n_args: %d\n",
7697 for (i = 0; i < params->n_args; i++) {
7698 char *arg_name = params->args_name[i];
7699 char *arg_value = params->args_value[i];
7701 if (CGNAPT_DEBUG > 2) {
7702 printf("CGNAPT args[%d]: %s %d, %s\n", i, arg_name,
7703 atoi(arg_value), arg_value);
7705 if (strcmp(arg_name, "prv_que_handler") == 0) {
7707 if (prv_que_handler_present) {
7708 printf("Duplicate pktq_in_prv ..\n\n");
7711 prv_que_handler_present = 1;
7716 /* get the first token */
7717 token = strtok(arg_value, "(");
7718 token = strtok(token, ")");
7719 token = strtok(token, ",");
7720 printf("***** prv_que_handler *****\n");
7722 if (token == NULL) {
7723 printf("string is null\n");
7724 printf("invalid prv_que_handler value/n");
7727 printf("string is :%s\n", token);
7729 /* walk through other tokens */
7730 while (token != NULL) {
7731 printf(" %s\n", token);
7732 rxport = atoi(token);
7733 cgnapt_prv_que_port_index[n_prv_in_port++] =
7735 if (rxport < PIPELINE_MAX_PORT_IN)
7736 cgnapt_in_port_egress_prv[rxport] = 1;
7737 token = strtok(NULL, ",");
7740 if (n_prv_in_port == 0) {
7741 printf("VNF common parse err - "
7742 "no prv RX phy port\n");
7748 if (strcmp(arg_name, "cgnapt_meta_offset") == 0) {
7749 if (cgnapt_meta_offset_present) {
7750 printf("CG-NAPT parse error:");
7751 printf("cgnapt_meta_offset initizlized "
7752 "mulitple times\n");
7755 cgnapt_meta_offset_present = 1;
7757 temp = atoi(arg_value);
7760 printf("cgnapt_meta_offset is invalid :");
7761 printf("Not be more than metadata size\n");
7764 cgnapt_meta_offset = (uint16_t) temp;
7766 if (strcmp(arg_name, "vnf_set") == 0)
7769 if (strcmp(arg_name, "public_ip_range") == 0) {
7770 public_ip_range_present = 1;
7771 if (public_ip_port_range_present) {
7772 printf("CG-NAPT parse error:");
7773 printf("public_ip_range with "
7774 "public_ip_port_range_present\n");
7778 p->pub_ip_range = rte_realloc(p->pub_ip_range,
7781 RTE_CACHE_LINE_SIZE);
7783 if (!p->pub_ip_range) {
7784 printf("Memory allocation failed for "
7789 uint32_t sip = 0, eip = 0;
7791 if (sscanf(arg_value, "(%x,%x)", &sip, &eip) != 2) {
7792 printf("public_ip_range is invalid\n");
7796 if (sip <= 0 || eip <= 0 || sip >= eip) {
7797 printf("public_ip_range is invalid %x-%x\n",
7802 printf("public_ip_range: %d-%d\n",
7803 p->pub_ip_range[public_ip_range_count].
7805 p->pub_ip_range[public_ip_range_count].
7808 p->pub_ip_range_count = ++public_ip_range_count;
7812 if (strcmp(arg_name, "public_ip_port_range") == 0) {
7813 public_ip_port_range_present = 1;
7814 if (nat_only_config_flag || public_ip_range_present) {
7816 printf("CG-NAPT parse error:");
7817 printf("nat_only_config_flag OR ");
7818 printf("public_ip_range_present with "
7819 "public_ip_port_range_present\n");
7823 p->pub_ip_port_set = rte_realloc(
7825 sizeof(struct pub_ip_port_set),
7826 RTE_CACHE_LINE_SIZE);
7828 if (!p->pub_ip_port_set) {
7829 printf("Memory allocation failed for "
7837 if (sscanf(arg_value, "%x:(%d,%d)",
7838 &ip, &sp, &ep) != 3) {
7839 printf("Public IP or Port-range is invalid\n");
7843 if (ip <= 0 || sp <= 0 || ep <= 0 || sp > ep) {
7844 printf("Public IP or Port-range is invalid "
7845 "%x:%d-%d\n", ip, sp, ep);
7849 printf("public_ip: 0x%x Range:%d-%d\n",
7850 p->pub_ip_port_set[public_ip_count].ip = ip,
7851 p->pub_ip_port_set[public_ip_count].start_port = sp,
7852 p->pub_ip_port_set[public_ip_count].end_port = ep);
7854 napt_port_alloc_elem_count += (ep - sp + 1);
7855 printf("parse - napt_port_alloc_elem_count :%d\n",
7856 napt_port_alloc_elem_count);
7858 /* Store all public IPs of all CGNAPT threads
7859 * in the global variable
7861 /* to revisit indexing */
7862 all_public_ip[rte_jhash(&ip, 4, 0) %
7863 CGNAPT_MAX_PUB_IP].ip = ip;
7864 p->pub_ip_count = ++public_ip_count;
7865 printf("public_ip_count:%d hash:%d\n", public_ip_count,
7866 rte_jhash(&ip, 4, 0) % CGNAPT_MAX_PUB_IP);
7870 /* hw_checksum_reqd */
7871 if (strcmp(arg_name, "hw_checksum_reqd") == 0) {
7873 temp = atoi(arg_value);
7874 if ((temp != 0) && (temp != 1)) {
7875 printf("hw_checksum_reqd is invalid\n");
7878 p->hw_checksum_reqd = temp;
7882 /* nat_only_config_flag */
7883 if (strcmp(arg_name, "nat_only_config_flag") == 0) {
7884 nat_only_config_flag = 1;
7885 if (public_ip_port_range_present) {
7887 printf("CG-NAPT parse error:");
7888 printf("nat_only_config_flag with "
7889 "public_ip_port_range_present\n");
7895 /* max_port_per_client */
7896 if (strcmp(arg_name, "max_port_per_client") == 0) {
7897 if (max_port_present) {
7898 printf("CG-NAPT Parse Error: "
7899 "duplicate max_port_per_client\n");
7902 max_port_present = 1;
7905 max = atoi(arg_value);
7907 printf("max_port_per_client is invalid !!!\n");
7911 p->max_port_per_client = (uint16_t) max;
7913 if (p->max_port_per_client <= 0) {
7914 printf("max port per client is invalid\n");
7918 printf("max_port_per_client comp: %d\n",
7919 p->max_port_per_client);
7923 /* max_clients_per_ip */
7924 if (strcmp(arg_name, "max_clients_per_ip") == 0) {
7925 if (max_client_present) {
7926 printf("CG-NAPT parse Error: duplicate "
7927 "max_clients_per_ip\n");
7930 max_client_present = 1;
7932 if (nat_only_config_flag) {
7933 printf("CG-NAPT parse error:");
7934 printf("nat_only_config_flag with "
7935 "max_clients_per_ip\n");
7940 max = atoi(arg_value);
7942 printf("max_clients_per_ip is invalid !!!\n");
7946 p->max_clients_per_ip = (uint16_t) max;
7948 if (p->max_clients_per_ip <= 0) {
7949 printf("max_clients_per_ip is invalid\n");
7953 printf("max_clients_per_ip: %d\n",
7954 p->max_clients_per_ip);
7959 if (strcmp(arg_name, "n_entries") == 0) {
7960 if (n_entries_present)
7962 n_entries_present = 1;
7964 p->n_entries = atoi(arg_value);
7965 if (p->n_entries == 0)
7972 if (strcmp(arg_name, "n_flows") == 0) {
7973 if (n_flows_present)
7975 n_flows_present = 1;
7977 p->n_flows = atoi(arg_value);
7978 if (p->n_flows == 0)
7981 napt_common_table_hash_params.entries = p->n_flows;
7984 /* dest_if_offset Multiport Changes */
7985 if (strcmp(arg_name, "dest_if_offset") == 0) {
7986 if (dest_if_offset_present)
7988 //dest_if_offset_present = 1;
7990 dest_if_offset = atoi(arg_value);
7996 if (strcmp(arg_name, "key_offset") == 0) {
7997 if (key_offset_present)
7999 key_offset_present = 1;
8001 p->key_offset = atoi(arg_value);
8007 if (strcmp(arg_name, "key_size") == 0) {
8008 if (key_size_present)
8010 key_size_present = 1;
8012 p->key_size = atoi(arg_value);
8013 if ((p->key_size == 0) ||
8014 (p->key_size > PIPELINE_CGNAPT_KEY_MAX_SIZE) ||
8022 if (strcmp(arg_name, "hash_offset") == 0) {
8023 if (hash_offset_present)
8025 hash_offset_present = 1;
8027 p->hash_offset = atoi(arg_value);
8033 if (strcmp(arg_name, "pkt_type") == 0) {
8034 if (strcmp(arg_value, "ipv4") == 0) {
8035 p->traffic_type = TRAFFIC_TYPE_IPV4;
8036 printf("Traffic is set to IPv4\n");
8037 } else if (strcmp(arg_value, "ipv6") == 0) {
8038 p->traffic_type = TRAFFIC_TYPE_IPV6;
8039 printf("Traffic is set to IPv6\n");
8045 if (strcmp(arg_name, "cgnapt_debug") == 0) {
8046 CGNAPT_DEBUG = atoi(arg_value);
8051 /* any other Unknown argument return -1 */
8054 #ifdef NAT_ONLY_CONFIG_REQ
8055 if (nat_only_config_flag) {
8056 if (!public_ip_range_count) {
8057 printf("No public_ip_range %d for NAT only config.\n",
8058 public_ip_range_count);
8059 printf("Running static NAT only configuration\n");
8060 p->is_static_cgnapt = 1;
8065 if (!p->max_port_per_client)
8066 p->is_static_cgnapt = 1;
8069 /* Check that mandatory arguments are present */
8070 if ((n_flows_present == 0) ||
8071 (cgnapt_meta_offset_present == 0))
8078 * Function to initialize the pipeline
8081 * A pointer to struct pipeline_params
8083 * Void pointer - points to app params
8086 * void pointer to the pipeline, NULL 0 if failure
8088 static void *pipeline_cgnapt_init(struct pipeline_params *params, void *arg)
8089 /* (struct app_params *app) save it for use in port in handler */
8092 struct pipeline_cgnapt *p_nat;
8093 uint32_t size, i, in_ports_arg_size;
8095 /* Check input arguments */
8096 if ((params == NULL) ||
8097 (params->n_ports_in == 0) || (params->n_ports_out == 0))
8100 /* Memory allocation */
8101 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_cgnapt));
8102 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8103 p_nat = (struct pipeline_cgnapt *)p;
8104 global_pnat = p_nat;
8108 all_pipeline_cgnapt[n_cgnapt_pipeline++] = p_nat;
8110 strcpy(p->name, params->name);
8111 p->log_level = params->log_level;
8113 PLOG(p, HIGH, "CG-NAPT");
8114 /* Initialize all counters and arrays */
8116 p_nat->n_cgnapt_entry_deleted = 0;
8117 p_nat->n_cgnapt_entry_added = 0;
8118 p_nat->naptedPktCount = 0;
8119 p_nat->naptDroppedPktCount = 0;
8120 p_nat->inaptedPktCount = 0;
8121 p_nat->enaptedPktCount = 0;
8122 p_nat->receivedPktCount = 0;
8123 p_nat->missedPktCount = 0;
8124 p_nat->dynCgnaptCount = 0;
8125 p_nat->arpicmpPktCount = 0;
8127 p_nat->app_params_addr = (uint64_t) arg;
8128 for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
8129 p_nat->links_map[i] = 0xff;
8130 p_nat->outport_id[i] = 0xff;
8131 cgnapt_in_port_egress_prv[i] = 0;
8132 cgnapt_prv_que_port_index[i] = 0;
8134 p_nat->pipeline_num = 0xff;
8135 p_nat->hw_checksum_reqd = 0;
8136 p_nat->pub_ip_port_set = NULL;
8137 p_nat->pub_ip_count = 0;
8138 p_nat->traffic_type = TRAFFIC_TYPE_IPV4;
8139 p_nat->vnf_set = 0xff;
8141 /* For every init it should be reset */
8142 napt_port_alloc_elem_count = 0;
8144 #ifdef CGNAPT_TIMING_INST
8145 p_nat->in_port_exit_timestamp = 0;
8146 p_nat->external_time_sum = 0;
8147 p_nat->internal_time_sum = 0;
8148 p_nat->time_measurements = 0;
8149 p_nat->max_time_mesurements = 10000;
8150 p_nat->time_measurements_on = 0;
8153 #ifdef CGNAPT_DEBUGGING
8155 p_nat->naptDebugCount = 0;
8157 p_nat->naptDroppedPktCount1 = 0;
8158 p_nat->naptDroppedPktCount2 = 0;
8159 p_nat->naptDroppedPktCount3 = 0;
8160 p_nat->naptDroppedPktCount4 = 0;
8161 p_nat->naptDroppedPktCount5 = 0;
8162 p_nat->naptDroppedPktCount6 = 0;
8164 p_nat->missedpktcount1 = 0;
8165 p_nat->missedpktcount2 = 0;
8166 p_nat->missedpktcount3 = 0;
8167 p_nat->missedpktcount4 = 0;
8168 p_nat->missedpktcount5 = 0;
8169 p_nat->missedpktcount6 = 0;
8170 p_nat->missedpktcount7 = 0;
8171 p_nat->missedpktcount8 = 0;
8172 p_nat->missedpktcount9 = 0;
8173 p_nat->missedpktcount10 = 0;
8174 p_nat->missedpktcount11 = 0;
8175 p_nat->missedpktcount12 = 0;
8177 p_nat->max_port_dec_err1 = 0;
8178 p_nat->max_port_dec_err2 = 0;
8179 p_nat->max_port_dec_err3 = 0;
8180 p_nat->max_port_dec_success = 0;
8196 static int sip_enabled;
8200 #endif /* SIP_ALG */
8202 /*struct rte_pipeline_table_entry *entries[RTE_HASH_LOOKUP_BULK_MAX];*/
8203 /* bitmap of valid packets */
8204 p_nat->valid_packets = 0;
8205 /* bitmap of invalid packets to be dropped */
8206 p_nat->invalid_packets = 0;
8208 for (i = 0; i < RTE_HASH_LOOKUP_BULK_MAX; i++)
8209 p_nat->key_ptrs[i] = &(p_nat->keys[i]);
8211 p_nat->port_alloc_ring = NULL;
8213 /* Parse arguments */
8214 if (pipeline_cgnapt_parse_args(p_nat, params))
8217 p_nat->vnf_set = vnf_set_count;
8221 struct rte_pipeline_params pipeline_params = {
8222 .name = params->name,
8223 .socket_id = params->socket_id,
8224 .offset_port_id = cgnapt_meta_offset,
8227 p->p = rte_pipeline_create(&pipeline_params);
8235 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8237 uint32_t instr_size =
8238 RTE_CACHE_LINE_ROUNDUP((sizeof(uint64_t)) *
8241 (uint64_t *) rte_zmalloc(NULL, instr_size,
8242 RTE_CACHE_LINE_SIZE);
8244 (uint64_t *) rte_zmalloc(NULL, instr_size,
8245 RTE_CACHE_LINE_SIZE);
8247 (uint32_t *) rte_zmalloc(NULL, instr_size / 2,
8248 RTE_CACHE_LINE_SIZE);
8249 if ((inst_start_time == NULL) || (inst_end_time == NULL)
8250 || (inst_diff_time == NULL)) {
8251 printf("Inst array alloc failed .... ");
8256 /* Memory allocation for in_port_h_arg */
8257 in_ports_arg_size = RTE_CACHE_LINE_ROUNDUP(
8258 (sizeof(struct pipeline_cgnapt_in_port_h_arg)) *
8259 (params->n_ports_in));
8260 struct pipeline_cgnapt_in_port_h_arg *ap =
8261 (struct pipeline_cgnapt_in_port_h_arg *)
8264 RTE_CACHE_LINE_SIZE);
8268 myApp = (struct app_params *) arg;
8271 p->n_ports_in = params->n_ports_in;
8272 for (i = 0; i < p->n_ports_in; i++) {
8273 /* passing our cgnapt pipeline in call back arg */
8275 (ap[i]).in_port_id = i;
8277 struct rte_pipeline_port_in_params port_params = {
8279 pipeline_port_in_params_get_ops(¶ms->port_in
8282 pipeline_port_in_params_convert(¶ms->port_in
8284 .f_action = cgnapt_in_port_ah_mix,
8286 .burst_size = params->port_in[i].burst_size,
8289 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8291 instrumentation_port_in_arg = &(ap[i]);
8294 if (p_nat->traffic_type == TRAFFIC_TYPE_IPV4) {
8295 /* Private in-port handler */
8296 /* Multiport changes */
8297 if (cgnapt_in_port_egress_prv[i]) {
8298 port_params.f_action =
8299 cgnapt_in_port_ah_ipv4_prv;
8300 printf("CGNAPT port %d is IPv4 Prv\n", i);
8302 port_params.f_action =
8303 cgnapt_in_port_ah_ipv4_pub;
8304 printf("CGNAPT port %d is IPv4 Pub\n", i);
8308 if (p_nat->traffic_type == TRAFFIC_TYPE_IPV6) {
8309 if (cgnapt_in_port_egress_prv[i]) {
8310 port_params.f_action =
8311 cgnapt_in_port_ah_ipv6_prv;
8312 printf("CGNAPT port %d is IPv6 Prv\n", i);
8314 port_params.f_action =
8315 cgnapt_in_port_ah_ipv6_pub;
8316 printf("CGNAPT port %d is IPv6 Pub\n", i);
8320 int status = rte_pipeline_port_in_create(p->p,
8325 rte_pipeline_free(p->p);
8333 p->n_ports_out = params->n_ports_out;
8334 for (i = 0; i < p->n_ports_out; i++) {
8335 struct rte_pipeline_port_out_params port_params = {
8336 .ops = pipeline_port_out_params_get_ops(
8337 ¶ms->port_out[i]),
8338 .arg_create = pipeline_port_out_params_convert(
8339 ¶ms->port_out[i]),
8340 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
8341 .f_action = port_out_ah_cgnapt,
8348 int status = rte_pipeline_port_out_create(p->p,
8350 &p->port_out_id[i]);
8353 rte_pipeline_free(p->p);
8359 int pipeline_num = 0;
8361 ignore = sscanf(params->name, "PIPELINE%d", &pipeline_num);
8363 printf("Not able to read pipeline number\n");
8366 p_nat->pipeline_num = (uint8_t) pipeline_num;
8367 register_pipeline_Qs(p_nat->pipeline_num, p);
8368 set_link_map(p_nat->pipeline_num, p, p_nat->links_map);
8369 set_outport_id(p_nat->pipeline_num, p, p_nat->outport_id);
8375 if (napt_common_table == NULL) {
8376 if (create_napt_common_table(p_nat->n_flows)) {
8378 "CG-NAPT create_napt_common_table failed.");
8383 struct rte_pipeline_table_params table_params = {
8384 .ops = &rte_table_stub_ops,
8386 .f_action_hit = NULL,
8387 .f_action_miss = NULL,
8389 .action_data_size = 0,
8392 int status = rte_pipeline_table_create(p->p,
8397 rte_pipeline_free(p->p);
8401 struct rte_pipeline_table_entry default_entry = {
8402 .action = RTE_PIPELINE_ACTION_PORT_META
8404 struct rte_pipeline_table_entry *default_entry_ptr;
8405 status = rte_pipeline_table_default_entry_add(
8409 &default_entry_ptr);
8411 rte_pipeline_free(p->p);
8417 /* Connecting input ports to tables */
8418 for (i = 0; i < p->n_ports_in; i++) {
8419 int status = rte_pipeline_port_in_connect_to_table(p->p,
8426 rte_pipeline_free(p->p);
8432 /* Enable input ports */
8433 for (i = 0; i < p->n_ports_in; i++) {
8434 int status = rte_pipeline_port_in_enable(p->p,
8438 rte_pipeline_free(p->p);
8444 /* Check pipeline consistency */
8445 if (rte_pipeline_check(p->p) < 0) {
8446 rte_pipeline_free(p->p);
8451 /* Message queues */
8452 p->n_msgq = params->n_msgq;
8453 for (i = 0; i < p->n_msgq; i++)
8454 p->msgq_in[i] = params->msgq_in[i];
8455 for (i = 0; i < p->n_msgq; i++)
8456 p->msgq_out[i] = params->msgq_out[i];
8458 /* Message handlers */
8459 memcpy(p->handlers, handlers, sizeof(p->handlers));
8460 memcpy(p_nat->custom_handlers,
8461 custom_handlers, sizeof(p_nat->custom_handlers));
8463 if (!p_nat->is_static_cgnapt) {
8464 printf("Initializing dyn napt components ... %d\n",
8465 p_nat->pipeline_num);
8466 if (napt_port_alloc_init(p_nat) == -1) {
8467 printf("Error - napt_port_alloc_init failed - %d\n",
8468 p_nat->pipeline_num);
8473 if (max_port_per_client_hash == NULL) {
8474 rc = init_max_port_per_client(p_nat);
8476 printf("CGNAPT Error - "
8477 "init_max_port_per_client failed %d", rc);
8484 if (!icmp_pool_init) {
8486 /* create the arp_icmp mbuf rx pool */
8487 cgnapt_icmp_pktmbuf_tx_pool =
8488 rte_pktmbuf_pool_create("icmp_mbuf_tx_pool", 63, 32, 0,
8489 RTE_MBUF_DEFAULT_BUF_SIZE,
8491 if (cgnapt_icmp_pktmbuf_tx_pool == NULL) {
8492 PLOG(p, HIGH, "ICMP mbuf pool create failed.");
8497 rte_pktmbuf_alloc(cgnapt_icmp_pktmbuf_tx_pool);
8499 if (cgnapt_icmp_pkt == NULL) {
8500 printf("Failed to allocate cgnapt_icmp_pkt\n");
8507 cgnat_cnxn_tracker = rte_zmalloc(NULL, rte_ct_get_cnxn_tracker_size(),
8508 RTE_CACHE_LINE_SIZE);
8510 if (cgnat_cnxn_tracker == NULL) {
8511 printf("CGNAPT CT memory not allocated\n");
8514 rte_ct_initialize_default_timeouts(cgnat_cnxn_tracker);
8516 printf("CGNAPT CT Flows %d\n", p_nat->n_flows);
8518 ret = rte_ct_initialize_cnxn_tracker(cgnat_cnxn_tracker,
8520 "CGNAT_CT_COMMON_TABLE");
8530 if (pcp_init() == PCP_INIT_SUCCESS)
8531 printf("PCP contents are initialized successfully\n");
8533 printf("Error in initializing PCP contents\n");
8540 * Function for pipeline cleanup
8543 * A void pointer to pipeline
8548 static int pipeline_cgnapt_free(void *pipeline)
8550 struct pipeline *p = (struct pipeline *)pipeline;
8552 /* Check input arguments */
8556 /* Free resources */
8557 rte_pipeline_free(p->p);
8563 pipeline_cgnapt_track(void *pipeline, __rte_unused uint32_t port_in,
8566 struct pipeline *p = (struct pipeline *)pipeline;
8568 /* Check input arguments */
8569 if ((p == NULL) || (port_in >= p->n_ports_in) || (port_out == NULL))
8572 if (p->n_ports_in == 1) {
8581 * Function for pipeline timers
8584 * A void pointer to pipeline
8589 static int pipeline_cgnapt_timer(void *pipeline)
8591 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)pipeline;
8593 pipeline_msg_req_handle(&p_nat->p);
8595 rte_pipeline_flush(((struct pipeline *)p_nat)->p);
8601 * Function for pipeline custom handlers
8604 * A void pointer to pipeline
8606 * void pointer for incoming data
8609 * void pointer of response
8611 void *pipeline_cgnapt_msg_req_custom_handler(struct pipeline *p, void *msg)
8613 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
8614 struct pipeline_custom_msg_req *req = msg;
8615 pipeline_msg_req_handler f_handle;
8617 f_handle = (req->subtype < PIPELINE_CGNAPT_MSG_REQS) ?
8618 p_nat->custom_handlers[req->subtype] :
8619 pipeline_msg_req_invalid_handler;
8621 if (f_handle == NULL)
8622 f_handle = pipeline_msg_req_invalid_handler;
8624 return f_handle(p, req);
8628 * Function for adding NSP data
8631 * A void pointer to pipeline
8633 * void pointer for incoming data
8636 * void pointer of response
8638 void *pipeline_cgnapt_msg_req_nsp_add_handler(
8639 __rte_unused struct pipeline *p,
8642 struct pipeline_cgnapt_nsp_add_msg_req *req = msg;
8643 struct pipeline_cgnapt_nsp_add_msg_rsp *rsp = msg;
8645 struct cgnapt_nsp_node *node = NULL, *ll = nsp_ll;
8648 (req->nsp.depth == 32 || req->nsp.depth == 40
8649 || req->nsp.depth == 48 || req->nsp.depth == 56
8650 || req->nsp.depth == 64 || req->nsp.depth == 96)) {
8656 printf("be initial cond\n");
8657 if (nsp_ll == NULL) {
8658 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_nsp_node));
8659 node = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8661 printf("be 1st cond\n");
8667 memcpy(&node->nsp, &req->nsp,
8668 sizeof(struct pipeline_cgnapt_nsp_t));
8672 while (ll != NULL) {
8673 if (!memcmp(ll->nsp.prefix, req->nsp.prefix, 16)
8674 && ll->nsp.depth == req->nsp.depth) {
8675 printf("be 2st cond\n");
8683 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct cgnapt_nsp_node));
8684 node = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8686 printf("be 3st cond\n");
8692 memcpy(&node->nsp, &req->nsp,
8693 sizeof(struct pipeline_cgnapt_nsp_t));
8694 node->next = nsp_ll;
8701 printf("be 4st cond\n");
8706 * Function for deleting NSP data
8709 * A void pointer to pipeline
8711 * void pointer for incoming data
8714 * void pointer of response
8716 void *pipeline_cgnapt_msg_req_nsp_del_handler(
8717 __rte_unused struct pipeline *p,
8720 struct pipeline_cgnapt_nsp_del_msg_req *req = msg;
8721 struct pipeline_cgnapt_nsp_del_msg_rsp *rsp = msg;
8722 struct cgnapt_nsp_node *prev = NULL, *ll = nsp_ll;
8724 while (ll != NULL) {
8725 if (!memcmp(ll->nsp.prefix, req->nsp.prefix, 16)
8726 && ll->nsp.depth == req->nsp.depth) {
8728 prev->next = ll->next;
8751 * Function for adding NAPT entry
8754 * A void pointer to pipeline
8756 * void pointer for incoming data
8759 * void pointer of response
8761 void *pipeline_cgnapt_msg_req_entry_add_handler(struct pipeline *p, void *msg)
8763 struct pipeline_cgnapt_entry_add_msg_req *req = msg;
8764 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
8765 uint8_t type = req->data.type;
8766 uint32_t src_ip = (type == CGNAPT_ENTRY_IPV4) ?
8767 req->data.u.prv_ip :
8768 rte_bswap32(req->data.u.u32_prv_ipv6[3]);
8770 uint8_t src_ipv6[16];
8772 uint32_t dest_ip = req->data.pub_ip;
8773 uint16_t src_port = req->data.prv_port;
8774 uint16_t dest_port = req->data.pub_port;
8775 uint16_t rx_port = req->data.prv_phy_port;
8776 uint32_t ttl = req->data.ttl;
8778 if (type == CGNAPT_ENTRY_IPV6)
8779 memcpy(src_ipv6, req->data.u.prv_ipv6, 16);
8781 printf("CG-NAPT addm - PrvIP %x, PrvPort %d,", src_ip, src_port);
8782 printf("PubIP %x, PubPort %d,", dest_ip, dest_port);
8784 printf("PhyPort %d, ttl %u,", rx_port, ttl);
8785 printf("entry_type %d\n", type);
8786 #ifdef NAT_ONLY_CONFIG_REQ
8787 if (nat_only_config_flag) {
8788 if (!p_nat->is_static_cgnapt) {
8791 for (i = 0; i < p_nat->pub_ip_range_count; i++) {
8792 if (((dest_ip >= p_nat->pub_ip_range[i].start_ip)
8793 && (dest_ip <= p_nat->pub_ip_range[i].end_ip))) {
8794 printf("Error - static port cannot be in Dynamic "
8796 printf("%x-%x\n", p_nat->pub_ip_range[i].start_ip,
8797 p_nat->pub_ip_range[i].end_ip);
8803 if (pipeline_cgnapt_msg_req_entry_addm_pair(p, msg,
8809 printf("pipeline_cgnapt_msg_req_entry_addm_handler\n");
8813 #ifdef CGNAPT_DBG_PRNT
8814 printf("Success - pipeline_cgnapt_msg_req_entry_addm_handler");
8815 printf("added %d rule pairs.\n", count);
8821 if (!p_nat->is_static_cgnapt) {
8824 for (i = 0; i < p_nat->pub_ip_count; i++) {
8825 /* Check port range if same Public-IP */
8826 if (dest_ip != p_nat->pub_ip_port_set[i].ip)
8828 if (((dest_port >= p_nat->pub_ip_port_set[i].start_port) &&
8829 (dest_port <= p_nat->pub_ip_port_set[i].end_port))) {
8830 printf("Error - port cannot be in Dynamic "
8831 "port range %d-%d\n",
8832 p_nat->pub_ip_port_set[i].start_port,
8833 p_nat->pub_ip_port_set[i].end_port);
8839 if (pipeline_cgnapt_msg_req_entry_addm_pair
8840 (p, msg, src_ip, src_port, dest_ip, dest_port, rx_port,
8841 ttl, type, src_ipv6)) {
8842 printf("Error - pipeline_cgnapt_msg_req_entry_add_handler\n");
8847 #ifdef CGNAPT_DBG_PRNT
8848 printf("\nSuccess - pipeline_cgnapt_msg_req_entry_add_handler "
8855 * Function for adding a NAPT entry pair
8858 * A void pointer to pipeline
8860 * void pointer for incoming data
8866 * destination ip address
8870 * Physical receive port
8872 * time to live value
8874 * type of entry IPv4 vs IPv6
8876 * uint8_t array of IPv6 address
8879 * 0 if success, negative if fails
8882 pipeline_cgnapt_msg_req_entry_addm_pair(
8883 struct pipeline *p, __rte_unused void *msg,
8884 uint32_t src_ip, uint16_t src_port,
8885 uint32_t dest_ip, uint16_t dest_port,
8886 uint16_t rx_port, uint32_t ttl,
8887 uint8_t type, uint8_t src_ipv6[16])
8890 struct pipeline_cgnapt_entry_key key;
8891 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
8894 key.port = src_port;
8897 struct cgnapt_table_entry entry = {
8899 .action = RTE_PIPELINE_ACTION_PORT,
8900 .port_id = CGNAPT_PUB_PORT_ID,
8904 /*.prv_ip = src_ip, */
8905 .prv_port = src_port,
8907 .pub_port = dest_port,
8908 .prv_phy_port = rx_port,
8909 .pub_phy_port = get_prv_to_pub_port(&dest_ip,
8912 .timeout = STATIC_CGNAPT_TIMEOUT,
8919 if (type == CGNAPT_ENTRY_IPV4) {
8920 entry.data.type = CGNAPT_ENTRY_IPV4;
8921 entry.data.u.prv_ip = src_ip;
8923 entry.data.type = CGNAPT_ENTRY_IPV6;
8924 memcpy(entry.data.u.prv_ipv6, src_ipv6, 16);
8927 /* Also need to add a paired entry on our own */
8929 * Need to change key
8930 * Need to change entry header
8931 * Will keep the same entry and take care
8932 * of translation in table hit handler
8934 struct pipeline_cgnapt_entry_key second_key;
8936 /* Need to add a second ingress entry */
8937 second_key.ip = dest_ip;
8938 second_key.port = dest_port;
8939 second_key.pid = 0xffff;
8941 #ifdef NAT_ONLY_CONFIG_REQ
8942 if (nat_only_config_flag) {
8944 entry.data.pub_port = 0xffff;
8945 second_key.port = 0xffff;
8949 int32_t position = rte_hash_add_key(napt_common_table, &key);
8952 printf("CG-NAPT entry bulk add failed");
8953 printf(" ... returning without adding ...\n");
8957 memcpy(&napt_hash_tbl_entries[position], &entry,
8958 sizeof(struct cgnapt_table_entry));
8960 #ifdef CGNAPT_DEBUGGING
8961 if (p_nat->kpc1++ < 5)
8965 p_nat->n_cgnapt_entry_added++;
8967 /* Now modify the forward port for reverse entry */
8968 entry.head.port_id = CGNAPT_PRV_PORT_ID;
8970 position = rte_hash_add_key(napt_common_table, &second_key);
8973 printf("CG-NAPT entry reverse bulk add failed");
8974 printf(" ... returning with fwd add ...%d\n", position);
8978 memcpy(&napt_hash_tbl_entries[position], &entry,
8979 sizeof(struct cgnapt_table_entry));
8981 #ifdef CGNAPT_DEBUGGING
8982 if (p_nat->kpc1 < 5)
8983 print_key(&second_key);
8986 p_nat->n_cgnapt_entry_added++;
8991 * Function for adding multiple NAPT entries
8994 * A void pointer to pipeline
8996 * void pointer for incoming data
8999 * void pointer of response
9001 void *pipeline_cgnapt_msg_req_entry_addm_handler(struct pipeline *p, void *msg)
9003 struct pipeline_cgnapt_entry_addm_msg_req *req = msg;
9004 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9006 uint32_t max_ue = req->data.num_ue;
9007 uint8_t type = req->data.type;
9008 uint32_t src_ip = (type == CGNAPT_ENTRY_IPV4) ?
9009 req->data.u.prv_ip :
9010 rte_bswap32(req->data.u.u32_prv_ipv6[3]);
9012 uint8_t src_ipv6[16];
9014 uint32_t dest_ip = req->data.pub_ip;
9015 uint16_t src_port = req->data.prv_port;
9016 uint16_t dest_port = req->data.pub_port;
9017 uint16_t rx_port = req->data.prv_phy_port;
9018 uint32_t ttl = req->data.ttl;
9019 uint16_t max_src_port = req->data.prv_port_max;
9020 uint16_t max_dest_port = req->data.pub_port_max;
9022 uint16_t src_port_start = src_port;
9023 uint16_t dest_port_start = dest_port;
9024 uint32_t src_ip_temp;
9026 if (type == CGNAPT_ENTRY_IPV6)
9027 memcpy(src_ipv6, req->data.u.prv_ipv6, 16);
9029 printf("CG-NAPT addm - PrvIP %x, PrvPort %d,", src_ip, src_port);
9030 printf("PubIP %x, PubPort %d,", dest_ip, dest_port);
9031 printf("PhyPort %d, ttl %u, NumUe %d,", rx_port, ttl, max_ue);
9032 printf("mPrvPort %d, mPubPort %d,", max_src_port, max_dest_port);
9033 printf("entry_type %d\n", type);
9034 #ifdef NAT_ONLY_CONFIG_REQ
9035 if (nat_only_config_flag) {
9036 if (!p_nat->is_static_cgnapt) {
9039 for (i = 0; i < p_nat->pub_ip_range_count; i++) {
9040 if (((dest_ip >= p_nat->pub_ip_range[i].start_ip)
9041 && (dest_ip <= p_nat->pub_ip_range[i].end_ip)) ||
9042 (((dest_ip + max_ue) >=
9043 p_nat->pub_ip_range[i].start_ip) &&
9044 ((dest_ip + max_ue) <=
9045 p_nat->pub_ip_range[i].end_ip))) {
9046 printf("Error - static port cannot be in Dynamic "
9048 printf("%x-%x\n", p_nat->pub_ip_range[i].start_ip,
9049 p_nat->pub_ip_range[i].end_ip);
9056 for (uenum = 0; uenum < max_ue; uenum++) {
9058 if (pipeline_cgnapt_msg_req_entry_addm_pair(p, msg,
9064 printf("pipeline_cgnapt_msg_req_entry_addm_handler\n");
9074 #ifdef CGNAPT_DBG_PRNT
9075 printf("Success - pipeline_cgnapt_msg_req_entry_addm_handler");
9076 printf("added %d rule pairs.\n", count);
9083 if (!p_nat->is_static_cgnapt) {
9086 for (i = 0; i < p_nat->pub_ip_count; i++) {
9087 /* Check port range if same Public-IP */
9088 if (dest_ip != p_nat->pub_ip_port_set[i].ip)
9090 if (((dest_port >= p_nat->pub_ip_port_set[i].start_port) &&
9091 (dest_port <= p_nat->pub_ip_port_set[i].end_port)) ||
9092 ((max_dest_port >= p_nat->pub_ip_port_set[i].start_port)
9093 && max_dest_port <= p_nat->pub_ip_port_set[i].end_port)) {
9094 printf("Error - port cannot be in Dynamic port range %d-%d\n",
9095 p_nat->pub_ip_port_set[i].start_port,
9096 p_nat->pub_ip_port_set[i].end_port);
9102 for (uenum = 0; uenum < max_ue; uenum++) {
9103 if (pipeline_cgnapt_msg_req_entry_addm_pair
9104 (p, msg, src_ip, src_port, dest_ip, dest_port, rx_port,
9105 ttl, type, src_ipv6)) {
9106 printf("Error - pipeline_cgnapt_msg_req_entry_addm_handler\n");
9113 if (src_port > max_src_port) {
9114 src_port = src_port_start;
9116 if (req->data.type == CGNAPT_ENTRY_IPV6) {
9117 src_ip_temp = rte_bswap32(src_ip);
9118 memcpy(&src_ipv6[12], &src_ip_temp, 4);
9122 if (dest_port > max_dest_port) {
9123 dest_port = dest_port_start;
9128 #ifdef CGNAPT_DBG_PRNT
9129 printf("\nSuccess - pipeline_cgnapt_msg_req_entry_addm_handler added");
9130 printf("%d rule pairs.\n", count);
9136 * Function for deleting NAPT entry
9139 * A void pointer to pipeline
9141 * void pointer for incoming data
9144 * void pointer of response
9146 void *pipeline_cgnapt_msg_req_entry_del_handler(struct pipeline *p, void *msg)
9148 struct pipeline_cgnapt_entry_delete_msg_req *req = msg;
9149 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9150 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9153 uint8_t *KeyP = (void *)(&req->key);
9156 printf("pipeline_cgnapt_msg_req_entry_del_handler - Key: ");
9157 for (i = 0; i < (int)sizeof(struct pipeline_cgnapt_entry_key);
9159 printf(" %02x", KeyP[i]);
9160 printf(" ,KeySize %u\n",
9161 (int)sizeof(struct pipeline_cgnapt_entry_key));
9164 struct cgnapt_table_entry entry;
9166 /* If ingress key */
9167 if (!is_phy_port_privte(req->key.pid))
9168 req->key.pid = 0xffff;
9170 #ifdef NAT_ONLY_CONFIG_REQ
9171 if (nat_only_config_flag)
9172 req->key.port = 0xffff;
9176 position = rte_hash_lookup(napt_common_table, &req->key);
9177 if (position == -ENOENT) {
9178 printf("Entry not found\n");
9181 memcpy(&entry, &napt_hash_tbl_entries[position],
9182 sizeof(struct cgnapt_table_entry));
9183 position = rte_hash_del_key(napt_common_table, &req->key);
9184 p_nat->n_cgnapt_entry_deleted++;
9186 struct pipeline_cgnapt_entry_key second_key;
9188 if (is_phy_port_privte(req->key.pid)) {
9189 /* key is for egress - make second key for ingress */
9190 second_key.ip = entry.data.pub_ip;
9191 second_key.port = entry.data.pub_port;
9192 second_key.pid = 0xffff;
9195 /* key is for ingress - make second key for egress */
9196 second_key.ip = entry.data.u.prv_ip;
9197 second_key.port = entry.data.prv_port;
9198 second_key.pid = entry.data.prv_phy_port;
9201 #ifdef NAT_ONLY_CONFIG_REQ
9202 if (nat_only_config_flag)
9203 second_key.port = 0xffff;
9206 position = rte_hash_del_key(napt_common_table, &second_key);
9207 p_nat->n_cgnapt_entry_deleted++;
9212 void *pipeline_cgnapt_msg_req_entry_sync_handler(struct pipeline *p, void *msg)
9214 struct pipeline_cgnapt_entry_delete_msg_req *req = msg;
9215 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9217 rsp->status = rte_pipeline_table_entry_delete(
9221 &rsp->key_found, NULL);
9227 * Function to print the NAPT key
9230 * A pointer to struct pipeline_cgnapt_entry_key
9232 void print_key(struct pipeline_cgnapt_entry_key *key)
9234 uint8_t *KeyP = (void *)(key);
9238 for (i = 0; i < (int)sizeof(struct pipeline_cgnapt_entry_key); i++)
9239 printf(" %02x", KeyP[i]);
9243 * Function to print the table entry
9246 * A pointer to struct rte_pipeline_table_entry
9248 void print_entry1(struct rte_pipeline_table_entry *entry)
9250 uint8_t *entryP = (void *)(entry);
9254 for (i = 0; i < (int)sizeof(struct rte_pipeline_table_entry); i++)
9255 printf(" %02x", entryP[i]);
9259 * Function to print the NAPT table entry
9262 * A pointer to struct cgnapt_table_entry
9264 void print_cgnapt_entry(struct cgnapt_table_entry *entry)
9266 uint8_t *entryP = (void *)(entry);
9269 printf("CGNAPT Entry: ");
9270 for (i = 0; i < (int)sizeof(struct cgnapt_table_entry); i++)
9271 printf(" %02x", entryP[i]);
9272 printf(" size:%d\n", (int)sizeof(struct cgnapt_table_entry));
9276 * Function to get a free port
9279 * A pointer to struct pipeline_cgnapt
9281 * A uint32_t pointer to return corresponding ip address
9284 * free port number, 0 if error
9286 int get_free_iport(struct pipeline_cgnapt *p_nat, uint32_t *public_ip)
9289 /* If we don't have a valid napt_port_alloc_elem get one from
9292 if (p_nat->allocated_ports == NULL) {
9296 ret = rte_ring_dequeue(p_nat->port_alloc_ring, &ports);
9298 p_nat->allocated_ports =
9299 (struct napt_port_alloc_elem *)ports;
9301 #ifdef CGNAPT_DEBUGGING
9305 #ifdef CGNAPT_DBG_PRNT
9306 if (CGNAPT_DEBUG > 3)
9307 printf("p_nat->allocated_ports %p\n",
9308 p_nat->allocated_ports);
9311 printf("CGNAPT Err - get_free_iport rte_ring_dequeue "
9313 printf("%d, %d, %d\n", rte_ring_count(
9314 p_nat->port_alloc_ring), rte_ring_free_count(
9315 p_nat->port_alloc_ring), ret);
9317 #ifdef CGNAPT_DEBUGGING
9318 #ifdef CGNAPT_DBG_PRNT
9319 printf("Th%d GFP:: %" PRIu64 ", %" PRIu64 ", "
9320 "%" PRIu64", %" PRIu64 ",\n", p_nat->pipeline_num,
9321 p_nat->gfp_get, p_nat->gfp_ret, p_nat->gfp_suc,
9331 /* get the port from index count-1 and decrease count */
9332 port = p_nat->allocated_ports->ports
9333 [p_nat->allocated_ports->count - 1];
9334 *public_ip = p_nat->allocated_ports->ip_addr
9335 [p_nat->allocated_ports->count - 1];
9337 p_nat->allocated_ports->count -= 1;
9339 /* if count is zero, return buffer to mem pool */
9340 if (p_nat->allocated_ports->count == 0) {
9341 rte_mempool_put(napt_port_pool, p_nat->allocated_ports);
9343 #ifdef CGNAPT_DEBUGGING
9345 #ifdef CGNAPT_DBG_PRNT
9346 printf("Th%d Returned to pool p_nat->allocated_ports %p,",
9347 p_nat->pipeline_num, p_nat->allocated_ports);
9348 printf("%" PRIu64 ", %" PRIu64 ",",
9349 p_nat->gfp_get, p_nat->gfp_ret);
9350 printf("%" PRIu64 ", %" PRIu64 ",\n",
9351 p_nat->gfp_suc, p_nat->gfp_err);
9355 p_nat->allocated_ports = NULL;
9358 #ifdef CGNAPT_DEBUGGING
9366 * Function to free a port
9369 * Port number to free
9371 * Corresponding ip address
9373 * A pointer to struct pipeline_cgnapt
9376 void release_iport(uint16_t port_num, uint32_t public_ip,
9377 struct pipeline_cgnapt *p_nat)
9379 /* If we don't have a valid napt_port_alloc_elem get one
9382 if (p_nat->free_ports == NULL) {
9385 #ifdef CGNAPT_DEBUGGING
9389 if (rte_mempool_get(napt_port_pool, &ports) < 0) {
9390 #ifdef CGNAPT_DEBUGGING
9393 printf("CGNAPT release_iport error in getting "
9394 "port alloc buffer\n");
9398 p_nat->free_ports = (struct napt_port_alloc_elem *)ports;
9399 p_nat->free_ports->count = 0;
9402 /* put the port at index count and increase count */
9403 p_nat->free_ports->ip_addr[p_nat->free_ports->count] = public_ip;
9404 p_nat->free_ports->ports[p_nat->free_ports->count] = port_num;
9405 p_nat->free_ports->count += 1;
9407 /* if napt_port_alloc_elem is full add it to ring */
9410 #ifdef CGNAPT_DEBUGGING
9414 #ifdef CGNAPT_DBG_PRNT
9415 if (CGNAPT_DEBUG >= 2) {
9416 printf("CGNAPT port_alloc_ring before EnQ Cnt %d, Free %d\n",
9417 rte_ring_count(p_nat->port_alloc_ring),
9418 rte_ring_free_count(p_nat->port_alloc_ring));
9422 if (rte_ring_enqueue(p_nat->port_alloc_ring,
9423 (void *)p_nat->free_ports) != 0) {
9424 printf("CGNAPT release_iport Enqueue error %p\n",
9427 #ifdef CGNAPT_DEBUGGING
9432 #ifdef CGNAPT_DBG_PRNT
9433 if (CGNAPT_DEBUG >= 2) {
9434 printf("CGNAPT port_alloc_ring after EnQ Cnt %d",
9435 rte_ring_count(p_nat->port_alloc_ring));
9437 rte_ring_free_count(p_nat->port_alloc_ring));
9441 p_nat->free_ports = NULL;
9444 #ifdef CGNAPT_DEBUGGING
9450 * Function to initialize max ports per client data structures
9451 * Called during dynamic NAPT initialization.
9454 * A pointer to struct pipeline_cgnapt
9457 * 0 if success, negative if error
9459 int init_max_port_per_client(
9460 __rte_unused struct pipeline_cgnapt *p_nat)
9462 if (max_port_per_client_hash)
9465 /*MPPC_ALREADY_EXISTS */
9469 max_port_per_client_hash =
9470 rte_hash_create(&max_port_per_client_hash_params);
9471 if (!max_port_per_client_hash)
9474 /*MPPC_HASH_CREATE_ERROR */
9476 max_port_per_client_array =
9478 sizeof(struct max_port_per_client) * MAX_DYN_ENTRY,
9479 RTE_CACHE_LINE_SIZE);
9480 if (!max_port_per_client_array)
9483 /*MPPC_ARRAY_CREATE_ERROR */
9485 for (i = 0; i < MAX_DYN_ENTRY; i++) {
9486 max_port_per_client_array[i].prv_ip = 0;
9487 max_port_per_client_array[i].prv_phy_port = 0;
9488 max_port_per_client_array[i].max_port_cnt = 0;
9496 * Function to check if max ports for a client is reached
9498 * @param prv_ip_param
9499 * A uint32_t ip address of client
9500 * @param prv_phy_port_param
9501 * A uint32_t physical port id of the client
9503 * A pointer to struct pipeline_cgnapt
9506 * 0 if max port not reached, 1 if reached, -1 if error
9508 int is_max_port_per_client_reached(uint32_t prv_ip_param,
9509 uint32_t prv_phy_port_param,
9510 struct pipeline_cgnapt *p_nat)
9512 int index = MAX_PORT_INVALID_KEY;
9514 struct max_port_per_client_key key = {
9515 .prv_ip = prv_ip_param,
9516 .prv_phy_port = prv_phy_port_param,
9519 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9522 return MAX_PORT_INVALID_KEY;
9524 if (max_port_per_client_array[index].max_port_cnt >=
9525 p_nat->max_port_per_client)
9526 return MAX_PORT_REACHED;
9528 return MAX_PORT_NOT_REACHED;
9532 * Function to increase max ports for a client
9534 * @param prv_ip_param
9535 * A uint32_t ip address of client
9536 * @param prv_phy_port_param
9537 * A uint32_t physical port id of the client
9539 * A pointer to struct pipeline_cgnapt
9542 * 0 if max port reached, 1 if success, 2 if new entry, -1 if error
9544 int increment_max_port_counter(uint32_t prv_ip_param,
9545 uint32_t prv_phy_port_param,
9546 struct pipeline_cgnapt *p_nat)
9548 int index = MAX_PORT_INC_ERROR;
9550 struct max_port_per_client_key key = {
9551 .prv_ip = prv_ip_param,
9552 .prv_phy_port = prv_phy_port_param,
9555 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9557 if (index == -EINVAL)
9558 return MAX_PORT_INC_ERROR;
9560 if (index == -ENOENT) {
9561 if (max_port_per_client_add_entry(prv_ip_param,
9564 return MAX_PORT_INC_ERROR;
9566 return 2; /*return MAX_PORT_NEW_ENTRY; */
9569 if (CGNAPT_DEBUG > 2)
9570 printf("%s: max_port_cnt(%d), p_nat_max(%d)\n", __func__,
9571 max_port_per_client_array[index].max_port_cnt,
9572 p_nat->max_port_per_client);
9574 if (max_port_per_client_array[index].max_port_cnt <
9575 p_nat->max_port_per_client) {
9576 max_port_per_client_array[index].max_port_cnt++;
9577 return MAX_PORT_INC_SUCCESS;
9580 return MAX_PORT_INC_REACHED;
9584 * Function to decrease max ports for a client
9586 * @param prv_ip_param
9587 * A uint32_t ip address of client
9588 * @param prv_phy_port_param
9589 * A uint32_t physical port id of the client
9591 * A pointer to struct pipeline_cgnapt
9594 * 0 if count already 0, 1 if success, -1 if error
9596 int decrement_max_port_counter(uint32_t prv_ip_param,
9597 uint32_t prv_phy_port_param,
9598 struct pipeline_cgnapt *p_nat)
9600 int index = MAX_PORT_DEC_ERROR;
9602 struct max_port_per_client_key key = {
9603 .prv_ip = prv_ip_param,
9604 .prv_phy_port = prv_phy_port_param,
9607 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9610 #ifdef CGNAPT_DEBUGGING
9611 p_nat->max_port_dec_err1++;
9613 return MAX_PORT_DEC_ERROR;
9617 if (max_port_per_client_array[index].max_port_cnt > 0) {
9618 /* If it is the last port,ret this info which is used for
9619 * max_cli_per_pub_ip
9622 max_port_per_client_array[index].max_port_cnt--;
9623 /* Count should be atomic but we are good as we have only
9624 * one task handling this counter at a time (core affinity)
9628 if (max_port_per_client_array[index].max_port_cnt <= 0) {
9629 if (max_port_per_client_del_entry
9630 (prv_ip_param, prv_phy_port_param, p_nat) <= 0) {
9632 #ifdef CGNAPT_DEBUGGING
9633 p_nat->max_port_dec_err2++;
9635 return MAX_PORT_DEC_ERROR;
9638 #ifdef CGNAPT_DEBUGGING
9639 p_nat->max_port_dec_err3++;
9642 return MAX_PORT_DEC_REACHED;
9645 #ifdef CGNAPT_DEBUGGING
9646 p_nat->max_port_dec_success++;
9649 return MAX_PORT_DEC_SUCCESS;
9653 * Function to add a max ports per client entry
9655 * @param prv_ip_param
9656 * A uint32_t ip address of client
9657 * @param prv_phy_port_param
9658 * A uint32_t physical port id of the client
9660 * A pointer to struct pipeline_cgnapt
9663 * 0 no success, 1 if success, -1 if error
9665 int max_port_per_client_add_entry(
9666 uint32_t prv_ip_param,
9667 uint32_t prv_phy_port_param,
9668 __rte_unused struct pipeline_cgnapt *p_nat)
9670 int index = MAX_PORT_ADD_ERROR;
9672 struct max_port_per_client_key key = {
9673 .prv_ip = prv_ip_param,
9674 .prv_phy_port = prv_phy_port_param,
9677 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9678 if (index == -EINVAL)
9679 return MAX_PORT_ADD_ERROR;
9682 return MAX_PORT_ADD_UNSUCCESS;
9684 if (index == -ENOENT) {
9686 #ifdef CGNAPT_DBG_PRNT
9687 if (CGNAPT_DEBUG > 2)
9688 printf("max_port_per_client_add_entry fn: "
9689 "Entry does not exist\n");
9693 rte_hash_add_key(max_port_per_client_hash,
9694 (const void *)&key);
9695 if (index == -ENOSPC)
9696 return MAX_PORT_ADD_UNSUCCESS;
9698 #ifdef CGNAPT_DBG_PRNT
9699 if (CGNAPT_DEBUG > 2)
9700 printf("max_port_per_client_add_entry fn:"
9701 "Add entry index(%d)\n", index);
9704 max_port_per_client_array[index].prv_ip = prv_ip_param;
9705 max_port_per_client_array[index].prv_phy_port =
9709 max_port_per_client_array[index].max_port_cnt++;
9710 return MAX_PORT_ADD_SUCCESS;
9714 * Function to delete a max ports per client entry
9716 * @param prv_ip_param
9717 * A uint32_t ip address of client
9718 * @param prv_phy_port_param
9719 * A uint32_t physical port id of the client
9721 * A pointer to struct pipeline_cgnapt
9724 * 0 no success, 1 if success, -1 if error
9726 int max_port_per_client_del_entry(
9727 uint32_t prv_ip_param,
9728 uint32_t prv_phy_port_param,
9729 __rte_unused struct pipeline_cgnapt *p_nat)
9731 int index = MAX_PORT_DEL_ERROR;
9733 struct max_port_per_client_key key = {
9734 .prv_ip = prv_ip_param,
9735 .prv_phy_port = prv_phy_port_param,
9738 index = rte_hash_lookup(max_port_per_client_hash, (const void *)&key);
9740 if (index == -EINVAL)
9741 return MAX_PORT_DEL_ERROR;
9743 if (index == -ENOENT)
9744 return MAX_PORT_DEL_UNSUCCESS;
9746 index = rte_hash_del_key(max_port_per_client_hash, (const void *)&key);
9747 max_port_per_client_array[index].prv_ip = 0;
9748 max_port_per_client_array[index].prv_phy_port = 0;
9749 max_port_per_client_array[index].max_port_cnt = 0;
9751 return MAX_PORT_DEL_SUCCESS;
9755 * Function to execute debug commands
9758 * A pointer to struct pipeline
9760 * void pointer to incoming arguments
9762 void *pipeline_cgnapt_msg_req_entry_dbg_handler(struct pipeline *p, void *msg)
9764 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
9766 struct pipeline_cgnapt *p_nat = (struct pipeline_cgnapt *)p;
9770 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_STATS_SHOW) {
9771 printf("\nCG-NAPT Packet Stats:\n");
9772 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
9773 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
9774 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
9775 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
9776 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
9777 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
9778 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
9780 #ifdef CGNAPT_DEBUGGING
9781 printf("\n Drop detail 1:%" PRIu64 ",",
9782 p_nat->naptDroppedPktCount1);
9783 printf("\n Drop detail 2:%" PRIu64 ",",
9784 p_nat->naptDroppedPktCount2);
9785 printf("\n Drop detail 3:%" PRIu64 ",",
9786 p_nat->naptDroppedPktCount3);
9787 printf("\n Drop detail 4:%" PRIu64 ",",
9788 p_nat->naptDroppedPktCount4);
9789 printf("\n Drop detail 5:%" PRIu64 ",",
9790 p_nat->naptDroppedPktCount5);
9791 printf("\n Drop detail 6:%" PRIu64 "",
9792 p_nat->naptDroppedPktCount6);
9794 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9795 p_nat->missedpktcount1,
9796 p_nat->missedpktcount2);
9797 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9798 p_nat->missedpktcount3,
9799 p_nat->missedpktcount4);
9800 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9801 p_nat->missedpktcount5,
9802 p_nat->missedpktcount6);
9803 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9804 p_nat->missedpktcount7,
9805 p_nat->missedpktcount8);
9806 printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "",
9807 p_nat->missedpktcount9,
9808 p_nat->missedpktcount10);
9815 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_STATS_CLEAR) {
9816 printf("\nCG-NAPT Packet Stats:\n");
9817 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
9818 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
9819 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
9820 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
9821 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
9822 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
9823 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
9825 p_nat->naptedPktCount = 0;
9826 p_nat->naptDroppedPktCount = 0;
9827 p_nat->inaptedPktCount = 0;
9828 p_nat->enaptedPktCount = 0;
9829 p_nat->receivedPktCount = 0;
9830 p_nat->missedPktCount = 0;
9831 p_nat->arpicmpPktCount = 0;
9832 printf("CG-NAPT Packet Stats cleared\n");
9836 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DBG_LEVEL) {
9837 CGNAPT_DEBUG = Msg[CGNAPT_DBG_CMD_OFST + 1];
9838 printf("CG-NAPT debug level set to %d\n", CGNAPT_DEBUG);
9842 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DBG_SHOW) {
9844 printf("\nNAPT entries - added %" PRIu64 ",",
9845 p_nat->n_cgnapt_entry_added);
9846 printf("deleted %" PRIu64 ",", p_nat->n_cgnapt_entry_deleted);
9847 printf("current %" PRIu64 "", p_nat->n_cgnapt_entry_added -
9848 p_nat->n_cgnapt_entry_deleted);
9850 printf("\nCG-NAPT Packet Stats:\n");
9851 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
9852 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
9853 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
9854 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
9855 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
9856 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
9857 printf("arp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
9861 #ifdef PIPELINE_CGNAPT_INSTRUMENTATION
9862 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_INSTRUMENTATION) {
9863 if (Msg[CGNAPT_DBG_CMD_OFST1] ==
9864 CGNAPT_CMD_INSTRUMENTATION_SUB0) {
9867 uint32_t diff_sum = 0;
9869 printf("CG-NAPT Instrumentation ...\n");
9870 printf("Instrumentation data collected for fn# %d\n",
9871 cgnapt_num_func_to_inst);
9872 printf("Current collection index %d\n",
9875 if (Msg[CGNAPT_DBG_CMD_OFST + 2] == 2) {
9876 printf("Timer Start:\n");
9878 for (index = 0; index < INST_ARRAY_SIZE; index++) {
9879 if ((index % 5) == 0)
9881 printf(" 0x%jx", inst_start_time[index]);
9883 printf("\n\nTimer End:\n");
9885 for (index = 0; index < INST_ARRAY_SIZE; index++) {
9886 if ((index % 5) == 0)
9888 printf(" 0x%jx", inst_end_time[index]);
9892 for (index = 0; index < INST_ARRAY_SIZE; index++) {
9893 inst_diff_time[index] = (uint32_t) (inst_end_time[index] -
9894 inst_start_time[index]);
9897 if (Msg[CGNAPT_DBG_CMD_OFST + 2] ==
9898 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
9899 printf("\n\nTimer Diff:\n");
9901 for (index = 0; index < INST_ARRAY_SIZE; index++) {
9902 if (Msg[CGNAPT_DBG_CMD_OFST + 2] ==
9903 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
9904 if ((index % 5) == 0)
9906 printf(" 0x%08x", inst_diff_time[index]);
9909 diff_sum += inst_diff_time[index];
9912 printf("\ndiff_sum %u, INST_ARRAY_SIZE %d, Ave Time %u\n",
9913 diff_sum, INST_ARRAY_SIZE, (diff_sum / INST_ARRAY_SIZE));
9914 } else if (Msg[CGNAPT_DBG_CMD_OFST + 1] ==
9915 CGNAPT_CMD_INSTRUMENTATION_SUB1) {
9916 /* p plid entry dbg 7 1 0
9917 * p plid entry dbg 7 1 1 <--- pkt_work_cgnapt
9918 * p plid entry dbg 7 1 2 <--- pkt4_work_cgnapt
9919 * p plid entry dbg 7 1 3 <--- pkt_work_cgnapt_key
9920 * p plid entry dbg 7 1 4 <--- pkt4_work_cgnapt_key
9921 * p plid entry dbg 7 1 5 <--- in port ah to out port ah
9922 * - pkt life in the system
9923 * p plid entry dbg 7 1 6 <--- how long this instrumentation
9926 cgnapt_inst_index = 0;
9927 cgnapt_num_func_to_inst = Msg[CGNAPT_DBG_CMD_OFST + 2];
9928 printf("Instrumentation data collection started for fn# %d\n",
9929 cgnapt_num_func_to_inst);
9930 } else if (Msg[CGNAPT_DBG_CMD_OFST + 1] ==
9931 CGNAPT_CMD_INSTRUMENTATION_SUB2) {
9932 /* p plid entry dbg 7 2 0
9933 * Test all major functions by calling them multiple times
9934 * pkt_work_cgnapt, pkt4_work_cgnapt, pkt_work_cgnapt_key,
9935 * pkt4_work_cgnapt_key
9937 if (cgnapt_test_pktmbuf_pool == NULL) {
9938 cgnapt_test_pktmbuf_pool = rte_pktmbuf_pool_create(
9939 "cgnapt_test_pktmbuf_pool", 63, 32, 0,
9940 RTE_MBUF_DEFAULT_BUF_SIZE,
9944 if (cgnapt_test_pktmbuf_pool == NULL)
9945 printf("CGNAPT test mbuf pool create failed.\n");
9947 struct rte_mbuf *cgnapt_test_pkt0 =
9948 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
9949 if (cgnapt_test_pkt0 == NULL)
9950 printf("CGNAPT test pkt 0 alloc failed.");
9951 struct rte_mbuf *cgnapt_test_pkt1 =
9952 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
9953 if (cgnapt_test_pkt1 == NULL)
9954 printf("CGNAPT test pkt 1 alloc failed.");
9955 struct rte_mbuf *cgnapt_test_pkt2 =
9956 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
9957 if (cgnapt_test_pkt2 == NULL)
9958 printf("CGNAPT test pkt 2 alloc failed.");
9959 struct rte_mbuf *cgnapt_test_pkt3 =
9960 rte_pktmbuf_alloc(cgnapt_test_pktmbuf_pool);
9961 if (cgnapt_test_pkt3 == NULL)
9962 printf("CGNAPT test pkt 3 alloc failed.");
9964 struct rte_mbuf *cgnapt_test_pkts[4];
9966 cgnapt_test_pkts[0] = cgnapt_test_pkt0;
9967 cgnapt_test_pkts[1] = cgnapt_test_pkt1;
9968 cgnapt_test_pkts[2] = cgnapt_test_pkt2;
9969 cgnapt_test_pkts[3] = cgnapt_test_pkt3;
9971 uint32_t src_addr_offset =
9972 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_SRC_ADR_OFST;
9973 /* header room + eth hdr size +
9974 * src_aadr offset in ip header
9976 uint32_t dst_addr_offset =
9977 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
9978 /* header room + eth hdr size +
9979 * dst_aadr offset in ip header
9981 uint32_t prot_offset =
9982 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_PROTOCOL_OFST;
9983 /* header room + eth hdr size +
9984 * srprotocol char offset in ip header
9986 int pktCnt = 0, entCnt = 0, exCnt = 0;
9988 for (pktCnt = 0; pktCnt < 4; pktCnt++) {
9989 uint32_t *src_addr =
9990 RTE_MBUF_METADATA_UINT32_PTR
9991 (cgnapt_test_pkts[pktCnt], src_addr_offset);
9992 uint32_t *dst_addr =
9993 RTE_MBUF_METADATA_UINT32_PTR
9994 (cgnapt_test_pkts[pktCnt], dst_addr_offset);
9996 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10000 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10002 uint8_t *eth_dest =
10003 RTE_MBUF_METADATA_UINT8_PTR(cgnapt_test_pkts
10007 RTE_MBUF_METADATA_UINT8_PTR(
10008 cgnapt_test_pkts[pktCnt],
10011 uint16_t *src_port =
10012 RTE_MBUF_METADATA_UINT16_PTR
10013 (cgnapt_test_pkts[pktCnt],
10014 MBUF_HDR_ROOM + ETH_HDR_SIZE +
10016 uint16_t *dst_port =
10017 RTE_MBUF_METADATA_UINT16_PTR
10018 (cgnapt_test_pkts[pktCnt],
10019 MBUF_HDR_ROOM + ETH_HDR_SIZE +
10021 *src_addr = 0xc0a80001;
10022 *dst_addr = 0x90418634;
10033 eth_dest[0] = 0x90;
10034 eth_dest[1] = 0xE2;
10035 eth_dest[2] = 0xba;
10036 eth_dest[3] = 0x54;
10037 eth_dest[4] = 0x67;
10038 eth_dest[5] = 0xc8;
10040 struct rte_pipeline_table_entry *table_entries[4];
10041 struct cgnapt_table_entry ctable_entries[4];
10042 table_entries[0] = (struct rte_pipeline_table_entry *)
10043 &ctable_entries[0];
10044 table_entries[1] = (struct rte_pipeline_table_entry *)
10045 &ctable_entries[1];
10046 table_entries[2] = (struct rte_pipeline_table_entry *)
10047 &ctable_entries[2];
10048 table_entries[3] = (struct rte_pipeline_table_entry *)
10049 &ctable_entries[3];
10050 for (entCnt = 0; entCnt < 4; entCnt++) {
10051 ctable_entries[entCnt].head.action =
10052 RTE_PIPELINE_ACTION_PORT;
10053 ctable_entries[entCnt].head.port_id = 0;
10055 ctable_entries[entCnt].data.prv_ip = 0x01020304;
10056 ctable_entries[entCnt].data.prv_port = 1234;
10057 ctable_entries[entCnt].data.pub_ip = 0x0a0b0c0d;
10058 ctable_entries[entCnt].data.pub_port = 4000;
10059 ctable_entries[entCnt].data.prv_phy_port = 0;
10060 ctable_entries[entCnt].data.pub_phy_port = 1;
10061 ctable_entries[entCnt].data.ttl = 500;
10064 uint64_t time1 = rte_get_tsc_cycles();
10066 for (exCnt = 0; exCnt < 1000; exCnt++) {
10067 pkt_work_cgnapt_key(cgnapt_test_pkts[0],
10068 instrumentation_port_in_arg);
10070 uint64_t time2 = rte_get_tsc_cycles();
10072 printf("times for %d times execution of "
10073 "pkt_work_cgnapt_key 0x%jx",
10075 printf(", 0x%jx, diff %" PRIu64 "\n", time2,
10078 time1 = rte_get_tsc_cycles();
10079 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10080 pkt_work_cgnapt_key(cgnapt_test_pkts[0],
10081 instrumentation_port_in_arg);
10083 time2 = rte_get_tsc_cycles();
10084 printf("times for %d times execution of "
10085 "pkt_work_cgnapt_key 0x%jx", exCnt, time1);
10086 printf("0x%jx, diff %" PRIu64 "\n", time2,
10089 time1 = rte_get_tsc_cycles();
10090 for (exCnt = 0; exCnt < 1000; exCnt++) {
10091 pkt4_work_cgnapt_key(cgnapt_test_pkts,
10092 instrumentation_port_in_arg);
10094 time2 = rte_get_tsc_cycles();
10095 printf("times for %d times execution of "
10096 "pkt4_work_cgnapt_key 0x%jx",
10098 printf(" 0x%jx, diff %" PRIu64 "\n", time2,
10101 time1 = rte_get_tsc_cycles();
10102 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10103 pkt4_work_cgnapt_key(cgnapt_test_pkts,
10104 instrumentation_port_in_arg);
10106 time2 = rte_get_tsc_cycles();
10107 printf("times for %d times execution of "
10108 "pkt4_work_cgnapt_key 0x%jx",
10110 printf("0x%jx, diff %" PRIu64 "\n", time2,
10113 uint64_t mask = 0xff;
10115 time1 = rte_get_tsc_cycles();
10116 for (exCnt = 0; exCnt < 1000; exCnt++) {
10117 pkt_work_cgnapt(cgnapt_test_pkts[0],
10118 table_entries[0], 3, &mask,
10121 time2 = rte_get_tsc_cycles();
10122 printf("times for %d times execution of "
10123 "pkt_work_cgnapt 0x%jx",
10125 printf("0x%jx, diff %" PRIu64 "\n", time2,
10128 time1 = rte_get_tsc_cycles();
10129 for (exCnt = 0; exCnt < 1000000; exCnt++) {
10130 pkt_work_cgnapt(cgnapt_test_pkts[0],
10131 table_entries[0], 3, &mask,
10134 time2 = rte_get_tsc_cycles();
10135 printf("times for %d times execution of "
10136 "pkt_work_cgnapt 0x%jx",
10138 printf("0x%jx, diff %" PRIu64 "\n", time2,
10141 time1 = rte_get_tsc_cycles();
10142 for (exCnt = 0; exCnt < 1000; exCnt++) {
10143 pkt4_work_cgnapt(cgnapt_test_pkts,
10144 table_entries, 0, &mask, NULL);
10146 time2 = rte_get_tsc_cycles();
10147 printf("times for %d times execution of "
10148 "pkt4_work_cgnapt 0x%jx",
10150 printf("0x%jx, diff % " PRIu64 "\n", time2,
10153 int idummy = ctable_entries[0].data.prv_port;
10163 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_LS_ENTRY) {
10164 printf("CG-NAPT be entries are:\n");
10165 printf("Pipeline pointer %p\n", p);
10169 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_DYN) {
10170 printf("Total Number of dynamic napt entries: %" PRIu64 "\n",
10171 p_nat->dynCgnaptCount);
10173 #ifdef CGNAPT_DEBUGGING
10174 printf("MAX PORT PER CLIENT:");
10175 printf("%" PRIu64 ",%" PRIu64 ",%" PRIu64 "\n",
10176 p_nat->max_port_dec_err1, p_nat->max_port_dec_err2,
10177 p_nat->max_port_dec_err3);
10178 printf("MPPC success : %" PRIu64 "\n",
10179 p_nat->max_port_dec_success);
10181 printf("Release port:err:%" PRIu64 ",ret::%" PRIu64 ",get::%"
10182 PRIu64 ",suc::%" PRIu64 "\n", p_nat->pfb_err,
10183 p_nat->pfb_ret, p_nat->pfb_get, p_nat->pfb_suc);
10184 printf("Get port::err:%" PRIu64 ",ret::%" PRIu64 ",get::%"
10185 PRIu64 ",suc::%" PRIu64 "\n", p_nat->gfp_err,
10186 p_nat->gfp_ret, p_nat->gfp_get, p_nat->gfp_suc);
10187 printf("Ring Info:\n");
10188 rte_ring_dump(stdout, p_nat->port_alloc_ring);
10192 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_IPV6) {
10193 dual_stack_enable = Msg[CGNAPT_DBG_CMD_OFST + 1];
10194 printf("Dual Stack option set: %x\n", dual_stack_enable);
10198 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_MAPS_INFO) {
10199 pipelines_port_info();
10200 pipelines_map_info();
10204 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_ITER_COM_TBL) {
10205 uint32_t count = 0;
10213 rte_hash_iterate(napt_common_table, &key, &data,
10216 if ((index != -EINVAL) && (index != -ENOENT)) {
10217 printf("\n%04d ", count);
10218 rte_hexdump(stdout, "KEY", key,
10220 pipeline_cgnapt_entry_key));
10222 //print_key((struct pipeline_cgnapt_entry_key *)
10225 rte_hash_lookup(napt_common_table,
10227 print_cgnapt_entry(&napt_hash_tbl_entries
10232 } while (index != -ENOENT);
10236 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_IF_STATS) {
10238 struct app_params *app =
10239 (struct app_params *)p_nat->app_params_addr;
10242 cmd[0] = Msg[CGNAPT_DBG_CMD_OFST + 1];
10243 cmd[1] = Msg[CGNAPT_DBG_CMD_OFST + 2];
10245 case CGNAPT_IF_STATS_HWQ:
10246 printf("n_pktq_hwq_int :%d\n", app->n_pktq_hwq_in);
10247 printf("n_pktq_hwq_out :%d\n", app->n_pktq_hwq_out);
10251 for (i = 0; i < app->n_pktq_hwq_in; i++) {
10252 struct rte_eth_stats stats;
10254 rte_eth_stats_get(p_nat->links_map[i], &stats);
10256 if (is_phy_port_privte(i))
10257 printf("Private Port Stats %d\n", i);
10259 printf("Public Port Stats %d\n", i);
10261 printf("\n\tipackets : %" PRIu64 "",
10263 printf("\n\topackets : %" PRIu64 "",
10265 printf("\n\tierrors : %" PRIu64 "",
10267 printf("\n\toerrors : %" PRIu64 "",
10269 printf("\n\trx_nombuf: %" PRIu64 "",
10272 if (is_phy_port_privte(i))
10273 printf("Private Q:");
10275 printf("Public Q:");
10276 for (j = 0; j < RTE_ETHDEV_QUEUE_STAT_CNTRS;
10278 printf(" %" PRIu64 ", %" PRIu64 "|",
10279 stats.q_ipackets[j],
10280 stats.q_opackets[j]);
10288 case CGNAPT_IF_STATS_SWQ:
10290 printf("n_pktq_swq :%d\n", app->n_pktq_swq);
10292 if (cmd[1] < app->n_pktq_swq) {
10293 rte_ring_dump(stdout, app->swq[cmd[1]]);
10296 printf("SWQ number is invalid\n");
10299 case CGNAPT_IF_STATS_OTH:
10301 printf("config_file:%s\n", app->config_file);
10302 printf("script_file:%s\n", app->script_file);
10303 printf("parser_file:%s\n", app->parser_file);
10304 printf("output_file:%s\n", app->output_file);
10305 printf("n_msgq :%d\n", app->n_msgq);
10306 printf("n_pktq_tm :%d\n", app->n_pktq_tm);
10307 printf("n_pktq_source :%d\n", app->n_pktq_source);
10308 printf("n_pktq_sink :%d\n", app->n_pktq_sink);
10309 printf("n_pipelines :%d\n", app->n_pipelines);
10313 printf("Command does not match\n\n");
10321 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_MAX_CLI_PER_PUB_IP) {
10322 if (nat_only_config_flag) {
10323 printf("Command not supported for NAT only config.\n");
10328 printf("\tPublic IP: Num Clients\n");
10329 for (ii = 0; ii < CGNAPT_MAX_PUB_IP; ii++)
10330 printf("\t%x : %7d\n", all_public_ip[ii].ip,
10331 rte_atomic16_read(&all_public_ip[ii].count));
10335 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_PUB_IP_LIST) {
10338 for (i = 0; i < p_nat->pub_ip_count; i++)
10339 printf("%x : (%d,%d)\n", p_nat->pub_ip_port_set[i].ip,
10340 p_nat->pub_ip_port_set[i].start_port,
10341 p_nat->pub_ip_port_set[i].end_port);
10345 #ifdef CGNAPT_TIMING_INST
10346 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_TIMING_INST) {
10347 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 0) {
10348 p_nat->time_measurements_on = 1;
10349 p_nat->time_measurements = 0;
10350 printf("CGNAPT timing instrumentation turned on.\n");
10351 printf("Max samples %d\n", p_nat->max_time_mesurements);
10353 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 1) {
10354 p_nat->time_measurements_on = 0;
10355 printf("CGNAPT timing instrumentation turned off.\n");
10356 printf("Cur Samples %d\n", p_nat->time_measurements);
10358 if (Msg[CGNAPT_DBG_CMD_OFST + 1] == 2) {
10359 uint64_t sum = p_nat->external_time_sum +
10360 p_nat->internal_time_sum;
10361 uint64_t isump = (p_nat->internal_time_sum * 100) / sum;
10362 uint64_t esump = (p_nat->external_time_sum * 100) / sum;
10363 printf("CGNAPT timing instrumentation status ...\n");
10364 printf("Max Count %d, Cur Count %d, Status %d (1=ON)\n",
10365 p_nat->max_time_mesurements,
10366 p_nat->time_measurements,
10367 p_nat->time_measurements_on);
10368 printf("Internal Time Sum %" PRIu64 " , Ave %" PRIu64
10369 ", percent %" PRIu64 "\n",
10370 p_nat->internal_time_sum,
10371 (p_nat->internal_time_sum /
10372 p_nat->time_measurements), isump);
10373 printf("External Time Sum %" PRIu64 " , Ave %" PRIu64
10374 ", percent %" PRIu64 "\n",
10375 p_nat->external_time_sum,
10376 (p_nat->external_time_sum /
10377 p_nat->time_measurements), esump);
10384 if (Msg[CGNAPT_DBG_CMD_OFST] == CGNAPT_DBG_CMD_PRINT_NSP) {
10385 struct cgnapt_nsp_node *ll = nsp_ll;
10387 while (ll != NULL) {
10388 fprintf(stderr, "NSP Prefix/Depth=>%x%x:%x%x:%x%x: "
10389 "%x%x:%x%x:%x%x:%x%x:%x%x/%d",
10390 ll->nsp.prefix[0], ll->nsp.prefix[1],
10391 ll->nsp.prefix[2], ll->nsp.prefix[3],
10392 ll->nsp.prefix[4], ll->nsp.prefix[5],
10393 ll->nsp.prefix[6], ll->nsp.prefix[7],
10394 ll->nsp.prefix[8], ll->nsp.prefix[9],
10395 ll->nsp.prefix[10], ll->nsp.prefix[11],
10396 ll->nsp.prefix[12], ll->nsp.prefix[13],
10397 ll->nsp.prefix[14], ll->nsp.prefix[15],
10406 printf("CG-NAPT debug handler called with wrong args %x %x\n", Msg[0],
10410 for (i = 0; i < 20; i++)
10411 printf("%02x ", Msg[i]);
10417 * Function to print num of clients per IP address
10420 void print_num_ip_clients(void)
10422 if (nat_only_config_flag) {
10423 printf("Command not supported for NAT only config.\n");
10428 printf("\tPublic IP: Num Clients\n");
10429 for (ii = 0; ii < CGNAPT_MAX_PUB_IP; ii++)
10430 printf("\t%08x : %7d\n", all_public_ip[ii].ip,
10431 rte_atomic16_read(&all_public_ip[ii].count));
10435 * Function to print CGNAPT version info
10438 * An unused pointer to struct pipeline
10440 * void pointer to incoming arguments
10442 void *pipeline_cgnapt_msg_req_ver_handler(__rte_unused struct pipeline *p,
10445 struct pipeline_cgnapt_entry_delete_msg_rsp *rsp = msg;
10446 uint8_t *Msg = msg;
10450 printf("CG-NAPT debug handler called with args %x %x, offset %d\n",
10451 Msg[CGNAPT_VER_CMD_OFST], Msg[CGNAPT_VER_CMD_OFST + 1],
10452 CGNAPT_VER_CMD_OFST);
10454 if (Msg[CGNAPT_VER_CMD_OFST] == CGNAPT_VER_CMD_VER) {
10455 printf("CGNAPT Version %s\n", CGNAPT_VERSION);
10458 printf("CG-NAPT Version handler called with wrong args %x %x\n",
10462 for (i = 0; i < 20; i++)
10463 printf("%02x ", Msg[i]);
10469 * Function to show CGNAPT stats
10472 void all_cgnapt_stats(char *buf)
10475 struct pipeline_cgnapt *p_nat;
10476 uint64_t receivedPktCount = 0;
10477 uint64_t missedPktCount = 0;
10478 uint64_t naptDroppedPktCount = 0;
10479 uint64_t naptedPktCount = 0;
10480 uint64_t inaptedPktCount = 0;
10481 uint64_t enaptedPktCount = 0;
10482 uint64_t arpicmpPktCount = 0;
10484 len += sprintf(buf + len, "\nCG-NAPT Packet Stats:\n");
10485 for (i = 0; i < n_cgnapt_pipeline; i++) {
10486 p_nat = all_pipeline_cgnapt[i];
10488 receivedPktCount += p_nat->receivedPktCount;
10489 missedPktCount += p_nat->missedPktCount;
10490 naptDroppedPktCount += p_nat->naptDroppedPktCount;
10491 naptedPktCount += p_nat->naptedPktCount;
10492 inaptedPktCount += p_nat->inaptedPktCount;
10493 enaptedPktCount += p_nat->enaptedPktCount;
10494 arpicmpPktCount += p_nat->arpicmpPktCount;
10496 len += sprintf(buf + len, "pipeline %d stats:\n", p_nat->pipeline_num);
10497 len += sprintf(buf + len, "Received %" PRIu64 ",", p_nat->receivedPktCount);
10498 len += sprintf(buf + len, "Missed %" PRIu64 ",", p_nat->missedPktCount);
10499 len += sprintf(buf + len, "Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10500 len += sprintf(buf + len, "Translated %" PRIu64 ",", p_nat->naptedPktCount);
10501 len += sprintf(buf + len, "ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10502 len += sprintf(buf + len, "egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10503 len += sprintf(buf + len, "arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10505 printf("\nCG-NAPT Packet Stats:\n");
10506 printf("pipeline %d stats:\n", p_nat->pipeline_num);
10507 printf("Received %" PRIu64 ",", p_nat->receivedPktCount);
10508 printf("Missed %" PRIu64 ",", p_nat->missedPktCount);
10509 printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10510 printf("Translated %" PRIu64 ",", p_nat->naptedPktCount);
10511 printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10512 printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10513 printf("arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10517 #ifdef CGNAPT_DEBUGGING
10518 len += sprintf(buf + len, "\n Drop detail 1:%" PRIu64 ",",
10519 p_nat->naptDroppedPktCount1);
10520 len += sprintf(buf + len, "\n Drop detail 2:%" PRIu64 ",",
10521 p_nat->naptDroppedPktCount2);
10522 len += sprintf(buf + len, "\n Drop detail 3:%" PRIu64 ",",
10523 p_nat->naptDroppedPktCount3);
10524 len += sprintf(buf + len, "\n Drop detail 4:%" PRIu64 ",",
10525 p_nat->naptDroppedPktCount4);
10526 len += sprintf(buf + len, "\n Drop detail 5:%" PRIu64 ",",
10527 p_nat->naptDroppedPktCount5);
10528 len += sprintf(buf + len, "\n Drop detail 6:%" PRIu64 "",
10529 p_nat->naptDroppedPktCount6);
10531 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10532 p_nat->missedpktcount1,
10533 p_nat->missedpktcount2);
10534 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10535 p_nat->missedpktcount3,
10536 p_nat->missedpktcount4);
10537 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10538 p_nat->missedpktcount5,
10539 p_nat->missedpktcount6);
10540 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10541 p_nat->missedpktcount7,
10542 p_nat->missedpktcount8);
10543 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10544 p_nat->missedpktcount9,
10545 p_nat->missedpktcount10);
10551 len += sprintf(buf + len, "\nTotal pipeline stats:\n");
10552 len += sprintf(buf + len, "Received %" PRIu64 ",", receivedPktCount);
10553 len += sprintf(buf + len, "Missed %" PRIu64 ",", missedPktCount);
10554 len += sprintf(buf + len, "Dropped %" PRIu64 ",", naptDroppedPktCount);
10555 len += sprintf(buf + len, "Translated %" PRIu64 ",", naptedPktCount);
10556 len += sprintf(buf + len, "ingress %" PRIu64 ",", inaptedPktCount);
10557 len += sprintf(buf + len, "egress %" PRIu64 "\n", enaptedPktCount);
10558 len += sprintf(buf + len, "arpicmp pkts %" PRIu64 "\n", arpicmpPktCount);
10560 printf("\nTotal pipeline stats:\n");
10561 printf("Received %" PRIu64 ",", receivedPktCount);
10562 printf("Missed %" PRIu64 ",", missedPktCount);
10563 printf("Dropped %" PRIu64 ",", naptDroppedPktCount);
10564 printf("Translated %" PRIu64 ",", naptedPktCount);
10565 printf("ingress %" PRIu64 ",", inaptedPktCount);
10566 printf("egress %" PRIu64 "\n", enaptedPktCount);
10567 printf("arpicmp pkts %" PRIu64 "\n", arpicmpPktCount);
10569 if (!rest_api_supported())
10570 printf("%s\n", buf);
10573 void all_cgnapt_clear_stats(char *buf)
10576 struct pipeline_cgnapt *p_nat;
10577 len += sprintf(buf + len, "\nCG-NAPT Packet Stats:\n");
10578 for (i = 0; i < n_cgnapt_pipeline; i++) {
10579 p_nat = all_pipeline_cgnapt[i];
10581 len += sprintf(buf + len, "pipeline %d stats:\n", p_nat->pipeline_num);
10582 len += sprintf(buf + len, "Received %" PRIu64 ",", p_nat->receivedPktCount);
10583 len += sprintf(buf + len, "Missed %" PRIu64 ",", p_nat->missedPktCount);
10584 len += sprintf(buf + len, "Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount);
10585 len += sprintf(buf + len, "Translated %" PRIu64 ",", p_nat->naptedPktCount);
10586 len += sprintf(buf + len, "ingress %" PRIu64 ",", p_nat->inaptedPktCount);
10587 len += sprintf(buf + len, "egress %" PRIu64 "\n", p_nat->enaptedPktCount);
10588 len += sprintf(buf + len, "arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount);
10590 p_nat->receivedPktCount = 0;
10591 p_nat->missedPktCount = 0;
10592 p_nat->naptDroppedPktCount = 0;
10593 p_nat->naptedPktCount = 0;
10594 p_nat->inaptedPktCount = 0;
10595 p_nat->enaptedPktCount = 0;
10596 p_nat->arpicmpPktCount = 0;
10598 #ifdef CGNAPT_DEBUGGING
10599 len += sprintf(buf + len, "\n Drop detail 1:%" PRIu64 ",",
10600 p_nat->naptDroppedPktCount1);
10601 len += sprintf(buf + len, "\n Drop detail 2:%" PRIu64 ",",
10602 p_nat->naptDroppedPktCount2);
10603 len += sprintf(buf + len, "\n Drop detail 3:%" PRIu64 ",",
10604 p_nat->naptDroppedPktCount3);
10605 len += sprintf(buf + len, "\n Drop detail 4:%" PRIu64 ",",
10606 p_nat->naptDroppedPktCount4);
10607 len += sprintf(buf + len, "\n Drop detail 5:%" PRIu64 ",",
10608 p_nat->naptDroppedPktCount5);
10609 len += sprintf(buf + len, "\n Drop detail 6:%" PRIu64 "",
10610 p_nat->naptDroppedPktCount6);
10612 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10613 p_nat->missedpktcount1,
10614 p_nat->missedpktcount2);
10615 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10616 p_nat->missedpktcount3,
10617 p_nat->missedpktcount4);
10618 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10619 p_nat->missedpktcount5,
10620 p_nat->missedpktcount6);
10621 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10622 p_nat->missedpktcount7,
10623 p_nat->missedpktcount8);
10624 len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "",
10625 p_nat->missedpktcount9,
10626 p_nat->missedpktcount10);
10632 if (!rest_api_supported())
10633 printf("%s\n", buf);
10637 * Function to print common CGNAPT table entries
10640 void print_static_cgnapt_entries(void)
10642 uint32_t count = 0;
10647 struct cgnapt_table_entry *entry;
10649 index = rte_hash_iterate(napt_common_table,
10650 &key, &data, &next);
10652 if ((index != -EINVAL) && (index != -ENOENT)) {
10653 printf("\n%04d ", count);
10654 rte_hexdump(stdout, "KEY", key,
10655 sizeof(struct pipeline_cgnapt_entry_key));
10656 int32_t position = rte_hash_lookup(
10657 napt_common_table, key);
10658 entry = &napt_hash_tbl_entries[position];
10660 if (entry->data.timeout == STATIC_CGNAPT_TIMEOUT)
10661 rte_hexdump(stdout, "Entry",
10662 (const void *)entry,
10663 sizeof(struct cgnapt_table_entry));
10667 } while (index != -ENOENT);
10671 * Function to show CGNAPT stats
10675 struct pipeline_be_ops pipeline_cgnapt_be_ops = {
10676 .f_init = pipeline_cgnapt_init,
10677 .f_free = pipeline_cgnapt_free,
10679 .f_timer = pipeline_cgnapt_timer,
10680 .f_track = pipeline_cgnapt_track,