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