xref: /dpdk/app/test/test_reassembly_perf.c (revision f9e1d67f237a00cf94feb4413e3d978fdd632052)
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 					&eth_hdr->dst_addr);
1595acce750SPavan Nikhilesh 		rte_ether_unformat_addr("02:00:00:00:00:00",
1605acce750SPavan Nikhilesh 					&eth_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 					&eth_hdr->dst_addr);
2915acce750SPavan Nikhilesh 		rte_ether_unformat_addr("02:00:00:00:00:00",
2925acce750SPavan Nikhilesh 					&eth_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