#include <sys/queue.h>
#include <rte_common.h>
+#include <rte_errno.h>
#include <rte_debug.h>
#include <rte_log.h>
#include <rte_memory.h>
#include <rte_random.h>
#include <rte_cycles.h>
#include <rte_malloc.h>
+#include <rte_ether.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_mbuf_dyn.h>
#include "test.h"
+#define MEMPOOL_CACHE_SIZE 32
#define MBUF_DATA_SIZE 2048
#define NB_MBUF 128
#define MBUF_TEST_DATA_LEN 1464
#define MBUF_TEST_DATA_LEN2 50
+#define MBUF_TEST_DATA_LEN3 256
#define MBUF_TEST_HDR1_LEN 20
#define MBUF_TEST_HDR2_LEN 30
#define MBUF_TEST_ALL_HDRS_LEN (MBUF_TEST_HDR1_LEN+MBUF_TEST_HDR2_LEN)
+#define MBUF_TEST_SEG_SIZE 64
+#define MBUF_TEST_BURST 8
+#define EXT_BUF_TEST_DATA_LEN 1024
+#define MBUF_MAX_SEG 16
+#define MBUF_NO_HEADER 0
+#define MBUF_HEADER 1
+#define MBUF_NEG_TEST_READ 2
+#define VAL_NAME(flag) { flag, #flag }
+
+/* chain length in bulk test */
+#define CHAIN_LEN 16
/* size of private data for mbuf in pktmbuf_pool2 */
#define MBUF2_PRIV_SIZE 128
#ifdef RTE_MBUF_REFCNT_ATOMIC
-static volatile uint32_t refcnt_stop_slaves;
+static volatile uint32_t refcnt_stop_workers;
static unsigned refcnt_lcore[RTE_MAX_LCORE];
#endif
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);
rte_pktmbuf_free(clone2);
return -1;
}
-#undef GOTO_FAIL
/*
* test allocation and free of mbufs
return ret;
}
+/*
+ * test bulk allocation and bulk free of mbufs
+ */
+static int
+test_pktmbuf_pool_bulk(void)
+{
+ struct rte_mempool *pool = NULL;
+ struct rte_mempool *pool2 = NULL;
+ unsigned int i;
+ struct rte_mbuf *m;
+ struct rte_mbuf *mbufs[NB_MBUF];
+ int ret = 0;
+
+ /* We cannot use the preallocated mbuf pools because their caches
+ * prevent us from bulk allocating all objects in them.
+ * So we create our own mbuf pools without caches.
+ */
+ printf("Create mbuf pools for bulk allocation.\n");
+ pool = rte_pktmbuf_pool_create("test_pktmbuf_bulk",
+ NB_MBUF, 0, 0, MBUF_DATA_SIZE, SOCKET_ID_ANY);
+ if (pool == NULL) {
+ printf("rte_pktmbuf_pool_create() failed. rte_errno %d\n",
+ rte_errno);
+ goto err;
+ }
+ pool2 = rte_pktmbuf_pool_create("test_pktmbuf_bulk2",
+ NB_MBUF, 0, 0, MBUF_DATA_SIZE, SOCKET_ID_ANY);
+ if (pool2 == NULL) {
+ printf("rte_pktmbuf_pool_create() failed. rte_errno %d\n",
+ rte_errno);
+ goto err;
+ }
+
+ /* Preconditions: Mempools must be full. */
+ if (!(rte_mempool_full(pool) && rte_mempool_full(pool2))) {
+ printf("Test precondition failed: mempools not full\n");
+ goto err;
+ }
+ if (!(rte_mempool_avail_count(pool) == NB_MBUF &&
+ rte_mempool_avail_count(pool2) == NB_MBUF)) {
+ printf("Test precondition failed: mempools: %u+%u != %u+%u",
+ rte_mempool_avail_count(pool),
+ rte_mempool_avail_count(pool2),
+ NB_MBUF, NB_MBUF);
+ goto err;
+ }
+
+ printf("Test single bulk alloc, followed by multiple bulk free.\n");
+
+ /* Bulk allocate all mbufs in the pool, in one go. */
+ ret = rte_pktmbuf_alloc_bulk(pool, mbufs, NB_MBUF);
+ if (ret != 0) {
+ printf("rte_pktmbuf_alloc_bulk() failed: %d\n", ret);
+ goto err;
+ }
+ /* Test that they have been removed from the pool. */
+ if (!rte_mempool_empty(pool)) {
+ printf("mempool not empty\n");
+ goto err;
+ }
+ /* Bulk free all mbufs, in four steps. */
+ RTE_BUILD_BUG_ON(NB_MBUF % 4 != 0);
+ for (i = 0; i < NB_MBUF; i += NB_MBUF / 4) {
+ rte_pktmbuf_free_bulk(&mbufs[i], NB_MBUF / 4);
+ /* Test that they have been returned to the pool. */
+ if (rte_mempool_avail_count(pool) != i + NB_MBUF / 4) {
+ printf("mempool avail count incorrect\n");
+ goto err;
+ }
+ }
+
+ printf("Test multiple bulk alloc, followed by single bulk free.\n");
+
+ /* Bulk allocate all mbufs in the pool, in four steps. */
+ for (i = 0; i < NB_MBUF; i += NB_MBUF / 4) {
+ ret = rte_pktmbuf_alloc_bulk(pool, &mbufs[i], NB_MBUF / 4);
+ if (ret != 0) {
+ printf("rte_pktmbuf_alloc_bulk() failed: %d\n", ret);
+ goto err;
+ }
+ }
+ /* Test that they have been removed from the pool. */
+ if (!rte_mempool_empty(pool)) {
+ printf("mempool not empty\n");
+ goto err;
+ }
+ /* Bulk free all mbufs, in one go. */
+ rte_pktmbuf_free_bulk(mbufs, NB_MBUF);
+ /* Test that they have been returned to the pool. */
+ if (!rte_mempool_full(pool)) {
+ printf("mempool not full\n");
+ goto err;
+ }
+
+ printf("Test bulk free of single long chain.\n");
+
+ /* Bulk allocate all mbufs in the pool, in one go. */
+ ret = rte_pktmbuf_alloc_bulk(pool, mbufs, NB_MBUF);
+ if (ret != 0) {
+ printf("rte_pktmbuf_alloc_bulk() failed: %d\n", ret);
+ goto err;
+ }
+ /* Create a long mbuf chain. */
+ for (i = 1; i < NB_MBUF; i++) {
+ ret = rte_pktmbuf_chain(mbufs[0], mbufs[i]);
+ if (ret != 0) {
+ printf("rte_pktmbuf_chain() failed: %d\n", ret);
+ goto err;
+ }
+ mbufs[i] = NULL;
+ }
+ /* Free the mbuf chain containing all the mbufs. */
+ rte_pktmbuf_free_bulk(mbufs, 1);
+ /* Test that they have been returned to the pool. */
+ if (!rte_mempool_full(pool)) {
+ printf("mempool not full\n");
+ goto err;
+ }
+
+ printf("Test bulk free of multiple chains using multiple pools.\n");
+
+ /* Create mbuf chains containing mbufs from different pools. */
+ RTE_BUILD_BUG_ON(CHAIN_LEN % 2 != 0);
+ RTE_BUILD_BUG_ON(NB_MBUF % (CHAIN_LEN / 2) != 0);
+ for (i = 0; i < NB_MBUF * 2; i++) {
+ m = rte_pktmbuf_alloc((i & 4) ? pool2 : pool);
+ if (m == NULL) {
+ printf("rte_pktmbuf_alloc() failed (%u)\n", i);
+ goto err;
+ }
+ if ((i % CHAIN_LEN) == 0)
+ mbufs[i / CHAIN_LEN] = m;
+ else
+ rte_pktmbuf_chain(mbufs[i / CHAIN_LEN], m);
+ }
+ /* Test that both pools have been emptied. */
+ if (!(rte_mempool_empty(pool) && rte_mempool_empty(pool2))) {
+ printf("mempools not empty\n");
+ goto err;
+ }
+ /* Free one mbuf chain. */
+ rte_pktmbuf_free_bulk(mbufs, 1);
+ /* Test that the segments have been returned to the pools. */
+ if (!(rte_mempool_avail_count(pool) == CHAIN_LEN / 2 &&
+ rte_mempool_avail_count(pool2) == CHAIN_LEN / 2)) {
+ printf("all segments of first mbuf have not been returned\n");
+ goto err;
+ }
+ /* Free the remaining mbuf chains. */
+ rte_pktmbuf_free_bulk(&mbufs[1], NB_MBUF * 2 / CHAIN_LEN - 1);
+ /* Test that they have been returned to the pools. */
+ if (!(rte_mempool_full(pool) && rte_mempool_full(pool2))) {
+ printf("mempools not full\n");
+ goto err;
+ }
+
+ ret = 0;
+ goto done;
+
+err:
+ ret = -1;
+
+done:
+ printf("Free mbuf pools for bulk allocation.\n");
+ rte_mempool_free(pool);
+ rte_mempool_free(pool2);
+ return ret;
+}
+
/*
* test that the pointer to the data on a packet mbuf is set properly
*/
#ifdef RTE_MBUF_REFCNT_ATOMIC
static int
-test_refcnt_slave(void *arg)
+test_refcnt_worker(void *arg)
{
unsigned lcore, free;
void *mp = 0;
printf("%s started at lcore %u\n", __func__, lcore);
free = 0;
- while (refcnt_stop_slaves == 0) {
+ while (refcnt_stop_workers == 0) {
if (rte_ring_dequeue(refcnt_mbuf_ring, &mp) == 0) {
free++;
rte_pktmbuf_free(mp);
/* For each mbuf in the pool:
* - allocate mbuf,
* - increment it's reference up to N+1,
- * - enqueue it N times into the ring for slave cores to free.
+ * - enqueue it N times into the ring for worker cores to free.
*/
for (i = 0, n = rte_mempool_avail_count(refcnt_pool);
i != n && (m = rte_pktmbuf_alloc(refcnt_pool)) != NULL;
rte_panic("(lcore=%u, iter=%u): was able to allocate only "
"%u from %u mbufs\n", lcore, iter, i, n);
- /* wait till slave lcores will consume all mbufs */
+ /* wait till worker lcores will consume all mbufs */
while (!rte_ring_empty(refcnt_mbuf_ring))
;
}
static int
-test_refcnt_master(struct rte_mempool *refcnt_pool,
+test_refcnt_main(struct rte_mempool *refcnt_pool,
struct rte_ring *refcnt_mbuf_ring)
{
unsigned i, lcore;
for (i = 0; i != REFCNT_MAX_ITER; i++)
test_refcnt_iter(lcore, i, refcnt_pool, refcnt_mbuf_ring);
- refcnt_stop_slaves = 1;
+ refcnt_stop_workers = 1;
rte_wmb();
printf("%s finished at lcore %u\n", __func__, lcore);
test_refcnt_mbuf(void)
{
#ifdef RTE_MBUF_REFCNT_ATOMIC
- unsigned int master, slave, tref;
+ unsigned int main_lcore, worker, tref;
int ret = -1;
struct rte_mempool *refcnt_pool = NULL;
struct rte_ring *refcnt_mbuf_ring = NULL;
SOCKET_ID_ANY);
if (refcnt_pool == NULL) {
printf("%s: cannot allocate " MAKE_STRING(refcnt_pool) "\n",
- __func__);
+ __func__);
return -1;
}
refcnt_mbuf_ring = rte_ring_create("refcnt_mbuf_ring",
- rte_align32pow2(REFCNT_RING_SIZE), SOCKET_ID_ANY,
- RING_F_SP_ENQ);
+ rte_align32pow2(REFCNT_RING_SIZE), SOCKET_ID_ANY,
+ RING_F_SP_ENQ);
if (refcnt_mbuf_ring == NULL) {
printf("%s: cannot allocate " MAKE_STRING(refcnt_mbuf_ring)
- "\n", __func__);
+ "\n", __func__);
goto err;
}
- refcnt_stop_slaves = 0;
+ refcnt_stop_workers = 0;
memset(refcnt_lcore, 0, sizeof (refcnt_lcore));
- rte_eal_mp_remote_launch(test_refcnt_slave, refcnt_mbuf_ring,
- SKIP_MASTER);
+ rte_eal_mp_remote_launch(test_refcnt_worker, refcnt_mbuf_ring, SKIP_MAIN);
- test_refcnt_master(refcnt_pool, refcnt_mbuf_ring);
+ test_refcnt_main(refcnt_pool, refcnt_mbuf_ring);
rte_eal_mp_wait_lcore();
/* check that we porcessed all references */
tref = 0;
- master = rte_get_master_lcore();
+ main_lcore = rte_get_main_lcore();
- RTE_LCORE_FOREACH_SLAVE(slave)
- tref += refcnt_lcore[slave];
+ RTE_LCORE_FOREACH_WORKER(worker)
+ tref += refcnt_lcore[worker];
- if (tref != refcnt_lcore[master])
- rte_panic("refernced mbufs: %u, freed mbufs: %u\n",
- tref, refcnt_lcore[master]);
+ if (tref != refcnt_lcore[main_lcore])
+ rte_panic("referenced mbufs: %u, freed mbufs: %u\n",
+ tref, refcnt_lcore[main_lcore]);
rte_mempool_dump(stdout, refcnt_pool);
rte_ring_dump(stdout, refcnt_mbuf_ring);
}
#include <unistd.h>
+#include <sys/resource.h>
+#include <sys/time.h>
#include <sys/wait.h>
/* use fork() to test mbuf errors panic */
pid = fork();
if (pid == 0) {
+ struct rlimit rl;
+
+ /* No need to generate a coredump when panicking. */
+ rl.rlim_cur = rl.rlim_max = 0;
+ setrlimit(RLIMIT_CORE, &rl);
rte_mbuf_sanity_check(buf, 1); /* should panic */
exit(0); /* return normally if it doesn't panic */
- } else if (pid < 0){
+ } else if (pid < 0) {
printf("Fork Failed\n");
return -1;
}
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;
return (v1 == v2) ? 0 : -EINVAL;
}
+static int
+test_get_rx_ol_flag_list(void)
+{
+ int len = 6, ret = 0;
+ char buf[256] = "";
+ int buflen = 0;
+
+ /* Test case to check with null buffer */
+ ret = rte_get_rx_ol_flag_list(0, NULL, 0);
+ if (ret != -1)
+ GOTO_FAIL("%s expected: -1, received = %d\n", __func__, ret);
+
+ /* Test case to check with zero buffer len */
+ ret = rte_get_rx_ol_flag_list(PKT_RX_L4_CKSUM_MASK, buf, 0);
+ if (ret != -1)
+ GOTO_FAIL("%s expected: -1, received = %d\n", __func__, ret);
+
+ buflen = strlen(buf);
+ if (buflen != 0)
+ GOTO_FAIL("%s buffer should be empty, received = %d\n",
+ __func__, buflen);
+
+ /* Test case to check with reduced buffer len */
+ ret = rte_get_rx_ol_flag_list(0, buf, len);
+ if (ret != -1)
+ GOTO_FAIL("%s expected: -1, received = %d\n", __func__, ret);
+
+ buflen = strlen(buf);
+ if (buflen != (len - 1))
+ GOTO_FAIL("%s invalid buffer length retrieved, expected: %d,"
+ "received = %d\n", __func__,
+ (len - 1), buflen);
+
+ /* Test case to check with zero mask value */
+ ret = rte_get_rx_ol_flag_list(0, buf, sizeof(buf));
+ if (ret != 0)
+ GOTO_FAIL("%s expected: 0, received = %d\n", __func__, ret);
+
+ buflen = strlen(buf);
+ if (buflen == 0)
+ GOTO_FAIL("%s expected: %s, received length = 0\n", __func__,
+ "non-zero, buffer should not be empty");
+
+ /* Test case to check with valid mask value */
+ ret = rte_get_rx_ol_flag_list(PKT_RX_SEC_OFFLOAD, buf, sizeof(buf));
+ if (ret != 0)
+ GOTO_FAIL("%s expected: 0, received = %d\n", __func__, ret);
+
+ buflen = strlen(buf);
+ if (buflen == 0)
+ GOTO_FAIL("%s expected: %s, received length = 0\n", __func__,
+ "non-zero, buffer should not be empty");
+
+ return 0;
+fail:
+ return -1;
+}
+
+static int
+test_get_tx_ol_flag_list(void)
+{
+ int len = 6, ret = 0;
+ char buf[256] = "";
+ int buflen = 0;
+
+ /* Test case to check with null buffer */
+ ret = rte_get_tx_ol_flag_list(0, NULL, 0);
+ if (ret != -1)
+ GOTO_FAIL("%s expected: -1, received = %d\n", __func__, ret);
+
+ /* Test case to check with zero buffer len */
+ ret = rte_get_tx_ol_flag_list(PKT_TX_IP_CKSUM, buf, 0);
+ if (ret != -1)
+ GOTO_FAIL("%s expected: -1, received = %d\n", __func__, ret);
+
+ buflen = strlen(buf);
+ if (buflen != 0) {
+ GOTO_FAIL("%s buffer should be empty, received = %d\n",
+ __func__, buflen);
+ }
+
+ /* Test case to check with reduced buffer len */
+ ret = rte_get_tx_ol_flag_list(0, buf, len);
+ if (ret != -1)
+ GOTO_FAIL("%s expected: -1, received = %d\n", __func__, ret);
+
+ buflen = strlen(buf);
+ if (buflen != (len - 1))
+ GOTO_FAIL("%s invalid buffer length retrieved, expected: %d,"
+ "received = %d\n", __func__,
+ (len - 1), buflen);
+
+ /* Test case to check with zero mask value */
+ ret = rte_get_tx_ol_flag_list(0, buf, sizeof(buf));
+ if (ret != 0)
+ GOTO_FAIL("%s expected: 0, received = %d\n", __func__, ret);
+
+ buflen = strlen(buf);
+ if (buflen == 0)
+ GOTO_FAIL("%s expected: %s, received length = 0\n", __func__,
+ "non-zero, buffer should not be empty");
+
+ /* Test case to check with valid mask value */
+ ret = rte_get_tx_ol_flag_list(PKT_TX_UDP_CKSUM, buf, sizeof(buf));
+ if (ret != 0)
+ GOTO_FAIL("%s expected: 0, received = %d\n", __func__, ret);
+
+ buflen = strlen(buf);
+ if (buflen == 0)
+ GOTO_FAIL("%s expected: %s, received length = 0\n", __func__,
+ "non-zero, buffer should not be empty");
+
+ return 0;
+fail:
+ return -1;
+
+}
+
+struct flag_name {
+ uint64_t flag;
+ const char *name;
+};
+
+static int
+test_get_rx_ol_flag_name(void)
+{
+ uint16_t i;
+ const char *flag_str = NULL;
+ const struct flag_name rx_flags[] = {
+ VAL_NAME(PKT_RX_VLAN),
+ VAL_NAME(PKT_RX_RSS_HASH),
+ VAL_NAME(PKT_RX_FDIR),
+ VAL_NAME(PKT_RX_L4_CKSUM_BAD),
+ VAL_NAME(PKT_RX_L4_CKSUM_GOOD),
+ VAL_NAME(PKT_RX_L4_CKSUM_NONE),
+ VAL_NAME(PKT_RX_IP_CKSUM_BAD),
+ VAL_NAME(PKT_RX_IP_CKSUM_GOOD),
+ VAL_NAME(PKT_RX_IP_CKSUM_NONE),
+ VAL_NAME(PKT_RX_OUTER_IP_CKSUM_BAD),
+ VAL_NAME(PKT_RX_VLAN_STRIPPED),
+ VAL_NAME(PKT_RX_IEEE1588_PTP),
+ VAL_NAME(PKT_RX_IEEE1588_TMST),
+ VAL_NAME(PKT_RX_FDIR_ID),
+ VAL_NAME(PKT_RX_FDIR_FLX),
+ VAL_NAME(PKT_RX_QINQ_STRIPPED),
+ VAL_NAME(PKT_RX_LRO),
+ VAL_NAME(PKT_RX_SEC_OFFLOAD),
+ VAL_NAME(PKT_RX_SEC_OFFLOAD_FAILED),
+ VAL_NAME(PKT_RX_OUTER_L4_CKSUM_BAD),
+ VAL_NAME(PKT_RX_OUTER_L4_CKSUM_GOOD),
+ VAL_NAME(PKT_RX_OUTER_L4_CKSUM_INVALID),
+ };
+
+ /* Test case to check with valid flag */
+ for (i = 0; i < RTE_DIM(rx_flags); i++) {
+ flag_str = rte_get_rx_ol_flag_name(rx_flags[i].flag);
+ if (flag_str == NULL)
+ GOTO_FAIL("%s: Expected flagname = %s; received null\n",
+ __func__, rx_flags[i].name);
+ if (strcmp(flag_str, rx_flags[i].name) != 0)
+ GOTO_FAIL("%s: Expected flagname = %s; received = %s\n",
+ __func__, rx_flags[i].name, flag_str);
+ }
+ /* Test case to check with invalid flag */
+ flag_str = rte_get_rx_ol_flag_name(0);
+ if (flag_str != NULL) {
+ GOTO_FAIL("%s: Expected flag name = null; received = %s\n",
+ __func__, flag_str);
+ }
+
+ return 0;
+fail:
+ return -1;
+}
+
+static int
+test_get_tx_ol_flag_name(void)
+{
+ uint16_t i;
+ const char *flag_str = NULL;
+ const struct flag_name tx_flags[] = {
+ VAL_NAME(PKT_TX_VLAN),
+ VAL_NAME(PKT_TX_IP_CKSUM),
+ VAL_NAME(PKT_TX_TCP_CKSUM),
+ VAL_NAME(PKT_TX_SCTP_CKSUM),
+ VAL_NAME(PKT_TX_UDP_CKSUM),
+ VAL_NAME(PKT_TX_IEEE1588_TMST),
+ VAL_NAME(PKT_TX_TCP_SEG),
+ VAL_NAME(PKT_TX_IPV4),
+ VAL_NAME(PKT_TX_IPV6),
+ VAL_NAME(PKT_TX_OUTER_IP_CKSUM),
+ VAL_NAME(PKT_TX_OUTER_IPV4),
+ VAL_NAME(PKT_TX_OUTER_IPV6),
+ VAL_NAME(PKT_TX_TUNNEL_VXLAN),
+ VAL_NAME(PKT_TX_TUNNEL_GRE),
+ VAL_NAME(PKT_TX_TUNNEL_IPIP),
+ VAL_NAME(PKT_TX_TUNNEL_GENEVE),
+ VAL_NAME(PKT_TX_TUNNEL_MPLSINUDP),
+ VAL_NAME(PKT_TX_TUNNEL_VXLAN_GPE),
+ VAL_NAME(PKT_TX_TUNNEL_IP),
+ VAL_NAME(PKT_TX_TUNNEL_UDP),
+ VAL_NAME(PKT_TX_QINQ),
+ VAL_NAME(PKT_TX_MACSEC),
+ VAL_NAME(PKT_TX_SEC_OFFLOAD),
+ VAL_NAME(PKT_TX_UDP_SEG),
+ VAL_NAME(PKT_TX_OUTER_UDP_CKSUM),
+ };
+
+ /* Test case to check with valid flag */
+ for (i = 0; i < RTE_DIM(tx_flags); i++) {
+ flag_str = rte_get_tx_ol_flag_name(tx_flags[i].flag);
+ if (flag_str == NULL)
+ GOTO_FAIL("%s: Expected flagname = %s; received null\n",
+ __func__, tx_flags[i].name);
+ if (strcmp(flag_str, tx_flags[i].name) != 0)
+ GOTO_FAIL("%s: Expected flagname = %s; received = %s\n",
+ __func__, tx_flags[i].name, flag_str);
+ }
+ /* Test case to check with invalid flag */
+ flag_str = rte_get_tx_ol_flag_name(0);
+ if (flag_str != NULL) {
+ GOTO_FAIL("%s: Expected flag name = null; received = %s\n",
+ __func__, flag_str);
+ }
+
+ return 0;
+fail:
+ return -1;
+
+}
+
+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)
+{
+ struct rte_mbuf *m = NULL;
+ int ret = 0;
+
+ /* alloc a mbuf and do sanity check */
+ m = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (m == NULL)
+ GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
+ if (rte_pktmbuf_pkt_len(m) != 0)
+ GOTO_FAIL("%s: Bad packet length\n", __func__);
+ rte_mbuf_sanity_check(m, 0);
+ m->ol_flags = ol_flags;
+ m->tso_segsz = segsize;
+ ret = rte_validate_tx_offload(m);
+ if (ret != expected_retval)
+ GOTO_FAIL("%s(%s): expected ret val: %d; received: %d\n",
+ __func__, test_name, expected_retval, ret);
+ rte_pktmbuf_free(m);
+ m = NULL;
+ return 0;
+fail:
+ if (m) {
+ rte_pktmbuf_free(m);
+ m = NULL;
+ }
+ return -1;
+}
+
+static int
+test_mbuf_validate_tx_offload_one(struct rte_mempool *pktmbuf_pool)
+{
+ /* test to validate tx offload flags */
+ uint64_t ol_flags = 0;
+
+ /* test to validate if IP checksum is counted only for IPV4 packet */
+ /* set both IP checksum and IPV6 flags */
+ ol_flags |= PKT_TX_IP_CKSUM;
+ ol_flags |= PKT_TX_IPV6;
+ if (test_mbuf_validate_tx_offload("MBUF_TEST_IP_CKSUM_IPV6_SET",
+ pktmbuf_pool,
+ ol_flags, 0, -EINVAL) < 0)
+ GOTO_FAIL("%s failed: IP cksum is set incorrect.\n", __func__);
+ /* resetting ol_flags for next testcase */
+ ol_flags = 0;
+
+ /* test to validate if IP type is set when required */
+ ol_flags |= PKT_TX_L4_MASK;
+ if (test_mbuf_validate_tx_offload("MBUF_TEST_IP_TYPE_NOT_SET",
+ pktmbuf_pool,
+ ol_flags, 0, -EINVAL) < 0)
+ GOTO_FAIL("%s failed: IP type is not set.\n", __func__);
+
+ /* test if IP type is set when TCP SEG is on */
+ ol_flags |= PKT_TX_TCP_SEG;
+ if (test_mbuf_validate_tx_offload("MBUF_TEST_IP_TYPE_NOT_SET",
+ pktmbuf_pool,
+ ol_flags, 0, -EINVAL) < 0)
+ GOTO_FAIL("%s failed: IP type is not set.\n", __func__);
+
+ ol_flags = 0;
+ /* test to confirm IP type (IPV4/IPV6) is set */
+ ol_flags = PKT_TX_L4_MASK;
+ ol_flags |= PKT_TX_IPV6;
+ if (test_mbuf_validate_tx_offload("MBUF_TEST_IP_TYPE_SET",
+ pktmbuf_pool,
+ ol_flags, 0, 0) < 0)
+ GOTO_FAIL("%s failed: tx offload flag error.\n", __func__);
+
+ ol_flags = 0;
+ /* test to check TSO segment size is non-zero */
+ ol_flags |= PKT_TX_IPV4;
+ ol_flags |= PKT_TX_TCP_SEG;
+ /* set 0 tso segment size */
+ if (test_mbuf_validate_tx_offload("MBUF_TEST_NULL_TSO_SEGSZ",
+ pktmbuf_pool,
+ ol_flags, 0, -EINVAL) < 0)
+ GOTO_FAIL("%s failed: tso segment size is null.\n", __func__);
+
+ /* retain IPV4 and PKT_TX_TCP_SEG mask */
+ /* set valid tso segment size but IP CKSUM not set */
+ if (test_mbuf_validate_tx_offload("MBUF_TEST_TSO_IP_CKSUM_NOT_SET",
+ pktmbuf_pool,
+ ol_flags, 512, -EINVAL) < 0)
+ GOTO_FAIL("%s failed: IP CKSUM is not set.\n", __func__);
+
+ /* test to validate if IP checksum is set for TSO capability */
+ /* retain IPV4, TCP_SEG, tso_seg size */
+ ol_flags |= PKT_TX_IP_CKSUM;
+ if (test_mbuf_validate_tx_offload("MBUF_TEST_TSO_IP_CKSUM_SET",
+ pktmbuf_pool,
+ ol_flags, 512, 0) < 0)
+ GOTO_FAIL("%s failed: tx offload flag error.\n", __func__);
+
+ /* test to confirm TSO for IPV6 type */
+ ol_flags = 0;
+ ol_flags |= PKT_TX_IPV6;
+ ol_flags |= PKT_TX_TCP_SEG;
+ if (test_mbuf_validate_tx_offload("MBUF_TEST_TSO_IPV6_SET",
+ pktmbuf_pool,
+ ol_flags, 512, 0) < 0)
+ GOTO_FAIL("%s failed: TSO req not met.\n", __func__);
+
+ ol_flags = 0;
+ /* test if outer IP checksum set for non outer IPv4 packet */
+ ol_flags |= PKT_TX_IPV6;
+ ol_flags |= PKT_TX_OUTER_IP_CKSUM;
+ if (test_mbuf_validate_tx_offload("MBUF_TEST_OUTER_IPV4_NOT_SET",
+ pktmbuf_pool,
+ ol_flags, 512, -EINVAL) < 0)
+ GOTO_FAIL("%s failed: Outer IP cksum set.\n", __func__);
+
+ ol_flags = 0;
+ /* test to confirm outer IP checksum is set for outer IPV4 packet */
+ ol_flags |= PKT_TX_OUTER_IP_CKSUM;
+ ol_flags |= PKT_TX_OUTER_IPV4;
+ if (test_mbuf_validate_tx_offload("MBUF_TEST_OUTER_IPV4_SET",
+ pktmbuf_pool,
+ ol_flags, 512, 0) < 0)
+ GOTO_FAIL("%s failed: tx offload flag error.\n", __func__);
+
+ ol_flags = 0;
+ /* test to confirm if packets with no TX_OFFLOAD_MASK are skipped */
+ if (test_mbuf_validate_tx_offload("MBUF_TEST_OL_MASK_NOT_SET",
+ pktmbuf_pool,
+ ol_flags, 512, 0) < 0)
+ GOTO_FAIL("%s failed: tx offload flag error.\n", __func__);
+ return 0;
+fail:
+ return -1;
+}
+
+/*
+ * Test for allocating a bulk of mbufs
+ * define an array with positive sizes for mbufs allocations.
+ */
+static int
+test_pktmbuf_alloc_bulk(struct rte_mempool *pktmbuf_pool)
+{
+ int ret = 0;
+ unsigned int idx, loop;
+ unsigned int alloc_counts[] = {
+ 0,
+ MEMPOOL_CACHE_SIZE - 1,
+ MEMPOOL_CACHE_SIZE + 1,
+ MEMPOOL_CACHE_SIZE * 1.5,
+ MEMPOOL_CACHE_SIZE * 2,
+ MEMPOOL_CACHE_SIZE * 2 - 1,
+ MEMPOOL_CACHE_SIZE * 2 + 1,
+ MEMPOOL_CACHE_SIZE,
+ };
+
+ /* allocate a large array of mbuf pointers */
+ struct rte_mbuf *mbufs[NB_MBUF] = { 0 };
+ for (idx = 0; idx < RTE_DIM(alloc_counts); idx++) {
+ ret = rte_pktmbuf_alloc_bulk(pktmbuf_pool, mbufs,
+ alloc_counts[idx]);
+ if (ret == 0) {
+ for (loop = 0; loop < alloc_counts[idx] &&
+ mbufs[loop] != NULL; loop++)
+ rte_pktmbuf_free(mbufs[loop]);
+ } else if (ret != 0) {
+ printf("%s: Bulk alloc failed count(%u); ret val(%d)\n",
+ __func__, alloc_counts[idx], ret);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Negative testing for allocating a bulk of mbufs
+ */
+static int
+test_neg_pktmbuf_alloc_bulk(struct rte_mempool *pktmbuf_pool)
+{
+ int ret = 0;
+ unsigned int idx, loop;
+ unsigned int neg_alloc_counts[] = {
+ MEMPOOL_CACHE_SIZE - NB_MBUF,
+ NB_MBUF + 1,
+ NB_MBUF * 8,
+ UINT_MAX
+ };
+ struct rte_mbuf *mbufs[NB_MBUF * 8] = { 0 };
+
+ for (idx = 0; idx < RTE_DIM(neg_alloc_counts); idx++) {
+ ret = rte_pktmbuf_alloc_bulk(pktmbuf_pool, mbufs,
+ neg_alloc_counts[idx]);
+ if (ret == 0) {
+ printf("%s: Bulk alloc must fail! count(%u); ret(%d)\n",
+ __func__, neg_alloc_counts[idx], ret);
+ for (loop = 0; loop < neg_alloc_counts[idx] &&
+ mbufs[loop] != NULL; loop++)
+ rte_pktmbuf_free(mbufs[loop]);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Test to read mbuf packet using rte_pktmbuf_read
+ */
+static int
+test_pktmbuf_read(struct rte_mempool *pktmbuf_pool)
+{
+ struct rte_mbuf *m = NULL;
+ char *data = NULL;
+ const char *data_copy = NULL;
+ int off;
+
+ /* alloc a mbuf */
+ m = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (m == NULL)
+ GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
+ if (rte_pktmbuf_pkt_len(m) != 0)
+ GOTO_FAIL("%s: Bad packet length\n", __func__);
+ rte_mbuf_sanity_check(m, 0);
+
+ data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN2);
+ if (data == NULL)
+ GOTO_FAIL("%s: Cannot append data\n", __func__);
+ if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN2)
+ GOTO_FAIL("%s: Bad packet length\n", __func__);
+ memset(data, 0xfe, MBUF_TEST_DATA_LEN2);
+
+ /* read the data from mbuf */
+ data_copy = rte_pktmbuf_read(m, 0, MBUF_TEST_DATA_LEN2, NULL);
+ if (data_copy == NULL)
+ GOTO_FAIL("%s: Error in reading data!\n", __func__);
+ for (off = 0; off < MBUF_TEST_DATA_LEN2; off++) {
+ if (data_copy[off] != (char)0xfe)
+ GOTO_FAIL("Data corrupted at offset %u", off);
+ }
+ rte_pktmbuf_free(m);
+ m = NULL;
+
+ return 0;
+fail:
+ if (m) {
+ rte_pktmbuf_free(m);
+ m = NULL;
+ }
+ return -1;
+}
+
+/*
+ * Test to read mbuf packet data from offset
+ */
+static int
+test_pktmbuf_read_from_offset(struct rte_mempool *pktmbuf_pool)
+{
+ struct rte_mbuf *m = NULL;
+ struct ether_hdr *hdr = NULL;
+ char *data = NULL;
+ const char *data_copy = NULL;
+ unsigned int off;
+ unsigned int hdr_len = sizeof(struct rte_ether_hdr);
+
+ /* alloc a mbuf */
+ m = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (m == NULL)
+ GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
+
+ if (rte_pktmbuf_pkt_len(m) != 0)
+ GOTO_FAIL("%s: Bad packet length\n", __func__);
+ rte_mbuf_sanity_check(m, 0);
+
+ /* prepend an ethernet header */
+ hdr = (struct ether_hdr *)rte_pktmbuf_prepend(m, hdr_len);
+ if (hdr == NULL)
+ GOTO_FAIL("%s: Cannot prepend header\n", __func__);
+ if (rte_pktmbuf_pkt_len(m) != hdr_len)
+ GOTO_FAIL("%s: Bad pkt length", __func__);
+ if (rte_pktmbuf_data_len(m) != hdr_len)
+ GOTO_FAIL("%s: Bad data length", __func__);
+ memset(hdr, 0xde, hdr_len);
+
+ /* read mbuf header info from 0 offset */
+ data_copy = rte_pktmbuf_read(m, 0, hdr_len, NULL);
+ if (data_copy == NULL)
+ GOTO_FAIL("%s: Error in reading header!\n", __func__);
+ for (off = 0; off < hdr_len; off++) {
+ if (data_copy[off] != (char)0xde)
+ GOTO_FAIL("Header info corrupted at offset %u", off);
+ }
+
+ /* append sample data after ethernet header */
+ data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN2);
+ if (data == NULL)
+ GOTO_FAIL("%s: Cannot append data\n", __func__);
+ if (rte_pktmbuf_pkt_len(m) != hdr_len + MBUF_TEST_DATA_LEN2)
+ GOTO_FAIL("%s: Bad packet length\n", __func__);
+ if (rte_pktmbuf_data_len(m) != hdr_len + MBUF_TEST_DATA_LEN2)
+ GOTO_FAIL("%s: Bad data length\n", __func__);
+ memset(data, 0xcc, MBUF_TEST_DATA_LEN2);
+
+ /* read mbuf data after header info */
+ data_copy = rte_pktmbuf_read(m, hdr_len, MBUF_TEST_DATA_LEN2, NULL);
+ if (data_copy == NULL)
+ GOTO_FAIL("%s: Error in reading header data!\n", __func__);
+ for (off = 0; off < MBUF_TEST_DATA_LEN2; off++) {
+ if (data_copy[off] != (char)0xcc)
+ GOTO_FAIL("Data corrupted at offset %u", off);
+ }
+
+ /* partial reading of mbuf data */
+ data_copy = rte_pktmbuf_read(m, hdr_len + 5, MBUF_TEST_DATA_LEN2 - 5,
+ NULL);
+ if (data_copy == NULL)
+ GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
+ if (strlen(data_copy) != MBUF_TEST_DATA_LEN2 - 5)
+ GOTO_FAIL("%s: Incorrect data length!\n", __func__);
+ for (off = 0; off < MBUF_TEST_DATA_LEN2 - 5; off++) {
+ if (data_copy[off] != (char)0xcc)
+ GOTO_FAIL("Data corrupted at offset %u", off);
+ }
+
+ /* read length greater than mbuf data_len */
+ if (rte_pktmbuf_read(m, hdr_len, rte_pktmbuf_data_len(m) + 1,
+ NULL) != NULL)
+ GOTO_FAIL("%s: Requested len is larger than mbuf data len!\n",
+ __func__);
+
+ /* read length greater than mbuf pkt_len */
+ if (rte_pktmbuf_read(m, hdr_len, rte_pktmbuf_pkt_len(m) + 1,
+ NULL) != NULL)
+ GOTO_FAIL("%s: Requested len is larger than mbuf pkt len!\n",
+ __func__);
+
+ /* read data of zero len from valid offset */
+ data_copy = rte_pktmbuf_read(m, hdr_len, 0, NULL);
+ if (data_copy == NULL)
+ GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
+ if (strlen(data_copy) != MBUF_TEST_DATA_LEN2)
+ GOTO_FAIL("%s: Corrupted data content!\n", __func__);
+ for (off = 0; off < MBUF_TEST_DATA_LEN2; off++) {
+ if (data_copy[off] != (char)0xcc)
+ GOTO_FAIL("Data corrupted at offset %u", off);
+ }
+
+ /* read data of zero length from zero offset */
+ data_copy = rte_pktmbuf_read(m, 0, 0, NULL);
+ if (data_copy == NULL)
+ GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
+ /* check if the received address is the beginning of header info */
+ if (hdr != (const struct ether_hdr *)data_copy)
+ GOTO_FAIL("%s: Corrupted data address!\n", __func__);
+
+ /* read data of max length from valid offset */
+ data_copy = rte_pktmbuf_read(m, hdr_len, UINT_MAX, NULL);
+ if (data_copy == NULL)
+ GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
+ /* check if the received address is the beginning of data segment */
+ if (data_copy != data)
+ GOTO_FAIL("%s: Corrupted data address!\n", __func__);
+
+ /* try to read from mbuf with max size offset */
+ data_copy = rte_pktmbuf_read(m, UINT_MAX, 0, NULL);
+ if (data_copy != NULL)
+ GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
+
+ /* try to read from mbuf with max size offset and len */
+ data_copy = rte_pktmbuf_read(m, UINT_MAX, UINT_MAX, NULL);
+ if (data_copy != NULL)
+ GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
+
+ rte_pktmbuf_dump(stdout, m, rte_pktmbuf_pkt_len(m));
+
+ rte_pktmbuf_free(m);
+ m = NULL;
+
+ return 0;
+fail:
+ if (m) {
+ rte_pktmbuf_free(m);
+ m = NULL;
+ }
+ return -1;
+}
+
+struct test_case {
+ unsigned int seg_count;
+ unsigned int flags;
+ uint32_t read_off;
+ uint32_t read_len;
+ unsigned int seg_lengths[MBUF_MAX_SEG];
+};
+
+/* create a mbuf with different sized segments
+ * and fill with data [0x00 0x01 0x02 ...]
+ */
+static struct rte_mbuf *
+create_packet(struct rte_mempool *pktmbuf_pool,
+ struct test_case *test_data)
+{
+ uint16_t i, ret, seg, seg_len = 0;
+ uint32_t last_index = 0;
+ unsigned int seg_lengths[MBUF_MAX_SEG];
+ unsigned int hdr_len;
+ struct rte_mbuf *pkt = NULL;
+ struct rte_mbuf *pkt_seg = NULL;
+ char *hdr = NULL;
+ char *data = NULL;
+
+ memcpy(seg_lengths, test_data->seg_lengths,
+ sizeof(unsigned int)*test_data->seg_count);
+ for (seg = 0; seg < test_data->seg_count; seg++) {
+ hdr_len = 0;
+ seg_len = seg_lengths[seg];
+ pkt_seg = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (pkt_seg == NULL)
+ GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
+ if (rte_pktmbuf_pkt_len(pkt_seg) != 0)
+ GOTO_FAIL("%s: Bad packet length\n", __func__);
+ rte_mbuf_sanity_check(pkt_seg, 0);
+ /* Add header only for the first segment */
+ if (test_data->flags == MBUF_HEADER && seg == 0) {
+ hdr_len = sizeof(struct rte_ether_hdr);
+ /* prepend a header and fill with dummy data */
+ hdr = (char *)rte_pktmbuf_prepend(pkt_seg, hdr_len);
+ if (hdr == NULL)
+ GOTO_FAIL("%s: Cannot prepend header\n",
+ __func__);
+ if (rte_pktmbuf_pkt_len(pkt_seg) != hdr_len)
+ GOTO_FAIL("%s: Bad pkt length", __func__);
+ if (rte_pktmbuf_data_len(pkt_seg) != hdr_len)
+ GOTO_FAIL("%s: Bad data length", __func__);
+ for (i = 0; i < hdr_len; i++)
+ hdr[i] = (last_index + i) % 0xffff;
+ last_index += hdr_len;
+ }
+ /* skip appending segment with 0 length */
+ if (seg_len == 0)
+ continue;
+ data = rte_pktmbuf_append(pkt_seg, seg_len);
+ if (data == NULL)
+ GOTO_FAIL("%s: Cannot append data segment\n", __func__);
+ if (rte_pktmbuf_pkt_len(pkt_seg) != hdr_len + seg_len)
+ GOTO_FAIL("%s: Bad packet segment length: %d\n",
+ __func__, rte_pktmbuf_pkt_len(pkt_seg));
+ if (rte_pktmbuf_data_len(pkt_seg) != hdr_len + seg_len)
+ GOTO_FAIL("%s: Bad data length\n", __func__);
+ for (i = 0; i < seg_len; i++)
+ data[i] = (last_index + i) % 0xffff;
+ /* to fill continuous data from one seg to another */
+ last_index += i;
+ /* create chained mbufs */
+ if (seg == 0)
+ pkt = pkt_seg;
+ else {
+ ret = rte_pktmbuf_chain(pkt, pkt_seg);
+ if (ret != 0)
+ GOTO_FAIL("%s:FAIL: Chained mbuf creation %d\n",
+ __func__, ret);
+ }
+
+ pkt_seg = pkt_seg->next;
+ }
+ return pkt;
+fail:
+ if (pkt != NULL) {
+ rte_pktmbuf_free(pkt);
+ pkt = NULL;
+ }
+ if (pkt_seg != NULL) {
+ rte_pktmbuf_free(pkt_seg);
+ pkt_seg = NULL;
+ }
+ return NULL;
+}
+
+static int
+test_pktmbuf_read_from_chain(struct rte_mempool *pktmbuf_pool)
+{
+ struct rte_mbuf *m;
+ struct test_case test_cases[] = {
+ {
+ .seg_lengths = { 100, 100, 100 },
+ .seg_count = 3,
+ .flags = MBUF_NO_HEADER,
+ .read_off = 0,
+ .read_len = 300
+ },
+ {
+ .seg_lengths = { 100, 125, 150 },
+ .seg_count = 3,
+ .flags = MBUF_NO_HEADER,
+ .read_off = 99,
+ .read_len = 201
+ },
+ {
+ .seg_lengths = { 100, 100 },
+ .seg_count = 2,
+ .flags = MBUF_NO_HEADER,
+ .read_off = 0,
+ .read_len = 100
+ },
+ {
+ .seg_lengths = { 100, 200 },
+ .seg_count = 2,
+ .flags = MBUF_HEADER,
+ .read_off = sizeof(struct rte_ether_hdr),
+ .read_len = 150
+ },
+ {
+ .seg_lengths = { 1000, 100 },
+ .seg_count = 2,
+ .flags = MBUF_NO_HEADER,
+ .read_off = 0,
+ .read_len = 1000
+ },
+ {
+ .seg_lengths = { 1024, 0, 100 },
+ .seg_count = 3,
+ .flags = MBUF_NO_HEADER,
+ .read_off = 100,
+ .read_len = 1001
+ },
+ {
+ .seg_lengths = { 1000, 1, 1000 },
+ .seg_count = 3,
+ .flags = MBUF_NO_HEADER,
+ .read_off = 1000,
+ .read_len = 2
+ },
+ {
+ .seg_lengths = { MBUF_TEST_DATA_LEN,
+ MBUF_TEST_DATA_LEN2,
+ MBUF_TEST_DATA_LEN3, 800, 10 },
+ .seg_count = 5,
+ .flags = MBUF_NEG_TEST_READ,
+ .read_off = 1000,
+ .read_len = MBUF_DATA_SIZE
+ },
+ };
+
+ uint32_t i, pos;
+ const char *data_copy = NULL;
+ char data_buf[MBUF_DATA_SIZE];
+
+ memset(data_buf, 0, MBUF_DATA_SIZE);
+
+ for (i = 0; i < RTE_DIM(test_cases); i++) {
+ m = create_packet(pktmbuf_pool, &test_cases[i]);
+ if (m == NULL)
+ GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
+
+ data_copy = rte_pktmbuf_read(m, test_cases[i].read_off,
+ test_cases[i].read_len, data_buf);
+ if (test_cases[i].flags == MBUF_NEG_TEST_READ) {
+ if (data_copy != NULL)
+ GOTO_FAIL("%s: mbuf data read should fail!\n",
+ __func__);
+ else {
+ rte_pktmbuf_free(m);
+ m = NULL;
+ continue;
+ }
+ }
+ if (data_copy == NULL)
+ GOTO_FAIL("%s: Error in reading packet data!\n",
+ __func__);
+ for (pos = 0; pos < test_cases[i].read_len; pos++) {
+ if (data_copy[pos] !=
+ (char)((test_cases[i].read_off + pos)
+ % 0xffff))
+ GOTO_FAIL("Data corrupted at offset %u is %2X",
+ pos, data_copy[pos]);
+ }
+ rte_pktmbuf_dump(stdout, m, rte_pktmbuf_pkt_len(m));
+ rte_pktmbuf_free(m);
+ m = NULL;
+ }
+ return 0;
+
+fail:
+ if (m != NULL) {
+ rte_pktmbuf_free(m);
+ m = NULL;
+ }
+ return -1;
+}
+
+/* Define a free call back function to be used for external buffer */
+static void
+ext_buf_free_callback_fn(void *addr __rte_unused, void *opaque)
+{
+ void *ext_buf_addr = opaque;
+
+ if (ext_buf_addr == NULL) {
+ printf("External buffer address is invalid\n");
+ return;
+ }
+ rte_free(ext_buf_addr);
+ ext_buf_addr = NULL;
+ printf("External buffer freed via callback\n");
+}
+
+/*
+ * Test to initialize shared data in external buffer before attaching to mbuf
+ * - Allocate mbuf with no data.
+ * - Allocate external buffer with size should be large enough to accommodate
+ * rte_mbuf_ext_shared_info.
+ * - Invoke pktmbuf_ext_shinfo_init_helper to initialize shared data.
+ * - Invoke rte_pktmbuf_attach_extbuf to attach external buffer to the mbuf.
+ * - Clone another mbuf and attach the same external buffer to it.
+ * - Invoke rte_pktmbuf_detach_extbuf to detach the external buffer from mbuf.
+ */
+static int
+test_pktmbuf_ext_shinfo_init_helper(struct rte_mempool *pktmbuf_pool)
+{
+ struct rte_mbuf *m = NULL;
+ struct rte_mbuf *clone = NULL;
+ struct rte_mbuf_ext_shared_info *ret_shinfo = NULL;
+ rte_iova_t buf_iova;
+ void *ext_buf_addr = NULL;
+ uint16_t buf_len = EXT_BUF_TEST_DATA_LEN +
+ sizeof(struct rte_mbuf_ext_shared_info);
+
+ /* alloc a mbuf */
+ m = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (m == NULL)
+ GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
+ if (rte_pktmbuf_pkt_len(m) != 0)
+ GOTO_FAIL("%s: Bad packet length\n", __func__);
+ rte_mbuf_sanity_check(m, 0);
+
+ ext_buf_addr = rte_malloc("External buffer", buf_len,
+ RTE_CACHE_LINE_SIZE);
+ if (ext_buf_addr == NULL)
+ GOTO_FAIL("%s: External buffer allocation failed\n", __func__);
+
+ ret_shinfo = rte_pktmbuf_ext_shinfo_init_helper(ext_buf_addr, &buf_len,
+ ext_buf_free_callback_fn, ext_buf_addr);
+ if (ret_shinfo == NULL)
+ GOTO_FAIL("%s: Shared info initialization failed!\n", __func__);
+
+ if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 1)
+ GOTO_FAIL("%s: External refcount is not 1\n", __func__);
+
+ if (rte_mbuf_refcnt_read(m) != 1)
+ GOTO_FAIL("%s: Invalid refcnt in mbuf\n", __func__);
+
+ buf_iova = rte_mempool_virt2iova(ext_buf_addr);
+ rte_pktmbuf_attach_extbuf(m, ext_buf_addr, buf_iova, buf_len,
+ ret_shinfo);
+ if (m->ol_flags != EXT_ATTACHED_MBUF)
+ GOTO_FAIL("%s: External buffer is not attached to mbuf\n",
+ __func__);
+
+ /* allocate one more mbuf */
+ clone = rte_pktmbuf_clone(m, pktmbuf_pool);
+ if (clone == NULL)
+ GOTO_FAIL("%s: mbuf clone allocation failed!\n", __func__);
+ if (rte_pktmbuf_pkt_len(clone) != 0)
+ GOTO_FAIL("%s: Bad packet length\n", __func__);
+
+ /* attach the same external buffer to the cloned mbuf */
+ rte_pktmbuf_attach_extbuf(clone, ext_buf_addr, buf_iova, buf_len,
+ ret_shinfo);
+ if (clone->ol_flags != EXT_ATTACHED_MBUF)
+ GOTO_FAIL("%s: External buffer is not attached to mbuf\n",
+ __func__);
+
+ if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 2)
+ GOTO_FAIL("%s: Invalid ext_buf ref_cnt\n", __func__);
+
+ /* test to manually update ext_buf_ref_cnt from 2 to 3*/
+ rte_mbuf_ext_refcnt_update(ret_shinfo, 1);
+ if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 3)
+ GOTO_FAIL("%s: Update ext_buf ref_cnt failed\n", __func__);
+
+ /* reset the ext_refcnt before freeing the external buffer */
+ rte_mbuf_ext_refcnt_set(ret_shinfo, 2);
+ if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 2)
+ GOTO_FAIL("%s: set ext_buf ref_cnt failed\n", __func__);
+
+ /* detach the external buffer from mbufs */
+ rte_pktmbuf_detach_extbuf(m);
+ /* check if ref cnt is decremented */
+ if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 1)
+ GOTO_FAIL("%s: Invalid ext_buf ref_cnt\n", __func__);
+
+ rte_pktmbuf_detach_extbuf(clone);
+ if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 0)
+ GOTO_FAIL("%s: Invalid ext_buf ref_cnt\n", __func__);
+
+ rte_pktmbuf_free(m);
+ m = NULL;
+ rte_pktmbuf_free(clone);
+ clone = NULL;
+
+ return 0;
+
+fail:
+ if (m) {
+ rte_pktmbuf_free(m);
+ m = NULL;
+ }
+ if (clone) {
+ rte_pktmbuf_free(clone);
+ clone = NULL;
+ }
+ if (ext_buf_addr != NULL) {
+ rte_free(ext_buf_addr);
+ ext_buf_addr = NULL;
+ }
+ 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])) {
+ if (rte_errno == EBUSY)
+ printf("mbuf test error skipped: dynfield is busy\n");
+ else
+ 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, flag3=%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)
{
/* create pktmbuf pool if it does not exist */
pktmbuf_pool = rte_pktmbuf_pool_create("test_pktmbuf_pool",
- NB_MBUF, 32, 0, MBUF_DATA_SIZE, SOCKET_ID_ANY);
+ NB_MBUF, MEMPOOL_CACHE_SIZE, 0, MBUF_DATA_SIZE,
+ SOCKET_ID_ANY);
if (pktmbuf_pool == NULL) {
printf("cannot allocate mbuf pool\n");
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",
- NB_MBUF, 32, MBUF2_PRIV_SIZE, 0, SOCKET_ID_ANY);
+ NB_MBUF, MEMPOOL_CACHE_SIZE, MBUF2_PRIV_SIZE, 0,
+ SOCKET_ID_ANY);
if (pktmbuf_pool2 == NULL) {
printf("cannot allocate mbuf pool\n");
goto err;
}
+ /* test bulk mbuf alloc and free */
+ if (test_pktmbuf_pool_bulk() < 0) {
+ printf("test_pktmbuf_pool_bulk() failed\n");
+ goto err;
+ }
+
/* test that the pointer to the data on a packet mbuf is set properly */
if (test_pktmbuf_pool_ptr(pktmbuf_pool) < 0) {
printf("test_pktmbuf_pool_ptr() failed\n");
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;
}
+ if (test_get_rx_ol_flag_list() < 0) {
+ printf("test_rte_get_rx_ol_flag_list() failed\n");
+ goto err;
+ }
+
+ if (test_get_tx_ol_flag_list() < 0) {
+ printf("test_rte_get_tx_ol_flag_list() failed\n");
+ goto err;
+ }
+
+ if (test_get_rx_ol_flag_name() < 0) {
+ printf("test_rte_get_rx_ol_flag_name() failed\n");
+ goto err;
+ }
+
+ if (test_get_tx_ol_flag_name() < 0) {
+ printf("test_rte_get_tx_ol_flag_name() failed\n");
+ goto err;
+ }
+
+ if (test_mbuf_validate_tx_offload_one(pktmbuf_pool) < 0) {
+ printf("test_mbuf_validate_tx_offload_one() failed\n");
+ goto err;
+ }
+
+ /* test for allocating a bulk of mbufs with various sizes */
+ if (test_pktmbuf_alloc_bulk(pktmbuf_pool) < 0) {
+ printf("test_rte_pktmbuf_alloc_bulk() failed\n");
+ goto err;
+ }
+
+ /* test for allocating a bulk of mbufs with various sizes */
+ if (test_neg_pktmbuf_alloc_bulk(pktmbuf_pool) < 0) {
+ printf("test_neg_rte_pktmbuf_alloc_bulk() failed\n");
+ goto err;
+ }
+
+ /* test to read mbuf packet */
+ if (test_pktmbuf_read(pktmbuf_pool) < 0) {
+ printf("test_rte_pktmbuf_read() failed\n");
+ goto err;
+ }
+
+ /* test to read mbuf packet from offset */
+ if (test_pktmbuf_read_from_offset(pktmbuf_pool) < 0) {
+ printf("test_rte_pktmbuf_read_from_offset() failed\n");
+ goto err;
+ }
+
+ /* test to read data from chain of mbufs with data segments */
+ if (test_pktmbuf_read_from_chain(pktmbuf_pool) < 0) {
+ printf("test_rte_pktmbuf_read_from_chain() failed\n");
+ goto err;
+ }
+
+ /* test to initialize shared info. at the end of external buffer */
+ if (test_pktmbuf_ext_shinfo_init_helper(pktmbuf_pool) < 0) {
+ printf("test_pktmbuf_ext_shinfo_init_helper() failed\n");
+ 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);
rte_mempool_free(pktmbuf_pool2);
return ret;
}
+#undef GOTO_FAIL
REGISTER_TEST_COMMAND(mbuf_autotest, test_mbuf);