xref: /f-stack/dpdk/app/test/test_mbuf.c (revision 2d9fd380)
14418919fSjohnjiang /* SPDX-License-Identifier: BSD-3-Clause
24418919fSjohnjiang  * Copyright(c) 2010-2014 Intel Corporation
34418919fSjohnjiang  */
44418919fSjohnjiang 
54418919fSjohnjiang #include <string.h>
64418919fSjohnjiang #include <stdarg.h>
74418919fSjohnjiang #include <stdio.h>
84418919fSjohnjiang #include <stdlib.h>
94418919fSjohnjiang #include <stdint.h>
104418919fSjohnjiang #include <inttypes.h>
114418919fSjohnjiang #include <errno.h>
124418919fSjohnjiang #include <sys/queue.h>
134418919fSjohnjiang 
144418919fSjohnjiang #include <rte_common.h>
154418919fSjohnjiang #include <rte_errno.h>
164418919fSjohnjiang #include <rte_debug.h>
174418919fSjohnjiang #include <rte_log.h>
184418919fSjohnjiang #include <rte_memory.h>
194418919fSjohnjiang #include <rte_memcpy.h>
204418919fSjohnjiang #include <rte_launch.h>
214418919fSjohnjiang #include <rte_eal.h>
224418919fSjohnjiang #include <rte_per_lcore.h>
234418919fSjohnjiang #include <rte_lcore.h>
244418919fSjohnjiang #include <rte_atomic.h>
254418919fSjohnjiang #include <rte_branch_prediction.h>
264418919fSjohnjiang #include <rte_ring.h>
274418919fSjohnjiang #include <rte_mempool.h>
284418919fSjohnjiang #include <rte_mbuf.h>
294418919fSjohnjiang #include <rte_random.h>
304418919fSjohnjiang #include <rte_cycles.h>
314418919fSjohnjiang #include <rte_malloc.h>
324418919fSjohnjiang #include <rte_ether.h>
334418919fSjohnjiang #include <rte_ip.h>
344418919fSjohnjiang #include <rte_tcp.h>
354418919fSjohnjiang #include <rte_mbuf_dyn.h>
364418919fSjohnjiang 
374418919fSjohnjiang #include "test.h"
384418919fSjohnjiang 
394418919fSjohnjiang #define MEMPOOL_CACHE_SIZE      32
404418919fSjohnjiang #define MBUF_DATA_SIZE          2048
414418919fSjohnjiang #define NB_MBUF                 128
424418919fSjohnjiang #define MBUF_TEST_DATA_LEN      1464
434418919fSjohnjiang #define MBUF_TEST_DATA_LEN2     50
444418919fSjohnjiang #define MBUF_TEST_DATA_LEN3     256
454418919fSjohnjiang #define MBUF_TEST_HDR1_LEN      20
464418919fSjohnjiang #define MBUF_TEST_HDR2_LEN      30
474418919fSjohnjiang #define MBUF_TEST_ALL_HDRS_LEN  (MBUF_TEST_HDR1_LEN+MBUF_TEST_HDR2_LEN)
484418919fSjohnjiang #define MBUF_TEST_SEG_SIZE      64
494418919fSjohnjiang #define MBUF_TEST_BURST         8
504418919fSjohnjiang #define EXT_BUF_TEST_DATA_LEN   1024
514418919fSjohnjiang #define MBUF_MAX_SEG            16
524418919fSjohnjiang #define MBUF_NO_HEADER		0
534418919fSjohnjiang #define MBUF_HEADER		1
544418919fSjohnjiang #define MBUF_NEG_TEST_READ	2
554418919fSjohnjiang #define VAL_NAME(flag)          { flag, #flag }
564418919fSjohnjiang 
574418919fSjohnjiang /* chain length in bulk test */
584418919fSjohnjiang #define CHAIN_LEN 16
594418919fSjohnjiang 
604418919fSjohnjiang /* size of private data for mbuf in pktmbuf_pool2 */
614418919fSjohnjiang #define MBUF2_PRIV_SIZE         128
624418919fSjohnjiang 
634418919fSjohnjiang #define REFCNT_MAX_ITER         64
644418919fSjohnjiang #define REFCNT_MAX_TIMEOUT      10
654418919fSjohnjiang #define REFCNT_MAX_REF          (RTE_MAX_LCORE)
664418919fSjohnjiang #define REFCNT_MBUF_NUM         64
674418919fSjohnjiang #define REFCNT_RING_SIZE        (REFCNT_MBUF_NUM * REFCNT_MAX_REF)
684418919fSjohnjiang 
694418919fSjohnjiang #define MAGIC_DATA              0x42424242
704418919fSjohnjiang 
714418919fSjohnjiang #define MAKE_STRING(x)          # x
724418919fSjohnjiang 
734418919fSjohnjiang #ifdef RTE_MBUF_REFCNT_ATOMIC
744418919fSjohnjiang 
75*2d9fd380Sjfb8856606 static volatile uint32_t refcnt_stop_workers;
764418919fSjohnjiang static unsigned refcnt_lcore[RTE_MAX_LCORE];
774418919fSjohnjiang 
784418919fSjohnjiang #endif
794418919fSjohnjiang 
804418919fSjohnjiang /*
814418919fSjohnjiang  * MBUF
824418919fSjohnjiang  * ====
834418919fSjohnjiang  *
844418919fSjohnjiang  * #. Allocate a mbuf pool.
854418919fSjohnjiang  *
864418919fSjohnjiang  *    - The pool contains NB_MBUF elements, where each mbuf is MBUF_SIZE
874418919fSjohnjiang  *      bytes long.
884418919fSjohnjiang  *
894418919fSjohnjiang  * #. Test multiple allocations of mbufs from this pool.
904418919fSjohnjiang  *
914418919fSjohnjiang  *    - Allocate NB_MBUF and store pointers in a table.
924418919fSjohnjiang  *    - If an allocation fails, return an error.
934418919fSjohnjiang  *    - Free all these mbufs.
944418919fSjohnjiang  *    - Repeat the same test to check that mbufs were freed correctly.
954418919fSjohnjiang  *
964418919fSjohnjiang  * #. Test data manipulation in pktmbuf.
974418919fSjohnjiang  *
984418919fSjohnjiang  *    - Alloc an mbuf.
994418919fSjohnjiang  *    - Append data using rte_pktmbuf_append().
1004418919fSjohnjiang  *    - Test for error in rte_pktmbuf_append() when len is too large.
1014418919fSjohnjiang  *    - Trim data at the end of mbuf using rte_pktmbuf_trim().
1024418919fSjohnjiang  *    - Test for error in rte_pktmbuf_trim() when len is too large.
1034418919fSjohnjiang  *    - Prepend a header using rte_pktmbuf_prepend().
1044418919fSjohnjiang  *    - Test for error in rte_pktmbuf_prepend() when len is too large.
1054418919fSjohnjiang  *    - Remove data at the beginning of mbuf using rte_pktmbuf_adj().
1064418919fSjohnjiang  *    - Test for error in rte_pktmbuf_adj() when len is too large.
1074418919fSjohnjiang  *    - Check that appended data is not corrupt.
1084418919fSjohnjiang  *    - Free the mbuf.
1094418919fSjohnjiang  *    - Between all these tests, check data_len and pkt_len, and
1104418919fSjohnjiang  *      that the mbuf is contiguous.
1114418919fSjohnjiang  *    - Repeat the test to check that allocation operations
1124418919fSjohnjiang  *      reinitialize the mbuf correctly.
1134418919fSjohnjiang  *
1144418919fSjohnjiang  * #. Test packet cloning
1154418919fSjohnjiang  *    - Clone a mbuf and verify the data
1164418919fSjohnjiang  *    - Clone the cloned mbuf and verify the data
1174418919fSjohnjiang  *    - Attach a mbuf to another that does not have the same priv_size.
1184418919fSjohnjiang  */
1194418919fSjohnjiang 
1204418919fSjohnjiang #define GOTO_FAIL(str, ...) do {					\
1214418919fSjohnjiang 		printf("mbuf test FAILED (l.%d): <" str ">\n",		\
1224418919fSjohnjiang 		       __LINE__,  ##__VA_ARGS__);			\
1234418919fSjohnjiang 		goto fail;						\
1244418919fSjohnjiang } while(0)
1254418919fSjohnjiang 
1264418919fSjohnjiang /*
1274418919fSjohnjiang  * test data manipulation in mbuf with non-ascii data
1284418919fSjohnjiang  */
1294418919fSjohnjiang static int
test_pktmbuf_with_non_ascii_data(struct rte_mempool * pktmbuf_pool)1304418919fSjohnjiang test_pktmbuf_with_non_ascii_data(struct rte_mempool *pktmbuf_pool)
1314418919fSjohnjiang {
1324418919fSjohnjiang 	struct rte_mbuf *m = NULL;
1334418919fSjohnjiang 	char *data;
1344418919fSjohnjiang 
1354418919fSjohnjiang 	m = rte_pktmbuf_alloc(pktmbuf_pool);
1364418919fSjohnjiang 	if (m == NULL)
1374418919fSjohnjiang 		GOTO_FAIL("Cannot allocate mbuf");
1384418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(m) != 0)
1394418919fSjohnjiang 		GOTO_FAIL("Bad length");
1404418919fSjohnjiang 
1414418919fSjohnjiang 	data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN);
1424418919fSjohnjiang 	if (data == NULL)
1434418919fSjohnjiang 		GOTO_FAIL("Cannot append data");
1444418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
1454418919fSjohnjiang 		GOTO_FAIL("Bad pkt length");
1464418919fSjohnjiang 	if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
1474418919fSjohnjiang 		GOTO_FAIL("Bad data length");
1484418919fSjohnjiang 	memset(data, 0xff, rte_pktmbuf_pkt_len(m));
1494418919fSjohnjiang 	if (!rte_pktmbuf_is_contiguous(m))
1504418919fSjohnjiang 		GOTO_FAIL("Buffer should be continuous");
1514418919fSjohnjiang 	rte_pktmbuf_dump(stdout, m, MBUF_TEST_DATA_LEN);
1524418919fSjohnjiang 
1534418919fSjohnjiang 	rte_pktmbuf_free(m);
1544418919fSjohnjiang 
1554418919fSjohnjiang 	return 0;
1564418919fSjohnjiang 
1574418919fSjohnjiang fail:
1584418919fSjohnjiang 	if(m) {
1594418919fSjohnjiang 		rte_pktmbuf_free(m);
1604418919fSjohnjiang 	}
1614418919fSjohnjiang 	return -1;
1624418919fSjohnjiang }
1634418919fSjohnjiang 
1644418919fSjohnjiang /*
1654418919fSjohnjiang  * test data manipulation in mbuf
1664418919fSjohnjiang  */
1674418919fSjohnjiang static int
test_one_pktmbuf(struct rte_mempool * pktmbuf_pool)1684418919fSjohnjiang test_one_pktmbuf(struct rte_mempool *pktmbuf_pool)
1694418919fSjohnjiang {
1704418919fSjohnjiang 	struct rte_mbuf *m = NULL;
1714418919fSjohnjiang 	char *data, *data2, *hdr;
1724418919fSjohnjiang 	unsigned i;
1734418919fSjohnjiang 
1744418919fSjohnjiang 	printf("Test pktmbuf API\n");
1754418919fSjohnjiang 
1764418919fSjohnjiang 	/* alloc a mbuf */
1774418919fSjohnjiang 
1784418919fSjohnjiang 	m = rte_pktmbuf_alloc(pktmbuf_pool);
1794418919fSjohnjiang 	if (m == NULL)
1804418919fSjohnjiang 		GOTO_FAIL("Cannot allocate mbuf");
1814418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(m) != 0)
1824418919fSjohnjiang 		GOTO_FAIL("Bad length");
1834418919fSjohnjiang 
1844418919fSjohnjiang 	rte_pktmbuf_dump(stdout, m, 0);
1854418919fSjohnjiang 
1864418919fSjohnjiang 	/* append data */
1874418919fSjohnjiang 
1884418919fSjohnjiang 	data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN);
1894418919fSjohnjiang 	if (data == NULL)
1904418919fSjohnjiang 		GOTO_FAIL("Cannot append data");
1914418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
1924418919fSjohnjiang 		GOTO_FAIL("Bad pkt length");
1934418919fSjohnjiang 	if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
1944418919fSjohnjiang 		GOTO_FAIL("Bad data length");
1954418919fSjohnjiang 	memset(data, 0x66, rte_pktmbuf_pkt_len(m));
1964418919fSjohnjiang 	if (!rte_pktmbuf_is_contiguous(m))
1974418919fSjohnjiang 		GOTO_FAIL("Buffer should be continuous");
1984418919fSjohnjiang 	rte_pktmbuf_dump(stdout, m, MBUF_TEST_DATA_LEN);
1994418919fSjohnjiang 	rte_pktmbuf_dump(stdout, m, 2*MBUF_TEST_DATA_LEN);
2004418919fSjohnjiang 
2014418919fSjohnjiang 	/* this append should fail */
2024418919fSjohnjiang 
2034418919fSjohnjiang 	data2 = rte_pktmbuf_append(m, (uint16_t)(rte_pktmbuf_tailroom(m) + 1));
2044418919fSjohnjiang 	if (data2 != NULL)
2054418919fSjohnjiang 		GOTO_FAIL("Append should not succeed");
2064418919fSjohnjiang 
2074418919fSjohnjiang 	/* append some more data */
2084418919fSjohnjiang 
2094418919fSjohnjiang 	data2 = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN2);
2104418919fSjohnjiang 	if (data2 == NULL)
2114418919fSjohnjiang 		GOTO_FAIL("Cannot append data");
2124418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_DATA_LEN2)
2134418919fSjohnjiang 		GOTO_FAIL("Bad pkt length");
2144418919fSjohnjiang 	if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_DATA_LEN2)
2154418919fSjohnjiang 		GOTO_FAIL("Bad data length");
2164418919fSjohnjiang 	if (!rte_pktmbuf_is_contiguous(m))
2174418919fSjohnjiang 		GOTO_FAIL("Buffer should be continuous");
2184418919fSjohnjiang 
2194418919fSjohnjiang 	/* trim data at the end of mbuf */
2204418919fSjohnjiang 
2214418919fSjohnjiang 	if (rte_pktmbuf_trim(m, MBUF_TEST_DATA_LEN2) < 0)
2224418919fSjohnjiang 		GOTO_FAIL("Cannot trim data");
2234418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
2244418919fSjohnjiang 		GOTO_FAIL("Bad pkt length");
2254418919fSjohnjiang 	if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
2264418919fSjohnjiang 		GOTO_FAIL("Bad data length");
2274418919fSjohnjiang 	if (!rte_pktmbuf_is_contiguous(m))
2284418919fSjohnjiang 		GOTO_FAIL("Buffer should be continuous");
2294418919fSjohnjiang 
2304418919fSjohnjiang 	/* this trim should fail */
2314418919fSjohnjiang 
2324418919fSjohnjiang 	if (rte_pktmbuf_trim(m, (uint16_t)(rte_pktmbuf_data_len(m) + 1)) == 0)
2334418919fSjohnjiang 		GOTO_FAIL("trim should not succeed");
2344418919fSjohnjiang 
2354418919fSjohnjiang 	/* prepend one header */
2364418919fSjohnjiang 
2374418919fSjohnjiang 	hdr = rte_pktmbuf_prepend(m, MBUF_TEST_HDR1_LEN);
2384418919fSjohnjiang 	if (hdr == NULL)
2394418919fSjohnjiang 		GOTO_FAIL("Cannot prepend");
2404418919fSjohnjiang 	if (data - hdr != MBUF_TEST_HDR1_LEN)
2414418919fSjohnjiang 		GOTO_FAIL("Prepend failed");
2424418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_HDR1_LEN)
2434418919fSjohnjiang 		GOTO_FAIL("Bad pkt length");
2444418919fSjohnjiang 	if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_HDR1_LEN)
2454418919fSjohnjiang 		GOTO_FAIL("Bad data length");
2464418919fSjohnjiang 	if (!rte_pktmbuf_is_contiguous(m))
2474418919fSjohnjiang 		GOTO_FAIL("Buffer should be continuous");
2484418919fSjohnjiang 	memset(hdr, 0x55, MBUF_TEST_HDR1_LEN);
2494418919fSjohnjiang 
2504418919fSjohnjiang 	/* prepend another header */
2514418919fSjohnjiang 
2524418919fSjohnjiang 	hdr = rte_pktmbuf_prepend(m, MBUF_TEST_HDR2_LEN);
2534418919fSjohnjiang 	if (hdr == NULL)
2544418919fSjohnjiang 		GOTO_FAIL("Cannot prepend");
2554418919fSjohnjiang 	if (data - hdr != MBUF_TEST_ALL_HDRS_LEN)
2564418919fSjohnjiang 		GOTO_FAIL("Prepend failed");
2574418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_ALL_HDRS_LEN)
2584418919fSjohnjiang 		GOTO_FAIL("Bad pkt length");
2594418919fSjohnjiang 	if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_ALL_HDRS_LEN)
2604418919fSjohnjiang 		GOTO_FAIL("Bad data length");
2614418919fSjohnjiang 	if (!rte_pktmbuf_is_contiguous(m))
2624418919fSjohnjiang 		GOTO_FAIL("Buffer should be continuous");
2634418919fSjohnjiang 	memset(hdr, 0x55, MBUF_TEST_HDR2_LEN);
2644418919fSjohnjiang 
2654418919fSjohnjiang 	rte_mbuf_sanity_check(m, 1);
2664418919fSjohnjiang 	rte_mbuf_sanity_check(m, 0);
2674418919fSjohnjiang 	rte_pktmbuf_dump(stdout, m, 0);
2684418919fSjohnjiang 
2694418919fSjohnjiang 	/* this prepend should fail */
2704418919fSjohnjiang 
2714418919fSjohnjiang 	hdr = rte_pktmbuf_prepend(m, (uint16_t)(rte_pktmbuf_headroom(m) + 1));
2724418919fSjohnjiang 	if (hdr != NULL)
2734418919fSjohnjiang 		GOTO_FAIL("prepend should not succeed");
2744418919fSjohnjiang 
2754418919fSjohnjiang 	/* remove data at beginning of mbuf (adj) */
2764418919fSjohnjiang 
2774418919fSjohnjiang 	if (data != rte_pktmbuf_adj(m, MBUF_TEST_ALL_HDRS_LEN))
2784418919fSjohnjiang 		GOTO_FAIL("rte_pktmbuf_adj failed");
2794418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
2804418919fSjohnjiang 		GOTO_FAIL("Bad pkt length");
2814418919fSjohnjiang 	if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
2824418919fSjohnjiang 		GOTO_FAIL("Bad data length");
2834418919fSjohnjiang 	if (!rte_pktmbuf_is_contiguous(m))
2844418919fSjohnjiang 		GOTO_FAIL("Buffer should be continuous");
2854418919fSjohnjiang 
2864418919fSjohnjiang 	/* this adj should fail */
2874418919fSjohnjiang 
2884418919fSjohnjiang 	if (rte_pktmbuf_adj(m, (uint16_t)(rte_pktmbuf_data_len(m) + 1)) != NULL)
2894418919fSjohnjiang 		GOTO_FAIL("rte_pktmbuf_adj should not succeed");
2904418919fSjohnjiang 
2914418919fSjohnjiang 	/* check data */
2924418919fSjohnjiang 
2934418919fSjohnjiang 	if (!rte_pktmbuf_is_contiguous(m))
2944418919fSjohnjiang 		GOTO_FAIL("Buffer should be continuous");
2954418919fSjohnjiang 
2964418919fSjohnjiang 	for (i=0; i<MBUF_TEST_DATA_LEN; i++) {
2974418919fSjohnjiang 		if (data[i] != 0x66)
2984418919fSjohnjiang 			GOTO_FAIL("Data corrupted at offset %u", i);
2994418919fSjohnjiang 	}
3004418919fSjohnjiang 
3014418919fSjohnjiang 	/* free mbuf */
3024418919fSjohnjiang 
3034418919fSjohnjiang 	rte_pktmbuf_free(m);
3044418919fSjohnjiang 	m = NULL;
3054418919fSjohnjiang 	return 0;
3064418919fSjohnjiang 
3074418919fSjohnjiang fail:
3084418919fSjohnjiang 	if (m)
3094418919fSjohnjiang 		rte_pktmbuf_free(m);
3104418919fSjohnjiang 	return -1;
3114418919fSjohnjiang }
3124418919fSjohnjiang 
313*2d9fd380Sjfb8856606 static uint16_t
testclone_refcnt_read(struct rte_mbuf * m)314*2d9fd380Sjfb8856606 testclone_refcnt_read(struct rte_mbuf *m)
315*2d9fd380Sjfb8856606 {
316*2d9fd380Sjfb8856606 	return RTE_MBUF_HAS_PINNED_EXTBUF(m) ?
317*2d9fd380Sjfb8856606 	       rte_mbuf_ext_refcnt_read(m->shinfo) :
318*2d9fd380Sjfb8856606 	       rte_mbuf_refcnt_read(m);
319*2d9fd380Sjfb8856606 }
320*2d9fd380Sjfb8856606 
3214418919fSjohnjiang static int
testclone_testupdate_testdetach(struct rte_mempool * pktmbuf_pool,struct rte_mempool * clone_pool)322*2d9fd380Sjfb8856606 testclone_testupdate_testdetach(struct rte_mempool *pktmbuf_pool,
323*2d9fd380Sjfb8856606 				struct rte_mempool *clone_pool)
3244418919fSjohnjiang {
3254418919fSjohnjiang 	struct rte_mbuf *m = NULL;
3264418919fSjohnjiang 	struct rte_mbuf *clone = NULL;
3274418919fSjohnjiang 	struct rte_mbuf *clone2 = NULL;
3284418919fSjohnjiang 	unaligned_uint32_t *data;
3294418919fSjohnjiang 
3304418919fSjohnjiang 	/* alloc a mbuf */
3314418919fSjohnjiang 	m = rte_pktmbuf_alloc(pktmbuf_pool);
3324418919fSjohnjiang 	if (m == NULL)
3334418919fSjohnjiang 		GOTO_FAIL("ooops not allocating mbuf");
3344418919fSjohnjiang 
3354418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(m) != 0)
3364418919fSjohnjiang 		GOTO_FAIL("Bad length");
3374418919fSjohnjiang 
3384418919fSjohnjiang 	rte_pktmbuf_append(m, sizeof(uint32_t));
3394418919fSjohnjiang 	data = rte_pktmbuf_mtod(m, unaligned_uint32_t *);
3404418919fSjohnjiang 	*data = MAGIC_DATA;
3414418919fSjohnjiang 
3424418919fSjohnjiang 	/* clone the allocated mbuf */
343*2d9fd380Sjfb8856606 	clone = rte_pktmbuf_clone(m, clone_pool);
3444418919fSjohnjiang 	if (clone == NULL)
3454418919fSjohnjiang 		GOTO_FAIL("cannot clone data\n");
3464418919fSjohnjiang 
3474418919fSjohnjiang 	data = rte_pktmbuf_mtod(clone, unaligned_uint32_t *);
3484418919fSjohnjiang 	if (*data != MAGIC_DATA)
3494418919fSjohnjiang 		GOTO_FAIL("invalid data in clone\n");
3504418919fSjohnjiang 
351*2d9fd380Sjfb8856606 	if (testclone_refcnt_read(m) != 2)
3524418919fSjohnjiang 		GOTO_FAIL("invalid refcnt in m\n");
3534418919fSjohnjiang 
3544418919fSjohnjiang 	/* free the clone */
3554418919fSjohnjiang 	rte_pktmbuf_free(clone);
3564418919fSjohnjiang 	clone = NULL;
3574418919fSjohnjiang 
3584418919fSjohnjiang 	/* same test with a chained mbuf */
3594418919fSjohnjiang 	m->next = rte_pktmbuf_alloc(pktmbuf_pool);
3604418919fSjohnjiang 	if (m->next == NULL)
3614418919fSjohnjiang 		GOTO_FAIL("Next Pkt Null\n");
3624418919fSjohnjiang 	m->nb_segs = 2;
3634418919fSjohnjiang 
3644418919fSjohnjiang 	rte_pktmbuf_append(m->next, sizeof(uint32_t));
3654418919fSjohnjiang 	m->pkt_len = 2 * sizeof(uint32_t);
3664418919fSjohnjiang 
3674418919fSjohnjiang 	data = rte_pktmbuf_mtod(m->next, unaligned_uint32_t *);
3684418919fSjohnjiang 	*data = MAGIC_DATA;
3694418919fSjohnjiang 
370*2d9fd380Sjfb8856606 	clone = rte_pktmbuf_clone(m, clone_pool);
3714418919fSjohnjiang 	if (clone == NULL)
3724418919fSjohnjiang 		GOTO_FAIL("cannot clone data\n");
3734418919fSjohnjiang 
3744418919fSjohnjiang 	data = rte_pktmbuf_mtod(clone, unaligned_uint32_t *);
3754418919fSjohnjiang 	if (*data != MAGIC_DATA)
3764418919fSjohnjiang 		GOTO_FAIL("invalid data in clone\n");
3774418919fSjohnjiang 
3784418919fSjohnjiang 	data = rte_pktmbuf_mtod(clone->next, unaligned_uint32_t *);
3794418919fSjohnjiang 	if (*data != MAGIC_DATA)
3804418919fSjohnjiang 		GOTO_FAIL("invalid data in clone->next\n");
3814418919fSjohnjiang 
382*2d9fd380Sjfb8856606 	if (testclone_refcnt_read(m) != 2)
3834418919fSjohnjiang 		GOTO_FAIL("invalid refcnt in m\n");
3844418919fSjohnjiang 
385*2d9fd380Sjfb8856606 	if (testclone_refcnt_read(m->next) != 2)
3864418919fSjohnjiang 		GOTO_FAIL("invalid refcnt in m->next\n");
3874418919fSjohnjiang 
3884418919fSjohnjiang 	/* try to clone the clone */
3894418919fSjohnjiang 
390*2d9fd380Sjfb8856606 	clone2 = rte_pktmbuf_clone(clone, clone_pool);
3914418919fSjohnjiang 	if (clone2 == NULL)
3924418919fSjohnjiang 		GOTO_FAIL("cannot clone the clone\n");
3934418919fSjohnjiang 
3944418919fSjohnjiang 	data = rte_pktmbuf_mtod(clone2, unaligned_uint32_t *);
3954418919fSjohnjiang 	if (*data != MAGIC_DATA)
3964418919fSjohnjiang 		GOTO_FAIL("invalid data in clone2\n");
3974418919fSjohnjiang 
3984418919fSjohnjiang 	data = rte_pktmbuf_mtod(clone2->next, unaligned_uint32_t *);
3994418919fSjohnjiang 	if (*data != MAGIC_DATA)
4004418919fSjohnjiang 		GOTO_FAIL("invalid data in clone2->next\n");
4014418919fSjohnjiang 
402*2d9fd380Sjfb8856606 	if (testclone_refcnt_read(m) != 3)
4034418919fSjohnjiang 		GOTO_FAIL("invalid refcnt in m\n");
4044418919fSjohnjiang 
405*2d9fd380Sjfb8856606 	if (testclone_refcnt_read(m->next) != 3)
4064418919fSjohnjiang 		GOTO_FAIL("invalid refcnt in m->next\n");
4074418919fSjohnjiang 
4084418919fSjohnjiang 	/* free mbuf */
4094418919fSjohnjiang 	rte_pktmbuf_free(m);
4104418919fSjohnjiang 	rte_pktmbuf_free(clone);
4114418919fSjohnjiang 	rte_pktmbuf_free(clone2);
4124418919fSjohnjiang 
4134418919fSjohnjiang 	m = NULL;
4144418919fSjohnjiang 	clone = NULL;
4154418919fSjohnjiang 	clone2 = NULL;
4164418919fSjohnjiang 	printf("%s ok\n", __func__);
4174418919fSjohnjiang 	return 0;
4184418919fSjohnjiang 
4194418919fSjohnjiang fail:
4204418919fSjohnjiang 	if (m)
4214418919fSjohnjiang 		rte_pktmbuf_free(m);
4224418919fSjohnjiang 	if (clone)
4234418919fSjohnjiang 		rte_pktmbuf_free(clone);
4244418919fSjohnjiang 	if (clone2)
4254418919fSjohnjiang 		rte_pktmbuf_free(clone2);
4264418919fSjohnjiang 	return -1;
4274418919fSjohnjiang }
4284418919fSjohnjiang 
4294418919fSjohnjiang static int
test_pktmbuf_copy(struct rte_mempool * pktmbuf_pool,struct rte_mempool * clone_pool)430*2d9fd380Sjfb8856606 test_pktmbuf_copy(struct rte_mempool *pktmbuf_pool,
431*2d9fd380Sjfb8856606 		  struct rte_mempool *clone_pool)
4324418919fSjohnjiang {
4334418919fSjohnjiang 	struct rte_mbuf *m = NULL;
4344418919fSjohnjiang 	struct rte_mbuf *copy = NULL;
4354418919fSjohnjiang 	struct rte_mbuf *copy2 = NULL;
4364418919fSjohnjiang 	struct rte_mbuf *clone = NULL;
4374418919fSjohnjiang 	unaligned_uint32_t *data;
4384418919fSjohnjiang 
4394418919fSjohnjiang 	/* alloc a mbuf */
4404418919fSjohnjiang 	m = rte_pktmbuf_alloc(pktmbuf_pool);
4414418919fSjohnjiang 	if (m == NULL)
4424418919fSjohnjiang 		GOTO_FAIL("ooops not allocating mbuf");
4434418919fSjohnjiang 
4444418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(m) != 0)
4454418919fSjohnjiang 		GOTO_FAIL("Bad length");
4464418919fSjohnjiang 
4474418919fSjohnjiang 	rte_pktmbuf_append(m, sizeof(uint32_t));
4484418919fSjohnjiang 	data = rte_pktmbuf_mtod(m, unaligned_uint32_t *);
4494418919fSjohnjiang 	*data = MAGIC_DATA;
4504418919fSjohnjiang 
4514418919fSjohnjiang 	/* copy the allocated mbuf */
4524418919fSjohnjiang 	copy = rte_pktmbuf_copy(m, pktmbuf_pool, 0, UINT32_MAX);
4534418919fSjohnjiang 	if (copy == NULL)
4544418919fSjohnjiang 		GOTO_FAIL("cannot copy data\n");
4554418919fSjohnjiang 
4564418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(copy) != sizeof(uint32_t))
4574418919fSjohnjiang 		GOTO_FAIL("copy length incorrect\n");
4584418919fSjohnjiang 
4594418919fSjohnjiang 	if (rte_pktmbuf_data_len(copy) != sizeof(uint32_t))
4604418919fSjohnjiang 		GOTO_FAIL("copy data length incorrect\n");
4614418919fSjohnjiang 
4624418919fSjohnjiang 	data = rte_pktmbuf_mtod(copy, unaligned_uint32_t *);
4634418919fSjohnjiang 	if (*data != MAGIC_DATA)
4644418919fSjohnjiang 		GOTO_FAIL("invalid data in copy\n");
4654418919fSjohnjiang 
4664418919fSjohnjiang 	/* free the copy */
4674418919fSjohnjiang 	rte_pktmbuf_free(copy);
4684418919fSjohnjiang 	copy = NULL;
4694418919fSjohnjiang 
4704418919fSjohnjiang 	/* same test with a cloned mbuf */
471*2d9fd380Sjfb8856606 	clone = rte_pktmbuf_clone(m, clone_pool);
4724418919fSjohnjiang 	if (clone == NULL)
4734418919fSjohnjiang 		GOTO_FAIL("cannot clone data\n");
4744418919fSjohnjiang 
475*2d9fd380Sjfb8856606 	if ((!RTE_MBUF_HAS_PINNED_EXTBUF(m) &&
476*2d9fd380Sjfb8856606 	     !RTE_MBUF_CLONED(clone)) ||
477*2d9fd380Sjfb8856606 	    (RTE_MBUF_HAS_PINNED_EXTBUF(m) &&
478*2d9fd380Sjfb8856606 	     !RTE_MBUF_HAS_EXTBUF(clone)))
4794418919fSjohnjiang 		GOTO_FAIL("clone did not give a cloned mbuf\n");
4804418919fSjohnjiang 
4814418919fSjohnjiang 	copy = rte_pktmbuf_copy(clone, pktmbuf_pool, 0, UINT32_MAX);
4824418919fSjohnjiang 	if (copy == NULL)
4834418919fSjohnjiang 		GOTO_FAIL("cannot copy cloned mbuf\n");
4844418919fSjohnjiang 
4854418919fSjohnjiang 	if (RTE_MBUF_CLONED(copy))
4864418919fSjohnjiang 		GOTO_FAIL("copy of clone is cloned?\n");
4874418919fSjohnjiang 
4884418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(copy) != sizeof(uint32_t))
4894418919fSjohnjiang 		GOTO_FAIL("copy clone length incorrect\n");
4904418919fSjohnjiang 
4914418919fSjohnjiang 	if (rte_pktmbuf_data_len(copy) != sizeof(uint32_t))
4924418919fSjohnjiang 		GOTO_FAIL("copy clone data length incorrect\n");
4934418919fSjohnjiang 
4944418919fSjohnjiang 	data = rte_pktmbuf_mtod(copy, unaligned_uint32_t *);
4954418919fSjohnjiang 	if (*data != MAGIC_DATA)
4964418919fSjohnjiang 		GOTO_FAIL("invalid data in clone copy\n");
4974418919fSjohnjiang 	rte_pktmbuf_free(clone);
4984418919fSjohnjiang 	rte_pktmbuf_free(copy);
4994418919fSjohnjiang 	copy = NULL;
5004418919fSjohnjiang 	clone = NULL;
5014418919fSjohnjiang 
5024418919fSjohnjiang 
5034418919fSjohnjiang 	/* same test with a chained mbuf */
5044418919fSjohnjiang 	m->next = rte_pktmbuf_alloc(pktmbuf_pool);
5054418919fSjohnjiang 	if (m->next == NULL)
5064418919fSjohnjiang 		GOTO_FAIL("Next Pkt Null\n");
5074418919fSjohnjiang 	m->nb_segs = 2;
5084418919fSjohnjiang 
5094418919fSjohnjiang 	rte_pktmbuf_append(m->next, sizeof(uint32_t));
5104418919fSjohnjiang 	m->pkt_len = 2 * sizeof(uint32_t);
5114418919fSjohnjiang 	data = rte_pktmbuf_mtod(m->next, unaligned_uint32_t *);
5124418919fSjohnjiang 	*data = MAGIC_DATA + 1;
5134418919fSjohnjiang 
5144418919fSjohnjiang 	copy = rte_pktmbuf_copy(m, pktmbuf_pool, 0, UINT32_MAX);
5154418919fSjohnjiang 	if (copy == NULL)
5164418919fSjohnjiang 		GOTO_FAIL("cannot copy data\n");
5174418919fSjohnjiang 
5184418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(copy) != 2 * sizeof(uint32_t))
5194418919fSjohnjiang 		GOTO_FAIL("chain copy length incorrect\n");
5204418919fSjohnjiang 
5214418919fSjohnjiang 	if (rte_pktmbuf_data_len(copy) != 2 * sizeof(uint32_t))
5224418919fSjohnjiang 		GOTO_FAIL("chain copy data length incorrect\n");
5234418919fSjohnjiang 
5244418919fSjohnjiang 	data = rte_pktmbuf_mtod(copy, unaligned_uint32_t *);
5254418919fSjohnjiang 	if (data[0] != MAGIC_DATA || data[1] != MAGIC_DATA + 1)
5264418919fSjohnjiang 		GOTO_FAIL("invalid data in copy\n");
5274418919fSjohnjiang 
5284418919fSjohnjiang 	rte_pktmbuf_free(copy2);
5294418919fSjohnjiang 
5304418919fSjohnjiang 	/* test offset copy */
5314418919fSjohnjiang 	copy2 = rte_pktmbuf_copy(copy, pktmbuf_pool,
5324418919fSjohnjiang 				 sizeof(uint32_t), UINT32_MAX);
5334418919fSjohnjiang 	if (copy2 == NULL)
5344418919fSjohnjiang 		GOTO_FAIL("cannot copy the copy\n");
5354418919fSjohnjiang 
5364418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(copy2) != sizeof(uint32_t))
5374418919fSjohnjiang 		GOTO_FAIL("copy with offset, length incorrect\n");
5384418919fSjohnjiang 
5394418919fSjohnjiang 	if (rte_pktmbuf_data_len(copy2) != sizeof(uint32_t))
5404418919fSjohnjiang 		GOTO_FAIL("copy with offset, data length incorrect\n");
5414418919fSjohnjiang 
5424418919fSjohnjiang 	data = rte_pktmbuf_mtod(copy2, unaligned_uint32_t *);
5434418919fSjohnjiang 	if (data[0] != MAGIC_DATA + 1)
5444418919fSjohnjiang 		GOTO_FAIL("copy with offset, invalid data\n");
5454418919fSjohnjiang 
5464418919fSjohnjiang 	rte_pktmbuf_free(copy2);
5474418919fSjohnjiang 
5484418919fSjohnjiang 	/* test truncation copy */
5494418919fSjohnjiang 	copy2 = rte_pktmbuf_copy(copy, pktmbuf_pool,
5504418919fSjohnjiang 				 0, sizeof(uint32_t));
5514418919fSjohnjiang 	if (copy2 == NULL)
5524418919fSjohnjiang 		GOTO_FAIL("cannot copy the copy\n");
5534418919fSjohnjiang 
5544418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(copy2) != sizeof(uint32_t))
5554418919fSjohnjiang 		GOTO_FAIL("copy with truncate, length incorrect\n");
5564418919fSjohnjiang 
5574418919fSjohnjiang 	if (rte_pktmbuf_data_len(copy2) != sizeof(uint32_t))
5584418919fSjohnjiang 		GOTO_FAIL("copy with truncate, data length incorrect\n");
5594418919fSjohnjiang 
5604418919fSjohnjiang 	data = rte_pktmbuf_mtod(copy2, unaligned_uint32_t *);
5614418919fSjohnjiang 	if (data[0] != MAGIC_DATA)
5624418919fSjohnjiang 		GOTO_FAIL("copy with truncate, invalid data\n");
5634418919fSjohnjiang 
5644418919fSjohnjiang 	/* free mbuf */
5654418919fSjohnjiang 	rte_pktmbuf_free(m);
5664418919fSjohnjiang 	rte_pktmbuf_free(copy);
5674418919fSjohnjiang 	rte_pktmbuf_free(copy2);
5684418919fSjohnjiang 
5694418919fSjohnjiang 	m = NULL;
5704418919fSjohnjiang 	copy = NULL;
5714418919fSjohnjiang 	copy2 = NULL;
5724418919fSjohnjiang 	printf("%s ok\n", __func__);
5734418919fSjohnjiang 	return 0;
5744418919fSjohnjiang 
5754418919fSjohnjiang fail:
5764418919fSjohnjiang 	if (m)
5774418919fSjohnjiang 		rte_pktmbuf_free(m);
5784418919fSjohnjiang 	if (copy)
5794418919fSjohnjiang 		rte_pktmbuf_free(copy);
5804418919fSjohnjiang 	if (copy2)
5814418919fSjohnjiang 		rte_pktmbuf_free(copy2);
5824418919fSjohnjiang 	return -1;
5834418919fSjohnjiang }
5844418919fSjohnjiang 
5854418919fSjohnjiang static int
test_attach_from_different_pool(struct rte_mempool * pktmbuf_pool,struct rte_mempool * pktmbuf_pool2)5864418919fSjohnjiang test_attach_from_different_pool(struct rte_mempool *pktmbuf_pool,
5874418919fSjohnjiang 				struct rte_mempool *pktmbuf_pool2)
5884418919fSjohnjiang {
5894418919fSjohnjiang 	struct rte_mbuf *m = NULL;
5904418919fSjohnjiang 	struct rte_mbuf *clone = NULL;
5914418919fSjohnjiang 	struct rte_mbuf *clone2 = NULL;
5924418919fSjohnjiang 	char *data, *c_data, *c_data2;
5934418919fSjohnjiang 
5944418919fSjohnjiang 	/* alloc a mbuf */
5954418919fSjohnjiang 	m = rte_pktmbuf_alloc(pktmbuf_pool);
5964418919fSjohnjiang 	if (m == NULL)
5974418919fSjohnjiang 		GOTO_FAIL("cannot allocate mbuf");
5984418919fSjohnjiang 
5994418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(m) != 0)
6004418919fSjohnjiang 		GOTO_FAIL("Bad length");
6014418919fSjohnjiang 
6024418919fSjohnjiang 	data = rte_pktmbuf_mtod(m, char *);
6034418919fSjohnjiang 
6044418919fSjohnjiang 	/* allocate a new mbuf from the second pool, and attach it to the first
6054418919fSjohnjiang 	 * mbuf */
6064418919fSjohnjiang 	clone = rte_pktmbuf_alloc(pktmbuf_pool2);
6074418919fSjohnjiang 	if (clone == NULL)
6084418919fSjohnjiang 		GOTO_FAIL("cannot allocate mbuf from second pool\n");
6094418919fSjohnjiang 
6104418919fSjohnjiang 	/* check data room size and priv size, and erase priv */
6114418919fSjohnjiang 	if (rte_pktmbuf_data_room_size(clone->pool) != 0)
6124418919fSjohnjiang 		GOTO_FAIL("data room size should be 0\n");
6134418919fSjohnjiang 	if (rte_pktmbuf_priv_size(clone->pool) != MBUF2_PRIV_SIZE)
6144418919fSjohnjiang 		GOTO_FAIL("data room size should be %d\n", MBUF2_PRIV_SIZE);
6154418919fSjohnjiang 	memset(clone + 1, 0, MBUF2_PRIV_SIZE);
6164418919fSjohnjiang 
6174418919fSjohnjiang 	/* save data pointer to compare it after detach() */
6184418919fSjohnjiang 	c_data = rte_pktmbuf_mtod(clone, char *);
6194418919fSjohnjiang 	if (c_data != (char *)clone + sizeof(*clone) + MBUF2_PRIV_SIZE)
6204418919fSjohnjiang 		GOTO_FAIL("bad data pointer in clone");
6214418919fSjohnjiang 	if (rte_pktmbuf_headroom(clone) != 0)
6224418919fSjohnjiang 		GOTO_FAIL("bad headroom in clone");
6234418919fSjohnjiang 
6244418919fSjohnjiang 	rte_pktmbuf_attach(clone, m);
6254418919fSjohnjiang 
6264418919fSjohnjiang 	if (rte_pktmbuf_mtod(clone, char *) != data)
6274418919fSjohnjiang 		GOTO_FAIL("clone was not attached properly\n");
6284418919fSjohnjiang 	if (rte_pktmbuf_headroom(clone) != RTE_PKTMBUF_HEADROOM)
6294418919fSjohnjiang 		GOTO_FAIL("bad headroom in clone after attach");
6304418919fSjohnjiang 	if (rte_mbuf_refcnt_read(m) != 2)
6314418919fSjohnjiang 		GOTO_FAIL("invalid refcnt in m\n");
6324418919fSjohnjiang 
6334418919fSjohnjiang 	/* allocate a new mbuf from the second pool, and attach it to the first
6344418919fSjohnjiang 	 * cloned mbuf */
6354418919fSjohnjiang 	clone2 = rte_pktmbuf_alloc(pktmbuf_pool2);
6364418919fSjohnjiang 	if (clone2 == NULL)
6374418919fSjohnjiang 		GOTO_FAIL("cannot allocate clone2 from second pool\n");
6384418919fSjohnjiang 
6394418919fSjohnjiang 	/* check data room size and priv size, and erase priv */
6404418919fSjohnjiang 	if (rte_pktmbuf_data_room_size(clone2->pool) != 0)
6414418919fSjohnjiang 		GOTO_FAIL("data room size should be 0\n");
6424418919fSjohnjiang 	if (rte_pktmbuf_priv_size(clone2->pool) != MBUF2_PRIV_SIZE)
6434418919fSjohnjiang 		GOTO_FAIL("data room size should be %d\n", MBUF2_PRIV_SIZE);
6444418919fSjohnjiang 	memset(clone2 + 1, 0, MBUF2_PRIV_SIZE);
6454418919fSjohnjiang 
6464418919fSjohnjiang 	/* save data pointer to compare it after detach() */
6474418919fSjohnjiang 	c_data2 = rte_pktmbuf_mtod(clone2, char *);
6484418919fSjohnjiang 	if (c_data2 != (char *)clone2 + sizeof(*clone2) + MBUF2_PRIV_SIZE)
6494418919fSjohnjiang 		GOTO_FAIL("bad data pointer in clone2");
6504418919fSjohnjiang 	if (rte_pktmbuf_headroom(clone2) != 0)
6514418919fSjohnjiang 		GOTO_FAIL("bad headroom in clone2");
6524418919fSjohnjiang 
6534418919fSjohnjiang 	rte_pktmbuf_attach(clone2, clone);
6544418919fSjohnjiang 
6554418919fSjohnjiang 	if (rte_pktmbuf_mtod(clone2, char *) != data)
6564418919fSjohnjiang 		GOTO_FAIL("clone2 was not attached properly\n");
6574418919fSjohnjiang 	if (rte_pktmbuf_headroom(clone2) != RTE_PKTMBUF_HEADROOM)
6584418919fSjohnjiang 		GOTO_FAIL("bad headroom in clone2 after attach");
6594418919fSjohnjiang 	if (rte_mbuf_refcnt_read(m) != 3)
6604418919fSjohnjiang 		GOTO_FAIL("invalid refcnt in m\n");
6614418919fSjohnjiang 
6624418919fSjohnjiang 	/* detach the clones */
6634418919fSjohnjiang 	rte_pktmbuf_detach(clone);
6644418919fSjohnjiang 	if (c_data != rte_pktmbuf_mtod(clone, char *))
6654418919fSjohnjiang 		GOTO_FAIL("clone was not detached properly\n");
6664418919fSjohnjiang 	if (rte_mbuf_refcnt_read(m) != 2)
6674418919fSjohnjiang 		GOTO_FAIL("invalid refcnt in m\n");
6684418919fSjohnjiang 
6694418919fSjohnjiang 	rte_pktmbuf_detach(clone2);
6704418919fSjohnjiang 	if (c_data2 != rte_pktmbuf_mtod(clone2, char *))
6714418919fSjohnjiang 		GOTO_FAIL("clone2 was not detached properly\n");
6724418919fSjohnjiang 	if (rte_mbuf_refcnt_read(m) != 1)
6734418919fSjohnjiang 		GOTO_FAIL("invalid refcnt in m\n");
6744418919fSjohnjiang 
6754418919fSjohnjiang 	/* free the clones and the initial mbuf */
6764418919fSjohnjiang 	rte_pktmbuf_free(clone2);
6774418919fSjohnjiang 	rte_pktmbuf_free(clone);
6784418919fSjohnjiang 	rte_pktmbuf_free(m);
6794418919fSjohnjiang 	printf("%s ok\n", __func__);
6804418919fSjohnjiang 	return 0;
6814418919fSjohnjiang 
6824418919fSjohnjiang fail:
6834418919fSjohnjiang 	if (m)
6844418919fSjohnjiang 		rte_pktmbuf_free(m);
6854418919fSjohnjiang 	if (clone)
6864418919fSjohnjiang 		rte_pktmbuf_free(clone);
6874418919fSjohnjiang 	if (clone2)
6884418919fSjohnjiang 		rte_pktmbuf_free(clone2);
6894418919fSjohnjiang 	return -1;
6904418919fSjohnjiang }
6914418919fSjohnjiang 
6924418919fSjohnjiang /*
6934418919fSjohnjiang  * test allocation and free of mbufs
6944418919fSjohnjiang  */
6954418919fSjohnjiang static int
test_pktmbuf_pool(struct rte_mempool * pktmbuf_pool)6964418919fSjohnjiang test_pktmbuf_pool(struct rte_mempool *pktmbuf_pool)
6974418919fSjohnjiang {
6984418919fSjohnjiang 	unsigned i;
6994418919fSjohnjiang 	struct rte_mbuf *m[NB_MBUF];
7004418919fSjohnjiang 	int ret = 0;
7014418919fSjohnjiang 
7024418919fSjohnjiang 	for (i=0; i<NB_MBUF; i++)
7034418919fSjohnjiang 		m[i] = NULL;
7044418919fSjohnjiang 
7054418919fSjohnjiang 	/* alloc NB_MBUF mbufs */
7064418919fSjohnjiang 	for (i=0; i<NB_MBUF; i++) {
7074418919fSjohnjiang 		m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
7084418919fSjohnjiang 		if (m[i] == NULL) {
7094418919fSjohnjiang 			printf("rte_pktmbuf_alloc() failed (%u)\n", i);
7104418919fSjohnjiang 			ret = -1;
7114418919fSjohnjiang 		}
7124418919fSjohnjiang 	}
7134418919fSjohnjiang 	struct rte_mbuf *extra = NULL;
7144418919fSjohnjiang 	extra = rte_pktmbuf_alloc(pktmbuf_pool);
7154418919fSjohnjiang 	if(extra != NULL) {
7164418919fSjohnjiang 		printf("Error pool not empty");
7174418919fSjohnjiang 		ret = -1;
7184418919fSjohnjiang 	}
7194418919fSjohnjiang 	extra = rte_pktmbuf_clone(m[0], pktmbuf_pool);
7204418919fSjohnjiang 	if(extra != NULL) {
7214418919fSjohnjiang 		printf("Error pool not empty");
7224418919fSjohnjiang 		ret = -1;
7234418919fSjohnjiang 	}
7244418919fSjohnjiang 	/* free them */
7254418919fSjohnjiang 	for (i=0; i<NB_MBUF; i++) {
7264418919fSjohnjiang 		if (m[i] != NULL)
7274418919fSjohnjiang 			rte_pktmbuf_free(m[i]);
7284418919fSjohnjiang 	}
7294418919fSjohnjiang 
7304418919fSjohnjiang 	return ret;
7314418919fSjohnjiang }
7324418919fSjohnjiang 
7334418919fSjohnjiang /*
7344418919fSjohnjiang  * test bulk allocation and bulk free of mbufs
7354418919fSjohnjiang  */
7364418919fSjohnjiang static int
test_pktmbuf_pool_bulk(void)7374418919fSjohnjiang test_pktmbuf_pool_bulk(void)
7384418919fSjohnjiang {
7394418919fSjohnjiang 	struct rte_mempool *pool = NULL;
7404418919fSjohnjiang 	struct rte_mempool *pool2 = NULL;
7414418919fSjohnjiang 	unsigned int i;
7424418919fSjohnjiang 	struct rte_mbuf *m;
7434418919fSjohnjiang 	struct rte_mbuf *mbufs[NB_MBUF];
7444418919fSjohnjiang 	int ret = 0;
7454418919fSjohnjiang 
7464418919fSjohnjiang 	/* We cannot use the preallocated mbuf pools because their caches
7474418919fSjohnjiang 	 * prevent us from bulk allocating all objects in them.
7484418919fSjohnjiang 	 * So we create our own mbuf pools without caches.
7494418919fSjohnjiang 	 */
7504418919fSjohnjiang 	printf("Create mbuf pools for bulk allocation.\n");
7514418919fSjohnjiang 	pool = rte_pktmbuf_pool_create("test_pktmbuf_bulk",
7524418919fSjohnjiang 			NB_MBUF, 0, 0, MBUF_DATA_SIZE, SOCKET_ID_ANY);
7534418919fSjohnjiang 	if (pool == NULL) {
7544418919fSjohnjiang 		printf("rte_pktmbuf_pool_create() failed. rte_errno %d\n",
7554418919fSjohnjiang 		       rte_errno);
7564418919fSjohnjiang 		goto err;
7574418919fSjohnjiang 	}
7584418919fSjohnjiang 	pool2 = rte_pktmbuf_pool_create("test_pktmbuf_bulk2",
7594418919fSjohnjiang 			NB_MBUF, 0, 0, MBUF_DATA_SIZE, SOCKET_ID_ANY);
7604418919fSjohnjiang 	if (pool2 == NULL) {
7614418919fSjohnjiang 		printf("rte_pktmbuf_pool_create() failed. rte_errno %d\n",
7624418919fSjohnjiang 		       rte_errno);
7634418919fSjohnjiang 		goto err;
7644418919fSjohnjiang 	}
7654418919fSjohnjiang 
7664418919fSjohnjiang 	/* Preconditions: Mempools must be full. */
7674418919fSjohnjiang 	if (!(rte_mempool_full(pool) && rte_mempool_full(pool2))) {
7684418919fSjohnjiang 		printf("Test precondition failed: mempools not full\n");
7694418919fSjohnjiang 		goto err;
7704418919fSjohnjiang 	}
7714418919fSjohnjiang 	if (!(rte_mempool_avail_count(pool) == NB_MBUF &&
7724418919fSjohnjiang 			rte_mempool_avail_count(pool2) == NB_MBUF)) {
7734418919fSjohnjiang 		printf("Test precondition failed: mempools: %u+%u != %u+%u",
7744418919fSjohnjiang 		       rte_mempool_avail_count(pool),
7754418919fSjohnjiang 		       rte_mempool_avail_count(pool2),
7764418919fSjohnjiang 		       NB_MBUF, NB_MBUF);
7774418919fSjohnjiang 		goto err;
7784418919fSjohnjiang 	}
7794418919fSjohnjiang 
7804418919fSjohnjiang 	printf("Test single bulk alloc, followed by multiple bulk free.\n");
7814418919fSjohnjiang 
7824418919fSjohnjiang 	/* Bulk allocate all mbufs in the pool, in one go. */
7834418919fSjohnjiang 	ret = rte_pktmbuf_alloc_bulk(pool, mbufs, NB_MBUF);
7844418919fSjohnjiang 	if (ret != 0) {
7854418919fSjohnjiang 		printf("rte_pktmbuf_alloc_bulk() failed: %d\n", ret);
7864418919fSjohnjiang 		goto err;
7874418919fSjohnjiang 	}
7884418919fSjohnjiang 	/* Test that they have been removed from the pool. */
7894418919fSjohnjiang 	if (!rte_mempool_empty(pool)) {
7904418919fSjohnjiang 		printf("mempool not empty\n");
7914418919fSjohnjiang 		goto err;
7924418919fSjohnjiang 	}
7934418919fSjohnjiang 	/* Bulk free all mbufs, in four steps. */
7944418919fSjohnjiang 	RTE_BUILD_BUG_ON(NB_MBUF % 4 != 0);
7954418919fSjohnjiang 	for (i = 0; i < NB_MBUF; i += NB_MBUF / 4) {
7964418919fSjohnjiang 		rte_pktmbuf_free_bulk(&mbufs[i], NB_MBUF / 4);
7974418919fSjohnjiang 		/* Test that they have been returned to the pool. */
7984418919fSjohnjiang 		if (rte_mempool_avail_count(pool) != i + NB_MBUF / 4) {
7994418919fSjohnjiang 			printf("mempool avail count incorrect\n");
8004418919fSjohnjiang 			goto err;
8014418919fSjohnjiang 		}
8024418919fSjohnjiang 	}
8034418919fSjohnjiang 
8044418919fSjohnjiang 	printf("Test multiple bulk alloc, followed by single bulk free.\n");
8054418919fSjohnjiang 
8064418919fSjohnjiang 	/* Bulk allocate all mbufs in the pool, in four steps. */
8074418919fSjohnjiang 	for (i = 0; i < NB_MBUF; i += NB_MBUF / 4) {
8084418919fSjohnjiang 		ret = rte_pktmbuf_alloc_bulk(pool, &mbufs[i], NB_MBUF / 4);
8094418919fSjohnjiang 		if (ret != 0) {
8104418919fSjohnjiang 			printf("rte_pktmbuf_alloc_bulk() failed: %d\n", ret);
8114418919fSjohnjiang 			goto err;
8124418919fSjohnjiang 		}
8134418919fSjohnjiang 	}
8144418919fSjohnjiang 	/* Test that they have been removed from the pool. */
8154418919fSjohnjiang 	if (!rte_mempool_empty(pool)) {
8164418919fSjohnjiang 		printf("mempool not empty\n");
8174418919fSjohnjiang 		goto err;
8184418919fSjohnjiang 	}
8194418919fSjohnjiang 	/* Bulk free all mbufs, in one go. */
8204418919fSjohnjiang 	rte_pktmbuf_free_bulk(mbufs, NB_MBUF);
8214418919fSjohnjiang 	/* Test that they have been returned to the pool. */
8224418919fSjohnjiang 	if (!rte_mempool_full(pool)) {
8234418919fSjohnjiang 		printf("mempool not full\n");
8244418919fSjohnjiang 		goto err;
8254418919fSjohnjiang 	}
8264418919fSjohnjiang 
8274418919fSjohnjiang 	printf("Test bulk free of single long chain.\n");
8284418919fSjohnjiang 
8294418919fSjohnjiang 	/* Bulk allocate all mbufs in the pool, in one go. */
8304418919fSjohnjiang 	ret = rte_pktmbuf_alloc_bulk(pool, mbufs, NB_MBUF);
8314418919fSjohnjiang 	if (ret != 0) {
8324418919fSjohnjiang 		printf("rte_pktmbuf_alloc_bulk() failed: %d\n", ret);
8334418919fSjohnjiang 		goto err;
8344418919fSjohnjiang 	}
8354418919fSjohnjiang 	/* Create a long mbuf chain. */
8364418919fSjohnjiang 	for (i = 1; i < NB_MBUF; i++) {
8374418919fSjohnjiang 		ret = rte_pktmbuf_chain(mbufs[0], mbufs[i]);
8384418919fSjohnjiang 		if (ret != 0) {
8394418919fSjohnjiang 			printf("rte_pktmbuf_chain() failed: %d\n", ret);
8404418919fSjohnjiang 			goto err;
8414418919fSjohnjiang 		}
8424418919fSjohnjiang 		mbufs[i] = NULL;
8434418919fSjohnjiang 	}
8444418919fSjohnjiang 	/* Free the mbuf chain containing all the mbufs. */
8454418919fSjohnjiang 	rte_pktmbuf_free_bulk(mbufs, 1);
8464418919fSjohnjiang 	/* Test that they have been returned to the pool. */
8474418919fSjohnjiang 	if (!rte_mempool_full(pool)) {
8484418919fSjohnjiang 		printf("mempool not full\n");
8494418919fSjohnjiang 		goto err;
8504418919fSjohnjiang 	}
8514418919fSjohnjiang 
8524418919fSjohnjiang 	printf("Test bulk free of multiple chains using multiple pools.\n");
8534418919fSjohnjiang 
8544418919fSjohnjiang 	/* Create mbuf chains containing mbufs from different pools. */
8554418919fSjohnjiang 	RTE_BUILD_BUG_ON(CHAIN_LEN % 2 != 0);
8564418919fSjohnjiang 	RTE_BUILD_BUG_ON(NB_MBUF % (CHAIN_LEN / 2) != 0);
8574418919fSjohnjiang 	for (i = 0; i < NB_MBUF * 2; i++) {
8584418919fSjohnjiang 		m = rte_pktmbuf_alloc((i & 4) ? pool2 : pool);
8594418919fSjohnjiang 		if (m == NULL) {
8604418919fSjohnjiang 			printf("rte_pktmbuf_alloc() failed (%u)\n", i);
8614418919fSjohnjiang 			goto err;
8624418919fSjohnjiang 		}
8634418919fSjohnjiang 		if ((i % CHAIN_LEN) == 0)
8644418919fSjohnjiang 			mbufs[i / CHAIN_LEN] = m;
8654418919fSjohnjiang 		else
8664418919fSjohnjiang 			rte_pktmbuf_chain(mbufs[i / CHAIN_LEN], m);
8674418919fSjohnjiang 	}
8684418919fSjohnjiang 	/* Test that both pools have been emptied. */
8694418919fSjohnjiang 	if (!(rte_mempool_empty(pool) && rte_mempool_empty(pool2))) {
8704418919fSjohnjiang 		printf("mempools not empty\n");
8714418919fSjohnjiang 		goto err;
8724418919fSjohnjiang 	}
8734418919fSjohnjiang 	/* Free one mbuf chain. */
8744418919fSjohnjiang 	rte_pktmbuf_free_bulk(mbufs, 1);
8754418919fSjohnjiang 	/* Test that the segments have been returned to the pools. */
8764418919fSjohnjiang 	if (!(rte_mempool_avail_count(pool) == CHAIN_LEN / 2 &&
8774418919fSjohnjiang 			rte_mempool_avail_count(pool2) == CHAIN_LEN / 2)) {
8784418919fSjohnjiang 		printf("all segments of first mbuf have not been returned\n");
8794418919fSjohnjiang 		goto err;
8804418919fSjohnjiang 	}
8814418919fSjohnjiang 	/* Free the remaining mbuf chains. */
8824418919fSjohnjiang 	rte_pktmbuf_free_bulk(&mbufs[1], NB_MBUF * 2 / CHAIN_LEN - 1);
8834418919fSjohnjiang 	/* Test that they have been returned to the pools. */
8844418919fSjohnjiang 	if (!(rte_mempool_full(pool) && rte_mempool_full(pool2))) {
8854418919fSjohnjiang 		printf("mempools not full\n");
8864418919fSjohnjiang 		goto err;
8874418919fSjohnjiang 	}
8884418919fSjohnjiang 
8894418919fSjohnjiang 	ret = 0;
8904418919fSjohnjiang 	goto done;
8914418919fSjohnjiang 
8924418919fSjohnjiang err:
8934418919fSjohnjiang 	ret = -1;
8944418919fSjohnjiang 
8954418919fSjohnjiang done:
8964418919fSjohnjiang 	printf("Free mbuf pools for bulk allocation.\n");
8974418919fSjohnjiang 	rte_mempool_free(pool);
8984418919fSjohnjiang 	rte_mempool_free(pool2);
8994418919fSjohnjiang 	return ret;
9004418919fSjohnjiang }
9014418919fSjohnjiang 
9024418919fSjohnjiang /*
9034418919fSjohnjiang  * test that the pointer to the data on a packet mbuf is set properly
9044418919fSjohnjiang  */
9054418919fSjohnjiang static int
test_pktmbuf_pool_ptr(struct rte_mempool * pktmbuf_pool)9064418919fSjohnjiang test_pktmbuf_pool_ptr(struct rte_mempool *pktmbuf_pool)
9074418919fSjohnjiang {
9084418919fSjohnjiang 	unsigned i;
9094418919fSjohnjiang 	struct rte_mbuf *m[NB_MBUF];
9104418919fSjohnjiang 	int ret = 0;
9114418919fSjohnjiang 
9124418919fSjohnjiang 	for (i=0; i<NB_MBUF; i++)
9134418919fSjohnjiang 		m[i] = NULL;
9144418919fSjohnjiang 
9154418919fSjohnjiang 	/* alloc NB_MBUF mbufs */
9164418919fSjohnjiang 	for (i=0; i<NB_MBUF; i++) {
9174418919fSjohnjiang 		m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
9184418919fSjohnjiang 		if (m[i] == NULL) {
9194418919fSjohnjiang 			printf("rte_pktmbuf_alloc() failed (%u)\n", i);
9204418919fSjohnjiang 			ret = -1;
9214418919fSjohnjiang 			break;
9224418919fSjohnjiang 		}
9234418919fSjohnjiang 		m[i]->data_off += 64;
9244418919fSjohnjiang 	}
9254418919fSjohnjiang 
9264418919fSjohnjiang 	/* free them */
9274418919fSjohnjiang 	for (i=0; i<NB_MBUF; i++) {
9284418919fSjohnjiang 		if (m[i] != NULL)
9294418919fSjohnjiang 			rte_pktmbuf_free(m[i]);
9304418919fSjohnjiang 	}
9314418919fSjohnjiang 
9324418919fSjohnjiang 	for (i=0; i<NB_MBUF; i++)
9334418919fSjohnjiang 		m[i] = NULL;
9344418919fSjohnjiang 
9354418919fSjohnjiang 	/* alloc NB_MBUF mbufs */
9364418919fSjohnjiang 	for (i=0; i<NB_MBUF; i++) {
9374418919fSjohnjiang 		m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
9384418919fSjohnjiang 		if (m[i] == NULL) {
9394418919fSjohnjiang 			printf("rte_pktmbuf_alloc() failed (%u)\n", i);
9404418919fSjohnjiang 			ret = -1;
9414418919fSjohnjiang 			break;
9424418919fSjohnjiang 		}
9434418919fSjohnjiang 		if (m[i]->data_off != RTE_PKTMBUF_HEADROOM) {
9444418919fSjohnjiang 			printf("invalid data_off\n");
9454418919fSjohnjiang 			ret = -1;
9464418919fSjohnjiang 		}
9474418919fSjohnjiang 	}
9484418919fSjohnjiang 
9494418919fSjohnjiang 	/* free them */
9504418919fSjohnjiang 	for (i=0; i<NB_MBUF; i++) {
9514418919fSjohnjiang 		if (m[i] != NULL)
9524418919fSjohnjiang 			rte_pktmbuf_free(m[i]);
9534418919fSjohnjiang 	}
9544418919fSjohnjiang 
9554418919fSjohnjiang 	return ret;
9564418919fSjohnjiang }
9574418919fSjohnjiang 
9584418919fSjohnjiang static int
test_pktmbuf_free_segment(struct rte_mempool * pktmbuf_pool)9594418919fSjohnjiang test_pktmbuf_free_segment(struct rte_mempool *pktmbuf_pool)
9604418919fSjohnjiang {
9614418919fSjohnjiang 	unsigned i;
9624418919fSjohnjiang 	struct rte_mbuf *m[NB_MBUF];
9634418919fSjohnjiang 	int ret = 0;
9644418919fSjohnjiang 
9654418919fSjohnjiang 	for (i=0; i<NB_MBUF; i++)
9664418919fSjohnjiang 		m[i] = NULL;
9674418919fSjohnjiang 
9684418919fSjohnjiang 	/* alloc NB_MBUF mbufs */
9694418919fSjohnjiang 	for (i=0; i<NB_MBUF; i++) {
9704418919fSjohnjiang 		m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
9714418919fSjohnjiang 		if (m[i] == NULL) {
9724418919fSjohnjiang 			printf("rte_pktmbuf_alloc() failed (%u)\n", i);
9734418919fSjohnjiang 			ret = -1;
9744418919fSjohnjiang 		}
9754418919fSjohnjiang 	}
9764418919fSjohnjiang 
9774418919fSjohnjiang 	/* free them */
9784418919fSjohnjiang 	for (i=0; i<NB_MBUF; i++) {
9794418919fSjohnjiang 		if (m[i] != NULL) {
9804418919fSjohnjiang 			struct rte_mbuf *mb, *mt;
9814418919fSjohnjiang 
9824418919fSjohnjiang 			mb = m[i];
9834418919fSjohnjiang 			while(mb != NULL) {
9844418919fSjohnjiang 				mt = mb;
9854418919fSjohnjiang 				mb = mb->next;
9864418919fSjohnjiang 				rte_pktmbuf_free_seg(mt);
9874418919fSjohnjiang 			}
9884418919fSjohnjiang 		}
9894418919fSjohnjiang 	}
9904418919fSjohnjiang 
9914418919fSjohnjiang 	return ret;
9924418919fSjohnjiang }
9934418919fSjohnjiang 
9944418919fSjohnjiang /*
9954418919fSjohnjiang  * Stress test for rte_mbuf atomic refcnt.
9964418919fSjohnjiang  * Implies that RTE_MBUF_REFCNT_ATOMIC is defined.
9974418919fSjohnjiang  * For more efficiency, recommended to run with RTE_LIBRTE_MBUF_DEBUG defined.
9984418919fSjohnjiang  */
9994418919fSjohnjiang 
10004418919fSjohnjiang #ifdef RTE_MBUF_REFCNT_ATOMIC
10014418919fSjohnjiang 
10024418919fSjohnjiang static int
test_refcnt_worker(void * arg)1003*2d9fd380Sjfb8856606 test_refcnt_worker(void *arg)
10044418919fSjohnjiang {
10054418919fSjohnjiang 	unsigned lcore, free;
10064418919fSjohnjiang 	void *mp = 0;
10074418919fSjohnjiang 	struct rte_ring *refcnt_mbuf_ring = arg;
10084418919fSjohnjiang 
10094418919fSjohnjiang 	lcore = rte_lcore_id();
10104418919fSjohnjiang 	printf("%s started at lcore %u\n", __func__, lcore);
10114418919fSjohnjiang 
10124418919fSjohnjiang 	free = 0;
1013*2d9fd380Sjfb8856606 	while (refcnt_stop_workers == 0) {
10144418919fSjohnjiang 		if (rte_ring_dequeue(refcnt_mbuf_ring, &mp) == 0) {
10154418919fSjohnjiang 			free++;
10164418919fSjohnjiang 			rte_pktmbuf_free(mp);
10174418919fSjohnjiang 		}
10184418919fSjohnjiang 	}
10194418919fSjohnjiang 
10204418919fSjohnjiang 	refcnt_lcore[lcore] += free;
10214418919fSjohnjiang 	printf("%s finished at lcore %u, "
10224418919fSjohnjiang 	       "number of freed mbufs: %u\n",
10234418919fSjohnjiang 	       __func__, lcore, free);
10244418919fSjohnjiang 	return 0;
10254418919fSjohnjiang }
10264418919fSjohnjiang 
10274418919fSjohnjiang static void
test_refcnt_iter(unsigned int lcore,unsigned int iter,struct rte_mempool * refcnt_pool,struct rte_ring * refcnt_mbuf_ring)10284418919fSjohnjiang test_refcnt_iter(unsigned int lcore, unsigned int iter,
10294418919fSjohnjiang 		 struct rte_mempool *refcnt_pool,
10304418919fSjohnjiang 		 struct rte_ring *refcnt_mbuf_ring)
10314418919fSjohnjiang {
10324418919fSjohnjiang 	uint16_t ref;
10334418919fSjohnjiang 	unsigned i, n, tref, wn;
10344418919fSjohnjiang 	struct rte_mbuf *m;
10354418919fSjohnjiang 
10364418919fSjohnjiang 	tref = 0;
10374418919fSjohnjiang 
10384418919fSjohnjiang 	/* For each mbuf in the pool:
10394418919fSjohnjiang 	 * - allocate mbuf,
10404418919fSjohnjiang 	 * - increment it's reference up to N+1,
1041*2d9fd380Sjfb8856606 	 * - enqueue it N times into the ring for worker cores to free.
10424418919fSjohnjiang 	 */
10434418919fSjohnjiang 	for (i = 0, n = rte_mempool_avail_count(refcnt_pool);
10444418919fSjohnjiang 	    i != n && (m = rte_pktmbuf_alloc(refcnt_pool)) != NULL;
10454418919fSjohnjiang 	    i++) {
10464418919fSjohnjiang 		ref = RTE_MAX(rte_rand() % REFCNT_MAX_REF, 1UL);
10474418919fSjohnjiang 		tref += ref;
10484418919fSjohnjiang 		if ((ref & 1) != 0) {
10494418919fSjohnjiang 			rte_pktmbuf_refcnt_update(m, ref);
10504418919fSjohnjiang 			while (ref-- != 0)
10514418919fSjohnjiang 				rte_ring_enqueue(refcnt_mbuf_ring, m);
10524418919fSjohnjiang 		} else {
10534418919fSjohnjiang 			while (ref-- != 0) {
10544418919fSjohnjiang 				rte_pktmbuf_refcnt_update(m, 1);
10554418919fSjohnjiang 				rte_ring_enqueue(refcnt_mbuf_ring, m);
10564418919fSjohnjiang 			}
10574418919fSjohnjiang 		}
10584418919fSjohnjiang 		rte_pktmbuf_free(m);
10594418919fSjohnjiang 	}
10604418919fSjohnjiang 
10614418919fSjohnjiang 	if (i != n)
10624418919fSjohnjiang 		rte_panic("(lcore=%u, iter=%u): was able to allocate only "
10634418919fSjohnjiang 		          "%u from %u mbufs\n", lcore, iter, i, n);
10644418919fSjohnjiang 
1065*2d9fd380Sjfb8856606 	/* wait till worker lcores  will consume all mbufs */
10664418919fSjohnjiang 	while (!rte_ring_empty(refcnt_mbuf_ring))
10674418919fSjohnjiang 		;
10684418919fSjohnjiang 
10694418919fSjohnjiang 	/* check that all mbufs are back into mempool by now */
10704418919fSjohnjiang 	for (wn = 0; wn != REFCNT_MAX_TIMEOUT; wn++) {
10714418919fSjohnjiang 		if ((i = rte_mempool_avail_count(refcnt_pool)) == n) {
10724418919fSjohnjiang 			refcnt_lcore[lcore] += tref;
10734418919fSjohnjiang 			printf("%s(lcore=%u, iter=%u) completed, "
10744418919fSjohnjiang 			    "%u references processed\n",
10754418919fSjohnjiang 			    __func__, lcore, iter, tref);
10764418919fSjohnjiang 			return;
10774418919fSjohnjiang 		}
10784418919fSjohnjiang 		rte_delay_ms(100);
10794418919fSjohnjiang 	}
10804418919fSjohnjiang 
10814418919fSjohnjiang 	rte_panic("(lcore=%u, iter=%u): after %us only "
10824418919fSjohnjiang 	          "%u of %u mbufs left free\n", lcore, iter, wn, i, n);
10834418919fSjohnjiang }
10844418919fSjohnjiang 
10854418919fSjohnjiang static int
test_refcnt_main(struct rte_mempool * refcnt_pool,struct rte_ring * refcnt_mbuf_ring)1086*2d9fd380Sjfb8856606 test_refcnt_main(struct rte_mempool *refcnt_pool,
10874418919fSjohnjiang 		   struct rte_ring *refcnt_mbuf_ring)
10884418919fSjohnjiang {
10894418919fSjohnjiang 	unsigned i, lcore;
10904418919fSjohnjiang 
10914418919fSjohnjiang 	lcore = rte_lcore_id();
10924418919fSjohnjiang 	printf("%s started at lcore %u\n", __func__, lcore);
10934418919fSjohnjiang 
10944418919fSjohnjiang 	for (i = 0; i != REFCNT_MAX_ITER; i++)
10954418919fSjohnjiang 		test_refcnt_iter(lcore, i, refcnt_pool, refcnt_mbuf_ring);
10964418919fSjohnjiang 
1097*2d9fd380Sjfb8856606 	refcnt_stop_workers = 1;
10984418919fSjohnjiang 	rte_wmb();
10994418919fSjohnjiang 
11004418919fSjohnjiang 	printf("%s finished at lcore %u\n", __func__, lcore);
11014418919fSjohnjiang 	return 0;
11024418919fSjohnjiang }
11034418919fSjohnjiang 
11044418919fSjohnjiang #endif
11054418919fSjohnjiang 
11064418919fSjohnjiang static int
test_refcnt_mbuf(void)11074418919fSjohnjiang test_refcnt_mbuf(void)
11084418919fSjohnjiang {
11094418919fSjohnjiang #ifdef RTE_MBUF_REFCNT_ATOMIC
1110*2d9fd380Sjfb8856606 	unsigned int main_lcore, worker, tref;
11114418919fSjohnjiang 	int ret = -1;
11124418919fSjohnjiang 	struct rte_mempool *refcnt_pool = NULL;
11134418919fSjohnjiang 	struct rte_ring *refcnt_mbuf_ring = NULL;
11144418919fSjohnjiang 
11154418919fSjohnjiang 	if (rte_lcore_count() < 2) {
11164418919fSjohnjiang 		printf("Not enough cores for test_refcnt_mbuf, expecting at least 2\n");
11174418919fSjohnjiang 		return TEST_SKIPPED;
11184418919fSjohnjiang 	}
11194418919fSjohnjiang 
11204418919fSjohnjiang 	printf("starting %s, at %u lcores\n", __func__, rte_lcore_count());
11214418919fSjohnjiang 
11224418919fSjohnjiang 	/* create refcnt pool & ring if they don't exist */
11234418919fSjohnjiang 
11244418919fSjohnjiang 	refcnt_pool = rte_pktmbuf_pool_create(MAKE_STRING(refcnt_pool),
11254418919fSjohnjiang 					      REFCNT_MBUF_NUM, 0, 0, 0,
11264418919fSjohnjiang 					      SOCKET_ID_ANY);
11274418919fSjohnjiang 	if (refcnt_pool == NULL) {
11284418919fSjohnjiang 		printf("%s: cannot allocate " MAKE_STRING(refcnt_pool) "\n",
11294418919fSjohnjiang 		       __func__);
11304418919fSjohnjiang 		return -1;
11314418919fSjohnjiang 	}
11324418919fSjohnjiang 
11334418919fSjohnjiang 	refcnt_mbuf_ring = rte_ring_create("refcnt_mbuf_ring",
11344418919fSjohnjiang 					   rte_align32pow2(REFCNT_RING_SIZE), SOCKET_ID_ANY,
11354418919fSjohnjiang 					   RING_F_SP_ENQ);
11364418919fSjohnjiang 	if (refcnt_mbuf_ring == NULL) {
11374418919fSjohnjiang 		printf("%s: cannot allocate " MAKE_STRING(refcnt_mbuf_ring)
11384418919fSjohnjiang 		       "\n", __func__);
11394418919fSjohnjiang 		goto err;
11404418919fSjohnjiang 	}
11414418919fSjohnjiang 
1142*2d9fd380Sjfb8856606 	refcnt_stop_workers = 0;
11434418919fSjohnjiang 	memset(refcnt_lcore, 0, sizeof (refcnt_lcore));
11444418919fSjohnjiang 
1145*2d9fd380Sjfb8856606 	rte_eal_mp_remote_launch(test_refcnt_worker, refcnt_mbuf_ring, SKIP_MAIN);
11464418919fSjohnjiang 
1147*2d9fd380Sjfb8856606 	test_refcnt_main(refcnt_pool, refcnt_mbuf_ring);
11484418919fSjohnjiang 
11494418919fSjohnjiang 	rte_eal_mp_wait_lcore();
11504418919fSjohnjiang 
11514418919fSjohnjiang 	/* check that we porcessed all references */
11524418919fSjohnjiang 	tref = 0;
1153*2d9fd380Sjfb8856606 	main_lcore = rte_get_main_lcore();
11544418919fSjohnjiang 
1155*2d9fd380Sjfb8856606 	RTE_LCORE_FOREACH_WORKER(worker)
1156*2d9fd380Sjfb8856606 		tref += refcnt_lcore[worker];
11574418919fSjohnjiang 
1158*2d9fd380Sjfb8856606 	if (tref != refcnt_lcore[main_lcore])
11590c6bd470Sfengbojiang 		rte_panic("referenced mbufs: %u, freed mbufs: %u\n",
1160*2d9fd380Sjfb8856606 			  tref, refcnt_lcore[main_lcore]);
11614418919fSjohnjiang 
11624418919fSjohnjiang 	rte_mempool_dump(stdout, refcnt_pool);
11634418919fSjohnjiang 	rte_ring_dump(stdout, refcnt_mbuf_ring);
11644418919fSjohnjiang 
11654418919fSjohnjiang 	ret = 0;
11664418919fSjohnjiang 
11674418919fSjohnjiang err:
11684418919fSjohnjiang 	rte_mempool_free(refcnt_pool);
11694418919fSjohnjiang 	rte_ring_free(refcnt_mbuf_ring);
11704418919fSjohnjiang 	return ret;
11714418919fSjohnjiang #else
11724418919fSjohnjiang 	return 0;
11734418919fSjohnjiang #endif
11744418919fSjohnjiang }
11754418919fSjohnjiang 
11764418919fSjohnjiang #include <unistd.h>
11774418919fSjohnjiang #include <sys/wait.h>
11784418919fSjohnjiang 
11794418919fSjohnjiang /* use fork() to test mbuf errors panic */
11804418919fSjohnjiang static int
verify_mbuf_check_panics(struct rte_mbuf * buf)11814418919fSjohnjiang verify_mbuf_check_panics(struct rte_mbuf *buf)
11824418919fSjohnjiang {
11834418919fSjohnjiang 	int pid;
11844418919fSjohnjiang 	int status;
11854418919fSjohnjiang 
11864418919fSjohnjiang 	pid = fork();
11874418919fSjohnjiang 
11884418919fSjohnjiang 	if (pid == 0) {
11894418919fSjohnjiang 		rte_mbuf_sanity_check(buf, 1); /* should panic */
11904418919fSjohnjiang 		exit(0);  /* return normally if it doesn't panic */
11914418919fSjohnjiang 	} else if (pid < 0){
11924418919fSjohnjiang 		printf("Fork Failed\n");
11934418919fSjohnjiang 		return -1;
11944418919fSjohnjiang 	}
11954418919fSjohnjiang 	wait(&status);
11964418919fSjohnjiang 	if(status == 0)
11974418919fSjohnjiang 		return -1;
11984418919fSjohnjiang 
11994418919fSjohnjiang 	return 0;
12004418919fSjohnjiang }
12014418919fSjohnjiang 
12024418919fSjohnjiang static int
test_failing_mbuf_sanity_check(struct rte_mempool * pktmbuf_pool)12034418919fSjohnjiang test_failing_mbuf_sanity_check(struct rte_mempool *pktmbuf_pool)
12044418919fSjohnjiang {
12054418919fSjohnjiang 	struct rte_mbuf *buf;
12064418919fSjohnjiang 	struct rte_mbuf badbuf;
12074418919fSjohnjiang 
12084418919fSjohnjiang 	printf("Checking rte_mbuf_sanity_check for failure conditions\n");
12094418919fSjohnjiang 
12104418919fSjohnjiang 	/* get a good mbuf to use to make copies */
12114418919fSjohnjiang 	buf = rte_pktmbuf_alloc(pktmbuf_pool);
12124418919fSjohnjiang 	if (buf == NULL)
12134418919fSjohnjiang 		return -1;
1214*2d9fd380Sjfb8856606 
12154418919fSjohnjiang 	printf("Checking good mbuf initially\n");
12164418919fSjohnjiang 	if (verify_mbuf_check_panics(buf) != -1)
12174418919fSjohnjiang 		return -1;
12184418919fSjohnjiang 
12194418919fSjohnjiang 	printf("Now checking for error conditions\n");
12204418919fSjohnjiang 
12214418919fSjohnjiang 	if (verify_mbuf_check_panics(NULL)) {
12224418919fSjohnjiang 		printf("Error with NULL mbuf test\n");
12234418919fSjohnjiang 		return -1;
12244418919fSjohnjiang 	}
12254418919fSjohnjiang 
12264418919fSjohnjiang 	badbuf = *buf;
12274418919fSjohnjiang 	badbuf.pool = NULL;
12284418919fSjohnjiang 	if (verify_mbuf_check_panics(&badbuf)) {
12294418919fSjohnjiang 		printf("Error with bad-pool mbuf test\n");
12304418919fSjohnjiang 		return -1;
12314418919fSjohnjiang 	}
12324418919fSjohnjiang 
12334418919fSjohnjiang 	badbuf = *buf;
12344418919fSjohnjiang 	badbuf.buf_iova = 0;
12354418919fSjohnjiang 	if (verify_mbuf_check_panics(&badbuf)) {
12364418919fSjohnjiang 		printf("Error with bad-physaddr mbuf test\n");
12374418919fSjohnjiang 		return -1;
12384418919fSjohnjiang 	}
12394418919fSjohnjiang 
12404418919fSjohnjiang 	badbuf = *buf;
12414418919fSjohnjiang 	badbuf.buf_addr = NULL;
12424418919fSjohnjiang 	if (verify_mbuf_check_panics(&badbuf)) {
12434418919fSjohnjiang 		printf("Error with bad-addr mbuf test\n");
12444418919fSjohnjiang 		return -1;
12454418919fSjohnjiang 	}
12464418919fSjohnjiang 
12474418919fSjohnjiang 	badbuf = *buf;
12484418919fSjohnjiang 	badbuf.refcnt = 0;
12494418919fSjohnjiang 	if (verify_mbuf_check_panics(&badbuf)) {
12504418919fSjohnjiang 		printf("Error with bad-refcnt(0) mbuf test\n");
12514418919fSjohnjiang 		return -1;
12524418919fSjohnjiang 	}
12534418919fSjohnjiang 
12544418919fSjohnjiang 	badbuf = *buf;
12554418919fSjohnjiang 	badbuf.refcnt = UINT16_MAX;
12564418919fSjohnjiang 	if (verify_mbuf_check_panics(&badbuf)) {
12574418919fSjohnjiang 		printf("Error with bad-refcnt(MAX) mbuf test\n");
12584418919fSjohnjiang 		return -1;
12594418919fSjohnjiang 	}
12604418919fSjohnjiang 
12614418919fSjohnjiang 	return 0;
12624418919fSjohnjiang }
12634418919fSjohnjiang 
12644418919fSjohnjiang static int
test_mbuf_linearize(struct rte_mempool * pktmbuf_pool,int pkt_len,int nb_segs)12654418919fSjohnjiang test_mbuf_linearize(struct rte_mempool *pktmbuf_pool, int pkt_len,
12664418919fSjohnjiang 		    int nb_segs)
12674418919fSjohnjiang {
12684418919fSjohnjiang 
12694418919fSjohnjiang 	struct rte_mbuf *m = NULL, *mbuf = NULL;
12704418919fSjohnjiang 	uint8_t *data;
12714418919fSjohnjiang 	int data_len = 0;
12724418919fSjohnjiang 	int remain;
12734418919fSjohnjiang 	int seg, seg_len;
12744418919fSjohnjiang 	int i;
12754418919fSjohnjiang 
12764418919fSjohnjiang 	if (pkt_len < 1) {
12774418919fSjohnjiang 		printf("Packet size must be 1 or more (is %d)\n", pkt_len);
12784418919fSjohnjiang 		return -1;
12794418919fSjohnjiang 	}
12804418919fSjohnjiang 
12814418919fSjohnjiang 	if (nb_segs < 1) {
12824418919fSjohnjiang 		printf("Number of segments must be 1 or more (is %d)\n",
12834418919fSjohnjiang 				nb_segs);
12844418919fSjohnjiang 		return -1;
12854418919fSjohnjiang 	}
12864418919fSjohnjiang 
12874418919fSjohnjiang 	seg_len = pkt_len / nb_segs;
12884418919fSjohnjiang 	if (seg_len == 0)
12894418919fSjohnjiang 		seg_len = 1;
12904418919fSjohnjiang 
12914418919fSjohnjiang 	remain = pkt_len;
12924418919fSjohnjiang 
12934418919fSjohnjiang 	/* Create chained mbuf_src and fill it generated data */
12944418919fSjohnjiang 	for (seg = 0; remain > 0; seg++) {
12954418919fSjohnjiang 
12964418919fSjohnjiang 		m = rte_pktmbuf_alloc(pktmbuf_pool);
12974418919fSjohnjiang 		if (m == NULL) {
12984418919fSjohnjiang 			printf("Cannot create segment for source mbuf");
12994418919fSjohnjiang 			goto fail;
13004418919fSjohnjiang 		}
13014418919fSjohnjiang 
13024418919fSjohnjiang 		/* Make sure if tailroom is zeroed */
13034418919fSjohnjiang 		memset(rte_pktmbuf_mtod(m, uint8_t *), 0,
13044418919fSjohnjiang 				rte_pktmbuf_tailroom(m));
13054418919fSjohnjiang 
13064418919fSjohnjiang 		data_len = remain;
13074418919fSjohnjiang 		if (data_len > seg_len)
13084418919fSjohnjiang 			data_len = seg_len;
13094418919fSjohnjiang 
13104418919fSjohnjiang 		data = (uint8_t *)rte_pktmbuf_append(m, data_len);
13114418919fSjohnjiang 		if (data == NULL) {
13124418919fSjohnjiang 			printf("Cannot append %d bytes to the mbuf\n",
13134418919fSjohnjiang 					data_len);
13144418919fSjohnjiang 			goto fail;
13154418919fSjohnjiang 		}
13164418919fSjohnjiang 
13174418919fSjohnjiang 		for (i = 0; i < data_len; i++)
13184418919fSjohnjiang 			data[i] = (seg * seg_len + i) % 0x0ff;
13194418919fSjohnjiang 
13204418919fSjohnjiang 		if (seg == 0)
13214418919fSjohnjiang 			mbuf = m;
13224418919fSjohnjiang 		else
13234418919fSjohnjiang 			rte_pktmbuf_chain(mbuf, m);
13244418919fSjohnjiang 
13254418919fSjohnjiang 		remain -= data_len;
13264418919fSjohnjiang 	}
13274418919fSjohnjiang 
13284418919fSjohnjiang 	/* Create destination buffer to store coalesced data */
13294418919fSjohnjiang 	if (rte_pktmbuf_linearize(mbuf)) {
13304418919fSjohnjiang 		printf("Mbuf linearization failed\n");
13314418919fSjohnjiang 		goto fail;
13324418919fSjohnjiang 	}
13334418919fSjohnjiang 
13344418919fSjohnjiang 	if (!rte_pktmbuf_is_contiguous(mbuf)) {
13354418919fSjohnjiang 		printf("Source buffer should be contiguous after "
13364418919fSjohnjiang 				"linearization\n");
13374418919fSjohnjiang 		goto fail;
13384418919fSjohnjiang 	}
13394418919fSjohnjiang 
13404418919fSjohnjiang 	data = rte_pktmbuf_mtod(mbuf, uint8_t *);
13414418919fSjohnjiang 
13424418919fSjohnjiang 	for (i = 0; i < pkt_len; i++)
13434418919fSjohnjiang 		if (data[i] != (i % 0x0ff)) {
13444418919fSjohnjiang 			printf("Incorrect data in linearized mbuf\n");
13454418919fSjohnjiang 			goto fail;
13464418919fSjohnjiang 		}
13474418919fSjohnjiang 
13484418919fSjohnjiang 	rte_pktmbuf_free(mbuf);
13494418919fSjohnjiang 	return 0;
13504418919fSjohnjiang 
13514418919fSjohnjiang fail:
13524418919fSjohnjiang 	if (mbuf)
13534418919fSjohnjiang 		rte_pktmbuf_free(mbuf);
13544418919fSjohnjiang 	return -1;
13554418919fSjohnjiang }
13564418919fSjohnjiang 
13574418919fSjohnjiang static int
test_mbuf_linearize_check(struct rte_mempool * pktmbuf_pool)13584418919fSjohnjiang test_mbuf_linearize_check(struct rte_mempool *pktmbuf_pool)
13594418919fSjohnjiang {
13604418919fSjohnjiang 	struct test_mbuf_array {
13614418919fSjohnjiang 		int size;
13624418919fSjohnjiang 		int nb_segs;
13634418919fSjohnjiang 	} mbuf_array[] = {
13644418919fSjohnjiang 			{ 128, 1 },
13654418919fSjohnjiang 			{ 64, 64 },
13664418919fSjohnjiang 			{ 512, 10 },
13674418919fSjohnjiang 			{ 250, 11 },
13684418919fSjohnjiang 			{ 123, 8 },
13694418919fSjohnjiang 	};
13704418919fSjohnjiang 	unsigned int i;
13714418919fSjohnjiang 
13724418919fSjohnjiang 	printf("Test mbuf linearize API\n");
13734418919fSjohnjiang 
13744418919fSjohnjiang 	for (i = 0; i < RTE_DIM(mbuf_array); i++)
13754418919fSjohnjiang 		if (test_mbuf_linearize(pktmbuf_pool, mbuf_array[i].size,
13764418919fSjohnjiang 				mbuf_array[i].nb_segs)) {
13774418919fSjohnjiang 			printf("Test failed for %d, %d\n", mbuf_array[i].size,
13784418919fSjohnjiang 					mbuf_array[i].nb_segs);
13794418919fSjohnjiang 			return -1;
13804418919fSjohnjiang 		}
13814418919fSjohnjiang 
13824418919fSjohnjiang 	return 0;
13834418919fSjohnjiang }
13844418919fSjohnjiang 
13854418919fSjohnjiang /*
13864418919fSjohnjiang  * Helper function for test_tx_ofload
13874418919fSjohnjiang  */
13884418919fSjohnjiang static inline void
set_tx_offload(struct rte_mbuf * mb,uint64_t il2,uint64_t il3,uint64_t il4,uint64_t tso,uint64_t ol3,uint64_t ol2)13894418919fSjohnjiang set_tx_offload(struct rte_mbuf *mb, uint64_t il2, uint64_t il3, uint64_t il4,
13904418919fSjohnjiang 	uint64_t tso, uint64_t ol3, uint64_t ol2)
13914418919fSjohnjiang {
13924418919fSjohnjiang 	mb->l2_len = il2;
13934418919fSjohnjiang 	mb->l3_len = il3;
13944418919fSjohnjiang 	mb->l4_len = il4;
13954418919fSjohnjiang 	mb->tso_segsz = tso;
13964418919fSjohnjiang 	mb->outer_l3_len = ol3;
13974418919fSjohnjiang 	mb->outer_l2_len = ol2;
13984418919fSjohnjiang }
13994418919fSjohnjiang 
14004418919fSjohnjiang static int
test_tx_offload(void)14014418919fSjohnjiang test_tx_offload(void)
14024418919fSjohnjiang {
14034418919fSjohnjiang 	struct rte_mbuf *mb;
14044418919fSjohnjiang 	uint64_t tm, v1, v2;
14054418919fSjohnjiang 	size_t sz;
14064418919fSjohnjiang 	uint32_t i;
14074418919fSjohnjiang 
14084418919fSjohnjiang 	static volatile struct {
14094418919fSjohnjiang 		uint16_t l2;
14104418919fSjohnjiang 		uint16_t l3;
14114418919fSjohnjiang 		uint16_t l4;
14124418919fSjohnjiang 		uint16_t tso;
14134418919fSjohnjiang 	} txof;
14144418919fSjohnjiang 
14154418919fSjohnjiang 	const uint32_t num = 0x10000;
14164418919fSjohnjiang 
14174418919fSjohnjiang 	txof.l2 = rte_rand() % (1 <<  RTE_MBUF_L2_LEN_BITS);
14184418919fSjohnjiang 	txof.l3 = rte_rand() % (1 <<  RTE_MBUF_L3_LEN_BITS);
14194418919fSjohnjiang 	txof.l4 = rte_rand() % (1 <<  RTE_MBUF_L4_LEN_BITS);
14204418919fSjohnjiang 	txof.tso = rte_rand() % (1 <<   RTE_MBUF_TSO_SEGSZ_BITS);
14214418919fSjohnjiang 
14224418919fSjohnjiang 	printf("%s started, tx_offload = {\n"
14234418919fSjohnjiang 		"\tl2_len=%#hx,\n"
14244418919fSjohnjiang 		"\tl3_len=%#hx,\n"
14254418919fSjohnjiang 		"\tl4_len=%#hx,\n"
14264418919fSjohnjiang 		"\ttso_segsz=%#hx,\n"
14274418919fSjohnjiang 		"\touter_l3_len=%#x,\n"
14284418919fSjohnjiang 		"\touter_l2_len=%#x,\n"
14294418919fSjohnjiang 		"};\n",
14304418919fSjohnjiang 		__func__,
14314418919fSjohnjiang 		txof.l2, txof.l3, txof.l4, txof.tso, txof.l3, txof.l2);
14324418919fSjohnjiang 
14334418919fSjohnjiang 	sz = sizeof(*mb) * num;
14344418919fSjohnjiang 	mb = rte_zmalloc(NULL, sz, RTE_CACHE_LINE_SIZE);
14354418919fSjohnjiang 	if (mb == NULL) {
14364418919fSjohnjiang 		printf("%s failed, out of memory\n", __func__);
14374418919fSjohnjiang 		return -ENOMEM;
14384418919fSjohnjiang 	}
14394418919fSjohnjiang 
14404418919fSjohnjiang 	memset(mb, 0, sz);
14414418919fSjohnjiang 	tm = rte_rdtsc_precise();
14424418919fSjohnjiang 
14434418919fSjohnjiang 	for (i = 0; i != num; i++)
14444418919fSjohnjiang 		set_tx_offload(mb + i, txof.l2, txof.l3, txof.l4,
14454418919fSjohnjiang 			txof.tso, txof.l3, txof.l2);
14464418919fSjohnjiang 
14474418919fSjohnjiang 	tm = rte_rdtsc_precise() - tm;
14484418919fSjohnjiang 	printf("%s set tx_offload by bit-fields: %u iterations, %"
14494418919fSjohnjiang 		PRIu64 " cycles, %#Lf cycles/iter\n",
14504418919fSjohnjiang 		__func__, num, tm, (long double)tm / num);
14514418919fSjohnjiang 
14524418919fSjohnjiang 	v1 = mb[rte_rand() % num].tx_offload;
14534418919fSjohnjiang 
14544418919fSjohnjiang 	memset(mb, 0, sz);
14554418919fSjohnjiang 	tm = rte_rdtsc_precise();
14564418919fSjohnjiang 
14574418919fSjohnjiang 	for (i = 0; i != num; i++)
14584418919fSjohnjiang 		mb[i].tx_offload = rte_mbuf_tx_offload(txof.l2, txof.l3,
14594418919fSjohnjiang 			txof.l4, txof.tso, txof.l3, txof.l2, 0);
14604418919fSjohnjiang 
14614418919fSjohnjiang 	tm = rte_rdtsc_precise() - tm;
14624418919fSjohnjiang 	printf("%s set raw tx_offload: %u iterations, %"
14634418919fSjohnjiang 		PRIu64 " cycles, %#Lf cycles/iter\n",
14644418919fSjohnjiang 		__func__, num, tm, (long double)tm / num);
14654418919fSjohnjiang 
14664418919fSjohnjiang 	v2 = mb[rte_rand() % num].tx_offload;
14674418919fSjohnjiang 
14684418919fSjohnjiang 	rte_free(mb);
14694418919fSjohnjiang 
14704418919fSjohnjiang 	printf("%s finished\n"
14714418919fSjohnjiang 		"expected tx_offload value: 0x%" PRIx64 ";\n"
14724418919fSjohnjiang 		"rte_mbuf_tx_offload value: 0x%" PRIx64 ";\n",
14734418919fSjohnjiang 		__func__, v1, v2);
14744418919fSjohnjiang 
14754418919fSjohnjiang 	return (v1 == v2) ? 0 : -EINVAL;
14764418919fSjohnjiang }
14774418919fSjohnjiang 
14784418919fSjohnjiang static int
test_get_rx_ol_flag_list(void)14794418919fSjohnjiang test_get_rx_ol_flag_list(void)
14804418919fSjohnjiang {
14814418919fSjohnjiang 	int len = 6, ret = 0;
14824418919fSjohnjiang 	char buf[256] = "";
14834418919fSjohnjiang 	int buflen = 0;
14844418919fSjohnjiang 
14854418919fSjohnjiang 	/* Test case to check with null buffer */
14864418919fSjohnjiang 	ret = rte_get_rx_ol_flag_list(0, NULL, 0);
14874418919fSjohnjiang 	if (ret != -1)
14884418919fSjohnjiang 		GOTO_FAIL("%s expected: -1, received = %d\n", __func__, ret);
14894418919fSjohnjiang 
14904418919fSjohnjiang 	/* Test case to check with zero buffer len */
14914418919fSjohnjiang 	ret = rte_get_rx_ol_flag_list(PKT_RX_L4_CKSUM_MASK, buf, 0);
14924418919fSjohnjiang 	if (ret != -1)
14934418919fSjohnjiang 		GOTO_FAIL("%s expected: -1, received = %d\n", __func__, ret);
14944418919fSjohnjiang 
14954418919fSjohnjiang 	buflen = strlen(buf);
14964418919fSjohnjiang 	if (buflen != 0)
14974418919fSjohnjiang 		GOTO_FAIL("%s buffer should be empty, received = %d\n",
14984418919fSjohnjiang 				__func__, buflen);
14994418919fSjohnjiang 
15004418919fSjohnjiang 	/* Test case to check with reduced buffer len */
15014418919fSjohnjiang 	ret = rte_get_rx_ol_flag_list(0, buf, len);
15024418919fSjohnjiang 	if (ret != -1)
15034418919fSjohnjiang 		GOTO_FAIL("%s expected: -1, received = %d\n", __func__, ret);
15044418919fSjohnjiang 
15054418919fSjohnjiang 	buflen = strlen(buf);
15064418919fSjohnjiang 	if (buflen != (len - 1))
15074418919fSjohnjiang 		GOTO_FAIL("%s invalid buffer length retrieved, expected: %d,"
15084418919fSjohnjiang 				"received = %d\n", __func__,
15094418919fSjohnjiang 				(len - 1), buflen);
15104418919fSjohnjiang 
15114418919fSjohnjiang 	/* Test case to check with zero mask value */
15124418919fSjohnjiang 	ret = rte_get_rx_ol_flag_list(0, buf, sizeof(buf));
15134418919fSjohnjiang 	if (ret != 0)
15144418919fSjohnjiang 		GOTO_FAIL("%s expected: 0, received = %d\n", __func__, ret);
15154418919fSjohnjiang 
15164418919fSjohnjiang 	buflen = strlen(buf);
15174418919fSjohnjiang 	if (buflen == 0)
15184418919fSjohnjiang 		GOTO_FAIL("%s expected: %s, received length = 0\n", __func__,
15194418919fSjohnjiang 				"non-zero, buffer should not be empty");
15204418919fSjohnjiang 
15214418919fSjohnjiang 	/* Test case to check with valid mask value */
15224418919fSjohnjiang 	ret = rte_get_rx_ol_flag_list(PKT_RX_SEC_OFFLOAD, buf, sizeof(buf));
15234418919fSjohnjiang 	if (ret != 0)
15244418919fSjohnjiang 		GOTO_FAIL("%s expected: 0, received = %d\n", __func__, ret);
15254418919fSjohnjiang 
15264418919fSjohnjiang 	buflen = strlen(buf);
15274418919fSjohnjiang 	if (buflen == 0)
15284418919fSjohnjiang 		GOTO_FAIL("%s expected: %s, received length = 0\n", __func__,
15294418919fSjohnjiang 				"non-zero, buffer should not be empty");
15304418919fSjohnjiang 
15314418919fSjohnjiang 	return 0;
15324418919fSjohnjiang fail:
15334418919fSjohnjiang 	return -1;
15344418919fSjohnjiang }
15354418919fSjohnjiang 
15364418919fSjohnjiang static int
test_get_tx_ol_flag_list(void)15374418919fSjohnjiang test_get_tx_ol_flag_list(void)
15384418919fSjohnjiang {
15394418919fSjohnjiang 	int len = 6, ret = 0;
15404418919fSjohnjiang 	char buf[256] = "";
15414418919fSjohnjiang 	int buflen = 0;
15424418919fSjohnjiang 
15434418919fSjohnjiang 	/* Test case to check with null buffer */
15444418919fSjohnjiang 	ret = rte_get_tx_ol_flag_list(0, NULL, 0);
15454418919fSjohnjiang 	if (ret != -1)
15464418919fSjohnjiang 		GOTO_FAIL("%s expected: -1, received = %d\n", __func__, ret);
15474418919fSjohnjiang 
15484418919fSjohnjiang 	/* Test case to check with zero buffer len */
15494418919fSjohnjiang 	ret = rte_get_tx_ol_flag_list(PKT_TX_IP_CKSUM, buf, 0);
15504418919fSjohnjiang 	if (ret != -1)
15514418919fSjohnjiang 		GOTO_FAIL("%s expected: -1, received = %d\n", __func__, ret);
15524418919fSjohnjiang 
15534418919fSjohnjiang 	buflen = strlen(buf);
15544418919fSjohnjiang 	if (buflen != 0) {
15554418919fSjohnjiang 		GOTO_FAIL("%s buffer should be empty, received = %d\n",
15564418919fSjohnjiang 				__func__, buflen);
15574418919fSjohnjiang 	}
15584418919fSjohnjiang 
15594418919fSjohnjiang 	/* Test case to check with reduced buffer len */
15604418919fSjohnjiang 	ret = rte_get_tx_ol_flag_list(0, buf, len);
15614418919fSjohnjiang 	if (ret != -1)
15624418919fSjohnjiang 		GOTO_FAIL("%s expected: -1, received = %d\n", __func__, ret);
15634418919fSjohnjiang 
15644418919fSjohnjiang 	buflen = strlen(buf);
15654418919fSjohnjiang 	if (buflen != (len - 1))
15664418919fSjohnjiang 		GOTO_FAIL("%s invalid buffer length retrieved, expected: %d,"
15674418919fSjohnjiang 				"received = %d\n", __func__,
15684418919fSjohnjiang 				(len - 1), buflen);
15694418919fSjohnjiang 
15704418919fSjohnjiang 	/* Test case to check with zero mask value */
15714418919fSjohnjiang 	ret = rte_get_tx_ol_flag_list(0, buf, sizeof(buf));
15724418919fSjohnjiang 	if (ret != 0)
15734418919fSjohnjiang 		GOTO_FAIL("%s expected: 0, received = %d\n", __func__, ret);
15744418919fSjohnjiang 
15754418919fSjohnjiang 	buflen = strlen(buf);
15764418919fSjohnjiang 	if (buflen == 0)
15774418919fSjohnjiang 		GOTO_FAIL("%s expected: %s, received length = 0\n", __func__,
15784418919fSjohnjiang 				"non-zero, buffer should not be empty");
15794418919fSjohnjiang 
15804418919fSjohnjiang 	/* Test case to check with valid mask value */
15814418919fSjohnjiang 	ret = rte_get_tx_ol_flag_list(PKT_TX_UDP_CKSUM, buf, sizeof(buf));
15824418919fSjohnjiang 	if (ret != 0)
15834418919fSjohnjiang 		GOTO_FAIL("%s expected: 0, received = %d\n", __func__, ret);
15844418919fSjohnjiang 
15854418919fSjohnjiang 	buflen = strlen(buf);
15864418919fSjohnjiang 	if (buflen == 0)
15874418919fSjohnjiang 		GOTO_FAIL("%s expected: %s, received length = 0\n", __func__,
15884418919fSjohnjiang 				"non-zero, buffer should not be empty");
15894418919fSjohnjiang 
15904418919fSjohnjiang 	return 0;
15914418919fSjohnjiang fail:
15924418919fSjohnjiang 	return -1;
15934418919fSjohnjiang 
15944418919fSjohnjiang }
15954418919fSjohnjiang 
15964418919fSjohnjiang struct flag_name {
15974418919fSjohnjiang 	uint64_t flag;
15984418919fSjohnjiang 	const char *name;
15994418919fSjohnjiang };
16004418919fSjohnjiang 
16014418919fSjohnjiang static int
test_get_rx_ol_flag_name(void)16024418919fSjohnjiang test_get_rx_ol_flag_name(void)
16034418919fSjohnjiang {
16044418919fSjohnjiang 	uint16_t i;
16054418919fSjohnjiang 	const char *flag_str = NULL;
16064418919fSjohnjiang 	const struct flag_name rx_flags[] = {
16074418919fSjohnjiang 		VAL_NAME(PKT_RX_VLAN),
16084418919fSjohnjiang 		VAL_NAME(PKT_RX_RSS_HASH),
16094418919fSjohnjiang 		VAL_NAME(PKT_RX_FDIR),
16104418919fSjohnjiang 		VAL_NAME(PKT_RX_L4_CKSUM_BAD),
16114418919fSjohnjiang 		VAL_NAME(PKT_RX_L4_CKSUM_GOOD),
16124418919fSjohnjiang 		VAL_NAME(PKT_RX_L4_CKSUM_NONE),
16134418919fSjohnjiang 		VAL_NAME(PKT_RX_IP_CKSUM_BAD),
16144418919fSjohnjiang 		VAL_NAME(PKT_RX_IP_CKSUM_GOOD),
16154418919fSjohnjiang 		VAL_NAME(PKT_RX_IP_CKSUM_NONE),
16164418919fSjohnjiang 		VAL_NAME(PKT_RX_EIP_CKSUM_BAD),
16174418919fSjohnjiang 		VAL_NAME(PKT_RX_VLAN_STRIPPED),
16184418919fSjohnjiang 		VAL_NAME(PKT_RX_IEEE1588_PTP),
16194418919fSjohnjiang 		VAL_NAME(PKT_RX_IEEE1588_TMST),
16204418919fSjohnjiang 		VAL_NAME(PKT_RX_FDIR_ID),
16214418919fSjohnjiang 		VAL_NAME(PKT_RX_FDIR_FLX),
16224418919fSjohnjiang 		VAL_NAME(PKT_RX_QINQ_STRIPPED),
16234418919fSjohnjiang 		VAL_NAME(PKT_RX_LRO),
16244418919fSjohnjiang 		VAL_NAME(PKT_RX_SEC_OFFLOAD),
16254418919fSjohnjiang 		VAL_NAME(PKT_RX_SEC_OFFLOAD_FAILED),
16264418919fSjohnjiang 		VAL_NAME(PKT_RX_OUTER_L4_CKSUM_BAD),
16274418919fSjohnjiang 		VAL_NAME(PKT_RX_OUTER_L4_CKSUM_GOOD),
16284418919fSjohnjiang 		VAL_NAME(PKT_RX_OUTER_L4_CKSUM_INVALID),
16294418919fSjohnjiang 	};
16304418919fSjohnjiang 
16314418919fSjohnjiang 	/* Test case to check with valid flag */
16324418919fSjohnjiang 	for (i = 0; i < RTE_DIM(rx_flags); i++) {
16334418919fSjohnjiang 		flag_str = rte_get_rx_ol_flag_name(rx_flags[i].flag);
16344418919fSjohnjiang 		if (flag_str == NULL)
16354418919fSjohnjiang 			GOTO_FAIL("%s: Expected flagname = %s; received null\n",
16364418919fSjohnjiang 					__func__, rx_flags[i].name);
16374418919fSjohnjiang 		if (strcmp(flag_str, rx_flags[i].name) != 0)
16384418919fSjohnjiang 			GOTO_FAIL("%s: Expected flagname = %s; received = %s\n",
16394418919fSjohnjiang 				__func__, rx_flags[i].name, flag_str);
16404418919fSjohnjiang 	}
16414418919fSjohnjiang 	/* Test case to check with invalid flag */
16424418919fSjohnjiang 	flag_str = rte_get_rx_ol_flag_name(0);
16434418919fSjohnjiang 	if (flag_str != NULL) {
16444418919fSjohnjiang 		GOTO_FAIL("%s: Expected flag name = null; received = %s\n",
16454418919fSjohnjiang 				__func__, flag_str);
16464418919fSjohnjiang 	}
16474418919fSjohnjiang 
16484418919fSjohnjiang 	return 0;
16494418919fSjohnjiang fail:
16504418919fSjohnjiang 	return -1;
16514418919fSjohnjiang }
16524418919fSjohnjiang 
16534418919fSjohnjiang static int
test_get_tx_ol_flag_name(void)16544418919fSjohnjiang test_get_tx_ol_flag_name(void)
16554418919fSjohnjiang {
16564418919fSjohnjiang 	uint16_t i;
16574418919fSjohnjiang 	const char *flag_str = NULL;
16584418919fSjohnjiang 	const struct flag_name tx_flags[] = {
16594418919fSjohnjiang 		VAL_NAME(PKT_TX_VLAN),
16604418919fSjohnjiang 		VAL_NAME(PKT_TX_IP_CKSUM),
16614418919fSjohnjiang 		VAL_NAME(PKT_TX_TCP_CKSUM),
16624418919fSjohnjiang 		VAL_NAME(PKT_TX_SCTP_CKSUM),
16634418919fSjohnjiang 		VAL_NAME(PKT_TX_UDP_CKSUM),
16644418919fSjohnjiang 		VAL_NAME(PKT_TX_IEEE1588_TMST),
16654418919fSjohnjiang 		VAL_NAME(PKT_TX_TCP_SEG),
16664418919fSjohnjiang 		VAL_NAME(PKT_TX_IPV4),
16674418919fSjohnjiang 		VAL_NAME(PKT_TX_IPV6),
16684418919fSjohnjiang 		VAL_NAME(PKT_TX_OUTER_IP_CKSUM),
16694418919fSjohnjiang 		VAL_NAME(PKT_TX_OUTER_IPV4),
16704418919fSjohnjiang 		VAL_NAME(PKT_TX_OUTER_IPV6),
16714418919fSjohnjiang 		VAL_NAME(PKT_TX_TUNNEL_VXLAN),
16724418919fSjohnjiang 		VAL_NAME(PKT_TX_TUNNEL_GRE),
16734418919fSjohnjiang 		VAL_NAME(PKT_TX_TUNNEL_IPIP),
16744418919fSjohnjiang 		VAL_NAME(PKT_TX_TUNNEL_GENEVE),
16754418919fSjohnjiang 		VAL_NAME(PKT_TX_TUNNEL_MPLSINUDP),
16764418919fSjohnjiang 		VAL_NAME(PKT_TX_TUNNEL_VXLAN_GPE),
16774418919fSjohnjiang 		VAL_NAME(PKT_TX_TUNNEL_IP),
16784418919fSjohnjiang 		VAL_NAME(PKT_TX_TUNNEL_UDP),
16794418919fSjohnjiang 		VAL_NAME(PKT_TX_QINQ),
16804418919fSjohnjiang 		VAL_NAME(PKT_TX_MACSEC),
16814418919fSjohnjiang 		VAL_NAME(PKT_TX_SEC_OFFLOAD),
16824418919fSjohnjiang 		VAL_NAME(PKT_TX_UDP_SEG),
16834418919fSjohnjiang 		VAL_NAME(PKT_TX_OUTER_UDP_CKSUM),
16844418919fSjohnjiang 	};
16854418919fSjohnjiang 
16864418919fSjohnjiang 	/* Test case to check with valid flag */
16874418919fSjohnjiang 	for (i = 0; i < RTE_DIM(tx_flags); i++) {
16884418919fSjohnjiang 		flag_str = rte_get_tx_ol_flag_name(tx_flags[i].flag);
16894418919fSjohnjiang 		if (flag_str == NULL)
16904418919fSjohnjiang 			GOTO_FAIL("%s: Expected flagname = %s; received null\n",
16914418919fSjohnjiang 				__func__, tx_flags[i].name);
16924418919fSjohnjiang 		if (strcmp(flag_str, tx_flags[i].name) != 0)
16934418919fSjohnjiang 			GOTO_FAIL("%s: Expected flagname = %s; received = %s\n",
16944418919fSjohnjiang 				__func__, tx_flags[i].name, flag_str);
16954418919fSjohnjiang 	}
16964418919fSjohnjiang 	/* Test case to check with invalid flag */
16974418919fSjohnjiang 	flag_str = rte_get_tx_ol_flag_name(0);
16984418919fSjohnjiang 	if (flag_str != NULL) {
16994418919fSjohnjiang 		GOTO_FAIL("%s: Expected flag name = null; received = %s\n",
17004418919fSjohnjiang 				__func__, flag_str);
17014418919fSjohnjiang 	}
17024418919fSjohnjiang 
17034418919fSjohnjiang 	return 0;
17044418919fSjohnjiang fail:
17054418919fSjohnjiang 	return -1;
17064418919fSjohnjiang 
17074418919fSjohnjiang }
17084418919fSjohnjiang 
17094418919fSjohnjiang static int
test_mbuf_validate_tx_offload(const char * test_name,struct rte_mempool * pktmbuf_pool,uint64_t ol_flags,uint16_t segsize,int expected_retval)17104418919fSjohnjiang test_mbuf_validate_tx_offload(const char *test_name,
17114418919fSjohnjiang 		struct rte_mempool *pktmbuf_pool,
17124418919fSjohnjiang 		uint64_t ol_flags,
17134418919fSjohnjiang 		uint16_t segsize,
17144418919fSjohnjiang 		int expected_retval)
17154418919fSjohnjiang {
17164418919fSjohnjiang 	struct rte_mbuf *m = NULL;
17174418919fSjohnjiang 	int ret = 0;
17184418919fSjohnjiang 
17194418919fSjohnjiang 	/* alloc a mbuf and do sanity check */
17204418919fSjohnjiang 	m = rte_pktmbuf_alloc(pktmbuf_pool);
17214418919fSjohnjiang 	if (m == NULL)
17224418919fSjohnjiang 		GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
17234418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(m) != 0)
17244418919fSjohnjiang 		GOTO_FAIL("%s: Bad packet length\n", __func__);
17254418919fSjohnjiang 	rte_mbuf_sanity_check(m, 0);
17264418919fSjohnjiang 	m->ol_flags = ol_flags;
17274418919fSjohnjiang 	m->tso_segsz = segsize;
17284418919fSjohnjiang 	ret = rte_validate_tx_offload(m);
17294418919fSjohnjiang 	if (ret != expected_retval)
17304418919fSjohnjiang 		GOTO_FAIL("%s(%s): expected ret val: %d; received: %d\n",
17314418919fSjohnjiang 				__func__, test_name, expected_retval, ret);
17324418919fSjohnjiang 	rte_pktmbuf_free(m);
17334418919fSjohnjiang 	m = NULL;
17344418919fSjohnjiang 	return 0;
17354418919fSjohnjiang fail:
17364418919fSjohnjiang 	if (m) {
17374418919fSjohnjiang 		rte_pktmbuf_free(m);
17384418919fSjohnjiang 		m = NULL;
17394418919fSjohnjiang 	}
17404418919fSjohnjiang 	return -1;
17414418919fSjohnjiang }
17424418919fSjohnjiang 
17434418919fSjohnjiang static int
test_mbuf_validate_tx_offload_one(struct rte_mempool * pktmbuf_pool)17444418919fSjohnjiang test_mbuf_validate_tx_offload_one(struct rte_mempool *pktmbuf_pool)
17454418919fSjohnjiang {
17464418919fSjohnjiang 	/* test to validate tx offload flags */
17474418919fSjohnjiang 	uint64_t ol_flags = 0;
17484418919fSjohnjiang 
17494418919fSjohnjiang 	/* test to validate if IP checksum is counted only for IPV4 packet */
17504418919fSjohnjiang 	/* set both IP checksum and IPV6 flags */
17514418919fSjohnjiang 	ol_flags |= PKT_TX_IP_CKSUM;
17524418919fSjohnjiang 	ol_flags |= PKT_TX_IPV6;
17534418919fSjohnjiang 	if (test_mbuf_validate_tx_offload("MBUF_TEST_IP_CKSUM_IPV6_SET",
17544418919fSjohnjiang 				pktmbuf_pool,
17554418919fSjohnjiang 				ol_flags, 0, -EINVAL) < 0)
17564418919fSjohnjiang 		GOTO_FAIL("%s failed: IP cksum is set incorrect.\n", __func__);
17574418919fSjohnjiang 	/* resetting ol_flags for next testcase */
17584418919fSjohnjiang 	ol_flags = 0;
17594418919fSjohnjiang 
17604418919fSjohnjiang 	/* test to validate if IP type is set when required */
17614418919fSjohnjiang 	ol_flags |= PKT_TX_L4_MASK;
17624418919fSjohnjiang 	if (test_mbuf_validate_tx_offload("MBUF_TEST_IP_TYPE_NOT_SET",
17634418919fSjohnjiang 				pktmbuf_pool,
17644418919fSjohnjiang 				ol_flags, 0, -EINVAL) < 0)
17654418919fSjohnjiang 		GOTO_FAIL("%s failed: IP type is not set.\n", __func__);
17664418919fSjohnjiang 
17674418919fSjohnjiang 	/* test if IP type is set when TCP SEG is on */
17684418919fSjohnjiang 	ol_flags |= PKT_TX_TCP_SEG;
17694418919fSjohnjiang 	if (test_mbuf_validate_tx_offload("MBUF_TEST_IP_TYPE_NOT_SET",
17704418919fSjohnjiang 				pktmbuf_pool,
17714418919fSjohnjiang 				ol_flags, 0, -EINVAL) < 0)
17724418919fSjohnjiang 		GOTO_FAIL("%s failed: IP type is not set.\n", __func__);
17734418919fSjohnjiang 
17744418919fSjohnjiang 	ol_flags = 0;
17754418919fSjohnjiang 	/* test to confirm IP type (IPV4/IPV6) is set */
17764418919fSjohnjiang 	ol_flags = PKT_TX_L4_MASK;
17774418919fSjohnjiang 	ol_flags |= PKT_TX_IPV6;
17784418919fSjohnjiang 	if (test_mbuf_validate_tx_offload("MBUF_TEST_IP_TYPE_SET",
17794418919fSjohnjiang 				pktmbuf_pool,
17804418919fSjohnjiang 				ol_flags, 0, 0) < 0)
17814418919fSjohnjiang 		GOTO_FAIL("%s failed: tx offload flag error.\n", __func__);
17824418919fSjohnjiang 
17834418919fSjohnjiang 	ol_flags = 0;
17844418919fSjohnjiang 	/* test to check TSO segment size is non-zero */
17854418919fSjohnjiang 	ol_flags |= PKT_TX_IPV4;
17864418919fSjohnjiang 	ol_flags |= PKT_TX_TCP_SEG;
17874418919fSjohnjiang 	/* set 0 tso segment size */
17884418919fSjohnjiang 	if (test_mbuf_validate_tx_offload("MBUF_TEST_NULL_TSO_SEGSZ",
17894418919fSjohnjiang 				pktmbuf_pool,
17904418919fSjohnjiang 				ol_flags, 0, -EINVAL) < 0)
17914418919fSjohnjiang 		GOTO_FAIL("%s failed: tso segment size is null.\n", __func__);
17924418919fSjohnjiang 
17934418919fSjohnjiang 	/* retain IPV4 and PKT_TX_TCP_SEG mask */
17944418919fSjohnjiang 	/* set valid tso segment size but IP CKSUM not set */
17954418919fSjohnjiang 	if (test_mbuf_validate_tx_offload("MBUF_TEST_TSO_IP_CKSUM_NOT_SET",
17964418919fSjohnjiang 				pktmbuf_pool,
17974418919fSjohnjiang 				ol_flags, 512, -EINVAL) < 0)
17984418919fSjohnjiang 		GOTO_FAIL("%s failed: IP CKSUM is not set.\n", __func__);
17994418919fSjohnjiang 
18004418919fSjohnjiang 	/* test to validate if IP checksum is set for TSO capability */
18014418919fSjohnjiang 	/* retain IPV4, TCP_SEG, tso_seg size */
18024418919fSjohnjiang 	ol_flags |= PKT_TX_IP_CKSUM;
18034418919fSjohnjiang 	if (test_mbuf_validate_tx_offload("MBUF_TEST_TSO_IP_CKSUM_SET",
18044418919fSjohnjiang 				pktmbuf_pool,
18054418919fSjohnjiang 				ol_flags, 512, 0) < 0)
18064418919fSjohnjiang 		GOTO_FAIL("%s failed: tx offload flag error.\n", __func__);
18074418919fSjohnjiang 
18084418919fSjohnjiang 	/* test to confirm TSO for IPV6 type */
18094418919fSjohnjiang 	ol_flags = 0;
18104418919fSjohnjiang 	ol_flags |= PKT_TX_IPV6;
18114418919fSjohnjiang 	ol_flags |= PKT_TX_TCP_SEG;
18124418919fSjohnjiang 	if (test_mbuf_validate_tx_offload("MBUF_TEST_TSO_IPV6_SET",
18134418919fSjohnjiang 				pktmbuf_pool,
18144418919fSjohnjiang 				ol_flags, 512, 0) < 0)
18154418919fSjohnjiang 		GOTO_FAIL("%s failed: TSO req not met.\n", __func__);
18164418919fSjohnjiang 
18174418919fSjohnjiang 	ol_flags = 0;
18184418919fSjohnjiang 	/* test if outer IP checksum set for non outer IPv4 packet */
18194418919fSjohnjiang 	ol_flags |= PKT_TX_IPV6;
18204418919fSjohnjiang 	ol_flags |= PKT_TX_OUTER_IP_CKSUM;
18214418919fSjohnjiang 	if (test_mbuf_validate_tx_offload("MBUF_TEST_OUTER_IPV4_NOT_SET",
18224418919fSjohnjiang 				pktmbuf_pool,
18234418919fSjohnjiang 				ol_flags, 512, -EINVAL) < 0)
18244418919fSjohnjiang 		GOTO_FAIL("%s failed: Outer IP cksum set.\n", __func__);
18254418919fSjohnjiang 
18264418919fSjohnjiang 	ol_flags = 0;
18274418919fSjohnjiang 	/* test to confirm outer IP checksum is set for outer IPV4 packet */
18284418919fSjohnjiang 	ol_flags |= PKT_TX_OUTER_IP_CKSUM;
18294418919fSjohnjiang 	ol_flags |= PKT_TX_OUTER_IPV4;
18304418919fSjohnjiang 	if (test_mbuf_validate_tx_offload("MBUF_TEST_OUTER_IPV4_SET",
18314418919fSjohnjiang 				pktmbuf_pool,
18324418919fSjohnjiang 				ol_flags, 512, 0) < 0)
18334418919fSjohnjiang 		GOTO_FAIL("%s failed: tx offload flag error.\n", __func__);
18344418919fSjohnjiang 
18354418919fSjohnjiang 	ol_flags = 0;
18364418919fSjohnjiang 	/* test to confirm if packets with no TX_OFFLOAD_MASK are skipped */
18374418919fSjohnjiang 	if (test_mbuf_validate_tx_offload("MBUF_TEST_OL_MASK_NOT_SET",
18384418919fSjohnjiang 				pktmbuf_pool,
18394418919fSjohnjiang 				ol_flags, 512, 0) < 0)
18404418919fSjohnjiang 		GOTO_FAIL("%s failed: tx offload flag error.\n", __func__);
18414418919fSjohnjiang 	return 0;
18424418919fSjohnjiang fail:
18434418919fSjohnjiang 	return -1;
18444418919fSjohnjiang }
18454418919fSjohnjiang 
18464418919fSjohnjiang /*
18474418919fSjohnjiang  * Test for allocating a bulk of mbufs
18484418919fSjohnjiang  * define an array with positive sizes for mbufs allocations.
18494418919fSjohnjiang  */
18504418919fSjohnjiang static int
test_pktmbuf_alloc_bulk(struct rte_mempool * pktmbuf_pool)18514418919fSjohnjiang test_pktmbuf_alloc_bulk(struct rte_mempool *pktmbuf_pool)
18524418919fSjohnjiang {
18534418919fSjohnjiang 	int ret = 0;
18544418919fSjohnjiang 	unsigned int idx, loop;
18554418919fSjohnjiang 	unsigned int alloc_counts[] = {
18564418919fSjohnjiang 		0,
18574418919fSjohnjiang 		MEMPOOL_CACHE_SIZE - 1,
18584418919fSjohnjiang 		MEMPOOL_CACHE_SIZE + 1,
18594418919fSjohnjiang 		MEMPOOL_CACHE_SIZE * 1.5,
18604418919fSjohnjiang 		MEMPOOL_CACHE_SIZE * 2,
18614418919fSjohnjiang 		MEMPOOL_CACHE_SIZE * 2 - 1,
18624418919fSjohnjiang 		MEMPOOL_CACHE_SIZE * 2 + 1,
18634418919fSjohnjiang 		MEMPOOL_CACHE_SIZE,
18644418919fSjohnjiang 	};
18654418919fSjohnjiang 
18664418919fSjohnjiang 	/* allocate a large array of mbuf pointers */
18674418919fSjohnjiang 	struct rte_mbuf *mbufs[NB_MBUF] = { 0 };
18684418919fSjohnjiang 	for (idx = 0; idx < RTE_DIM(alloc_counts); idx++) {
18694418919fSjohnjiang 		ret = rte_pktmbuf_alloc_bulk(pktmbuf_pool, mbufs,
18704418919fSjohnjiang 				alloc_counts[idx]);
18714418919fSjohnjiang 		if (ret == 0) {
18724418919fSjohnjiang 			for (loop = 0; loop < alloc_counts[idx] &&
18734418919fSjohnjiang 					mbufs[loop] != NULL; loop++)
18744418919fSjohnjiang 				rte_pktmbuf_free(mbufs[loop]);
18754418919fSjohnjiang 		} else if (ret != 0) {
18764418919fSjohnjiang 			printf("%s: Bulk alloc failed count(%u); ret val(%d)\n",
18774418919fSjohnjiang 					__func__, alloc_counts[idx], ret);
18784418919fSjohnjiang 			return -1;
18794418919fSjohnjiang 		}
18804418919fSjohnjiang 	}
18814418919fSjohnjiang 	return 0;
18824418919fSjohnjiang }
18834418919fSjohnjiang 
18844418919fSjohnjiang /*
18854418919fSjohnjiang  * Negative testing for allocating a bulk of mbufs
18864418919fSjohnjiang  */
18874418919fSjohnjiang static int
test_neg_pktmbuf_alloc_bulk(struct rte_mempool * pktmbuf_pool)18884418919fSjohnjiang test_neg_pktmbuf_alloc_bulk(struct rte_mempool *pktmbuf_pool)
18894418919fSjohnjiang {
18904418919fSjohnjiang 	int ret = 0;
18914418919fSjohnjiang 	unsigned int idx, loop;
18924418919fSjohnjiang 	unsigned int neg_alloc_counts[] = {
18934418919fSjohnjiang 		MEMPOOL_CACHE_SIZE - NB_MBUF,
18944418919fSjohnjiang 		NB_MBUF + 1,
18954418919fSjohnjiang 		NB_MBUF * 8,
18964418919fSjohnjiang 		UINT_MAX
18974418919fSjohnjiang 	};
18984418919fSjohnjiang 	struct rte_mbuf *mbufs[NB_MBUF * 8] = { 0 };
18994418919fSjohnjiang 
19004418919fSjohnjiang 	for (idx = 0; idx < RTE_DIM(neg_alloc_counts); idx++) {
19014418919fSjohnjiang 		ret = rte_pktmbuf_alloc_bulk(pktmbuf_pool, mbufs,
19024418919fSjohnjiang 				neg_alloc_counts[idx]);
19034418919fSjohnjiang 		if (ret == 0) {
19044418919fSjohnjiang 			printf("%s: Bulk alloc must fail! count(%u); ret(%d)\n",
19054418919fSjohnjiang 					__func__, neg_alloc_counts[idx], ret);
19064418919fSjohnjiang 			for (loop = 0; loop < neg_alloc_counts[idx] &&
19074418919fSjohnjiang 					mbufs[loop] != NULL; loop++)
19084418919fSjohnjiang 				rte_pktmbuf_free(mbufs[loop]);
19094418919fSjohnjiang 			return -1;
19104418919fSjohnjiang 		}
19114418919fSjohnjiang 	}
19124418919fSjohnjiang 	return 0;
19134418919fSjohnjiang }
19144418919fSjohnjiang 
19154418919fSjohnjiang /*
19164418919fSjohnjiang  * Test to read mbuf packet using rte_pktmbuf_read
19174418919fSjohnjiang  */
19184418919fSjohnjiang static int
test_pktmbuf_read(struct rte_mempool * pktmbuf_pool)19194418919fSjohnjiang test_pktmbuf_read(struct rte_mempool *pktmbuf_pool)
19204418919fSjohnjiang {
19214418919fSjohnjiang 	struct rte_mbuf *m = NULL;
19224418919fSjohnjiang 	char *data = NULL;
19234418919fSjohnjiang 	const char *data_copy = NULL;
19244418919fSjohnjiang 	int off;
19254418919fSjohnjiang 
19264418919fSjohnjiang 	/* alloc a mbuf */
19274418919fSjohnjiang 	m = rte_pktmbuf_alloc(pktmbuf_pool);
19284418919fSjohnjiang 	if (m == NULL)
19294418919fSjohnjiang 		GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
19304418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(m) != 0)
19314418919fSjohnjiang 		GOTO_FAIL("%s: Bad packet length\n", __func__);
19324418919fSjohnjiang 	rte_mbuf_sanity_check(m, 0);
19334418919fSjohnjiang 
19344418919fSjohnjiang 	data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN2);
19354418919fSjohnjiang 	if (data == NULL)
19364418919fSjohnjiang 		GOTO_FAIL("%s: Cannot append data\n", __func__);
19374418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN2)
19384418919fSjohnjiang 		GOTO_FAIL("%s: Bad packet length\n", __func__);
19394418919fSjohnjiang 	memset(data, 0xfe, MBUF_TEST_DATA_LEN2);
19404418919fSjohnjiang 
19414418919fSjohnjiang 	/* read the data from mbuf */
19424418919fSjohnjiang 	data_copy = rte_pktmbuf_read(m, 0, MBUF_TEST_DATA_LEN2, NULL);
19434418919fSjohnjiang 	if (data_copy == NULL)
19444418919fSjohnjiang 		GOTO_FAIL("%s: Error in reading data!\n", __func__);
19454418919fSjohnjiang 	for (off = 0; off < MBUF_TEST_DATA_LEN2; off++) {
19464418919fSjohnjiang 		if (data_copy[off] != (char)0xfe)
19474418919fSjohnjiang 			GOTO_FAIL("Data corrupted at offset %u", off);
19484418919fSjohnjiang 	}
19494418919fSjohnjiang 	rte_pktmbuf_free(m);
19504418919fSjohnjiang 	m = NULL;
19514418919fSjohnjiang 
19524418919fSjohnjiang 	return 0;
19534418919fSjohnjiang fail:
19544418919fSjohnjiang 	if (m) {
19554418919fSjohnjiang 		rte_pktmbuf_free(m);
19564418919fSjohnjiang 		m = NULL;
19574418919fSjohnjiang 	}
19584418919fSjohnjiang 	return -1;
19594418919fSjohnjiang }
19604418919fSjohnjiang 
19614418919fSjohnjiang /*
19624418919fSjohnjiang  * Test to read mbuf packet data from offset
19634418919fSjohnjiang  */
19644418919fSjohnjiang static int
test_pktmbuf_read_from_offset(struct rte_mempool * pktmbuf_pool)19654418919fSjohnjiang test_pktmbuf_read_from_offset(struct rte_mempool *pktmbuf_pool)
19664418919fSjohnjiang {
19674418919fSjohnjiang 	struct rte_mbuf *m = NULL;
19684418919fSjohnjiang 	struct ether_hdr *hdr = NULL;
19694418919fSjohnjiang 	char *data = NULL;
19704418919fSjohnjiang 	const char *data_copy = NULL;
19714418919fSjohnjiang 	unsigned int off;
19724418919fSjohnjiang 	unsigned int hdr_len = sizeof(struct rte_ether_hdr);
19734418919fSjohnjiang 
19744418919fSjohnjiang 	/* alloc a mbuf */
19754418919fSjohnjiang 	m = rte_pktmbuf_alloc(pktmbuf_pool);
19764418919fSjohnjiang 	if (m == NULL)
19774418919fSjohnjiang 		GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
19784418919fSjohnjiang 
19794418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(m) != 0)
19804418919fSjohnjiang 		GOTO_FAIL("%s: Bad packet length\n", __func__);
19814418919fSjohnjiang 	rte_mbuf_sanity_check(m, 0);
19824418919fSjohnjiang 
19834418919fSjohnjiang 	/* prepend an ethernet header */
19844418919fSjohnjiang 	hdr = (struct ether_hdr *)rte_pktmbuf_prepend(m, hdr_len);
19854418919fSjohnjiang 	if (hdr == NULL)
19864418919fSjohnjiang 		GOTO_FAIL("%s: Cannot prepend header\n", __func__);
19874418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(m) != hdr_len)
19884418919fSjohnjiang 		GOTO_FAIL("%s: Bad pkt length", __func__);
19894418919fSjohnjiang 	if (rte_pktmbuf_data_len(m) != hdr_len)
19904418919fSjohnjiang 		GOTO_FAIL("%s: Bad data length", __func__);
19914418919fSjohnjiang 	memset(hdr, 0xde, hdr_len);
19924418919fSjohnjiang 
19934418919fSjohnjiang 	/* read mbuf header info from 0 offset */
19944418919fSjohnjiang 	data_copy = rte_pktmbuf_read(m, 0, hdr_len, NULL);
19954418919fSjohnjiang 	if (data_copy == NULL)
19964418919fSjohnjiang 		GOTO_FAIL("%s: Error in reading header!\n", __func__);
19974418919fSjohnjiang 	for (off = 0; off < hdr_len; off++) {
19984418919fSjohnjiang 		if (data_copy[off] != (char)0xde)
19994418919fSjohnjiang 			GOTO_FAIL("Header info corrupted at offset %u", off);
20004418919fSjohnjiang 	}
20014418919fSjohnjiang 
20024418919fSjohnjiang 	/* append sample data after ethernet header */
20034418919fSjohnjiang 	data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN2);
20044418919fSjohnjiang 	if (data == NULL)
20054418919fSjohnjiang 		GOTO_FAIL("%s: Cannot append data\n", __func__);
20064418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(m) != hdr_len + MBUF_TEST_DATA_LEN2)
20074418919fSjohnjiang 		GOTO_FAIL("%s: Bad packet length\n", __func__);
20084418919fSjohnjiang 	if (rte_pktmbuf_data_len(m) != hdr_len + MBUF_TEST_DATA_LEN2)
20094418919fSjohnjiang 		GOTO_FAIL("%s: Bad data length\n", __func__);
20104418919fSjohnjiang 	memset(data, 0xcc, MBUF_TEST_DATA_LEN2);
20114418919fSjohnjiang 
20124418919fSjohnjiang 	/* read mbuf data after header info */
20134418919fSjohnjiang 	data_copy = rte_pktmbuf_read(m, hdr_len, MBUF_TEST_DATA_LEN2, NULL);
20144418919fSjohnjiang 	if (data_copy == NULL)
20154418919fSjohnjiang 		GOTO_FAIL("%s: Error in reading header data!\n", __func__);
20164418919fSjohnjiang 	for (off = 0; off < MBUF_TEST_DATA_LEN2; off++) {
20174418919fSjohnjiang 		if (data_copy[off] != (char)0xcc)
20184418919fSjohnjiang 			GOTO_FAIL("Data corrupted at offset %u", off);
20194418919fSjohnjiang 	}
20204418919fSjohnjiang 
20214418919fSjohnjiang 	/* partial reading of mbuf data */
20224418919fSjohnjiang 	data_copy = rte_pktmbuf_read(m, hdr_len + 5, MBUF_TEST_DATA_LEN2 - 5,
20234418919fSjohnjiang 			NULL);
20244418919fSjohnjiang 	if (data_copy == NULL)
20254418919fSjohnjiang 		GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
20264418919fSjohnjiang 	if (strlen(data_copy) != MBUF_TEST_DATA_LEN2 - 5)
20274418919fSjohnjiang 		GOTO_FAIL("%s: Incorrect data length!\n", __func__);
20284418919fSjohnjiang 	for (off = 0; off < MBUF_TEST_DATA_LEN2 - 5; off++) {
20294418919fSjohnjiang 		if (data_copy[off] != (char)0xcc)
20304418919fSjohnjiang 			GOTO_FAIL("Data corrupted at offset %u", off);
20314418919fSjohnjiang 	}
20324418919fSjohnjiang 
20334418919fSjohnjiang 	/* read length greater than mbuf data_len */
20344418919fSjohnjiang 	if (rte_pktmbuf_read(m, hdr_len, rte_pktmbuf_data_len(m) + 1,
20354418919fSjohnjiang 				NULL) != NULL)
20364418919fSjohnjiang 		GOTO_FAIL("%s: Requested len is larger than mbuf data len!\n",
20374418919fSjohnjiang 				__func__);
20384418919fSjohnjiang 
20394418919fSjohnjiang 	/* read length greater than mbuf pkt_len */
20404418919fSjohnjiang 	if (rte_pktmbuf_read(m, hdr_len, rte_pktmbuf_pkt_len(m) + 1,
20414418919fSjohnjiang 				NULL) != NULL)
20424418919fSjohnjiang 		GOTO_FAIL("%s: Requested len is larger than mbuf pkt len!\n",
20434418919fSjohnjiang 				__func__);
20444418919fSjohnjiang 
20454418919fSjohnjiang 	/* read data of zero len from valid offset */
20464418919fSjohnjiang 	data_copy = rte_pktmbuf_read(m, hdr_len, 0, NULL);
20474418919fSjohnjiang 	if (data_copy == NULL)
20484418919fSjohnjiang 		GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
20494418919fSjohnjiang 	if (strlen(data_copy) != MBUF_TEST_DATA_LEN2)
20504418919fSjohnjiang 		GOTO_FAIL("%s: Corrupted data content!\n", __func__);
20514418919fSjohnjiang 	for (off = 0; off < MBUF_TEST_DATA_LEN2; off++) {
20524418919fSjohnjiang 		if (data_copy[off] != (char)0xcc)
20534418919fSjohnjiang 			GOTO_FAIL("Data corrupted at offset %u", off);
20544418919fSjohnjiang 	}
20554418919fSjohnjiang 
20564418919fSjohnjiang 	/* read data of zero length from zero offset */
20574418919fSjohnjiang 	data_copy = rte_pktmbuf_read(m, 0, 0, NULL);
20584418919fSjohnjiang 	if (data_copy == NULL)
20594418919fSjohnjiang 		GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
20604418919fSjohnjiang 	/* check if the received address is the beginning of header info */
20614418919fSjohnjiang 	if (hdr != (const struct ether_hdr *)data_copy)
20624418919fSjohnjiang 		GOTO_FAIL("%s: Corrupted data address!\n", __func__);
20634418919fSjohnjiang 
20644418919fSjohnjiang 	/* read data of max length from valid offset */
20654418919fSjohnjiang 	data_copy = rte_pktmbuf_read(m, hdr_len, UINT_MAX, NULL);
20664418919fSjohnjiang 	if (data_copy == NULL)
20674418919fSjohnjiang 		GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
20684418919fSjohnjiang 	/* check if the received address is the beginning of data segment */
20694418919fSjohnjiang 	if (data_copy != data)
20704418919fSjohnjiang 		GOTO_FAIL("%s: Corrupted data address!\n", __func__);
20714418919fSjohnjiang 
20724418919fSjohnjiang 	/* try to read from mbuf with max size offset */
20734418919fSjohnjiang 	data_copy = rte_pktmbuf_read(m, UINT_MAX, 0, NULL);
20744418919fSjohnjiang 	if (data_copy != NULL)
20754418919fSjohnjiang 		GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
20764418919fSjohnjiang 
20774418919fSjohnjiang 	/* try to read from mbuf with max size offset and len */
20784418919fSjohnjiang 	data_copy = rte_pktmbuf_read(m, UINT_MAX, UINT_MAX, NULL);
20794418919fSjohnjiang 	if (data_copy != NULL)
20804418919fSjohnjiang 		GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
20814418919fSjohnjiang 
20824418919fSjohnjiang 	rte_pktmbuf_dump(stdout, m, rte_pktmbuf_pkt_len(m));
20834418919fSjohnjiang 
20844418919fSjohnjiang 	rte_pktmbuf_free(m);
20854418919fSjohnjiang 	m = NULL;
20864418919fSjohnjiang 
20874418919fSjohnjiang 	return 0;
20884418919fSjohnjiang fail:
20894418919fSjohnjiang 	if (m) {
20904418919fSjohnjiang 		rte_pktmbuf_free(m);
20914418919fSjohnjiang 		m = NULL;
20924418919fSjohnjiang 	}
20934418919fSjohnjiang 	return -1;
20944418919fSjohnjiang }
20954418919fSjohnjiang 
20964418919fSjohnjiang struct test_case {
20974418919fSjohnjiang 	unsigned int seg_count;
20984418919fSjohnjiang 	unsigned int flags;
20994418919fSjohnjiang 	uint32_t read_off;
21004418919fSjohnjiang 	uint32_t read_len;
21014418919fSjohnjiang 	unsigned int seg_lengths[MBUF_MAX_SEG];
21024418919fSjohnjiang };
21034418919fSjohnjiang 
21044418919fSjohnjiang /* create a mbuf with different sized segments
21054418919fSjohnjiang  *  and fill with data [0x00 0x01 0x02 ...]
21064418919fSjohnjiang  */
21074418919fSjohnjiang static struct rte_mbuf *
create_packet(struct rte_mempool * pktmbuf_pool,struct test_case * test_data)21084418919fSjohnjiang create_packet(struct rte_mempool *pktmbuf_pool,
21094418919fSjohnjiang 		struct test_case *test_data)
21104418919fSjohnjiang {
21114418919fSjohnjiang 	uint16_t i, ret, seg, seg_len = 0;
21124418919fSjohnjiang 	uint32_t last_index = 0;
21134418919fSjohnjiang 	unsigned int seg_lengths[MBUF_MAX_SEG];
21144418919fSjohnjiang 	unsigned int hdr_len;
21154418919fSjohnjiang 	struct rte_mbuf *pkt = NULL;
21164418919fSjohnjiang 	struct rte_mbuf	*pkt_seg = NULL;
21174418919fSjohnjiang 	char *hdr = NULL;
21184418919fSjohnjiang 	char *data = NULL;
21194418919fSjohnjiang 
21204418919fSjohnjiang 	memcpy(seg_lengths, test_data->seg_lengths,
21214418919fSjohnjiang 			sizeof(unsigned int)*test_data->seg_count);
21224418919fSjohnjiang 	for (seg = 0; seg < test_data->seg_count; seg++) {
21234418919fSjohnjiang 		hdr_len = 0;
21244418919fSjohnjiang 		seg_len =  seg_lengths[seg];
21254418919fSjohnjiang 		pkt_seg = rte_pktmbuf_alloc(pktmbuf_pool);
21264418919fSjohnjiang 		if (pkt_seg == NULL)
21274418919fSjohnjiang 			GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
21284418919fSjohnjiang 		if (rte_pktmbuf_pkt_len(pkt_seg) != 0)
21294418919fSjohnjiang 			GOTO_FAIL("%s: Bad packet length\n", __func__);
21304418919fSjohnjiang 		rte_mbuf_sanity_check(pkt_seg, 0);
21314418919fSjohnjiang 		/* Add header only for the first segment */
21324418919fSjohnjiang 		if (test_data->flags == MBUF_HEADER && seg == 0) {
21334418919fSjohnjiang 			hdr_len = sizeof(struct rte_ether_hdr);
21344418919fSjohnjiang 			/* prepend a header and fill with dummy data */
21354418919fSjohnjiang 			hdr = (char *)rte_pktmbuf_prepend(pkt_seg, hdr_len);
21364418919fSjohnjiang 			if (hdr == NULL)
21374418919fSjohnjiang 				GOTO_FAIL("%s: Cannot prepend header\n",
21384418919fSjohnjiang 						__func__);
21394418919fSjohnjiang 			if (rte_pktmbuf_pkt_len(pkt_seg) != hdr_len)
21404418919fSjohnjiang 				GOTO_FAIL("%s: Bad pkt length", __func__);
21414418919fSjohnjiang 			if (rte_pktmbuf_data_len(pkt_seg) != hdr_len)
21424418919fSjohnjiang 				GOTO_FAIL("%s: Bad data length", __func__);
21434418919fSjohnjiang 			for (i = 0; i < hdr_len; i++)
21444418919fSjohnjiang 				hdr[i] = (last_index + i) % 0xffff;
21454418919fSjohnjiang 			last_index += hdr_len;
21464418919fSjohnjiang 		}
21474418919fSjohnjiang 		/* skip appending segment with 0 length */
21484418919fSjohnjiang 		if (seg_len == 0)
21494418919fSjohnjiang 			continue;
21504418919fSjohnjiang 		data = rte_pktmbuf_append(pkt_seg, seg_len);
21514418919fSjohnjiang 		if (data == NULL)
21524418919fSjohnjiang 			GOTO_FAIL("%s: Cannot append data segment\n", __func__);
21534418919fSjohnjiang 		if (rte_pktmbuf_pkt_len(pkt_seg) != hdr_len + seg_len)
21544418919fSjohnjiang 			GOTO_FAIL("%s: Bad packet segment length: %d\n",
21554418919fSjohnjiang 					__func__, rte_pktmbuf_pkt_len(pkt_seg));
21564418919fSjohnjiang 		if (rte_pktmbuf_data_len(pkt_seg) != hdr_len + seg_len)
21574418919fSjohnjiang 			GOTO_FAIL("%s: Bad data length\n", __func__);
21584418919fSjohnjiang 		for (i = 0; i < seg_len; i++)
21594418919fSjohnjiang 			data[i] = (last_index + i) % 0xffff;
21604418919fSjohnjiang 		/* to fill continuous data from one seg to another */
21614418919fSjohnjiang 		last_index += i;
21624418919fSjohnjiang 		/* create chained mbufs */
21634418919fSjohnjiang 		if (seg == 0)
21644418919fSjohnjiang 			pkt = pkt_seg;
21654418919fSjohnjiang 		else {
21664418919fSjohnjiang 			ret = rte_pktmbuf_chain(pkt, pkt_seg);
21674418919fSjohnjiang 			if (ret != 0)
21684418919fSjohnjiang 				GOTO_FAIL("%s:FAIL: Chained mbuf creation %d\n",
21694418919fSjohnjiang 						__func__, ret);
21704418919fSjohnjiang 		}
21714418919fSjohnjiang 
21724418919fSjohnjiang 		pkt_seg = pkt_seg->next;
21734418919fSjohnjiang 	}
21744418919fSjohnjiang 	return pkt;
21754418919fSjohnjiang fail:
21764418919fSjohnjiang 	if (pkt != NULL) {
21774418919fSjohnjiang 		rte_pktmbuf_free(pkt);
21784418919fSjohnjiang 		pkt = NULL;
21794418919fSjohnjiang 	}
21804418919fSjohnjiang 	if (pkt_seg != NULL) {
21814418919fSjohnjiang 		rte_pktmbuf_free(pkt_seg);
21824418919fSjohnjiang 		pkt_seg = NULL;
21834418919fSjohnjiang 	}
21844418919fSjohnjiang 	return NULL;
21854418919fSjohnjiang }
21864418919fSjohnjiang 
21874418919fSjohnjiang static int
test_pktmbuf_read_from_chain(struct rte_mempool * pktmbuf_pool)21884418919fSjohnjiang test_pktmbuf_read_from_chain(struct rte_mempool *pktmbuf_pool)
21894418919fSjohnjiang {
21904418919fSjohnjiang 	struct rte_mbuf *m;
21914418919fSjohnjiang 	struct test_case test_cases[] = {
21924418919fSjohnjiang 		{
21934418919fSjohnjiang 			.seg_lengths = { 100, 100, 100 },
21944418919fSjohnjiang 			.seg_count = 3,
21954418919fSjohnjiang 			.flags = MBUF_NO_HEADER,
21964418919fSjohnjiang 			.read_off = 0,
21974418919fSjohnjiang 			.read_len = 300
21984418919fSjohnjiang 		},
21994418919fSjohnjiang 		{
22004418919fSjohnjiang 			.seg_lengths = { 100, 125, 150 },
22014418919fSjohnjiang 			.seg_count = 3,
22024418919fSjohnjiang 			.flags = MBUF_NO_HEADER,
22034418919fSjohnjiang 			.read_off = 99,
22044418919fSjohnjiang 			.read_len = 201
22054418919fSjohnjiang 		},
22064418919fSjohnjiang 		{
22074418919fSjohnjiang 			.seg_lengths = { 100, 100 },
22084418919fSjohnjiang 			.seg_count = 2,
22094418919fSjohnjiang 			.flags = MBUF_NO_HEADER,
22104418919fSjohnjiang 			.read_off = 0,
22114418919fSjohnjiang 			.read_len = 100
22124418919fSjohnjiang 		},
22134418919fSjohnjiang 		{
22144418919fSjohnjiang 			.seg_lengths = { 100, 200 },
22154418919fSjohnjiang 			.seg_count = 2,
22164418919fSjohnjiang 			.flags = MBUF_HEADER,
22174418919fSjohnjiang 			.read_off = sizeof(struct rte_ether_hdr),
22184418919fSjohnjiang 			.read_len = 150
22194418919fSjohnjiang 		},
22204418919fSjohnjiang 		{
22214418919fSjohnjiang 			.seg_lengths = { 1000, 100 },
22224418919fSjohnjiang 			.seg_count = 2,
22234418919fSjohnjiang 			.flags = MBUF_NO_HEADER,
22244418919fSjohnjiang 			.read_off = 0,
22254418919fSjohnjiang 			.read_len = 1000
22264418919fSjohnjiang 		},
22274418919fSjohnjiang 		{
22284418919fSjohnjiang 			.seg_lengths = { 1024, 0, 100 },
22294418919fSjohnjiang 			.seg_count = 3,
22304418919fSjohnjiang 			.flags = MBUF_NO_HEADER,
22314418919fSjohnjiang 			.read_off = 100,
22324418919fSjohnjiang 			.read_len = 1001
22334418919fSjohnjiang 		},
22344418919fSjohnjiang 		{
22354418919fSjohnjiang 			.seg_lengths = { 1000, 1, 1000 },
22364418919fSjohnjiang 			.seg_count = 3,
22374418919fSjohnjiang 			.flags = MBUF_NO_HEADER,
22384418919fSjohnjiang 			.read_off = 1000,
22394418919fSjohnjiang 			.read_len = 2
22404418919fSjohnjiang 		},
22414418919fSjohnjiang 		{
22424418919fSjohnjiang 			.seg_lengths = { MBUF_TEST_DATA_LEN,
22434418919fSjohnjiang 					MBUF_TEST_DATA_LEN2,
22444418919fSjohnjiang 					MBUF_TEST_DATA_LEN3, 800, 10 },
22454418919fSjohnjiang 			.seg_count = 5,
22464418919fSjohnjiang 			.flags = MBUF_NEG_TEST_READ,
22474418919fSjohnjiang 			.read_off = 1000,
22484418919fSjohnjiang 			.read_len = MBUF_DATA_SIZE
22494418919fSjohnjiang 		},
22504418919fSjohnjiang 	};
22514418919fSjohnjiang 
22524418919fSjohnjiang 	uint32_t i, pos;
22534418919fSjohnjiang 	const char *data_copy = NULL;
22544418919fSjohnjiang 	char data_buf[MBUF_DATA_SIZE];
22554418919fSjohnjiang 
22564418919fSjohnjiang 	memset(data_buf, 0, MBUF_DATA_SIZE);
22574418919fSjohnjiang 
22584418919fSjohnjiang 	for (i = 0; i < RTE_DIM(test_cases); i++) {
22594418919fSjohnjiang 		m = create_packet(pktmbuf_pool, &test_cases[i]);
22604418919fSjohnjiang 		if (m == NULL)
22614418919fSjohnjiang 			GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
22624418919fSjohnjiang 
22634418919fSjohnjiang 		data_copy = rte_pktmbuf_read(m, test_cases[i].read_off,
22644418919fSjohnjiang 				test_cases[i].read_len, data_buf);
22654418919fSjohnjiang 		if (test_cases[i].flags == MBUF_NEG_TEST_READ) {
22664418919fSjohnjiang 			if (data_copy != NULL)
22674418919fSjohnjiang 				GOTO_FAIL("%s: mbuf data read should fail!\n",
22684418919fSjohnjiang 						__func__);
22694418919fSjohnjiang 			else {
22704418919fSjohnjiang 				rte_pktmbuf_free(m);
22714418919fSjohnjiang 				m = NULL;
22724418919fSjohnjiang 				continue;
22734418919fSjohnjiang 			}
22744418919fSjohnjiang 		}
22754418919fSjohnjiang 		if (data_copy == NULL)
22764418919fSjohnjiang 			GOTO_FAIL("%s: Error in reading packet data!\n",
22774418919fSjohnjiang 					__func__);
22784418919fSjohnjiang 		for (pos = 0; pos < test_cases[i].read_len; pos++) {
22794418919fSjohnjiang 			if (data_copy[pos] !=
22804418919fSjohnjiang 					(char)((test_cases[i].read_off + pos)
22814418919fSjohnjiang 						% 0xffff))
22824418919fSjohnjiang 				GOTO_FAIL("Data corrupted at offset %u is %2X",
22834418919fSjohnjiang 						pos, data_copy[pos]);
22844418919fSjohnjiang 		}
22854418919fSjohnjiang 		rte_pktmbuf_dump(stdout, m, rte_pktmbuf_pkt_len(m));
22864418919fSjohnjiang 		rte_pktmbuf_free(m);
22874418919fSjohnjiang 		m = NULL;
22884418919fSjohnjiang 	}
22894418919fSjohnjiang 	return 0;
22904418919fSjohnjiang 
22914418919fSjohnjiang fail:
22924418919fSjohnjiang 	if (m != NULL) {
22934418919fSjohnjiang 		rte_pktmbuf_free(m);
22944418919fSjohnjiang 		m = NULL;
22954418919fSjohnjiang 	}
22964418919fSjohnjiang 	return -1;
22974418919fSjohnjiang }
22984418919fSjohnjiang 
22994418919fSjohnjiang /* Define a free call back function to be used for external buffer */
23004418919fSjohnjiang static void
ext_buf_free_callback_fn(void * addr __rte_unused,void * opaque)23014418919fSjohnjiang ext_buf_free_callback_fn(void *addr __rte_unused, void *opaque)
23024418919fSjohnjiang {
23034418919fSjohnjiang 	void *ext_buf_addr = opaque;
23044418919fSjohnjiang 
23054418919fSjohnjiang 	if (ext_buf_addr == NULL) {
23064418919fSjohnjiang 		printf("External buffer address is invalid\n");
23074418919fSjohnjiang 		return;
23084418919fSjohnjiang 	}
23094418919fSjohnjiang 	rte_free(ext_buf_addr);
23104418919fSjohnjiang 	ext_buf_addr = NULL;
23114418919fSjohnjiang 	printf("External buffer freed via callback\n");
23124418919fSjohnjiang }
23134418919fSjohnjiang 
23144418919fSjohnjiang /*
23154418919fSjohnjiang  * Test to initialize shared data in external buffer before attaching to mbuf
23164418919fSjohnjiang  *  - Allocate mbuf with no data.
23174418919fSjohnjiang  *  - Allocate external buffer with size should be large enough to accommodate
23184418919fSjohnjiang  *     rte_mbuf_ext_shared_info.
23194418919fSjohnjiang  *  - Invoke pktmbuf_ext_shinfo_init_helper to initialize shared data.
23204418919fSjohnjiang  *  - Invoke rte_pktmbuf_attach_extbuf to attach external buffer to the mbuf.
23214418919fSjohnjiang  *  - Clone another mbuf and attach the same external buffer to it.
23224418919fSjohnjiang  *  - Invoke rte_pktmbuf_detach_extbuf to detach the external buffer from mbuf.
23234418919fSjohnjiang  */
23244418919fSjohnjiang static int
test_pktmbuf_ext_shinfo_init_helper(struct rte_mempool * pktmbuf_pool)23254418919fSjohnjiang test_pktmbuf_ext_shinfo_init_helper(struct rte_mempool *pktmbuf_pool)
23264418919fSjohnjiang {
23274418919fSjohnjiang 	struct rte_mbuf *m = NULL;
23284418919fSjohnjiang 	struct rte_mbuf *clone = NULL;
23294418919fSjohnjiang 	struct rte_mbuf_ext_shared_info *ret_shinfo = NULL;
23304418919fSjohnjiang 	rte_iova_t buf_iova;
23314418919fSjohnjiang 	void *ext_buf_addr = NULL;
23324418919fSjohnjiang 	uint16_t buf_len = EXT_BUF_TEST_DATA_LEN +
23334418919fSjohnjiang 				sizeof(struct rte_mbuf_ext_shared_info);
23344418919fSjohnjiang 
23354418919fSjohnjiang 	/* alloc a mbuf */
23364418919fSjohnjiang 	m = rte_pktmbuf_alloc(pktmbuf_pool);
23374418919fSjohnjiang 	if (m == NULL)
23384418919fSjohnjiang 		GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
23394418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(m) != 0)
23404418919fSjohnjiang 		GOTO_FAIL("%s: Bad packet length\n", __func__);
23414418919fSjohnjiang 	rte_mbuf_sanity_check(m, 0);
23424418919fSjohnjiang 
23434418919fSjohnjiang 	ext_buf_addr = rte_malloc("External buffer", buf_len,
23444418919fSjohnjiang 			RTE_CACHE_LINE_SIZE);
23454418919fSjohnjiang 	if (ext_buf_addr == NULL)
23464418919fSjohnjiang 		GOTO_FAIL("%s: External buffer allocation failed\n", __func__);
23474418919fSjohnjiang 
23484418919fSjohnjiang 	ret_shinfo = rte_pktmbuf_ext_shinfo_init_helper(ext_buf_addr, &buf_len,
23494418919fSjohnjiang 		ext_buf_free_callback_fn, ext_buf_addr);
23504418919fSjohnjiang 	if (ret_shinfo == NULL)
23514418919fSjohnjiang 		GOTO_FAIL("%s: Shared info initialization failed!\n", __func__);
23524418919fSjohnjiang 
23534418919fSjohnjiang 	if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 1)
23544418919fSjohnjiang 		GOTO_FAIL("%s: External refcount is not 1\n", __func__);
23554418919fSjohnjiang 
23564418919fSjohnjiang 	if (rte_mbuf_refcnt_read(m) != 1)
23574418919fSjohnjiang 		GOTO_FAIL("%s: Invalid refcnt in mbuf\n", __func__);
23584418919fSjohnjiang 
23594418919fSjohnjiang 	buf_iova = rte_mempool_virt2iova(ext_buf_addr);
23604418919fSjohnjiang 	rte_pktmbuf_attach_extbuf(m, ext_buf_addr, buf_iova, buf_len,
23614418919fSjohnjiang 		ret_shinfo);
23624418919fSjohnjiang 	if (m->ol_flags != EXT_ATTACHED_MBUF)
23634418919fSjohnjiang 		GOTO_FAIL("%s: External buffer is not attached to mbuf\n",
23644418919fSjohnjiang 				__func__);
23654418919fSjohnjiang 
23664418919fSjohnjiang 	/* allocate one more mbuf */
23674418919fSjohnjiang 	clone = rte_pktmbuf_clone(m, pktmbuf_pool);
23684418919fSjohnjiang 	if (clone == NULL)
23694418919fSjohnjiang 		GOTO_FAIL("%s: mbuf clone allocation failed!\n", __func__);
23704418919fSjohnjiang 	if (rte_pktmbuf_pkt_len(clone) != 0)
23714418919fSjohnjiang 		GOTO_FAIL("%s: Bad packet length\n", __func__);
23724418919fSjohnjiang 
23734418919fSjohnjiang 	/* attach the same external buffer to the cloned mbuf */
23744418919fSjohnjiang 	rte_pktmbuf_attach_extbuf(clone, ext_buf_addr, buf_iova, buf_len,
23754418919fSjohnjiang 			ret_shinfo);
23764418919fSjohnjiang 	if (clone->ol_flags != EXT_ATTACHED_MBUF)
23774418919fSjohnjiang 		GOTO_FAIL("%s: External buffer is not attached to mbuf\n",
23784418919fSjohnjiang 				__func__);
23794418919fSjohnjiang 
23804418919fSjohnjiang 	if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 2)
23814418919fSjohnjiang 		GOTO_FAIL("%s: Invalid ext_buf ref_cnt\n", __func__);
23824418919fSjohnjiang 
23834418919fSjohnjiang 	/* test to manually update ext_buf_ref_cnt from 2 to 3*/
23844418919fSjohnjiang 	rte_mbuf_ext_refcnt_update(ret_shinfo, 1);
23854418919fSjohnjiang 	if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 3)
23864418919fSjohnjiang 		GOTO_FAIL("%s: Update ext_buf ref_cnt failed\n", __func__);
23874418919fSjohnjiang 
23884418919fSjohnjiang 	/* reset the ext_refcnt before freeing the external buffer */
23894418919fSjohnjiang 	rte_mbuf_ext_refcnt_set(ret_shinfo, 2);
23904418919fSjohnjiang 	if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 2)
23914418919fSjohnjiang 		GOTO_FAIL("%s: set ext_buf ref_cnt failed\n", __func__);
23924418919fSjohnjiang 
23934418919fSjohnjiang 	/* detach the external buffer from mbufs */
23944418919fSjohnjiang 	rte_pktmbuf_detach_extbuf(m);
23954418919fSjohnjiang 	/* check if ref cnt is decremented */
23964418919fSjohnjiang 	if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 1)
23974418919fSjohnjiang 		GOTO_FAIL("%s: Invalid ext_buf ref_cnt\n", __func__);
23984418919fSjohnjiang 
23994418919fSjohnjiang 	rte_pktmbuf_detach_extbuf(clone);
24004418919fSjohnjiang 	if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 0)
24014418919fSjohnjiang 		GOTO_FAIL("%s: Invalid ext_buf ref_cnt\n", __func__);
24024418919fSjohnjiang 
24034418919fSjohnjiang 	rte_pktmbuf_free(m);
24044418919fSjohnjiang 	m = NULL;
24054418919fSjohnjiang 	rte_pktmbuf_free(clone);
24064418919fSjohnjiang 	clone = NULL;
24074418919fSjohnjiang 
24084418919fSjohnjiang 	return 0;
24094418919fSjohnjiang 
24104418919fSjohnjiang fail:
24114418919fSjohnjiang 	if (m) {
24124418919fSjohnjiang 		rte_pktmbuf_free(m);
24134418919fSjohnjiang 		m = NULL;
24144418919fSjohnjiang 	}
24154418919fSjohnjiang 	if (clone) {
24164418919fSjohnjiang 		rte_pktmbuf_free(clone);
24174418919fSjohnjiang 		clone = NULL;
24184418919fSjohnjiang 	}
24194418919fSjohnjiang 	if (ext_buf_addr != NULL) {
24204418919fSjohnjiang 		rte_free(ext_buf_addr);
24214418919fSjohnjiang 		ext_buf_addr = NULL;
24224418919fSjohnjiang 	}
24234418919fSjohnjiang 	return -1;
24244418919fSjohnjiang }
24254418919fSjohnjiang 
2426*2d9fd380Sjfb8856606 /*
2427*2d9fd380Sjfb8856606  * Test the mbuf pool with pinned external data buffers
2428*2d9fd380Sjfb8856606  *  - Allocate memory zone for external buffer
2429*2d9fd380Sjfb8856606  *  - Create the mbuf pool with pinned external buffer
2430*2d9fd380Sjfb8856606  *  - Check the created pool with relevant mbuf pool unit tests
2431*2d9fd380Sjfb8856606  */
2432*2d9fd380Sjfb8856606 static int
test_pktmbuf_ext_pinned_buffer(struct rte_mempool * std_pool)2433*2d9fd380Sjfb8856606 test_pktmbuf_ext_pinned_buffer(struct rte_mempool *std_pool)
2434*2d9fd380Sjfb8856606 {
2435*2d9fd380Sjfb8856606 
2436*2d9fd380Sjfb8856606 	struct rte_pktmbuf_extmem ext_mem;
2437*2d9fd380Sjfb8856606 	struct rte_mempool *pinned_pool = NULL;
2438*2d9fd380Sjfb8856606 	const struct rte_memzone *mz = NULL;
2439*2d9fd380Sjfb8856606 
2440*2d9fd380Sjfb8856606 	printf("Test mbuf pool with external pinned data buffers\n");
2441*2d9fd380Sjfb8856606 
2442*2d9fd380Sjfb8856606 	/* Allocate memzone for the external data buffer */
2443*2d9fd380Sjfb8856606 	mz = rte_memzone_reserve("pinned_pool",
2444*2d9fd380Sjfb8856606 				 NB_MBUF * MBUF_DATA_SIZE,
2445*2d9fd380Sjfb8856606 				 SOCKET_ID_ANY,
2446*2d9fd380Sjfb8856606 				 RTE_MEMZONE_2MB | RTE_MEMZONE_SIZE_HINT_ONLY);
2447*2d9fd380Sjfb8856606 	if (mz == NULL)
2448*2d9fd380Sjfb8856606 		GOTO_FAIL("%s: Memzone allocation failed\n", __func__);
2449*2d9fd380Sjfb8856606 
2450*2d9fd380Sjfb8856606 	/* Create the mbuf pool with pinned external data buffer */
2451*2d9fd380Sjfb8856606 	ext_mem.buf_ptr = mz->addr;
2452*2d9fd380Sjfb8856606 	ext_mem.buf_iova = mz->iova;
2453*2d9fd380Sjfb8856606 	ext_mem.buf_len = mz->len;
2454*2d9fd380Sjfb8856606 	ext_mem.elt_size = MBUF_DATA_SIZE;
2455*2d9fd380Sjfb8856606 
2456*2d9fd380Sjfb8856606 	pinned_pool = rte_pktmbuf_pool_create_extbuf("test_pinned_pool",
2457*2d9fd380Sjfb8856606 				NB_MBUF, MEMPOOL_CACHE_SIZE, 0,
2458*2d9fd380Sjfb8856606 				MBUF_DATA_SIZE,	SOCKET_ID_ANY,
2459*2d9fd380Sjfb8856606 				&ext_mem, 1);
2460*2d9fd380Sjfb8856606 	if (pinned_pool == NULL)
2461*2d9fd380Sjfb8856606 		GOTO_FAIL("%s: Mbuf pool with pinned external"
2462*2d9fd380Sjfb8856606 			  " buffer creation failed\n", __func__);
2463*2d9fd380Sjfb8856606 	/* test multiple mbuf alloc */
2464*2d9fd380Sjfb8856606 	if (test_pktmbuf_pool(pinned_pool) < 0)
2465*2d9fd380Sjfb8856606 		GOTO_FAIL("%s: test_mbuf_pool(pinned) failed\n",
2466*2d9fd380Sjfb8856606 			  __func__);
2467*2d9fd380Sjfb8856606 
2468*2d9fd380Sjfb8856606 	/* do it another time to check that all mbufs were freed */
2469*2d9fd380Sjfb8856606 	if (test_pktmbuf_pool(pinned_pool) < 0)
2470*2d9fd380Sjfb8856606 		GOTO_FAIL("%s: test_mbuf_pool(pinned) failed (2)\n",
2471*2d9fd380Sjfb8856606 			  __func__);
2472*2d9fd380Sjfb8856606 
2473*2d9fd380Sjfb8856606 	/* test that the data pointer on a packet mbuf is set properly */
2474*2d9fd380Sjfb8856606 	if (test_pktmbuf_pool_ptr(pinned_pool) < 0)
2475*2d9fd380Sjfb8856606 		GOTO_FAIL("%s: test_pktmbuf_pool_ptr(pinned) failed\n",
2476*2d9fd380Sjfb8856606 			  __func__);
2477*2d9fd380Sjfb8856606 
2478*2d9fd380Sjfb8856606 	/* test data manipulation in mbuf with non-ascii data */
2479*2d9fd380Sjfb8856606 	if (test_pktmbuf_with_non_ascii_data(pinned_pool) < 0)
2480*2d9fd380Sjfb8856606 		GOTO_FAIL("%s: test_pktmbuf_with_non_ascii_data(pinned)"
2481*2d9fd380Sjfb8856606 			  " failed\n", __func__);
2482*2d9fd380Sjfb8856606 
2483*2d9fd380Sjfb8856606 	/* test free pktmbuf segment one by one */
2484*2d9fd380Sjfb8856606 	if (test_pktmbuf_free_segment(pinned_pool) < 0)
2485*2d9fd380Sjfb8856606 		GOTO_FAIL("%s: test_pktmbuf_free_segment(pinned) failed\n",
2486*2d9fd380Sjfb8856606 			  __func__);
2487*2d9fd380Sjfb8856606 
2488*2d9fd380Sjfb8856606 	if (testclone_testupdate_testdetach(pinned_pool, std_pool) < 0)
2489*2d9fd380Sjfb8856606 		GOTO_FAIL("%s: testclone_and_testupdate(pinned) failed\n",
2490*2d9fd380Sjfb8856606 			  __func__);
2491*2d9fd380Sjfb8856606 
2492*2d9fd380Sjfb8856606 	if (test_pktmbuf_copy(pinned_pool, std_pool) < 0)
2493*2d9fd380Sjfb8856606 		GOTO_FAIL("%s: test_pktmbuf_copy(pinned) failed\n",
2494*2d9fd380Sjfb8856606 			  __func__);
2495*2d9fd380Sjfb8856606 
2496*2d9fd380Sjfb8856606 	if (test_failing_mbuf_sanity_check(pinned_pool) < 0)
2497*2d9fd380Sjfb8856606 		GOTO_FAIL("%s: test_failing_mbuf_sanity_check(pinned)"
2498*2d9fd380Sjfb8856606 			  " failed\n", __func__);
2499*2d9fd380Sjfb8856606 
2500*2d9fd380Sjfb8856606 	if (test_mbuf_linearize_check(pinned_pool) < 0)
2501*2d9fd380Sjfb8856606 		GOTO_FAIL("%s: test_mbuf_linearize_check(pinned) failed\n",
2502*2d9fd380Sjfb8856606 			  __func__);
2503*2d9fd380Sjfb8856606 
2504*2d9fd380Sjfb8856606 	/* test for allocating a bulk of mbufs with various sizes */
2505*2d9fd380Sjfb8856606 	if (test_pktmbuf_alloc_bulk(pinned_pool) < 0)
2506*2d9fd380Sjfb8856606 		GOTO_FAIL("%s: test_rte_pktmbuf_alloc_bulk(pinned) failed\n",
2507*2d9fd380Sjfb8856606 			  __func__);
2508*2d9fd380Sjfb8856606 
2509*2d9fd380Sjfb8856606 	/* test for allocating a bulk of mbufs with various sizes */
2510*2d9fd380Sjfb8856606 	if (test_neg_pktmbuf_alloc_bulk(pinned_pool) < 0)
2511*2d9fd380Sjfb8856606 		GOTO_FAIL("%s: test_neg_rte_pktmbuf_alloc_bulk(pinned)"
2512*2d9fd380Sjfb8856606 			  " failed\n", __func__);
2513*2d9fd380Sjfb8856606 
2514*2d9fd380Sjfb8856606 	/* test to read mbuf packet */
2515*2d9fd380Sjfb8856606 	if (test_pktmbuf_read(pinned_pool) < 0)
2516*2d9fd380Sjfb8856606 		GOTO_FAIL("%s: test_rte_pktmbuf_read(pinned) failed\n",
2517*2d9fd380Sjfb8856606 			  __func__);
2518*2d9fd380Sjfb8856606 
2519*2d9fd380Sjfb8856606 	/* test to read mbuf packet from offset */
2520*2d9fd380Sjfb8856606 	if (test_pktmbuf_read_from_offset(pinned_pool) < 0)
2521*2d9fd380Sjfb8856606 		GOTO_FAIL("%s: test_rte_pktmbuf_read_from_offset(pinned)"
2522*2d9fd380Sjfb8856606 			  " failed\n", __func__);
2523*2d9fd380Sjfb8856606 
2524*2d9fd380Sjfb8856606 	/* test to read data from chain of mbufs with data segments */
2525*2d9fd380Sjfb8856606 	if (test_pktmbuf_read_from_chain(pinned_pool) < 0)
2526*2d9fd380Sjfb8856606 		GOTO_FAIL("%s: test_rte_pktmbuf_read_from_chain(pinned)"
2527*2d9fd380Sjfb8856606 			  " failed\n", __func__);
2528*2d9fd380Sjfb8856606 
2529*2d9fd380Sjfb8856606 	RTE_SET_USED(std_pool);
2530*2d9fd380Sjfb8856606 	rte_mempool_free(pinned_pool);
2531*2d9fd380Sjfb8856606 	rte_memzone_free(mz);
2532*2d9fd380Sjfb8856606 	return 0;
2533*2d9fd380Sjfb8856606 
2534*2d9fd380Sjfb8856606 fail:
2535*2d9fd380Sjfb8856606 	rte_mempool_free(pinned_pool);
2536*2d9fd380Sjfb8856606 	rte_memzone_free(mz);
2537*2d9fd380Sjfb8856606 	return -1;
2538*2d9fd380Sjfb8856606 }
2539*2d9fd380Sjfb8856606 
25404418919fSjohnjiang static int
test_mbuf_dyn(struct rte_mempool * pktmbuf_pool)25414418919fSjohnjiang test_mbuf_dyn(struct rte_mempool *pktmbuf_pool)
25424418919fSjohnjiang {
25434418919fSjohnjiang 	const struct rte_mbuf_dynfield dynfield = {
25444418919fSjohnjiang 		.name = "test-dynfield",
25454418919fSjohnjiang 		.size = sizeof(uint8_t),
25464418919fSjohnjiang 		.align = __alignof__(uint8_t),
25474418919fSjohnjiang 		.flags = 0,
25484418919fSjohnjiang 	};
25494418919fSjohnjiang 	const struct rte_mbuf_dynfield dynfield2 = {
25504418919fSjohnjiang 		.name = "test-dynfield2",
25514418919fSjohnjiang 		.size = sizeof(uint16_t),
25524418919fSjohnjiang 		.align = __alignof__(uint16_t),
25534418919fSjohnjiang 		.flags = 0,
25544418919fSjohnjiang 	};
25554418919fSjohnjiang 	const struct rte_mbuf_dynfield dynfield3 = {
25564418919fSjohnjiang 		.name = "test-dynfield3",
25574418919fSjohnjiang 		.size = sizeof(uint8_t),
25584418919fSjohnjiang 		.align = __alignof__(uint8_t),
25594418919fSjohnjiang 		.flags = 0,
25604418919fSjohnjiang 	};
25614418919fSjohnjiang 	const struct rte_mbuf_dynfield dynfield_fail_big = {
25624418919fSjohnjiang 		.name = "test-dynfield-fail-big",
25634418919fSjohnjiang 		.size = 256,
25644418919fSjohnjiang 		.align = 1,
25654418919fSjohnjiang 		.flags = 0,
25664418919fSjohnjiang 	};
25674418919fSjohnjiang 	const struct rte_mbuf_dynfield dynfield_fail_align = {
25684418919fSjohnjiang 		.name = "test-dynfield-fail-align",
25694418919fSjohnjiang 		.size = 1,
25704418919fSjohnjiang 		.align = 3,
25714418919fSjohnjiang 		.flags = 0,
25724418919fSjohnjiang 	};
25734418919fSjohnjiang 	const struct rte_mbuf_dynflag dynflag = {
25744418919fSjohnjiang 		.name = "test-dynflag",
25754418919fSjohnjiang 		.flags = 0,
25764418919fSjohnjiang 	};
25774418919fSjohnjiang 	const struct rte_mbuf_dynflag dynflag2 = {
25784418919fSjohnjiang 		.name = "test-dynflag2",
25794418919fSjohnjiang 		.flags = 0,
25804418919fSjohnjiang 	};
25814418919fSjohnjiang 	const struct rte_mbuf_dynflag dynflag3 = {
25824418919fSjohnjiang 		.name = "test-dynflag3",
25834418919fSjohnjiang 		.flags = 0,
25844418919fSjohnjiang 	};
25854418919fSjohnjiang 	struct rte_mbuf *m = NULL;
25864418919fSjohnjiang 	int offset, offset2, offset3;
25874418919fSjohnjiang 	int flag, flag2, flag3;
25884418919fSjohnjiang 	int ret;
25894418919fSjohnjiang 
25904418919fSjohnjiang 	printf("Test mbuf dynamic fields and flags\n");
25914418919fSjohnjiang 	rte_mbuf_dyn_dump(stdout);
25924418919fSjohnjiang 
25934418919fSjohnjiang 	offset = rte_mbuf_dynfield_register(&dynfield);
25944418919fSjohnjiang 	if (offset == -1)
25954418919fSjohnjiang 		GOTO_FAIL("failed to register dynamic field, offset=%d: %s",
25964418919fSjohnjiang 			offset, strerror(errno));
25974418919fSjohnjiang 
25984418919fSjohnjiang 	ret = rte_mbuf_dynfield_register(&dynfield);
25994418919fSjohnjiang 	if (ret != offset)
26004418919fSjohnjiang 		GOTO_FAIL("failed to lookup dynamic field, ret=%d: %s",
26014418919fSjohnjiang 			ret, strerror(errno));
26024418919fSjohnjiang 
26034418919fSjohnjiang 	offset2 = rte_mbuf_dynfield_register(&dynfield2);
26044418919fSjohnjiang 	if (offset2 == -1 || offset2 == offset || (offset2 & 1))
26054418919fSjohnjiang 		GOTO_FAIL("failed to register dynamic field 2, offset2=%d: %s",
26064418919fSjohnjiang 			offset2, strerror(errno));
26074418919fSjohnjiang 
26084418919fSjohnjiang 	offset3 = rte_mbuf_dynfield_register_offset(&dynfield3,
26094418919fSjohnjiang 				offsetof(struct rte_mbuf, dynfield1[1]));
26100c6bd470Sfengbojiang 	if (offset3 != offsetof(struct rte_mbuf, dynfield1[1])) {
26110c6bd470Sfengbojiang 		if (rte_errno == EBUSY)
26120c6bd470Sfengbojiang 			printf("mbuf test error skipped: dynfield is busy\n");
26130c6bd470Sfengbojiang 		else
26140c6bd470Sfengbojiang 			GOTO_FAIL("failed to register dynamic field 3, offset="
26150c6bd470Sfengbojiang 				"%d: %s", offset3, strerror(errno));
26160c6bd470Sfengbojiang 	}
26174418919fSjohnjiang 
26184418919fSjohnjiang 	printf("dynfield: offset=%d, offset2=%d, offset3=%d\n",
26194418919fSjohnjiang 		offset, offset2, offset3);
26204418919fSjohnjiang 
26214418919fSjohnjiang 	ret = rte_mbuf_dynfield_register(&dynfield_fail_big);
26224418919fSjohnjiang 	if (ret != -1)
26234418919fSjohnjiang 		GOTO_FAIL("dynamic field creation should fail (too big)");
26244418919fSjohnjiang 
26254418919fSjohnjiang 	ret = rte_mbuf_dynfield_register(&dynfield_fail_align);
26264418919fSjohnjiang 	if (ret != -1)
26274418919fSjohnjiang 		GOTO_FAIL("dynamic field creation should fail (bad alignment)");
26284418919fSjohnjiang 
26294418919fSjohnjiang 	ret = rte_mbuf_dynfield_register_offset(&dynfield_fail_align,
26304418919fSjohnjiang 				offsetof(struct rte_mbuf, ol_flags));
26314418919fSjohnjiang 	if (ret != -1)
26324418919fSjohnjiang 		GOTO_FAIL("dynamic field creation should fail (not avail)");
26334418919fSjohnjiang 
26344418919fSjohnjiang 	flag = rte_mbuf_dynflag_register(&dynflag);
26354418919fSjohnjiang 	if (flag == -1)
26364418919fSjohnjiang 		GOTO_FAIL("failed to register dynamic flag, flag=%d: %s",
26374418919fSjohnjiang 			flag, strerror(errno));
26384418919fSjohnjiang 
26394418919fSjohnjiang 	ret = rte_mbuf_dynflag_register(&dynflag);
26404418919fSjohnjiang 	if (ret != flag)
26414418919fSjohnjiang 		GOTO_FAIL("failed to lookup dynamic flag, ret=%d: %s",
26424418919fSjohnjiang 			ret, strerror(errno));
26434418919fSjohnjiang 
26444418919fSjohnjiang 	flag2 = rte_mbuf_dynflag_register(&dynflag2);
26454418919fSjohnjiang 	if (flag2 == -1 || flag2 == flag)
26464418919fSjohnjiang 		GOTO_FAIL("failed to register dynamic flag 2, flag2=%d: %s",
26474418919fSjohnjiang 			flag2, strerror(errno));
26484418919fSjohnjiang 
26494418919fSjohnjiang 	flag3 = rte_mbuf_dynflag_register_bitnum(&dynflag3,
26504418919fSjohnjiang 						rte_bsf64(PKT_LAST_FREE));
26514418919fSjohnjiang 	if (flag3 != rte_bsf64(PKT_LAST_FREE))
26520c6bd470Sfengbojiang 		GOTO_FAIL("failed to register dynamic flag 3, flag3=%d: %s",
26534418919fSjohnjiang 			flag3, strerror(errno));
26544418919fSjohnjiang 
26554418919fSjohnjiang 	printf("dynflag: flag=%d, flag2=%d, flag3=%d\n", flag, flag2, flag3);
26564418919fSjohnjiang 
26574418919fSjohnjiang 	/* set, get dynamic field */
26584418919fSjohnjiang 	m = rte_pktmbuf_alloc(pktmbuf_pool);
26594418919fSjohnjiang 	if (m == NULL)
26604418919fSjohnjiang 		GOTO_FAIL("Cannot allocate mbuf");
26614418919fSjohnjiang 
26624418919fSjohnjiang 	*RTE_MBUF_DYNFIELD(m, offset, uint8_t *) = 1;
26634418919fSjohnjiang 	if (*RTE_MBUF_DYNFIELD(m, offset, uint8_t *) != 1)
26644418919fSjohnjiang 		GOTO_FAIL("failed to read dynamic field");
26654418919fSjohnjiang 	*RTE_MBUF_DYNFIELD(m, offset2, uint16_t *) = 1000;
26664418919fSjohnjiang 	if (*RTE_MBUF_DYNFIELD(m, offset2, uint16_t *) != 1000)
26674418919fSjohnjiang 		GOTO_FAIL("failed to read dynamic field");
26684418919fSjohnjiang 
26694418919fSjohnjiang 	/* set a dynamic flag */
26704418919fSjohnjiang 	m->ol_flags |= (1ULL << flag);
26714418919fSjohnjiang 
26724418919fSjohnjiang 	rte_mbuf_dyn_dump(stdout);
26734418919fSjohnjiang 	rte_pktmbuf_free(m);
26744418919fSjohnjiang 	return 0;
26754418919fSjohnjiang fail:
26764418919fSjohnjiang 	rte_pktmbuf_free(m);
26774418919fSjohnjiang 	return -1;
26784418919fSjohnjiang }
26794418919fSjohnjiang 
26804418919fSjohnjiang static int
test_mbuf(void)26814418919fSjohnjiang test_mbuf(void)
26824418919fSjohnjiang {
26834418919fSjohnjiang 	int ret = -1;
26844418919fSjohnjiang 	struct rte_mempool *pktmbuf_pool = NULL;
26854418919fSjohnjiang 	struct rte_mempool *pktmbuf_pool2 = NULL;
26864418919fSjohnjiang 
26874418919fSjohnjiang 
26884418919fSjohnjiang 	RTE_BUILD_BUG_ON(sizeof(struct rte_mbuf) != RTE_CACHE_LINE_MIN_SIZE * 2);
26894418919fSjohnjiang 
26904418919fSjohnjiang 	/* create pktmbuf pool if it does not exist */
26914418919fSjohnjiang 	pktmbuf_pool = rte_pktmbuf_pool_create("test_pktmbuf_pool",
26924418919fSjohnjiang 			NB_MBUF, MEMPOOL_CACHE_SIZE, 0, MBUF_DATA_SIZE,
26934418919fSjohnjiang 			SOCKET_ID_ANY);
26944418919fSjohnjiang 
26954418919fSjohnjiang 	if (pktmbuf_pool == NULL) {
26964418919fSjohnjiang 		printf("cannot allocate mbuf pool\n");
26974418919fSjohnjiang 		goto err;
26984418919fSjohnjiang 	}
26994418919fSjohnjiang 
27004418919fSjohnjiang 	/* test registration of dynamic fields and flags */
27014418919fSjohnjiang 	if (test_mbuf_dyn(pktmbuf_pool) < 0) {
27024418919fSjohnjiang 		printf("mbuf dynflag test failed\n");
27034418919fSjohnjiang 		goto err;
27044418919fSjohnjiang 	}
27054418919fSjohnjiang 
27064418919fSjohnjiang 	/* create a specific pktmbuf pool with a priv_size != 0 and no data
27074418919fSjohnjiang 	 * room size */
27084418919fSjohnjiang 	pktmbuf_pool2 = rte_pktmbuf_pool_create("test_pktmbuf_pool2",
27094418919fSjohnjiang 			NB_MBUF, MEMPOOL_CACHE_SIZE, MBUF2_PRIV_SIZE, 0,
27104418919fSjohnjiang 			SOCKET_ID_ANY);
27114418919fSjohnjiang 
27124418919fSjohnjiang 	if (pktmbuf_pool2 == NULL) {
27134418919fSjohnjiang 		printf("cannot allocate mbuf pool\n");
27144418919fSjohnjiang 		goto err;
27154418919fSjohnjiang 	}
27164418919fSjohnjiang 
27174418919fSjohnjiang 	/* test multiple mbuf alloc */
27184418919fSjohnjiang 	if (test_pktmbuf_pool(pktmbuf_pool) < 0) {
27194418919fSjohnjiang 		printf("test_mbuf_pool() failed\n");
27204418919fSjohnjiang 		goto err;
27214418919fSjohnjiang 	}
27224418919fSjohnjiang 
27234418919fSjohnjiang 	/* do it another time to check that all mbufs were freed */
27244418919fSjohnjiang 	if (test_pktmbuf_pool(pktmbuf_pool) < 0) {
27254418919fSjohnjiang 		printf("test_mbuf_pool() failed (2)\n");
27264418919fSjohnjiang 		goto err;
27274418919fSjohnjiang 	}
27284418919fSjohnjiang 
27294418919fSjohnjiang 	/* test bulk mbuf alloc and free */
27304418919fSjohnjiang 	if (test_pktmbuf_pool_bulk() < 0) {
27314418919fSjohnjiang 		printf("test_pktmbuf_pool_bulk() failed\n");
27324418919fSjohnjiang 		goto err;
27334418919fSjohnjiang 	}
27344418919fSjohnjiang 
27354418919fSjohnjiang 	/* test that the pointer to the data on a packet mbuf is set properly */
27364418919fSjohnjiang 	if (test_pktmbuf_pool_ptr(pktmbuf_pool) < 0) {
27374418919fSjohnjiang 		printf("test_pktmbuf_pool_ptr() failed\n");
27384418919fSjohnjiang 		goto err;
27394418919fSjohnjiang 	}
27404418919fSjohnjiang 
27414418919fSjohnjiang 	/* test data manipulation in mbuf */
27424418919fSjohnjiang 	if (test_one_pktmbuf(pktmbuf_pool) < 0) {
27434418919fSjohnjiang 		printf("test_one_mbuf() failed\n");
27444418919fSjohnjiang 		goto err;
27454418919fSjohnjiang 	}
27464418919fSjohnjiang 
27474418919fSjohnjiang 
27484418919fSjohnjiang 	/*
27494418919fSjohnjiang 	 * do it another time, to check that allocation reinitialize
27504418919fSjohnjiang 	 * the mbuf correctly
27514418919fSjohnjiang 	 */
27524418919fSjohnjiang 	if (test_one_pktmbuf(pktmbuf_pool) < 0) {
27534418919fSjohnjiang 		printf("test_one_mbuf() failed (2)\n");
27544418919fSjohnjiang 		goto err;
27554418919fSjohnjiang 	}
27564418919fSjohnjiang 
27574418919fSjohnjiang 	if (test_pktmbuf_with_non_ascii_data(pktmbuf_pool) < 0) {
27584418919fSjohnjiang 		printf("test_pktmbuf_with_non_ascii_data() failed\n");
27594418919fSjohnjiang 		goto err;
27604418919fSjohnjiang 	}
27614418919fSjohnjiang 
27624418919fSjohnjiang 	/* test free pktmbuf segment one by one */
27634418919fSjohnjiang 	if (test_pktmbuf_free_segment(pktmbuf_pool) < 0) {
27644418919fSjohnjiang 		printf("test_pktmbuf_free_segment() failed.\n");
27654418919fSjohnjiang 		goto err;
27664418919fSjohnjiang 	}
27674418919fSjohnjiang 
2768*2d9fd380Sjfb8856606 	if (testclone_testupdate_testdetach(pktmbuf_pool, pktmbuf_pool) < 0) {
27694418919fSjohnjiang 		printf("testclone_and_testupdate() failed \n");
27704418919fSjohnjiang 		goto err;
27714418919fSjohnjiang 	}
27724418919fSjohnjiang 
2773*2d9fd380Sjfb8856606 	if (test_pktmbuf_copy(pktmbuf_pool, pktmbuf_pool) < 0) {
27744418919fSjohnjiang 		printf("test_pktmbuf_copy() failed\n");
27754418919fSjohnjiang 		goto err;
27764418919fSjohnjiang 	}
27774418919fSjohnjiang 
27784418919fSjohnjiang 	if (test_attach_from_different_pool(pktmbuf_pool, pktmbuf_pool2) < 0) {
27794418919fSjohnjiang 		printf("test_attach_from_different_pool() failed\n");
27804418919fSjohnjiang 		goto err;
27814418919fSjohnjiang 	}
27824418919fSjohnjiang 
27834418919fSjohnjiang 	if (test_refcnt_mbuf() < 0) {
27844418919fSjohnjiang 		printf("test_refcnt_mbuf() failed \n");
27854418919fSjohnjiang 		goto err;
27864418919fSjohnjiang 	}
27874418919fSjohnjiang 
27884418919fSjohnjiang 	if (test_failing_mbuf_sanity_check(pktmbuf_pool) < 0) {
27894418919fSjohnjiang 		printf("test_failing_mbuf_sanity_check() failed\n");
27904418919fSjohnjiang 		goto err;
27914418919fSjohnjiang 	}
27924418919fSjohnjiang 
27934418919fSjohnjiang 	if (test_mbuf_linearize_check(pktmbuf_pool) < 0) {
27944418919fSjohnjiang 		printf("test_mbuf_linearize_check() failed\n");
27954418919fSjohnjiang 		goto err;
27964418919fSjohnjiang 	}
27974418919fSjohnjiang 
27984418919fSjohnjiang 	if (test_tx_offload() < 0) {
27994418919fSjohnjiang 		printf("test_tx_offload() failed\n");
28004418919fSjohnjiang 		goto err;
28014418919fSjohnjiang 	}
28024418919fSjohnjiang 
28034418919fSjohnjiang 	if (test_get_rx_ol_flag_list() < 0) {
28044418919fSjohnjiang 		printf("test_rte_get_rx_ol_flag_list() failed\n");
28054418919fSjohnjiang 		goto err;
28064418919fSjohnjiang 	}
28074418919fSjohnjiang 
28084418919fSjohnjiang 	if (test_get_tx_ol_flag_list() < 0) {
28094418919fSjohnjiang 		printf("test_rte_get_tx_ol_flag_list() failed\n");
28104418919fSjohnjiang 		goto err;
28114418919fSjohnjiang 	}
28124418919fSjohnjiang 
28134418919fSjohnjiang 	if (test_get_rx_ol_flag_name() < 0) {
28144418919fSjohnjiang 		printf("test_rte_get_rx_ol_flag_name() failed\n");
28154418919fSjohnjiang 		goto err;
28164418919fSjohnjiang 	}
28174418919fSjohnjiang 
28184418919fSjohnjiang 	if (test_get_tx_ol_flag_name() < 0) {
28194418919fSjohnjiang 		printf("test_rte_get_tx_ol_flag_name() failed\n");
28204418919fSjohnjiang 		goto err;
28214418919fSjohnjiang 	}
28224418919fSjohnjiang 
28234418919fSjohnjiang 	if (test_mbuf_validate_tx_offload_one(pktmbuf_pool) < 0) {
28244418919fSjohnjiang 		printf("test_mbuf_validate_tx_offload_one() failed\n");
28254418919fSjohnjiang 		goto err;
28264418919fSjohnjiang 	}
28274418919fSjohnjiang 
28284418919fSjohnjiang 	/* test for allocating a bulk of mbufs with various sizes */
28294418919fSjohnjiang 	if (test_pktmbuf_alloc_bulk(pktmbuf_pool) < 0) {
28304418919fSjohnjiang 		printf("test_rte_pktmbuf_alloc_bulk() failed\n");
28314418919fSjohnjiang 		goto err;
28324418919fSjohnjiang 	}
28334418919fSjohnjiang 
28344418919fSjohnjiang 	/* test for allocating a bulk of mbufs with various sizes */
28354418919fSjohnjiang 	if (test_neg_pktmbuf_alloc_bulk(pktmbuf_pool) < 0) {
28364418919fSjohnjiang 		printf("test_neg_rte_pktmbuf_alloc_bulk() failed\n");
28374418919fSjohnjiang 		goto err;
28384418919fSjohnjiang 	}
28394418919fSjohnjiang 
28404418919fSjohnjiang 	/* test to read mbuf packet */
28414418919fSjohnjiang 	if (test_pktmbuf_read(pktmbuf_pool) < 0) {
28424418919fSjohnjiang 		printf("test_rte_pktmbuf_read() failed\n");
28434418919fSjohnjiang 		goto err;
28444418919fSjohnjiang 	}
28454418919fSjohnjiang 
28464418919fSjohnjiang 	/* test to read mbuf packet from offset */
28474418919fSjohnjiang 	if (test_pktmbuf_read_from_offset(pktmbuf_pool) < 0) {
28484418919fSjohnjiang 		printf("test_rte_pktmbuf_read_from_offset() failed\n");
28494418919fSjohnjiang 		goto err;
28504418919fSjohnjiang 	}
28514418919fSjohnjiang 
28524418919fSjohnjiang 	/* test to read data from chain of mbufs with data segments */
28534418919fSjohnjiang 	if (test_pktmbuf_read_from_chain(pktmbuf_pool) < 0) {
28544418919fSjohnjiang 		printf("test_rte_pktmbuf_read_from_chain() failed\n");
28554418919fSjohnjiang 		goto err;
28564418919fSjohnjiang 	}
28574418919fSjohnjiang 
28584418919fSjohnjiang 	/* test to initialize shared info. at the end of external buffer */
28594418919fSjohnjiang 	if (test_pktmbuf_ext_shinfo_init_helper(pktmbuf_pool) < 0) {
28604418919fSjohnjiang 		printf("test_pktmbuf_ext_shinfo_init_helper() failed\n");
28614418919fSjohnjiang 		goto err;
28624418919fSjohnjiang 	}
28634418919fSjohnjiang 
2864*2d9fd380Sjfb8856606 	/* test the mbuf pool with pinned external data buffers */
2865*2d9fd380Sjfb8856606 	if (test_pktmbuf_ext_pinned_buffer(pktmbuf_pool) < 0) {
2866*2d9fd380Sjfb8856606 		printf("test_pktmbuf_ext_pinned_buffer() failed\n");
2867*2d9fd380Sjfb8856606 		goto err;
2868*2d9fd380Sjfb8856606 	}
2869*2d9fd380Sjfb8856606 
2870*2d9fd380Sjfb8856606 
28714418919fSjohnjiang 	ret = 0;
28724418919fSjohnjiang err:
28734418919fSjohnjiang 	rte_mempool_free(pktmbuf_pool);
28744418919fSjohnjiang 	rte_mempool_free(pktmbuf_pool2);
28754418919fSjohnjiang 	return ret;
28764418919fSjohnjiang }
28774418919fSjohnjiang #undef GOTO_FAIL
28784418919fSjohnjiang 
28794418919fSjohnjiang REGISTER_TEST_COMMAND(mbuf_autotest, test_mbuf);
2880