15acce750SPavan Nikhilesh /* SPDX-License-Identifier: BSD-3-Clause 25acce750SPavan Nikhilesh * Copyright(c) 2023 Marvell. 35acce750SPavan Nikhilesh */ 45acce750SPavan Nikhilesh 55acce750SPavan Nikhilesh #include <rte_byteorder.h> 65acce750SPavan Nikhilesh #include <rte_common.h> 75acce750SPavan Nikhilesh #include <rte_cycles.h> 85acce750SPavan Nikhilesh #include <rte_ether.h> 95acce750SPavan Nikhilesh #include <rte_hexdump.h> 105acce750SPavan Nikhilesh #include <rte_ip.h> 115acce750SPavan Nikhilesh #include <rte_ip_frag.h> 125acce750SPavan Nikhilesh #include <rte_mbuf.h> 135acce750SPavan Nikhilesh #include <rte_mbuf_pool_ops.h> 145acce750SPavan Nikhilesh #include <rte_os_shim.h> 155acce750SPavan Nikhilesh #include <rte_random.h> 165acce750SPavan Nikhilesh #include <rte_udp.h> 175acce750SPavan Nikhilesh 185acce750SPavan Nikhilesh #include "test.h" 195acce750SPavan Nikhilesh 205acce750SPavan Nikhilesh #define MAX_FLOWS (1024 * 32) 215acce750SPavan Nikhilesh #define MAX_BKTS MAX_FLOWS 225acce750SPavan Nikhilesh #define MAX_ENTRIES_PER_BKT 16 235acce750SPavan Nikhilesh #define MAX_FRAGMENTS RTE_LIBRTE_IP_FRAG_MAX_FRAG 245acce750SPavan Nikhilesh #define MIN_FRAGMENTS 2 255acce750SPavan Nikhilesh #define MAX_PKTS (MAX_FLOWS * MAX_FRAGMENTS) 265acce750SPavan Nikhilesh 275acce750SPavan Nikhilesh #define MAX_PKT_LEN 2048 285acce750SPavan Nikhilesh #define MAX_TTL_MS (5 * MS_PER_S) 295acce750SPavan Nikhilesh 305acce750SPavan Nikhilesh /* use RFC863 Discard Protocol */ 315acce750SPavan Nikhilesh #define UDP_SRC_PORT 9 325acce750SPavan Nikhilesh #define UDP_DST_PORT 9 335acce750SPavan Nikhilesh 345acce750SPavan Nikhilesh /* use RFC5735 / RFC2544 reserved network test addresses */ 355acce750SPavan Nikhilesh #define IP_SRC_ADDR(x) ((198U << 24) | (18 << 16) | (0 << 8) | (x)) 365acce750SPavan Nikhilesh #define IP_DST_ADDR(x) ((198U << 24) | (18 << 16) | (1 << 15) | (x)) 375acce750SPavan Nikhilesh 385acce750SPavan Nikhilesh /* 2001:0200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180) */ 3989b5642dSRobin Jarry static struct rte_ipv6_addr ip6_addr = RTE_IPV6(0x2001, 0x0200, 0, 0, 0, 0, 0, 0); 405acce750SPavan Nikhilesh #define IP6_VERSION 6 415acce750SPavan Nikhilesh 425acce750SPavan Nikhilesh #define IP_DEFTTL 64 /* from RFC 1340. */ 435acce750SPavan Nikhilesh 445acce750SPavan Nikhilesh static struct rte_ip_frag_tbl *frag_tbl; 455acce750SPavan Nikhilesh static struct rte_mempool *pkt_pool; 465acce750SPavan Nikhilesh static struct rte_mbuf *mbufs[MAX_FLOWS][MAX_FRAGMENTS]; 475acce750SPavan Nikhilesh static uint8_t frag_per_flow[MAX_FLOWS]; 485acce750SPavan Nikhilesh static uint32_t flow_cnt; 495acce750SPavan Nikhilesh 505acce750SPavan Nikhilesh #define FILL_MODE_LINEAR 0 515acce750SPavan Nikhilesh #define FILL_MODE_RANDOM 1 525acce750SPavan Nikhilesh #define FILL_MODE_INTERLEAVED 2 535acce750SPavan Nikhilesh 545acce750SPavan Nikhilesh static int 555acce750SPavan Nikhilesh reassembly_test_setup(void) 565acce750SPavan Nikhilesh { 575acce750SPavan Nikhilesh uint64_t max_ttl_cyc = (MAX_TTL_MS * rte_get_timer_hz()) / 1E3; 585acce750SPavan Nikhilesh 595acce750SPavan Nikhilesh frag_tbl = rte_ip_frag_table_create(MAX_BKTS, MAX_ENTRIES_PER_BKT, 605acce750SPavan Nikhilesh MAX_BKTS * MAX_ENTRIES_PER_BKT, max_ttl_cyc, 615acce750SPavan Nikhilesh rte_socket_id()); 625acce750SPavan Nikhilesh if (frag_tbl == NULL) 635acce750SPavan Nikhilesh return TEST_FAILED; 645acce750SPavan Nikhilesh 655acce750SPavan Nikhilesh rte_mbuf_set_user_mempool_ops("ring_mp_mc"); 665acce750SPavan Nikhilesh pkt_pool = rte_pktmbuf_pool_create( 675acce750SPavan Nikhilesh "reassembly_perf_pool", MAX_FLOWS * MAX_FRAGMENTS, 0, 0, 685acce750SPavan Nikhilesh RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); 695acce750SPavan Nikhilesh if (pkt_pool == NULL) { 705acce750SPavan Nikhilesh printf("[%s] Failed to create pkt pool\n", __func__); 715acce750SPavan Nikhilesh rte_ip_frag_table_destroy(frag_tbl); 725acce750SPavan Nikhilesh return TEST_FAILED; 735acce750SPavan Nikhilesh } 745acce750SPavan Nikhilesh 755acce750SPavan Nikhilesh return TEST_SUCCESS; 765acce750SPavan Nikhilesh } 775acce750SPavan Nikhilesh 785acce750SPavan Nikhilesh static void 795acce750SPavan Nikhilesh reassembly_test_teardown(void) 805acce750SPavan Nikhilesh { 815acce750SPavan Nikhilesh if (frag_tbl != NULL) 825acce750SPavan Nikhilesh rte_ip_frag_table_destroy(frag_tbl); 835acce750SPavan Nikhilesh 845acce750SPavan Nikhilesh rte_mempool_free(pkt_pool); 855acce750SPavan Nikhilesh } 865acce750SPavan Nikhilesh 875acce750SPavan Nikhilesh static void 885acce750SPavan Nikhilesh randomize_array_positions(void **array, uint8_t sz) 895acce750SPavan Nikhilesh { 905acce750SPavan Nikhilesh void *tmp; 915acce750SPavan Nikhilesh int i, j; 925acce750SPavan Nikhilesh 935acce750SPavan Nikhilesh if (sz == 2) { 945acce750SPavan Nikhilesh tmp = array[0]; 955acce750SPavan Nikhilesh array[0] = array[1]; 965acce750SPavan Nikhilesh array[1] = tmp; 975acce750SPavan Nikhilesh } else { 985acce750SPavan Nikhilesh for (i = sz - 1; i > 0; i--) { 995acce750SPavan Nikhilesh j = rte_rand_max(i + 1); 1005acce750SPavan Nikhilesh tmp = array[i]; 1015acce750SPavan Nikhilesh array[i] = array[j]; 1025acce750SPavan Nikhilesh array[j] = tmp; 1035acce750SPavan Nikhilesh } 1045acce750SPavan Nikhilesh } 1055acce750SPavan Nikhilesh } 1065acce750SPavan Nikhilesh 1075acce750SPavan Nikhilesh static void 1085acce750SPavan Nikhilesh reassembly_print_banner(const char *proto_str) 1095acce750SPavan Nikhilesh { 1105acce750SPavan Nikhilesh printf("+==============================================================" 1115acce750SPavan Nikhilesh "============================================+\n"); 1125acce750SPavan Nikhilesh printf("| %-32s| %-3s : %-58d|\n", proto_str, "Flow Count", MAX_FLOWS); 1135acce750SPavan Nikhilesh printf("+================+================+=============+=============+" 1145acce750SPavan Nikhilesh "========================+===================+\n"); 1155acce750SPavan Nikhilesh printf("%-17s%-17s%-14s%-14s%-25s%-20s\n", "| Fragment Order", 1165acce750SPavan Nikhilesh "| Fragments/Flow", "| Outstanding", "| Cycles/Flow", 1175acce750SPavan Nikhilesh "| Cycles/Fragment insert", "| Cycles/Reassembly |"); 1185acce750SPavan Nikhilesh printf("+================+================+=============+=============+" 1195acce750SPavan Nikhilesh "========================+===================+\n"); 1205acce750SPavan Nikhilesh } 1215acce750SPavan Nikhilesh 1225acce750SPavan Nikhilesh static void 1235acce750SPavan Nikhilesh ipv4_frag_fill_data(struct rte_mbuf **mbuf, uint8_t nb_frags, uint32_t flow_id, 1245acce750SPavan Nikhilesh uint8_t fill_mode) 1255acce750SPavan Nikhilesh { 1265acce750SPavan Nikhilesh struct rte_ether_hdr *eth_hdr; 1275acce750SPavan Nikhilesh struct rte_ipv4_hdr *ip_hdr; 1285acce750SPavan Nikhilesh struct rte_udp_hdr *udp_hdr; 1295acce750SPavan Nikhilesh uint16_t frag_len; 1305acce750SPavan Nikhilesh uint8_t i; 1315acce750SPavan Nikhilesh 1325acce750SPavan Nikhilesh frag_len = MAX_PKT_LEN / nb_frags; 1335acce750SPavan Nikhilesh if (frag_len % 8) 1345acce750SPavan Nikhilesh frag_len = RTE_ALIGN_MUL_CEIL(frag_len, 8); 1355acce750SPavan Nikhilesh 1365acce750SPavan Nikhilesh for (i = 0; i < nb_frags; i++) { 1375acce750SPavan Nikhilesh struct rte_mbuf *frag = mbuf[i]; 1385acce750SPavan Nikhilesh uint16_t frag_offset = 0; 1395acce750SPavan Nikhilesh uint16_t pkt_len; 1405acce750SPavan Nikhilesh 1415acce750SPavan Nikhilesh frag_offset = i * (frag_len / 8); 1425acce750SPavan Nikhilesh 1435acce750SPavan Nikhilesh if (i == nb_frags - 1) 1445acce750SPavan Nikhilesh frag_len = MAX_PKT_LEN - (frag_len * (nb_frags - 1)); 1455acce750SPavan Nikhilesh else 1465acce750SPavan Nikhilesh frag_offset |= RTE_IPV4_HDR_MF_FLAG; 1475acce750SPavan Nikhilesh 1485acce750SPavan Nikhilesh rte_pktmbuf_reset_headroom(frag); 1495acce750SPavan Nikhilesh eth_hdr = rte_pktmbuf_mtod(frag, struct rte_ether_hdr *); 1505acce750SPavan Nikhilesh ip_hdr = rte_pktmbuf_mtod_offset(frag, struct rte_ipv4_hdr *, 1515acce750SPavan Nikhilesh sizeof(struct rte_ether_hdr)); 1525acce750SPavan Nikhilesh udp_hdr = rte_pktmbuf_mtod_offset( 1535acce750SPavan Nikhilesh frag, struct rte_udp_hdr *, 1545acce750SPavan Nikhilesh sizeof(struct rte_ether_hdr) + 1555acce750SPavan Nikhilesh sizeof(struct rte_ipv4_hdr)); 1565acce750SPavan Nikhilesh 1575acce750SPavan Nikhilesh rte_ether_unformat_addr("02:00:00:00:00:01", 1585acce750SPavan Nikhilesh ð_hdr->dst_addr); 1595acce750SPavan Nikhilesh rte_ether_unformat_addr("02:00:00:00:00:00", 1605acce750SPavan Nikhilesh ð_hdr->src_addr); 1615acce750SPavan Nikhilesh eth_hdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 1625acce750SPavan Nikhilesh 1635acce750SPavan Nikhilesh pkt_len = frag_len; 1645acce750SPavan Nikhilesh /* 1655acce750SPavan Nikhilesh * Initialize UDP header. 1665acce750SPavan Nikhilesh */ 1675acce750SPavan Nikhilesh if (i == 0) { 1685acce750SPavan Nikhilesh udp_hdr->src_port = rte_cpu_to_be_16(UDP_SRC_PORT); 1695acce750SPavan Nikhilesh udp_hdr->dst_port = rte_cpu_to_be_16(UDP_DST_PORT); 1705acce750SPavan Nikhilesh udp_hdr->dgram_len = rte_cpu_to_be_16(pkt_len); 1715acce750SPavan Nikhilesh udp_hdr->dgram_cksum = 0; /* No UDP checksum. */ 1725acce750SPavan Nikhilesh } 1735acce750SPavan Nikhilesh 1745acce750SPavan Nikhilesh /* 1755acce750SPavan Nikhilesh * Initialize IP header. 1765acce750SPavan Nikhilesh */ 1775acce750SPavan Nikhilesh pkt_len = (uint16_t)(pkt_len + sizeof(struct rte_ipv4_hdr)); 1785acce750SPavan Nikhilesh ip_hdr->version_ihl = RTE_IPV4_VHL_DEF; 1795acce750SPavan Nikhilesh ip_hdr->type_of_service = 0; 1805acce750SPavan Nikhilesh ip_hdr->fragment_offset = rte_cpu_to_be_16(frag_offset); 1815acce750SPavan Nikhilesh ip_hdr->time_to_live = IP_DEFTTL; 1825acce750SPavan Nikhilesh ip_hdr->next_proto_id = IPPROTO_UDP; 1835acce750SPavan Nikhilesh ip_hdr->packet_id = 1845acce750SPavan Nikhilesh rte_cpu_to_be_16((flow_id + 1) % UINT16_MAX); 1855acce750SPavan Nikhilesh ip_hdr->total_length = rte_cpu_to_be_16(pkt_len); 1865acce750SPavan Nikhilesh /* Using more than 32K flows will modify the 2nd octet of the IP. */ 1875acce750SPavan Nikhilesh ip_hdr->src_addr = rte_cpu_to_be_32(IP_SRC_ADDR(flow_id)); 1885acce750SPavan Nikhilesh ip_hdr->dst_addr = rte_cpu_to_be_32(IP_DST_ADDR(flow_id)); 1895acce750SPavan Nikhilesh 190*f9e1d67fSBruce Richardson ip_hdr->hdr_checksum = (uint16_t)rte_ipv4_cksum_simple(ip_hdr); 1915acce750SPavan Nikhilesh 1925acce750SPavan Nikhilesh frag->data_len = sizeof(struct rte_ether_hdr) + pkt_len; 1935acce750SPavan Nikhilesh frag->pkt_len = frag->data_len; 1945acce750SPavan Nikhilesh frag->l2_len = sizeof(struct rte_ether_hdr); 1955acce750SPavan Nikhilesh frag->l3_len = sizeof(struct rte_ipv4_hdr); 1965acce750SPavan Nikhilesh } 1975acce750SPavan Nikhilesh 1985acce750SPavan Nikhilesh if (fill_mode == FILL_MODE_RANDOM) 1995acce750SPavan Nikhilesh randomize_array_positions((void **)mbuf, nb_frags); 2005acce750SPavan Nikhilesh } 2015acce750SPavan Nikhilesh 2025acce750SPavan Nikhilesh static uint8_t 2035acce750SPavan Nikhilesh get_rand_frags(uint8_t max_frag) 2045acce750SPavan Nikhilesh { 2055acce750SPavan Nikhilesh uint8_t frags = rte_rand_max(max_frag + 1); 2065acce750SPavan Nikhilesh 2075acce750SPavan Nikhilesh return frags <= 1 ? MIN_FRAGMENTS : frags; 2085acce750SPavan Nikhilesh } 2095acce750SPavan Nikhilesh 2105acce750SPavan Nikhilesh static int 2115acce750SPavan Nikhilesh ipv4_rand_frag_pkt_setup(uint8_t fill_mode, uint8_t max_frag) 2125acce750SPavan Nikhilesh { 2135acce750SPavan Nikhilesh uint8_t nb_frag; 2145acce750SPavan Nikhilesh int i; 2155acce750SPavan Nikhilesh 2165acce750SPavan Nikhilesh for (i = 0; i < MAX_FLOWS; i++) { 2175acce750SPavan Nikhilesh nb_frag = get_rand_frags(max_frag); 2185acce750SPavan Nikhilesh if (rte_mempool_get_bulk(pkt_pool, (void **)mbufs[i], nb_frag) < 2195acce750SPavan Nikhilesh 0) 2205acce750SPavan Nikhilesh return TEST_FAILED; 2215acce750SPavan Nikhilesh ipv4_frag_fill_data(mbufs[i], nb_frag, i, fill_mode); 2225acce750SPavan Nikhilesh frag_per_flow[i] = nb_frag; 2235acce750SPavan Nikhilesh } 2245acce750SPavan Nikhilesh flow_cnt = i; 2255acce750SPavan Nikhilesh 2265acce750SPavan Nikhilesh return TEST_SUCCESS; 2275acce750SPavan Nikhilesh } 2285acce750SPavan Nikhilesh 2295acce750SPavan Nikhilesh static int 2305acce750SPavan Nikhilesh ipv4_frag_pkt_setup(uint8_t fill_mode, uint8_t nb_frag) 2315acce750SPavan Nikhilesh { 2325acce750SPavan Nikhilesh int i; 2335acce750SPavan Nikhilesh 2345acce750SPavan Nikhilesh for (i = 0; i < MAX_FLOWS; i++) { 2355acce750SPavan Nikhilesh if (rte_mempool_get_bulk(pkt_pool, (void **)mbufs[i], nb_frag) < 2365acce750SPavan Nikhilesh 0) 2375acce750SPavan Nikhilesh return TEST_FAILED; 2385acce750SPavan Nikhilesh ipv4_frag_fill_data(mbufs[i], nb_frag, i, fill_mode); 2395acce750SPavan Nikhilesh frag_per_flow[i] = nb_frag; 2405acce750SPavan Nikhilesh } 2415acce750SPavan Nikhilesh flow_cnt = i; 2425acce750SPavan Nikhilesh 2435acce750SPavan Nikhilesh return TEST_SUCCESS; 2445acce750SPavan Nikhilesh } 2455acce750SPavan Nikhilesh 2465acce750SPavan Nikhilesh static void 2475acce750SPavan Nikhilesh ipv6_frag_fill_data(struct rte_mbuf **mbuf, uint8_t nb_frags, uint32_t flow_id, 2485acce750SPavan Nikhilesh uint8_t fill_mode) 2495acce750SPavan Nikhilesh { 2505acce750SPavan Nikhilesh struct ipv6_extension_fragment *frag_hdr; 2515acce750SPavan Nikhilesh struct rte_ether_hdr *eth_hdr; 2525acce750SPavan Nikhilesh struct rte_ipv6_hdr *ip_hdr; 2535acce750SPavan Nikhilesh struct rte_udp_hdr *udp_hdr; 2545acce750SPavan Nikhilesh uint16_t frag_len; 2555acce750SPavan Nikhilesh uint8_t i; 2565acce750SPavan Nikhilesh 2575acce750SPavan Nikhilesh frag_len = MAX_PKT_LEN / nb_frags; 2585acce750SPavan Nikhilesh if (frag_len % 8) 2595acce750SPavan Nikhilesh frag_len = RTE_ALIGN_MUL_CEIL(frag_len, 8); 2605acce750SPavan Nikhilesh 2615acce750SPavan Nikhilesh for (i = 0; i < nb_frags; i++) { 2625acce750SPavan Nikhilesh struct rte_mbuf *frag = mbuf[i]; 2635acce750SPavan Nikhilesh uint16_t frag_offset = 0; 2645acce750SPavan Nikhilesh uint16_t pkt_len; 2655acce750SPavan Nikhilesh 2665acce750SPavan Nikhilesh frag_offset = i * (frag_len / 8); 2675acce750SPavan Nikhilesh frag_offset <<= 3; 2685acce750SPavan Nikhilesh if (i == nb_frags - 1) { 2695acce750SPavan Nikhilesh frag_len = MAX_PKT_LEN - (frag_len * (nb_frags - 1)); 2705acce750SPavan Nikhilesh frag_offset = RTE_IPV6_SET_FRAG_DATA(frag_offset, 0); 2715acce750SPavan Nikhilesh } else { 2725acce750SPavan Nikhilesh frag_offset = RTE_IPV6_SET_FRAG_DATA(frag_offset, 1); 2735acce750SPavan Nikhilesh } 2745acce750SPavan Nikhilesh 2755acce750SPavan Nikhilesh rte_pktmbuf_reset_headroom(frag); 2765acce750SPavan Nikhilesh eth_hdr = rte_pktmbuf_mtod(frag, struct rte_ether_hdr *); 2775acce750SPavan Nikhilesh ip_hdr = rte_pktmbuf_mtod_offset(frag, struct rte_ipv6_hdr *, 2785acce750SPavan Nikhilesh sizeof(struct rte_ether_hdr)); 2795acce750SPavan Nikhilesh udp_hdr = rte_pktmbuf_mtod_offset( 2805acce750SPavan Nikhilesh frag, struct rte_udp_hdr *, 2815acce750SPavan Nikhilesh sizeof(struct rte_ether_hdr) + 2825acce750SPavan Nikhilesh sizeof(struct rte_ipv6_hdr) + 2835acce750SPavan Nikhilesh RTE_IPV6_FRAG_HDR_SIZE); 2845acce750SPavan Nikhilesh frag_hdr = rte_pktmbuf_mtod_offset( 2855acce750SPavan Nikhilesh frag, struct ipv6_extension_fragment *, 2865acce750SPavan Nikhilesh sizeof(struct rte_ether_hdr) + 2875acce750SPavan Nikhilesh sizeof(struct rte_ipv6_hdr)); 2885acce750SPavan Nikhilesh 2895acce750SPavan Nikhilesh rte_ether_unformat_addr("02:00:00:00:00:01", 2905acce750SPavan Nikhilesh ð_hdr->dst_addr); 2915acce750SPavan Nikhilesh rte_ether_unformat_addr("02:00:00:00:00:00", 2925acce750SPavan Nikhilesh ð_hdr->src_addr); 2935acce750SPavan Nikhilesh eth_hdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 2945acce750SPavan Nikhilesh 2955acce750SPavan Nikhilesh pkt_len = frag_len; 2965acce750SPavan Nikhilesh /* 2975acce750SPavan Nikhilesh * Initialize UDP header. 2985acce750SPavan Nikhilesh */ 2995acce750SPavan Nikhilesh if (i == 0) { 3005acce750SPavan Nikhilesh udp_hdr->src_port = rte_cpu_to_be_16(UDP_SRC_PORT); 3015acce750SPavan Nikhilesh udp_hdr->dst_port = rte_cpu_to_be_16(UDP_DST_PORT); 3025acce750SPavan Nikhilesh udp_hdr->dgram_len = rte_cpu_to_be_16(pkt_len); 3035acce750SPavan Nikhilesh udp_hdr->dgram_cksum = 0; /* No UDP checksum. */ 3045acce750SPavan Nikhilesh } 3055acce750SPavan Nikhilesh 3065acce750SPavan Nikhilesh /* 3075acce750SPavan Nikhilesh * Initialize IP header. 3085acce750SPavan Nikhilesh */ 3095acce750SPavan Nikhilesh pkt_len = (uint16_t)(pkt_len + sizeof(struct rte_ipv6_hdr) + 3105acce750SPavan Nikhilesh RTE_IPV6_FRAG_HDR_SIZE); 3115acce750SPavan Nikhilesh ip_hdr->vtc_flow = rte_cpu_to_be_32(IP6_VERSION << 28); 3125acce750SPavan Nikhilesh ip_hdr->payload_len = 3135acce750SPavan Nikhilesh rte_cpu_to_be_16(pkt_len - sizeof(struct rte_ipv6_hdr)); 3145acce750SPavan Nikhilesh ip_hdr->proto = IPPROTO_FRAGMENT; 3155acce750SPavan Nikhilesh ip_hdr->hop_limits = IP_DEFTTL; 31689b5642dSRobin Jarry ip_hdr->src_addr = ip6_addr; 31789b5642dSRobin Jarry ip_hdr->dst_addr = ip6_addr; 31889b5642dSRobin Jarry ip_hdr->src_addr.a[7] = (flow_id >> 16) & 0xf; 31989b5642dSRobin Jarry ip_hdr->src_addr.a[7] |= 0x10; 32089b5642dSRobin Jarry ip_hdr->src_addr.a[8] = (flow_id >> 8) & 0xff; 32189b5642dSRobin Jarry ip_hdr->src_addr.a[9] = flow_id & 0xff; 3225acce750SPavan Nikhilesh 32389b5642dSRobin Jarry ip_hdr->dst_addr.a[7] = (flow_id >> 16) & 0xf; 32489b5642dSRobin Jarry ip_hdr->dst_addr.a[7] |= 0x20; 32589b5642dSRobin Jarry ip_hdr->dst_addr.a[8] = (flow_id >> 8) & 0xff; 32689b5642dSRobin Jarry ip_hdr->dst_addr.a[9] = flow_id & 0xff; 3275acce750SPavan Nikhilesh 3285acce750SPavan Nikhilesh frag_hdr->next_header = IPPROTO_UDP; 3295acce750SPavan Nikhilesh frag_hdr->reserved = 0; 3305acce750SPavan Nikhilesh frag_hdr->frag_data = rte_cpu_to_be_16(frag_offset); 3315acce750SPavan Nikhilesh frag_hdr->id = rte_cpu_to_be_32(flow_id + 1); 3325acce750SPavan Nikhilesh 3335acce750SPavan Nikhilesh frag->data_len = sizeof(struct rte_ether_hdr) + pkt_len; 3345acce750SPavan Nikhilesh frag->pkt_len = frag->data_len; 3355acce750SPavan Nikhilesh frag->l2_len = sizeof(struct rte_ether_hdr); 3365acce750SPavan Nikhilesh frag->l3_len = 3375acce750SPavan Nikhilesh sizeof(struct rte_ipv6_hdr) + RTE_IPV6_FRAG_HDR_SIZE; 3385acce750SPavan Nikhilesh } 3395acce750SPavan Nikhilesh 3405acce750SPavan Nikhilesh if (fill_mode == FILL_MODE_RANDOM) 3415acce750SPavan Nikhilesh randomize_array_positions((void **)mbuf, nb_frags); 3425acce750SPavan Nikhilesh } 3435acce750SPavan Nikhilesh 3445acce750SPavan Nikhilesh static int 3455acce750SPavan Nikhilesh ipv6_rand_frag_pkt_setup(uint8_t fill_mode, uint8_t max_frag) 3465acce750SPavan Nikhilesh { 3475acce750SPavan Nikhilesh uint8_t nb_frag; 3485acce750SPavan Nikhilesh int i; 3495acce750SPavan Nikhilesh 3505acce750SPavan Nikhilesh for (i = 0; i < MAX_FLOWS; i++) { 3515acce750SPavan Nikhilesh nb_frag = get_rand_frags(max_frag); 3525acce750SPavan Nikhilesh if (rte_mempool_get_bulk(pkt_pool, (void **)mbufs[i], nb_frag) < 3535acce750SPavan Nikhilesh 0) 3545acce750SPavan Nikhilesh return TEST_FAILED; 3555acce750SPavan Nikhilesh ipv6_frag_fill_data(mbufs[i], nb_frag, i, fill_mode); 3565acce750SPavan Nikhilesh frag_per_flow[i] = nb_frag; 3575acce750SPavan Nikhilesh } 3585acce750SPavan Nikhilesh flow_cnt = i; 3595acce750SPavan Nikhilesh 3605acce750SPavan Nikhilesh return TEST_SUCCESS; 3615acce750SPavan Nikhilesh } 3625acce750SPavan Nikhilesh 3635acce750SPavan Nikhilesh static int 3645acce750SPavan Nikhilesh ipv6_frag_pkt_setup(uint8_t fill_mode, uint8_t nb_frag) 3655acce750SPavan Nikhilesh { 3665acce750SPavan Nikhilesh int i; 3675acce750SPavan Nikhilesh 3685acce750SPavan Nikhilesh for (i = 0; i < MAX_FLOWS; i++) { 3695acce750SPavan Nikhilesh if (rte_mempool_get_bulk(pkt_pool, (void **)mbufs[i], nb_frag) < 3705acce750SPavan Nikhilesh 0) 3715acce750SPavan Nikhilesh return TEST_FAILED; 3725acce750SPavan Nikhilesh ipv6_frag_fill_data(mbufs[i], nb_frag, i, fill_mode); 3735acce750SPavan Nikhilesh frag_per_flow[i] = nb_frag; 3745acce750SPavan Nikhilesh } 3755acce750SPavan Nikhilesh flow_cnt = i; 3765acce750SPavan Nikhilesh 3775acce750SPavan Nikhilesh return TEST_SUCCESS; 3785acce750SPavan Nikhilesh } 3795acce750SPavan Nikhilesh 3805acce750SPavan Nikhilesh static void 3815acce750SPavan Nikhilesh frag_pkt_teardown(void) 3825acce750SPavan Nikhilesh { 3835acce750SPavan Nikhilesh uint32_t i; 3845acce750SPavan Nikhilesh 3855acce750SPavan Nikhilesh for (i = 0; i < flow_cnt; i++) 3865acce750SPavan Nikhilesh rte_pktmbuf_free(mbufs[i][0]); 3875acce750SPavan Nikhilesh } 3885acce750SPavan Nikhilesh 3895acce750SPavan Nikhilesh static void 3905acce750SPavan Nikhilesh reassembly_print_stats(int8_t nb_frags, uint8_t fill_order, 3915acce750SPavan Nikhilesh uint32_t outstanding, uint64_t cyc_per_flow, 3925acce750SPavan Nikhilesh uint64_t cyc_per_frag_insert, 3935acce750SPavan Nikhilesh uint64_t cyc_per_reassembly) 3945acce750SPavan Nikhilesh { 3955acce750SPavan Nikhilesh char frag_str[8], order_str[12]; 3965acce750SPavan Nikhilesh 3975acce750SPavan Nikhilesh if (nb_frags > 0) 3985acce750SPavan Nikhilesh snprintf(frag_str, sizeof(frag_str), "%d", nb_frags); 3995acce750SPavan Nikhilesh else 4005acce750SPavan Nikhilesh snprintf(frag_str, sizeof(frag_str), "RANDOM"); 4015acce750SPavan Nikhilesh 4025acce750SPavan Nikhilesh switch (fill_order) { 4035acce750SPavan Nikhilesh case FILL_MODE_LINEAR: 4045acce750SPavan Nikhilesh snprintf(order_str, sizeof(order_str), "LINEAR"); 4055acce750SPavan Nikhilesh break; 4065acce750SPavan Nikhilesh case FILL_MODE_RANDOM: 4075acce750SPavan Nikhilesh snprintf(order_str, sizeof(order_str), "RANDOM"); 4085acce750SPavan Nikhilesh break; 4095acce750SPavan Nikhilesh case FILL_MODE_INTERLEAVED: 4105acce750SPavan Nikhilesh snprintf(order_str, sizeof(order_str), "INTERLEAVED"); 4115acce750SPavan Nikhilesh break; 4125acce750SPavan Nikhilesh default: 4135acce750SPavan Nikhilesh break; 4145acce750SPavan Nikhilesh } 4155acce750SPavan Nikhilesh 4165acce750SPavan Nikhilesh printf("| %-14s | %-14s | %-11d | %-11" PRIu64 " | %-22" PRIu64 4175acce750SPavan Nikhilesh " | %-17" PRIu64 " |\n", 4185acce750SPavan Nikhilesh order_str, frag_str, outstanding, cyc_per_flow, 4195acce750SPavan Nikhilesh cyc_per_frag_insert, cyc_per_reassembly); 4205acce750SPavan Nikhilesh printf("+================+================+=============+=============+" 4215acce750SPavan Nikhilesh "========================+===================+\n"); 4225acce750SPavan Nikhilesh } 4235acce750SPavan Nikhilesh 4245acce750SPavan Nikhilesh static void 4255acce750SPavan Nikhilesh join_array(struct rte_mbuf **dest_arr, struct rte_mbuf **src_arr, 4265acce750SPavan Nikhilesh uint8_t offset, uint8_t sz) 4275acce750SPavan Nikhilesh { 4285acce750SPavan Nikhilesh int i, j; 4295acce750SPavan Nikhilesh 4305acce750SPavan Nikhilesh for (i = offset, j = 0; j < sz; i++, j++) 4315acce750SPavan Nikhilesh dest_arr[i] = src_arr[j]; 4325acce750SPavan Nikhilesh } 4335acce750SPavan Nikhilesh 4345acce750SPavan Nikhilesh static int 4355acce750SPavan Nikhilesh ipv4_reassembly_perf(int8_t nb_frags, uint8_t fill_order) 4365acce750SPavan Nikhilesh { 4375acce750SPavan Nikhilesh struct rte_ip_frag_death_row death_row; 4385acce750SPavan Nikhilesh uint64_t total_reassembled_cyc = 0; 4395acce750SPavan Nikhilesh uint64_t total_empty_cyc = 0; 4405acce750SPavan Nikhilesh uint64_t tstamp, flow_tstamp; 4415acce750SPavan Nikhilesh uint64_t frag_processed = 0; 4425acce750SPavan Nikhilesh uint64_t total_cyc = 0; 4435acce750SPavan Nikhilesh uint32_t i, j; 4445acce750SPavan Nikhilesh 4455acce750SPavan Nikhilesh for (i = 0; i < flow_cnt; i++) { 4465acce750SPavan Nikhilesh struct rte_mbuf *buf_out = NULL; 4475acce750SPavan Nikhilesh uint8_t reassembled = 0; 4485acce750SPavan Nikhilesh 4495acce750SPavan Nikhilesh flow_tstamp = rte_rdtsc_precise(); 4505acce750SPavan Nikhilesh for (j = 0; j < frag_per_flow[i]; j++) { 4515acce750SPavan Nikhilesh struct rte_mbuf *buf = mbufs[i][j]; 4525acce750SPavan Nikhilesh struct rte_ipv4_hdr *ip_hdr = rte_pktmbuf_mtod_offset( 4535acce750SPavan Nikhilesh buf, struct rte_ipv4_hdr *, buf->l2_len); 4545acce750SPavan Nikhilesh 4555acce750SPavan Nikhilesh tstamp = rte_rdtsc_precise(); 4565acce750SPavan Nikhilesh buf_out = rte_ipv4_frag_reassemble_packet( 4575acce750SPavan Nikhilesh frag_tbl, &death_row, buf, flow_tstamp, ip_hdr); 4585acce750SPavan Nikhilesh 4595acce750SPavan Nikhilesh if (buf_out == NULL) { 4605acce750SPavan Nikhilesh total_empty_cyc += rte_rdtsc_precise() - tstamp; 4615acce750SPavan Nikhilesh frag_processed++; 4625acce750SPavan Nikhilesh continue; 4635acce750SPavan Nikhilesh } else { 4645acce750SPavan Nikhilesh /*Packet out*/ 4655acce750SPavan Nikhilesh total_reassembled_cyc += 4665acce750SPavan Nikhilesh rte_rdtsc_precise() - tstamp; 4675acce750SPavan Nikhilesh reassembled = 1; 4685acce750SPavan Nikhilesh } 4695acce750SPavan Nikhilesh } 4705acce750SPavan Nikhilesh total_cyc += rte_rdtsc_precise() - flow_tstamp; 4715acce750SPavan Nikhilesh if (!reassembled || buf_out->nb_segs != frag_per_flow[i]) 4725acce750SPavan Nikhilesh return TEST_FAILED; 4735acce750SPavan Nikhilesh memset(mbufs[i], 0, sizeof(struct rte_mbuf *) * MAX_FRAGMENTS); 4745acce750SPavan Nikhilesh mbufs[i][0] = buf_out; 4755acce750SPavan Nikhilesh } 4765acce750SPavan Nikhilesh 4775acce750SPavan Nikhilesh reassembly_print_stats(nb_frags, fill_order, 0, total_cyc / flow_cnt, 4785acce750SPavan Nikhilesh total_empty_cyc / frag_processed, 4795acce750SPavan Nikhilesh total_reassembled_cyc / flow_cnt); 4805acce750SPavan Nikhilesh 4815acce750SPavan Nikhilesh return TEST_SUCCESS; 4825acce750SPavan Nikhilesh } 4835acce750SPavan Nikhilesh 4845acce750SPavan Nikhilesh static int 4855acce750SPavan Nikhilesh ipv4_outstanding_reassembly_perf(int8_t nb_frags, uint8_t fill_order, 4865acce750SPavan Nikhilesh uint32_t outstanding) 4875acce750SPavan Nikhilesh { 4885acce750SPavan Nikhilesh struct rte_ip_frag_death_row death_row; 4895acce750SPavan Nikhilesh uint64_t total_reassembled_cyc = 0; 4905acce750SPavan Nikhilesh uint64_t total_empty_cyc = 0; 4915acce750SPavan Nikhilesh uint64_t tstamp, flow_tstamp; 4925acce750SPavan Nikhilesh uint64_t frag_processed = 0; 4935acce750SPavan Nikhilesh uint64_t total_cyc = 0; 4945acce750SPavan Nikhilesh uint32_t i, j, k; 4955acce750SPavan Nikhilesh 4965acce750SPavan Nikhilesh k = outstanding; 4975acce750SPavan Nikhilesh /* Insert outstanding fragments */ 4985acce750SPavan Nikhilesh for (i = 0; k && (i < flow_cnt); i++) { 4995acce750SPavan Nikhilesh struct rte_mbuf *buf_out = NULL; 5005acce750SPavan Nikhilesh 5015acce750SPavan Nikhilesh flow_tstamp = rte_rdtsc_precise(); 5025acce750SPavan Nikhilesh for (j = frag_per_flow[i] - 1; j > 0; j--) { 5035acce750SPavan Nikhilesh struct rte_mbuf *buf = mbufs[i][j]; 5045acce750SPavan Nikhilesh struct rte_ipv4_hdr *ip_hdr = rte_pktmbuf_mtod_offset( 5055acce750SPavan Nikhilesh buf, struct rte_ipv4_hdr *, buf->l2_len); 5065acce750SPavan Nikhilesh 5075acce750SPavan Nikhilesh tstamp = rte_rdtsc_precise(); 5085acce750SPavan Nikhilesh buf_out = rte_ipv4_frag_reassemble_packet( 5095acce750SPavan Nikhilesh frag_tbl, &death_row, buf, flow_tstamp, ip_hdr); 5105acce750SPavan Nikhilesh total_empty_cyc += rte_rdtsc_precise() - tstamp; 5115acce750SPavan Nikhilesh frag_processed++; 5125acce750SPavan Nikhilesh if (buf_out != NULL) 5135acce750SPavan Nikhilesh return TEST_FAILED; 5145acce750SPavan Nikhilesh 5155acce750SPavan Nikhilesh k--; 5165acce750SPavan Nikhilesh } 5175acce750SPavan Nikhilesh frag_per_flow[i] = 1; 5185acce750SPavan Nikhilesh } 5195acce750SPavan Nikhilesh 5205acce750SPavan Nikhilesh for (i = 0; i < flow_cnt; i++) { 5215acce750SPavan Nikhilesh struct rte_mbuf *buf_out = NULL; 5225acce750SPavan Nikhilesh uint8_t reassembled = 0; 5235acce750SPavan Nikhilesh 5245acce750SPavan Nikhilesh flow_tstamp = rte_rdtsc_precise(); 5255acce750SPavan Nikhilesh for (j = 0; j < frag_per_flow[i]; j++) { 5265acce750SPavan Nikhilesh struct rte_mbuf *buf = mbufs[i][j]; 5275acce750SPavan Nikhilesh struct rte_ipv4_hdr *ip_hdr = rte_pktmbuf_mtod_offset( 5285acce750SPavan Nikhilesh buf, struct rte_ipv4_hdr *, buf->l2_len); 5295acce750SPavan Nikhilesh 5305acce750SPavan Nikhilesh tstamp = rte_rdtsc_precise(); 5315acce750SPavan Nikhilesh buf_out = rte_ipv4_frag_reassemble_packet( 5325acce750SPavan Nikhilesh frag_tbl, &death_row, buf, flow_tstamp, ip_hdr); 5335acce750SPavan Nikhilesh 5345acce750SPavan Nikhilesh if (buf_out == NULL) { 5355acce750SPavan Nikhilesh total_empty_cyc += rte_rdtsc_precise() - tstamp; 5365acce750SPavan Nikhilesh frag_processed++; 5375acce750SPavan Nikhilesh continue; 5385acce750SPavan Nikhilesh } else { 5395acce750SPavan Nikhilesh /*Packet out*/ 5405acce750SPavan Nikhilesh total_reassembled_cyc += 5415acce750SPavan Nikhilesh rte_rdtsc_precise() - tstamp; 5425acce750SPavan Nikhilesh reassembled = 1; 5435acce750SPavan Nikhilesh } 5445acce750SPavan Nikhilesh } 5455acce750SPavan Nikhilesh total_cyc += rte_rdtsc_precise() - flow_tstamp; 5465acce750SPavan Nikhilesh if (!reassembled) 5475acce750SPavan Nikhilesh return TEST_FAILED; 5485acce750SPavan Nikhilesh memset(mbufs[i], 0, sizeof(struct rte_mbuf *) * MAX_FRAGMENTS); 5495acce750SPavan Nikhilesh mbufs[i][0] = buf_out; 5505acce750SPavan Nikhilesh } 5515acce750SPavan Nikhilesh 5525acce750SPavan Nikhilesh reassembly_print_stats(nb_frags, fill_order, outstanding, 5535acce750SPavan Nikhilesh total_cyc / flow_cnt, 5545acce750SPavan Nikhilesh total_empty_cyc / frag_processed, 5555acce750SPavan Nikhilesh total_reassembled_cyc / flow_cnt); 5565acce750SPavan Nikhilesh 5575acce750SPavan Nikhilesh return TEST_SUCCESS; 5585acce750SPavan Nikhilesh } 5595acce750SPavan Nikhilesh 5605acce750SPavan Nikhilesh static int 5615acce750SPavan Nikhilesh ipv4_reassembly_interleaved_flows_perf(uint8_t nb_frags) 5625acce750SPavan Nikhilesh { 5635acce750SPavan Nikhilesh struct rte_ip_frag_death_row death_row; 5645acce750SPavan Nikhilesh uint64_t total_reassembled_cyc = 0; 5655acce750SPavan Nikhilesh uint64_t total_empty_cyc = 0; 5665acce750SPavan Nikhilesh uint64_t tstamp, flow_tstamp; 5675acce750SPavan Nikhilesh uint64_t frag_processed = 0; 5685acce750SPavan Nikhilesh uint64_t total_cyc = 0; 5695acce750SPavan Nikhilesh uint32_t i, j; 5705acce750SPavan Nikhilesh 5715acce750SPavan Nikhilesh for (i = 0; i < flow_cnt; i += 4) { 5725acce750SPavan Nikhilesh struct rte_mbuf *buf_out[4] = {NULL}; 5735acce750SPavan Nikhilesh uint8_t reassembled = 0; 5745acce750SPavan Nikhilesh uint8_t nb_frags = 0; 5755acce750SPavan Nikhilesh uint8_t prev = 0; 5765acce750SPavan Nikhilesh 5775acce750SPavan Nikhilesh for (j = 0; j < 4; j++) 5785acce750SPavan Nikhilesh nb_frags += frag_per_flow[i + j]; 5795acce750SPavan Nikhilesh 5805acce750SPavan Nikhilesh struct rte_mbuf *buf_arr[nb_frags]; 5815acce750SPavan Nikhilesh for (j = 0; j < 4; j++) { 5825acce750SPavan Nikhilesh join_array(buf_arr, mbufs[i + j], prev, 5835acce750SPavan Nikhilesh frag_per_flow[i + j]); 5845acce750SPavan Nikhilesh prev += frag_per_flow[i + j]; 5855acce750SPavan Nikhilesh } 5865acce750SPavan Nikhilesh randomize_array_positions((void **)buf_arr, nb_frags); 5875acce750SPavan Nikhilesh flow_tstamp = rte_rdtsc_precise(); 5885acce750SPavan Nikhilesh for (j = 0; j < nb_frags; j++) { 5895acce750SPavan Nikhilesh struct rte_mbuf *buf = buf_arr[j]; 5905acce750SPavan Nikhilesh struct rte_ipv4_hdr *ip_hdr = rte_pktmbuf_mtod_offset( 5915acce750SPavan Nikhilesh buf, struct rte_ipv4_hdr *, buf->l2_len); 5925acce750SPavan Nikhilesh 5935acce750SPavan Nikhilesh tstamp = rte_rdtsc_precise(); 5945acce750SPavan Nikhilesh buf_out[reassembled] = rte_ipv4_frag_reassemble_packet( 5955acce750SPavan Nikhilesh frag_tbl, &death_row, buf, flow_tstamp, ip_hdr); 5965acce750SPavan Nikhilesh 5975acce750SPavan Nikhilesh if (buf_out[reassembled] == NULL) { 5985acce750SPavan Nikhilesh total_empty_cyc += rte_rdtsc_precise() - tstamp; 5995acce750SPavan Nikhilesh frag_processed++; 6005acce750SPavan Nikhilesh continue; 6015acce750SPavan Nikhilesh } else { 6025acce750SPavan Nikhilesh /*Packet out*/ 6035acce750SPavan Nikhilesh total_reassembled_cyc += 6045acce750SPavan Nikhilesh rte_rdtsc_precise() - tstamp; 6055acce750SPavan Nikhilesh reassembled++; 6065acce750SPavan Nikhilesh } 6075acce750SPavan Nikhilesh } 6085acce750SPavan Nikhilesh total_cyc += rte_rdtsc_precise() - flow_tstamp; 6095acce750SPavan Nikhilesh if (reassembled != 4) 6105acce750SPavan Nikhilesh return TEST_FAILED; 6115acce750SPavan Nikhilesh for (j = 0; j < 4; j++) { 6125acce750SPavan Nikhilesh memset(mbufs[i + j], 0, 6135acce750SPavan Nikhilesh sizeof(struct rte_mbuf *) * MAX_FRAGMENTS); 6145acce750SPavan Nikhilesh mbufs[i + j][0] = buf_out[j]; 6155acce750SPavan Nikhilesh } 6165acce750SPavan Nikhilesh } 6175acce750SPavan Nikhilesh 6185acce750SPavan Nikhilesh reassembly_print_stats(nb_frags, FILL_MODE_INTERLEAVED, 0, 6195acce750SPavan Nikhilesh total_cyc / flow_cnt, 6205acce750SPavan Nikhilesh total_empty_cyc / frag_processed, 6215acce750SPavan Nikhilesh total_reassembled_cyc / flow_cnt); 6225acce750SPavan Nikhilesh 6235acce750SPavan Nikhilesh return TEST_SUCCESS; 6245acce750SPavan Nikhilesh } 6255acce750SPavan Nikhilesh 6265acce750SPavan Nikhilesh static int 6275acce750SPavan Nikhilesh ipv6_reassembly_perf(int8_t nb_frags, uint8_t fill_order) 6285acce750SPavan Nikhilesh { 6295acce750SPavan Nikhilesh struct rte_ip_frag_death_row death_row; 6305acce750SPavan Nikhilesh uint64_t total_reassembled_cyc = 0; 6315acce750SPavan Nikhilesh uint64_t total_empty_cyc = 0; 6325acce750SPavan Nikhilesh uint64_t tstamp, flow_tstamp; 6335acce750SPavan Nikhilesh uint64_t frag_processed = 0; 6345acce750SPavan Nikhilesh uint64_t total_cyc = 0; 6355acce750SPavan Nikhilesh uint32_t i, j; 6365acce750SPavan Nikhilesh 6375acce750SPavan Nikhilesh for (i = 0; i < flow_cnt; i++) { 6385acce750SPavan Nikhilesh struct rte_mbuf *buf_out = NULL; 6395acce750SPavan Nikhilesh uint8_t reassembled = 0; 6405acce750SPavan Nikhilesh 6415acce750SPavan Nikhilesh flow_tstamp = rte_rdtsc_precise(); 6425acce750SPavan Nikhilesh for (j = 0; j < frag_per_flow[i]; j++) { 6435acce750SPavan Nikhilesh struct rte_mbuf *buf = mbufs[i][j]; 6445acce750SPavan Nikhilesh struct rte_ipv6_hdr *ip_hdr = rte_pktmbuf_mtod_offset( 6455acce750SPavan Nikhilesh buf, struct rte_ipv6_hdr *, buf->l2_len); 6465acce750SPavan Nikhilesh struct ipv6_extension_fragment *frag_hdr = 6475acce750SPavan Nikhilesh rte_pktmbuf_mtod_offset( 6485acce750SPavan Nikhilesh buf, struct ipv6_extension_fragment *, 6495acce750SPavan Nikhilesh buf->l2_len + 6505acce750SPavan Nikhilesh sizeof(struct rte_ipv6_hdr)); 6515acce750SPavan Nikhilesh 6525acce750SPavan Nikhilesh tstamp = rte_rdtsc_precise(); 6535acce750SPavan Nikhilesh buf_out = rte_ipv6_frag_reassemble_packet( 6545acce750SPavan Nikhilesh frag_tbl, &death_row, buf, flow_tstamp, ip_hdr, 6555acce750SPavan Nikhilesh frag_hdr); 6565acce750SPavan Nikhilesh 6575acce750SPavan Nikhilesh if (buf_out == NULL) { 6585acce750SPavan Nikhilesh total_empty_cyc += rte_rdtsc_precise() - tstamp; 6595acce750SPavan Nikhilesh frag_processed++; 6605acce750SPavan Nikhilesh continue; 6615acce750SPavan Nikhilesh } else { 6625acce750SPavan Nikhilesh /*Packet out*/ 6635acce750SPavan Nikhilesh total_reassembled_cyc += 6645acce750SPavan Nikhilesh rte_rdtsc_precise() - tstamp; 6655acce750SPavan Nikhilesh reassembled = 1; 6665acce750SPavan Nikhilesh } 6675acce750SPavan Nikhilesh } 6685acce750SPavan Nikhilesh total_cyc += rte_rdtsc_precise() - flow_tstamp; 6695acce750SPavan Nikhilesh if (!reassembled || buf_out->nb_segs != frag_per_flow[i]) 6705acce750SPavan Nikhilesh return TEST_FAILED; 6715acce750SPavan Nikhilesh memset(mbufs[i], 0, sizeof(struct rte_mbuf *) * MAX_FRAGMENTS); 6725acce750SPavan Nikhilesh mbufs[i][0] = buf_out; 6735acce750SPavan Nikhilesh } 6745acce750SPavan Nikhilesh 6755acce750SPavan Nikhilesh reassembly_print_stats(nb_frags, fill_order, 0, total_cyc / flow_cnt, 6765acce750SPavan Nikhilesh total_empty_cyc / frag_processed, 6775acce750SPavan Nikhilesh total_reassembled_cyc / flow_cnt); 6785acce750SPavan Nikhilesh 6795acce750SPavan Nikhilesh return TEST_SUCCESS; 6805acce750SPavan Nikhilesh } 6815acce750SPavan Nikhilesh 6825acce750SPavan Nikhilesh static int 6835acce750SPavan Nikhilesh ipv6_outstanding_reassembly_perf(int8_t nb_frags, uint8_t fill_order, 6845acce750SPavan Nikhilesh uint32_t outstanding) 6855acce750SPavan Nikhilesh { 6865acce750SPavan Nikhilesh struct rte_ip_frag_death_row death_row; 6875acce750SPavan Nikhilesh uint64_t total_reassembled_cyc = 0; 6885acce750SPavan Nikhilesh uint64_t total_empty_cyc = 0; 6895acce750SPavan Nikhilesh uint64_t tstamp, flow_tstamp; 6905acce750SPavan Nikhilesh uint64_t frag_processed = 0; 6915acce750SPavan Nikhilesh uint64_t total_cyc = 0; 6925acce750SPavan Nikhilesh uint32_t i, j, k; 6935acce750SPavan Nikhilesh 6945acce750SPavan Nikhilesh k = outstanding; 6955acce750SPavan Nikhilesh /* Insert outstanding fragments */ 6965acce750SPavan Nikhilesh for (i = 0; k && (i < flow_cnt); i++) { 6975acce750SPavan Nikhilesh struct rte_mbuf *buf_out = NULL; 6985acce750SPavan Nikhilesh 6995acce750SPavan Nikhilesh flow_tstamp = rte_rdtsc_precise(); 7005acce750SPavan Nikhilesh for (j = frag_per_flow[i] - 1; j > 0; j--) { 7015acce750SPavan Nikhilesh struct rte_mbuf *buf = mbufs[i][j]; 7025acce750SPavan Nikhilesh struct rte_ipv6_hdr *ip_hdr = rte_pktmbuf_mtod_offset( 7035acce750SPavan Nikhilesh buf, struct rte_ipv6_hdr *, buf->l2_len); 7045acce750SPavan Nikhilesh struct ipv6_extension_fragment *frag_hdr = 7055acce750SPavan Nikhilesh rte_pktmbuf_mtod_offset( 7065acce750SPavan Nikhilesh buf, struct ipv6_extension_fragment *, 7075acce750SPavan Nikhilesh buf->l2_len + 7085acce750SPavan Nikhilesh sizeof(struct rte_ipv6_hdr)); 7095acce750SPavan Nikhilesh 7105acce750SPavan Nikhilesh tstamp = rte_rdtsc_precise(); 7115acce750SPavan Nikhilesh buf_out = rte_ipv6_frag_reassemble_packet( 7125acce750SPavan Nikhilesh frag_tbl, &death_row, buf, flow_tstamp, ip_hdr, 7135acce750SPavan Nikhilesh frag_hdr); 7145acce750SPavan Nikhilesh total_empty_cyc += rte_rdtsc_precise() - tstamp; 7155acce750SPavan Nikhilesh frag_processed++; 7165acce750SPavan Nikhilesh 7175acce750SPavan Nikhilesh if (buf_out != NULL) 7185acce750SPavan Nikhilesh return TEST_FAILED; 7195acce750SPavan Nikhilesh 7205acce750SPavan Nikhilesh k--; 7215acce750SPavan Nikhilesh } 7225acce750SPavan Nikhilesh frag_per_flow[i] = 1; 7235acce750SPavan Nikhilesh } 7245acce750SPavan Nikhilesh 7255acce750SPavan Nikhilesh for (i = 0; i < flow_cnt; i++) { 7265acce750SPavan Nikhilesh struct rte_mbuf *buf_out = NULL; 7275acce750SPavan Nikhilesh uint8_t reassembled = 0; 7285acce750SPavan Nikhilesh 7295acce750SPavan Nikhilesh flow_tstamp = rte_rdtsc_precise(); 7305acce750SPavan Nikhilesh for (j = 0; j < frag_per_flow[i]; j++) { 7315acce750SPavan Nikhilesh struct rte_mbuf *buf = mbufs[i][j]; 7325acce750SPavan Nikhilesh struct rte_ipv6_hdr *ip_hdr = rte_pktmbuf_mtod_offset( 7335acce750SPavan Nikhilesh buf, struct rte_ipv6_hdr *, buf->l2_len); 7345acce750SPavan Nikhilesh struct ipv6_extension_fragment *frag_hdr = 7355acce750SPavan Nikhilesh rte_pktmbuf_mtod_offset( 7365acce750SPavan Nikhilesh buf, struct ipv6_extension_fragment *, 7375acce750SPavan Nikhilesh buf->l2_len + 7385acce750SPavan Nikhilesh sizeof(struct rte_ipv6_hdr)); 7395acce750SPavan Nikhilesh 7405acce750SPavan Nikhilesh tstamp = rte_rdtsc_precise(); 7415acce750SPavan Nikhilesh buf_out = rte_ipv6_frag_reassemble_packet( 7425acce750SPavan Nikhilesh frag_tbl, &death_row, buf, flow_tstamp, ip_hdr, 7435acce750SPavan Nikhilesh frag_hdr); 7445acce750SPavan Nikhilesh 7455acce750SPavan Nikhilesh if (buf_out == NULL) { 7465acce750SPavan Nikhilesh total_empty_cyc += rte_rdtsc_precise() - tstamp; 7475acce750SPavan Nikhilesh frag_processed++; 7485acce750SPavan Nikhilesh continue; 7495acce750SPavan Nikhilesh } else { 7505acce750SPavan Nikhilesh /*Packet out*/ 7515acce750SPavan Nikhilesh total_reassembled_cyc += 7525acce750SPavan Nikhilesh rte_rdtsc_precise() - tstamp; 7535acce750SPavan Nikhilesh reassembled = 1; 7545acce750SPavan Nikhilesh } 7555acce750SPavan Nikhilesh } 7565acce750SPavan Nikhilesh total_cyc += rte_rdtsc_precise() - flow_tstamp; 7575acce750SPavan Nikhilesh if (!reassembled) 7585acce750SPavan Nikhilesh return TEST_FAILED; 7595acce750SPavan Nikhilesh memset(mbufs[i], 0, sizeof(struct rte_mbuf *) * MAX_FRAGMENTS); 7605acce750SPavan Nikhilesh mbufs[i][0] = buf_out; 7615acce750SPavan Nikhilesh } 7625acce750SPavan Nikhilesh 7635acce750SPavan Nikhilesh reassembly_print_stats(nb_frags, fill_order, outstanding, 7645acce750SPavan Nikhilesh total_cyc / flow_cnt, 7655acce750SPavan Nikhilesh total_empty_cyc / frag_processed, 7665acce750SPavan Nikhilesh total_reassembled_cyc / flow_cnt); 7675acce750SPavan Nikhilesh 7685acce750SPavan Nikhilesh return TEST_SUCCESS; 7695acce750SPavan Nikhilesh } 7705acce750SPavan Nikhilesh 7715acce750SPavan Nikhilesh static int 7725acce750SPavan Nikhilesh ipv6_reassembly_interleaved_flows_perf(int8_t nb_frags) 7735acce750SPavan Nikhilesh { 7745acce750SPavan Nikhilesh struct rte_ip_frag_death_row death_row; 7755acce750SPavan Nikhilesh uint64_t total_reassembled_cyc = 0; 7765acce750SPavan Nikhilesh uint64_t total_empty_cyc = 0; 7775acce750SPavan Nikhilesh uint64_t tstamp, flow_tstamp; 7785acce750SPavan Nikhilesh uint64_t frag_processed = 0; 7795acce750SPavan Nikhilesh uint64_t total_cyc = 0; 7805acce750SPavan Nikhilesh uint32_t i, j; 7815acce750SPavan Nikhilesh 7825acce750SPavan Nikhilesh for (i = 0; i < flow_cnt; i += 4) { 7835acce750SPavan Nikhilesh struct rte_mbuf *buf_out[4] = {NULL}; 7845acce750SPavan Nikhilesh uint8_t reassembled = 0; 7855acce750SPavan Nikhilesh uint8_t nb_frags = 0; 7865acce750SPavan Nikhilesh uint8_t prev = 0; 7875acce750SPavan Nikhilesh 7885acce750SPavan Nikhilesh for (j = 0; j < 4; j++) 7895acce750SPavan Nikhilesh nb_frags += frag_per_flow[i + j]; 7905acce750SPavan Nikhilesh 7915acce750SPavan Nikhilesh struct rte_mbuf *buf_arr[nb_frags]; 7925acce750SPavan Nikhilesh for (j = 0; j < 4; j++) { 7935acce750SPavan Nikhilesh join_array(buf_arr, mbufs[i + j], prev, 7945acce750SPavan Nikhilesh frag_per_flow[i + j]); 7955acce750SPavan Nikhilesh prev += frag_per_flow[i + j]; 7965acce750SPavan Nikhilesh } 7975acce750SPavan Nikhilesh randomize_array_positions((void **)buf_arr, nb_frags); 7985acce750SPavan Nikhilesh flow_tstamp = rte_rdtsc_precise(); 7995acce750SPavan Nikhilesh for (j = 0; j < nb_frags; j++) { 8005acce750SPavan Nikhilesh struct rte_mbuf *buf = buf_arr[j]; 8015acce750SPavan Nikhilesh struct rte_ipv6_hdr *ip_hdr = rte_pktmbuf_mtod_offset( 8025acce750SPavan Nikhilesh buf, struct rte_ipv6_hdr *, buf->l2_len); 8035acce750SPavan Nikhilesh struct ipv6_extension_fragment *frag_hdr = 8045acce750SPavan Nikhilesh rte_pktmbuf_mtod_offset( 8055acce750SPavan Nikhilesh buf, struct ipv6_extension_fragment *, 8065acce750SPavan Nikhilesh buf->l2_len + 8075acce750SPavan Nikhilesh sizeof(struct rte_ipv6_hdr)); 8085acce750SPavan Nikhilesh 8095acce750SPavan Nikhilesh tstamp = rte_rdtsc_precise(); 8105acce750SPavan Nikhilesh buf_out[reassembled] = rte_ipv6_frag_reassemble_packet( 8115acce750SPavan Nikhilesh frag_tbl, &death_row, buf, flow_tstamp, ip_hdr, 8125acce750SPavan Nikhilesh frag_hdr); 8135acce750SPavan Nikhilesh 8145acce750SPavan Nikhilesh if (buf_out[reassembled] == NULL) { 8155acce750SPavan Nikhilesh total_empty_cyc += rte_rdtsc_precise() - tstamp; 8165acce750SPavan Nikhilesh frag_processed++; 8175acce750SPavan Nikhilesh continue; 8185acce750SPavan Nikhilesh } else { 8195acce750SPavan Nikhilesh /*Packet out*/ 8205acce750SPavan Nikhilesh total_reassembled_cyc += 8215acce750SPavan Nikhilesh rte_rdtsc_precise() - tstamp; 8225acce750SPavan Nikhilesh reassembled++; 8235acce750SPavan Nikhilesh } 8245acce750SPavan Nikhilesh } 8255acce750SPavan Nikhilesh total_cyc += rte_rdtsc_precise() - flow_tstamp; 8265acce750SPavan Nikhilesh if (reassembled != 4) 8275acce750SPavan Nikhilesh return TEST_FAILED; 8285acce750SPavan Nikhilesh for (j = 0; j < 4; j++) { 8295acce750SPavan Nikhilesh memset(mbufs[i + j], 0, 8305acce750SPavan Nikhilesh sizeof(struct rte_mbuf *) * MAX_FRAGMENTS); 8315acce750SPavan Nikhilesh mbufs[i + j][0] = buf_out[j]; 8325acce750SPavan Nikhilesh } 8335acce750SPavan Nikhilesh } 8345acce750SPavan Nikhilesh 8355acce750SPavan Nikhilesh reassembly_print_stats(nb_frags, FILL_MODE_INTERLEAVED, 0, 8365acce750SPavan Nikhilesh total_cyc / flow_cnt, 8375acce750SPavan Nikhilesh total_empty_cyc / frag_processed, 8385acce750SPavan Nikhilesh total_reassembled_cyc / flow_cnt); 8395acce750SPavan Nikhilesh 8405acce750SPavan Nikhilesh return TEST_SUCCESS; 8415acce750SPavan Nikhilesh } 8425acce750SPavan Nikhilesh 8435acce750SPavan Nikhilesh static int 8445acce750SPavan Nikhilesh ipv4_reassembly_test(int8_t nb_frags, uint8_t fill_order, uint32_t outstanding) 8455acce750SPavan Nikhilesh { 8465acce750SPavan Nikhilesh int rc; 8475acce750SPavan Nikhilesh 8485acce750SPavan Nikhilesh if (nb_frags > 0) 8495acce750SPavan Nikhilesh rc = ipv4_frag_pkt_setup(fill_order, nb_frags); 8505acce750SPavan Nikhilesh else 8515acce750SPavan Nikhilesh rc = ipv4_rand_frag_pkt_setup(fill_order, MAX_FRAGMENTS); 8525acce750SPavan Nikhilesh 8535acce750SPavan Nikhilesh if (rc) 8545acce750SPavan Nikhilesh return rc; 8555acce750SPavan Nikhilesh 8565acce750SPavan Nikhilesh if (outstanding) 8575acce750SPavan Nikhilesh rc = ipv4_outstanding_reassembly_perf(nb_frags, fill_order, 8585acce750SPavan Nikhilesh outstanding); 8595acce750SPavan Nikhilesh else if (fill_order == FILL_MODE_INTERLEAVED) 8605acce750SPavan Nikhilesh rc = ipv4_reassembly_interleaved_flows_perf(nb_frags); 8615acce750SPavan Nikhilesh else 8625acce750SPavan Nikhilesh rc = ipv4_reassembly_perf(nb_frags, fill_order); 8635acce750SPavan Nikhilesh 8645acce750SPavan Nikhilesh frag_pkt_teardown(); 8655acce750SPavan Nikhilesh 8665acce750SPavan Nikhilesh return rc; 8675acce750SPavan Nikhilesh } 8685acce750SPavan Nikhilesh 8695acce750SPavan Nikhilesh static int 8705acce750SPavan Nikhilesh ipv6_reassembly_test(int8_t nb_frags, uint8_t fill_order, uint32_t outstanding) 8715acce750SPavan Nikhilesh { 8725acce750SPavan Nikhilesh int rc; 8735acce750SPavan Nikhilesh 8745acce750SPavan Nikhilesh if (nb_frags > 0) 8755acce750SPavan Nikhilesh rc = ipv6_frag_pkt_setup(fill_order, nb_frags); 8765acce750SPavan Nikhilesh else 8775acce750SPavan Nikhilesh rc = ipv6_rand_frag_pkt_setup(fill_order, MAX_FRAGMENTS); 8785acce750SPavan Nikhilesh 8795acce750SPavan Nikhilesh if (rc) 8805acce750SPavan Nikhilesh return rc; 8815acce750SPavan Nikhilesh 8825acce750SPavan Nikhilesh if (outstanding) 8835acce750SPavan Nikhilesh rc = ipv6_outstanding_reassembly_perf(nb_frags, fill_order, 8845acce750SPavan Nikhilesh outstanding); 8855acce750SPavan Nikhilesh else if (fill_order == FILL_MODE_INTERLEAVED) 8865acce750SPavan Nikhilesh rc = ipv6_reassembly_interleaved_flows_perf(nb_frags); 8875acce750SPavan Nikhilesh else 8885acce750SPavan Nikhilesh rc = ipv6_reassembly_perf(nb_frags, fill_order); 8895acce750SPavan Nikhilesh 8905acce750SPavan Nikhilesh frag_pkt_teardown(); 8915acce750SPavan Nikhilesh 8925acce750SPavan Nikhilesh return rc; 8935acce750SPavan Nikhilesh } 8945acce750SPavan Nikhilesh 8955acce750SPavan Nikhilesh static int 8965acce750SPavan Nikhilesh test_reassembly_perf(void) 8975acce750SPavan Nikhilesh { 8985acce750SPavan Nikhilesh int8_t nb_fragments[] = {2, 3, MAX_FRAGMENTS, -1 /* Random */}; 8995acce750SPavan Nikhilesh uint8_t order_type[] = {FILL_MODE_LINEAR, FILL_MODE_RANDOM}; 9005acce750SPavan Nikhilesh uint32_t outstanding[] = {100, 500, 1000, 2000, 3000}; 9015acce750SPavan Nikhilesh uint32_t i, j; 9025acce750SPavan Nikhilesh int rc; 9035acce750SPavan Nikhilesh 9045acce750SPavan Nikhilesh rc = reassembly_test_setup(); 9055acce750SPavan Nikhilesh if (rc) 9065acce750SPavan Nikhilesh return rc; 9075acce750SPavan Nikhilesh 9085acce750SPavan Nikhilesh reassembly_print_banner("IPV4"); 9095acce750SPavan Nikhilesh /* Test variable fragment count and ordering. */ 9105acce750SPavan Nikhilesh for (i = 0; i < RTE_DIM(nb_fragments); i++) { 9115acce750SPavan Nikhilesh for (j = 0; j < RTE_DIM(order_type); j++) { 9125acce750SPavan Nikhilesh rc = ipv4_reassembly_test(nb_fragments[i], 9135acce750SPavan Nikhilesh order_type[j], 0); 9145acce750SPavan Nikhilesh if (rc) 9155acce750SPavan Nikhilesh return rc; 9165acce750SPavan Nikhilesh } 9175acce750SPavan Nikhilesh } 9185acce750SPavan Nikhilesh 9195acce750SPavan Nikhilesh /* Test outstanding fragments in the table. */ 9205acce750SPavan Nikhilesh for (i = 0; i < RTE_DIM(outstanding); i++) { 9215acce750SPavan Nikhilesh rc = ipv4_reassembly_test(2, 0, outstanding[i]); 9225acce750SPavan Nikhilesh if (rc) 9235acce750SPavan Nikhilesh return rc; 9245acce750SPavan Nikhilesh } 9255acce750SPavan Nikhilesh for (i = 0; i < RTE_DIM(outstanding); i++) { 9265acce750SPavan Nikhilesh rc = ipv4_reassembly_test(MAX_FRAGMENTS, 0, outstanding[i]); 9275acce750SPavan Nikhilesh if (rc) 9285acce750SPavan Nikhilesh return rc; 9295acce750SPavan Nikhilesh } 9305acce750SPavan Nikhilesh 9315acce750SPavan Nikhilesh /* Test interleaved flow reassembly perf */ 9325acce750SPavan Nikhilesh for (i = 0; i < RTE_DIM(nb_fragments); i++) { 9335acce750SPavan Nikhilesh rc = ipv4_reassembly_test(nb_fragments[i], 9345acce750SPavan Nikhilesh FILL_MODE_INTERLEAVED, 0); 9355acce750SPavan Nikhilesh if (rc) 9365acce750SPavan Nikhilesh return rc; 9375acce750SPavan Nikhilesh } 9385acce750SPavan Nikhilesh printf("\n"); 9395acce750SPavan Nikhilesh reassembly_print_banner("IPV6"); 9405acce750SPavan Nikhilesh /* Test variable fragment count and ordering. */ 9415acce750SPavan Nikhilesh for (i = 0; i < RTE_DIM(nb_fragments); i++) { 9425acce750SPavan Nikhilesh for (j = 0; j < RTE_DIM(order_type); j++) { 9435acce750SPavan Nikhilesh rc = ipv6_reassembly_test(nb_fragments[i], 9445acce750SPavan Nikhilesh order_type[j], 0); 9455acce750SPavan Nikhilesh if (rc) 9465acce750SPavan Nikhilesh return rc; 9475acce750SPavan Nikhilesh } 9485acce750SPavan Nikhilesh } 9495acce750SPavan Nikhilesh 9505acce750SPavan Nikhilesh /* Test outstanding fragments in the table. */ 9515acce750SPavan Nikhilesh for (i = 0; i < RTE_DIM(outstanding); i++) { 9525acce750SPavan Nikhilesh rc = ipv6_reassembly_test(2, 0, outstanding[i]); 9535acce750SPavan Nikhilesh if (rc) 9545acce750SPavan Nikhilesh return rc; 9555acce750SPavan Nikhilesh } 9565acce750SPavan Nikhilesh 9575acce750SPavan Nikhilesh for (i = 0; i < RTE_DIM(outstanding); i++) { 9585acce750SPavan Nikhilesh rc = ipv6_reassembly_test(MAX_FRAGMENTS, 0, outstanding[i]); 9595acce750SPavan Nikhilesh if (rc) 9605acce750SPavan Nikhilesh return rc; 9615acce750SPavan Nikhilesh } 9625acce750SPavan Nikhilesh 9635acce750SPavan Nikhilesh /* Test interleaved flow reassembly perf */ 9645acce750SPavan Nikhilesh for (i = 0; i < RTE_DIM(nb_fragments); i++) { 9655acce750SPavan Nikhilesh rc = ipv6_reassembly_test(nb_fragments[i], 9665acce750SPavan Nikhilesh FILL_MODE_INTERLEAVED, 0); 9675acce750SPavan Nikhilesh if (rc) 9685acce750SPavan Nikhilesh return rc; 9695acce750SPavan Nikhilesh } 9705acce750SPavan Nikhilesh reassembly_test_teardown(); 9715acce750SPavan Nikhilesh 9725acce750SPavan Nikhilesh return TEST_SUCCESS; 9735acce750SPavan Nikhilesh } 9745acce750SPavan Nikhilesh 975e0a8442cSBruce Richardson REGISTER_PERF_TEST(reassembly_perf_autotest, test_reassembly_perf); 976