#include <rte_ether.h>
#include <rte_ip.h>
#include <rte_tcp.h>
+#include <rte_mbuf_dyn.h>
#include "test.h"
return -1;
}
+static uint16_t
+testclone_refcnt_read(struct rte_mbuf *m)
+{
+ return RTE_MBUF_HAS_PINNED_EXTBUF(m) ?
+ rte_mbuf_ext_refcnt_read(m->shinfo) :
+ rte_mbuf_refcnt_read(m);
+}
+
static int
-testclone_testupdate_testdetach(struct rte_mempool *pktmbuf_pool)
+testclone_testupdate_testdetach(struct rte_mempool *pktmbuf_pool,
+ struct rte_mempool *clone_pool)
{
struct rte_mbuf *m = NULL;
struct rte_mbuf *clone = NULL;
*data = MAGIC_DATA;
/* clone the allocated mbuf */
- clone = rte_pktmbuf_clone(m, pktmbuf_pool);
+ clone = rte_pktmbuf_clone(m, clone_pool);
if (clone == NULL)
GOTO_FAIL("cannot clone data\n");
if (*data != MAGIC_DATA)
GOTO_FAIL("invalid data in clone\n");
- if (rte_mbuf_refcnt_read(m) != 2)
+ if (testclone_refcnt_read(m) != 2)
GOTO_FAIL("invalid refcnt in m\n");
/* free the clone */
data = rte_pktmbuf_mtod(m->next, unaligned_uint32_t *);
*data = MAGIC_DATA;
- clone = rte_pktmbuf_clone(m, pktmbuf_pool);
+ clone = rte_pktmbuf_clone(m, clone_pool);
if (clone == NULL)
GOTO_FAIL("cannot clone data\n");
if (*data != MAGIC_DATA)
GOTO_FAIL("invalid data in clone->next\n");
- if (rte_mbuf_refcnt_read(m) != 2)
+ if (testclone_refcnt_read(m) != 2)
GOTO_FAIL("invalid refcnt in m\n");
- if (rte_mbuf_refcnt_read(m->next) != 2)
+ if (testclone_refcnt_read(m->next) != 2)
GOTO_FAIL("invalid refcnt in m->next\n");
/* try to clone the clone */
- clone2 = rte_pktmbuf_clone(clone, pktmbuf_pool);
+ clone2 = rte_pktmbuf_clone(clone, clone_pool);
if (clone2 == NULL)
GOTO_FAIL("cannot clone the clone\n");
if (*data != MAGIC_DATA)
GOTO_FAIL("invalid data in clone2->next\n");
- if (rte_mbuf_refcnt_read(m) != 3)
+ if (testclone_refcnt_read(m) != 3)
GOTO_FAIL("invalid refcnt in m\n");
- if (rte_mbuf_refcnt_read(m->next) != 3)
+ if (testclone_refcnt_read(m->next) != 3)
GOTO_FAIL("invalid refcnt in m->next\n");
/* free mbuf */
}
static int
-test_pktmbuf_copy(struct rte_mempool *pktmbuf_pool)
+test_pktmbuf_copy(struct rte_mempool *pktmbuf_pool,
+ struct rte_mempool *clone_pool)
{
struct rte_mbuf *m = NULL;
struct rte_mbuf *copy = NULL;
copy = NULL;
/* same test with a cloned mbuf */
- clone = rte_pktmbuf_clone(m, pktmbuf_pool);
+ clone = rte_pktmbuf_clone(m, clone_pool);
if (clone == NULL)
GOTO_FAIL("cannot clone data\n");
- if (!RTE_MBUF_CLONED(clone))
+ if ((!RTE_MBUF_HAS_PINNED_EXTBUF(m) &&
+ !RTE_MBUF_CLONED(clone)) ||
+ (RTE_MBUF_HAS_PINNED_EXTBUF(m) &&
+ !RTE_MBUF_HAS_EXTBUF(clone)))
GOTO_FAIL("clone did not give a cloned mbuf\n");
copy = rte_pktmbuf_copy(clone, pktmbuf_pool, 0, UINT32_MAX);
tref += refcnt_lcore[slave];
if (tref != refcnt_lcore[master])
- rte_panic("refernced mbufs: %u, freed mbufs: %u\n",
+ rte_panic("referenced mbufs: %u, freed mbufs: %u\n",
tref, refcnt_lcore[master]);
rte_mempool_dump(stdout, refcnt_pool);
buf = rte_pktmbuf_alloc(pktmbuf_pool);
if (buf == NULL)
return -1;
+
printf("Checking good mbuf initially\n");
if (verify_mbuf_check_panics(buf) != -1)
return -1;
VAL_NAME(PKT_TX_SEC_OFFLOAD),
VAL_NAME(PKT_TX_UDP_SEG),
VAL_NAME(PKT_TX_OUTER_UDP_CKSUM),
- VAL_NAME(PKT_TX_METADATA),
};
/* Test case to check with valid flag */
return -1;
}
+/*
+ * Test the mbuf pool with pinned external data buffers
+ * - Allocate memory zone for external buffer
+ * - Create the mbuf pool with pinned external buffer
+ * - Check the created pool with relevant mbuf pool unit tests
+ */
+static int
+test_pktmbuf_ext_pinned_buffer(struct rte_mempool *std_pool)
+{
+
+ struct rte_pktmbuf_extmem ext_mem;
+ struct rte_mempool *pinned_pool = NULL;
+ const struct rte_memzone *mz = NULL;
+
+ printf("Test mbuf pool with external pinned data buffers\n");
+
+ /* Allocate memzone for the external data buffer */
+ mz = rte_memzone_reserve("pinned_pool",
+ NB_MBUF * MBUF_DATA_SIZE,
+ SOCKET_ID_ANY,
+ RTE_MEMZONE_2MB | RTE_MEMZONE_SIZE_HINT_ONLY);
+ if (mz == NULL)
+ GOTO_FAIL("%s: Memzone allocation failed\n", __func__);
+
+ /* Create the mbuf pool with pinned external data buffer */
+ ext_mem.buf_ptr = mz->addr;
+ ext_mem.buf_iova = mz->iova;
+ ext_mem.buf_len = mz->len;
+ ext_mem.elt_size = MBUF_DATA_SIZE;
+
+ pinned_pool = rte_pktmbuf_pool_create_extbuf("test_pinned_pool",
+ NB_MBUF, MEMPOOL_CACHE_SIZE, 0,
+ MBUF_DATA_SIZE, SOCKET_ID_ANY,
+ &ext_mem, 1);
+ if (pinned_pool == NULL)
+ GOTO_FAIL("%s: Mbuf pool with pinned external"
+ " buffer creation failed\n", __func__);
+ /* test multiple mbuf alloc */
+ if (test_pktmbuf_pool(pinned_pool) < 0)
+ GOTO_FAIL("%s: test_mbuf_pool(pinned) failed\n",
+ __func__);
+
+ /* do it another time to check that all mbufs were freed */
+ if (test_pktmbuf_pool(pinned_pool) < 0)
+ GOTO_FAIL("%s: test_mbuf_pool(pinned) failed (2)\n",
+ __func__);
+
+ /* test that the data pointer on a packet mbuf is set properly */
+ if (test_pktmbuf_pool_ptr(pinned_pool) < 0)
+ GOTO_FAIL("%s: test_pktmbuf_pool_ptr(pinned) failed\n",
+ __func__);
+
+ /* test data manipulation in mbuf with non-ascii data */
+ if (test_pktmbuf_with_non_ascii_data(pinned_pool) < 0)
+ GOTO_FAIL("%s: test_pktmbuf_with_non_ascii_data(pinned)"
+ " failed\n", __func__);
+
+ /* test free pktmbuf segment one by one */
+ if (test_pktmbuf_free_segment(pinned_pool) < 0)
+ GOTO_FAIL("%s: test_pktmbuf_free_segment(pinned) failed\n",
+ __func__);
+
+ if (testclone_testupdate_testdetach(pinned_pool, std_pool) < 0)
+ GOTO_FAIL("%s: testclone_and_testupdate(pinned) failed\n",
+ __func__);
+
+ if (test_pktmbuf_copy(pinned_pool, std_pool) < 0)
+ GOTO_FAIL("%s: test_pktmbuf_copy(pinned) failed\n",
+ __func__);
+
+ if (test_failing_mbuf_sanity_check(pinned_pool) < 0)
+ GOTO_FAIL("%s: test_failing_mbuf_sanity_check(pinned)"
+ " failed\n", __func__);
+
+ if (test_mbuf_linearize_check(pinned_pool) < 0)
+ GOTO_FAIL("%s: test_mbuf_linearize_check(pinned) failed\n",
+ __func__);
+
+ /* test for allocating a bulk of mbufs with various sizes */
+ if (test_pktmbuf_alloc_bulk(pinned_pool) < 0)
+ GOTO_FAIL("%s: test_rte_pktmbuf_alloc_bulk(pinned) failed\n",
+ __func__);
+
+ /* test for allocating a bulk of mbufs with various sizes */
+ if (test_neg_pktmbuf_alloc_bulk(pinned_pool) < 0)
+ GOTO_FAIL("%s: test_neg_rte_pktmbuf_alloc_bulk(pinned)"
+ " failed\n", __func__);
+
+ /* test to read mbuf packet */
+ if (test_pktmbuf_read(pinned_pool) < 0)
+ GOTO_FAIL("%s: test_rte_pktmbuf_read(pinned) failed\n",
+ __func__);
+
+ /* test to read mbuf packet from offset */
+ if (test_pktmbuf_read_from_offset(pinned_pool) < 0)
+ GOTO_FAIL("%s: test_rte_pktmbuf_read_from_offset(pinned)"
+ " failed\n", __func__);
+
+ /* test to read data from chain of mbufs with data segments */
+ if (test_pktmbuf_read_from_chain(pinned_pool) < 0)
+ GOTO_FAIL("%s: test_rte_pktmbuf_read_from_chain(pinned)"
+ " failed\n", __func__);
+
+ RTE_SET_USED(std_pool);
+ rte_mempool_free(pinned_pool);
+ rte_memzone_free(mz);
+ return 0;
+
+fail:
+ rte_mempool_free(pinned_pool);
+ rte_memzone_free(mz);
+ return -1;
+}
+
+static int
+test_mbuf_dyn(struct rte_mempool *pktmbuf_pool)
+{
+ const struct rte_mbuf_dynfield dynfield = {
+ .name = "test-dynfield",
+ .size = sizeof(uint8_t),
+ .align = __alignof__(uint8_t),
+ .flags = 0,
+ };
+ const struct rte_mbuf_dynfield dynfield2 = {
+ .name = "test-dynfield2",
+ .size = sizeof(uint16_t),
+ .align = __alignof__(uint16_t),
+ .flags = 0,
+ };
+ const struct rte_mbuf_dynfield dynfield3 = {
+ .name = "test-dynfield3",
+ .size = sizeof(uint8_t),
+ .align = __alignof__(uint8_t),
+ .flags = 0,
+ };
+ const struct rte_mbuf_dynfield dynfield_fail_big = {
+ .name = "test-dynfield-fail-big",
+ .size = 256,
+ .align = 1,
+ .flags = 0,
+ };
+ const struct rte_mbuf_dynfield dynfield_fail_align = {
+ .name = "test-dynfield-fail-align",
+ .size = 1,
+ .align = 3,
+ .flags = 0,
+ };
+ const struct rte_mbuf_dynflag dynflag = {
+ .name = "test-dynflag",
+ .flags = 0,
+ };
+ const struct rte_mbuf_dynflag dynflag2 = {
+ .name = "test-dynflag2",
+ .flags = 0,
+ };
+ const struct rte_mbuf_dynflag dynflag3 = {
+ .name = "test-dynflag3",
+ .flags = 0,
+ };
+ struct rte_mbuf *m = NULL;
+ int offset, offset2, offset3;
+ int flag, flag2, flag3;
+ int ret;
+
+ printf("Test mbuf dynamic fields and flags\n");
+ rte_mbuf_dyn_dump(stdout);
+
+ offset = rte_mbuf_dynfield_register(&dynfield);
+ if (offset == -1)
+ GOTO_FAIL("failed to register dynamic field, offset=%d: %s",
+ offset, strerror(errno));
+
+ ret = rte_mbuf_dynfield_register(&dynfield);
+ if (ret != offset)
+ GOTO_FAIL("failed to lookup dynamic field, ret=%d: %s",
+ ret, strerror(errno));
+
+ offset2 = rte_mbuf_dynfield_register(&dynfield2);
+ if (offset2 == -1 || offset2 == offset || (offset2 & 1))
+ GOTO_FAIL("failed to register dynamic field 2, offset2=%d: %s",
+ offset2, strerror(errno));
+
+ offset3 = rte_mbuf_dynfield_register_offset(&dynfield3,
+ offsetof(struct rte_mbuf, dynfield1[1]));
+ if (offset3 != offsetof(struct rte_mbuf, dynfield1[1]))
+ GOTO_FAIL("failed to register dynamic field 3, offset=%d: %s",
+ offset3, strerror(errno));
+
+ printf("dynfield: offset=%d, offset2=%d, offset3=%d\n",
+ offset, offset2, offset3);
+
+ ret = rte_mbuf_dynfield_register(&dynfield_fail_big);
+ if (ret != -1)
+ GOTO_FAIL("dynamic field creation should fail (too big)");
+
+ ret = rte_mbuf_dynfield_register(&dynfield_fail_align);
+ if (ret != -1)
+ GOTO_FAIL("dynamic field creation should fail (bad alignment)");
+
+ ret = rte_mbuf_dynfield_register_offset(&dynfield_fail_align,
+ offsetof(struct rte_mbuf, ol_flags));
+ if (ret != -1)
+ GOTO_FAIL("dynamic field creation should fail (not avail)");
+
+ flag = rte_mbuf_dynflag_register(&dynflag);
+ if (flag == -1)
+ GOTO_FAIL("failed to register dynamic flag, flag=%d: %s",
+ flag, strerror(errno));
+
+ ret = rte_mbuf_dynflag_register(&dynflag);
+ if (ret != flag)
+ GOTO_FAIL("failed to lookup dynamic flag, ret=%d: %s",
+ ret, strerror(errno));
+
+ flag2 = rte_mbuf_dynflag_register(&dynflag2);
+ if (flag2 == -1 || flag2 == flag)
+ GOTO_FAIL("failed to register dynamic flag 2, flag2=%d: %s",
+ flag2, strerror(errno));
+
+ flag3 = rte_mbuf_dynflag_register_bitnum(&dynflag3,
+ rte_bsf64(PKT_LAST_FREE));
+ if (flag3 != rte_bsf64(PKT_LAST_FREE))
+ GOTO_FAIL("failed to register dynamic flag 3, flag2=%d: %s",
+ flag3, strerror(errno));
+
+ printf("dynflag: flag=%d, flag2=%d, flag3=%d\n", flag, flag2, flag3);
+
+ /* set, get dynamic field */
+ m = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (m == NULL)
+ GOTO_FAIL("Cannot allocate mbuf");
+
+ *RTE_MBUF_DYNFIELD(m, offset, uint8_t *) = 1;
+ if (*RTE_MBUF_DYNFIELD(m, offset, uint8_t *) != 1)
+ GOTO_FAIL("failed to read dynamic field");
+ *RTE_MBUF_DYNFIELD(m, offset2, uint16_t *) = 1000;
+ if (*RTE_MBUF_DYNFIELD(m, offset2, uint16_t *) != 1000)
+ GOTO_FAIL("failed to read dynamic field");
+
+ /* set a dynamic flag */
+ m->ol_flags |= (1ULL << flag);
+
+ rte_mbuf_dyn_dump(stdout);
+ rte_pktmbuf_free(m);
+ return 0;
+fail:
+ rte_pktmbuf_free(m);
+ return -1;
+}
+
static int
test_mbuf(void)
{
goto err;
}
+ /* test registration of dynamic fields and flags */
+ if (test_mbuf_dyn(pktmbuf_pool) < 0) {
+ printf("mbuf dynflag test failed\n");
+ goto err;
+ }
+
/* create a specific pktmbuf pool with a priv_size != 0 and no data
* room size */
pktmbuf_pool2 = rte_pktmbuf_pool_create("test_pktmbuf_pool2",
goto err;
}
- if (testclone_testupdate_testdetach(pktmbuf_pool) < 0) {
+ if (testclone_testupdate_testdetach(pktmbuf_pool, pktmbuf_pool) < 0) {
printf("testclone_and_testupdate() failed \n");
goto err;
}
- if (test_pktmbuf_copy(pktmbuf_pool) < 0) {
+ if (test_pktmbuf_copy(pktmbuf_pool, pktmbuf_pool) < 0) {
printf("test_pktmbuf_copy() failed\n");
goto err;
}
goto err;
}
+ /* test the mbuf pool with pinned external data buffers */
+ if (test_pktmbuf_ext_pinned_buffer(pktmbuf_pool) < 0) {
+ printf("test_pktmbuf_ext_pinned_buffer() failed\n");
+ goto err;
+ }
+
+
ret = 0;
err:
rte_mempool_free(pktmbuf_pool);