199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 299a2dd95SBruce Richardson * Copyright(c) 2010-2014 Intel Corporation. 399a2dd95SBruce Richardson * Copyright 2014 6WIND S.A. 499a2dd95SBruce Richardson */ 599a2dd95SBruce Richardson 699a2dd95SBruce Richardson #include <string.h> 799a2dd95SBruce Richardson #include <stdio.h> 899a2dd95SBruce Richardson #include <stdint.h> 999a2dd95SBruce Richardson #include <inttypes.h> 1099a2dd95SBruce Richardson #include <errno.h> 1199a2dd95SBruce Richardson 1299a2dd95SBruce Richardson #include <rte_debug.h> 1399a2dd95SBruce Richardson #include <rte_common.h> 1499a2dd95SBruce Richardson #include <rte_log.h> 1599a2dd95SBruce Richardson #include <rte_branch_prediction.h> 1699a2dd95SBruce Richardson #include <rte_mempool.h> 1799a2dd95SBruce Richardson #include <rte_mbuf.h> 1899a2dd95SBruce Richardson #include <rte_mbuf_pool_ops.h> 1999a2dd95SBruce Richardson #include <rte_hexdump.h> 2099a2dd95SBruce Richardson #include <rte_errno.h> 2199a2dd95SBruce Richardson #include <rte_memcpy.h> 2299a2dd95SBruce Richardson 2399a2dd95SBruce Richardson /* 2499a2dd95SBruce Richardson * pktmbuf pool constructor, given as a callback function to 2599a2dd95SBruce Richardson * rte_mempool_create(), or called directly if using 2699a2dd95SBruce Richardson * rte_mempool_create_empty()/rte_mempool_populate() 2799a2dd95SBruce Richardson */ 2899a2dd95SBruce Richardson void 2999a2dd95SBruce Richardson rte_pktmbuf_pool_init(struct rte_mempool *mp, void *opaque_arg) 3099a2dd95SBruce Richardson { 3199a2dd95SBruce Richardson struct rte_pktmbuf_pool_private *user_mbp_priv, *mbp_priv; 3299a2dd95SBruce Richardson struct rte_pktmbuf_pool_private default_mbp_priv; 3399a2dd95SBruce Richardson uint16_t roomsz; 3499a2dd95SBruce Richardson 35bd611385SOlivier Matz RTE_ASSERT(mp->private_data_size >= 36bd611385SOlivier Matz sizeof(struct rte_pktmbuf_pool_private)); 3799a2dd95SBruce Richardson RTE_ASSERT(mp->elt_size >= sizeof(struct rte_mbuf)); 3899a2dd95SBruce Richardson 3999a2dd95SBruce Richardson /* if no structure is provided, assume no mbuf private area */ 4099a2dd95SBruce Richardson user_mbp_priv = opaque_arg; 4199a2dd95SBruce Richardson if (user_mbp_priv == NULL) { 4299a2dd95SBruce Richardson memset(&default_mbp_priv, 0, sizeof(default_mbp_priv)); 4399a2dd95SBruce Richardson if (mp->elt_size > sizeof(struct rte_mbuf)) 4499a2dd95SBruce Richardson roomsz = mp->elt_size - sizeof(struct rte_mbuf); 4599a2dd95SBruce Richardson else 4699a2dd95SBruce Richardson roomsz = 0; 4799a2dd95SBruce Richardson default_mbp_priv.mbuf_data_room_size = roomsz; 4899a2dd95SBruce Richardson user_mbp_priv = &default_mbp_priv; 4999a2dd95SBruce Richardson } 5099a2dd95SBruce Richardson 5199a2dd95SBruce Richardson RTE_ASSERT(mp->elt_size >= sizeof(struct rte_mbuf) + 5299a2dd95SBruce Richardson ((user_mbp_priv->flags & RTE_PKTMBUF_POOL_F_PINNED_EXT_BUF) ? 5399a2dd95SBruce Richardson sizeof(struct rte_mbuf_ext_shared_info) : 5499a2dd95SBruce Richardson user_mbp_priv->mbuf_data_room_size) + 5599a2dd95SBruce Richardson user_mbp_priv->mbuf_priv_size); 5699a2dd95SBruce Richardson RTE_ASSERT((user_mbp_priv->flags & 5799a2dd95SBruce Richardson ~RTE_PKTMBUF_POOL_F_PINNED_EXT_BUF) == 0); 5899a2dd95SBruce Richardson 5999a2dd95SBruce Richardson mbp_priv = rte_mempool_get_priv(mp); 6099a2dd95SBruce Richardson memcpy(mbp_priv, user_mbp_priv, sizeof(*mbp_priv)); 6199a2dd95SBruce Richardson } 6299a2dd95SBruce Richardson 6399a2dd95SBruce Richardson /* 6499a2dd95SBruce Richardson * pktmbuf constructor, given as a callback function to 6599a2dd95SBruce Richardson * rte_mempool_obj_iter() or rte_mempool_create(). 6699a2dd95SBruce Richardson * Set the fields of a packet mbuf to their default values. 6799a2dd95SBruce Richardson */ 6899a2dd95SBruce Richardson void 6999a2dd95SBruce Richardson rte_pktmbuf_init(struct rte_mempool *mp, 7099a2dd95SBruce Richardson __rte_unused void *opaque_arg, 7199a2dd95SBruce Richardson void *_m, 7299a2dd95SBruce Richardson __rte_unused unsigned i) 7399a2dd95SBruce Richardson { 7499a2dd95SBruce Richardson struct rte_mbuf *m = _m; 7599a2dd95SBruce Richardson uint32_t mbuf_size, buf_len, priv_size; 7699a2dd95SBruce Richardson 77bd611385SOlivier Matz RTE_ASSERT(mp->private_data_size >= 78bd611385SOlivier Matz sizeof(struct rte_pktmbuf_pool_private)); 79bd611385SOlivier Matz 8099a2dd95SBruce Richardson priv_size = rte_pktmbuf_priv_size(mp); 8199a2dd95SBruce Richardson mbuf_size = sizeof(struct rte_mbuf) + priv_size; 8299a2dd95SBruce Richardson buf_len = rte_pktmbuf_data_room_size(mp); 8399a2dd95SBruce Richardson 8499a2dd95SBruce Richardson RTE_ASSERT(RTE_ALIGN(priv_size, RTE_MBUF_PRIV_ALIGN) == priv_size); 8599a2dd95SBruce Richardson RTE_ASSERT(mp->elt_size >= mbuf_size); 8699a2dd95SBruce Richardson RTE_ASSERT(buf_len <= UINT16_MAX); 8799a2dd95SBruce Richardson 8899a2dd95SBruce Richardson memset(m, 0, mbuf_size); 8999a2dd95SBruce Richardson /* start of buffer is after mbuf structure and priv data */ 9099a2dd95SBruce Richardson m->priv_size = priv_size; 9199a2dd95SBruce Richardson m->buf_addr = (char *)m + mbuf_size; 92*e811e2d7SShijith Thotton rte_mbuf_iova_set(m, rte_mempool_virt2iova(m) + mbuf_size); 9399a2dd95SBruce Richardson m->buf_len = (uint16_t)buf_len; 9499a2dd95SBruce Richardson 9599a2dd95SBruce Richardson /* keep some headroom between start of buffer and data */ 9699a2dd95SBruce Richardson m->data_off = RTE_MIN(RTE_PKTMBUF_HEADROOM, (uint16_t)m->buf_len); 9799a2dd95SBruce Richardson 9899a2dd95SBruce Richardson /* init some constant fields */ 9999a2dd95SBruce Richardson m->pool = mp; 10099a2dd95SBruce Richardson m->nb_segs = 1; 10199a2dd95SBruce Richardson m->port = RTE_MBUF_PORT_INVALID; 10299a2dd95SBruce Richardson rte_mbuf_refcnt_set(m, 1); 10399a2dd95SBruce Richardson m->next = NULL; 10499a2dd95SBruce Richardson } 10599a2dd95SBruce Richardson 10699a2dd95SBruce Richardson /* 10799a2dd95SBruce Richardson * @internal The callback routine called when reference counter in shinfo 10899a2dd95SBruce Richardson * for mbufs with pinned external buffer reaches zero. It means there is 10999a2dd95SBruce Richardson * no more reference to buffer backing mbuf and this one should be freed. 11099a2dd95SBruce Richardson * This routine is called for the regular (not with pinned external or 11199a2dd95SBruce Richardson * indirect buffer) mbufs on detaching from the mbuf with pinned external 11299a2dd95SBruce Richardson * buffer. 11399a2dd95SBruce Richardson */ 11499a2dd95SBruce Richardson static void 11599a2dd95SBruce Richardson rte_pktmbuf_free_pinned_extmem(void *addr, void *opaque) 11699a2dd95SBruce Richardson { 11799a2dd95SBruce Richardson struct rte_mbuf *m = opaque; 11899a2dd95SBruce Richardson 11999a2dd95SBruce Richardson RTE_SET_USED(addr); 12099a2dd95SBruce Richardson RTE_ASSERT(RTE_MBUF_HAS_EXTBUF(m)); 12199a2dd95SBruce Richardson RTE_ASSERT(RTE_MBUF_HAS_PINNED_EXTBUF(m)); 12299a2dd95SBruce Richardson RTE_ASSERT(m->shinfo->fcb_opaque == m); 12399a2dd95SBruce Richardson 12499a2dd95SBruce Richardson rte_mbuf_ext_refcnt_set(m->shinfo, 1); 125daa02b5cSOlivier Matz m->ol_flags = RTE_MBUF_F_EXTERNAL; 126efc6f910SOlivier Matz if (m->next != NULL) 12799a2dd95SBruce Richardson m->next = NULL; 128efc6f910SOlivier Matz if (m->nb_segs != 1) 12999a2dd95SBruce Richardson m->nb_segs = 1; 13099a2dd95SBruce Richardson rte_mbuf_raw_free(m); 13199a2dd95SBruce Richardson } 13299a2dd95SBruce Richardson 13399a2dd95SBruce Richardson /** The context to initialize the mbufs with pinned external buffers. */ 13499a2dd95SBruce Richardson struct rte_pktmbuf_extmem_init_ctx { 13599a2dd95SBruce Richardson const struct rte_pktmbuf_extmem *ext_mem; /* descriptor array. */ 13699a2dd95SBruce Richardson unsigned int ext_num; /* number of descriptors in array. */ 13799a2dd95SBruce Richardson unsigned int ext; /* loop descriptor index. */ 13899a2dd95SBruce Richardson size_t off; /* loop buffer offset. */ 13999a2dd95SBruce Richardson }; 14099a2dd95SBruce Richardson 14199a2dd95SBruce Richardson /** 14299a2dd95SBruce Richardson * @internal Packet mbuf constructor for pools with pinned external memory. 14399a2dd95SBruce Richardson * 14499a2dd95SBruce Richardson * This function initializes some fields in the mbuf structure that are 14599a2dd95SBruce Richardson * not modified by the user once created (origin pool, buffer start 14699a2dd95SBruce Richardson * address, and so on). This function is given as a callback function to 14799a2dd95SBruce Richardson * rte_mempool_obj_iter() called from rte_mempool_create_extmem(). 14899a2dd95SBruce Richardson * 14999a2dd95SBruce Richardson * @param mp 15099a2dd95SBruce Richardson * The mempool from which mbufs originate. 15199a2dd95SBruce Richardson * @param opaque_arg 15299a2dd95SBruce Richardson * A pointer to the rte_pktmbuf_extmem_init_ctx - initialization 15399a2dd95SBruce Richardson * context structure 15499a2dd95SBruce Richardson * @param m 15599a2dd95SBruce Richardson * The mbuf to initialize. 15699a2dd95SBruce Richardson * @param i 15799a2dd95SBruce Richardson * The index of the mbuf in the pool table. 15899a2dd95SBruce Richardson */ 15999a2dd95SBruce Richardson static void 16099a2dd95SBruce Richardson __rte_pktmbuf_init_extmem(struct rte_mempool *mp, 16199a2dd95SBruce Richardson void *opaque_arg, 16299a2dd95SBruce Richardson void *_m, 16399a2dd95SBruce Richardson __rte_unused unsigned int i) 16499a2dd95SBruce Richardson { 16599a2dd95SBruce Richardson struct rte_mbuf *m = _m; 16699a2dd95SBruce Richardson struct rte_pktmbuf_extmem_init_ctx *ctx = opaque_arg; 16799a2dd95SBruce Richardson const struct rte_pktmbuf_extmem *ext_mem; 16899a2dd95SBruce Richardson uint32_t mbuf_size, buf_len, priv_size; 16999a2dd95SBruce Richardson struct rte_mbuf_ext_shared_info *shinfo; 17099a2dd95SBruce Richardson 17199a2dd95SBruce Richardson priv_size = rte_pktmbuf_priv_size(mp); 17299a2dd95SBruce Richardson mbuf_size = sizeof(struct rte_mbuf) + priv_size; 17399a2dd95SBruce Richardson buf_len = rte_pktmbuf_data_room_size(mp); 17499a2dd95SBruce Richardson 17599a2dd95SBruce Richardson RTE_ASSERT(RTE_ALIGN(priv_size, RTE_MBUF_PRIV_ALIGN) == priv_size); 17699a2dd95SBruce Richardson RTE_ASSERT(mp->elt_size >= mbuf_size); 17799a2dd95SBruce Richardson RTE_ASSERT(buf_len <= UINT16_MAX); 17899a2dd95SBruce Richardson 17999a2dd95SBruce Richardson memset(m, 0, mbuf_size); 18099a2dd95SBruce Richardson m->priv_size = priv_size; 18199a2dd95SBruce Richardson m->buf_len = (uint16_t)buf_len; 18299a2dd95SBruce Richardson 18399a2dd95SBruce Richardson /* set the data buffer pointers to external memory */ 18499a2dd95SBruce Richardson ext_mem = ctx->ext_mem + ctx->ext; 18599a2dd95SBruce Richardson 18699a2dd95SBruce Richardson RTE_ASSERT(ctx->ext < ctx->ext_num); 18799a2dd95SBruce Richardson RTE_ASSERT(ctx->off + ext_mem->elt_size <= ext_mem->buf_len); 18899a2dd95SBruce Richardson 18999a2dd95SBruce Richardson m->buf_addr = RTE_PTR_ADD(ext_mem->buf_ptr, ctx->off); 190*e811e2d7SShijith Thotton rte_mbuf_iova_set(m, ext_mem->buf_iova == RTE_BAD_IOVA ? RTE_BAD_IOVA : 191*e811e2d7SShijith Thotton (ext_mem->buf_iova + ctx->off)); 19299a2dd95SBruce Richardson 19399a2dd95SBruce Richardson ctx->off += ext_mem->elt_size; 19499a2dd95SBruce Richardson if (ctx->off + ext_mem->elt_size > ext_mem->buf_len) { 19599a2dd95SBruce Richardson ctx->off = 0; 19699a2dd95SBruce Richardson ++ctx->ext; 19799a2dd95SBruce Richardson } 19899a2dd95SBruce Richardson /* keep some headroom between start of buffer and data */ 19999a2dd95SBruce Richardson m->data_off = RTE_MIN(RTE_PKTMBUF_HEADROOM, (uint16_t)m->buf_len); 20099a2dd95SBruce Richardson 20199a2dd95SBruce Richardson /* init some constant fields */ 20299a2dd95SBruce Richardson m->pool = mp; 20399a2dd95SBruce Richardson m->nb_segs = 1; 20499a2dd95SBruce Richardson m->port = RTE_MBUF_PORT_INVALID; 205daa02b5cSOlivier Matz m->ol_flags = RTE_MBUF_F_EXTERNAL; 20699a2dd95SBruce Richardson rte_mbuf_refcnt_set(m, 1); 20799a2dd95SBruce Richardson m->next = NULL; 20899a2dd95SBruce Richardson 20999a2dd95SBruce Richardson /* init external buffer shared info items */ 21099a2dd95SBruce Richardson shinfo = RTE_PTR_ADD(m, mbuf_size); 21199a2dd95SBruce Richardson m->shinfo = shinfo; 21299a2dd95SBruce Richardson shinfo->free_cb = rte_pktmbuf_free_pinned_extmem; 21399a2dd95SBruce Richardson shinfo->fcb_opaque = m; 21499a2dd95SBruce Richardson rte_mbuf_ext_refcnt_set(shinfo, 1); 21599a2dd95SBruce Richardson } 21699a2dd95SBruce Richardson 21799a2dd95SBruce Richardson /* Helper to create a mbuf pool with given mempool ops name*/ 21899a2dd95SBruce Richardson struct rte_mempool * 21999a2dd95SBruce Richardson rte_pktmbuf_pool_create_by_ops(const char *name, unsigned int n, 22099a2dd95SBruce Richardson unsigned int cache_size, uint16_t priv_size, uint16_t data_room_size, 22199a2dd95SBruce Richardson int socket_id, const char *ops_name) 22299a2dd95SBruce Richardson { 22399a2dd95SBruce Richardson struct rte_mempool *mp; 22499a2dd95SBruce Richardson struct rte_pktmbuf_pool_private mbp_priv; 22599a2dd95SBruce Richardson const char *mp_ops_name = ops_name; 22699a2dd95SBruce Richardson unsigned elt_size; 22799a2dd95SBruce Richardson int ret; 22899a2dd95SBruce Richardson 22999a2dd95SBruce Richardson if (RTE_ALIGN(priv_size, RTE_MBUF_PRIV_ALIGN) != priv_size) { 23099a2dd95SBruce Richardson RTE_LOG(ERR, MBUF, "mbuf priv_size=%u is not aligned\n", 23199a2dd95SBruce Richardson priv_size); 23299a2dd95SBruce Richardson rte_errno = EINVAL; 23399a2dd95SBruce Richardson return NULL; 23499a2dd95SBruce Richardson } 23599a2dd95SBruce Richardson elt_size = sizeof(struct rte_mbuf) + (unsigned)priv_size + 23699a2dd95SBruce Richardson (unsigned)data_room_size; 23799a2dd95SBruce Richardson memset(&mbp_priv, 0, sizeof(mbp_priv)); 23899a2dd95SBruce Richardson mbp_priv.mbuf_data_room_size = data_room_size; 23999a2dd95SBruce Richardson mbp_priv.mbuf_priv_size = priv_size; 24099a2dd95SBruce Richardson 24199a2dd95SBruce Richardson mp = rte_mempool_create_empty(name, n, elt_size, cache_size, 24299a2dd95SBruce Richardson sizeof(struct rte_pktmbuf_pool_private), socket_id, 0); 24399a2dd95SBruce Richardson if (mp == NULL) 24499a2dd95SBruce Richardson return NULL; 24599a2dd95SBruce Richardson 24699a2dd95SBruce Richardson if (mp_ops_name == NULL) 24799a2dd95SBruce Richardson mp_ops_name = rte_mbuf_best_mempool_ops(); 24899a2dd95SBruce Richardson ret = rte_mempool_set_ops_byname(mp, mp_ops_name, NULL); 24999a2dd95SBruce Richardson if (ret != 0) { 25099a2dd95SBruce Richardson RTE_LOG(ERR, MBUF, "error setting mempool handler\n"); 25199a2dd95SBruce Richardson rte_mempool_free(mp); 25299a2dd95SBruce Richardson rte_errno = -ret; 25399a2dd95SBruce Richardson return NULL; 25499a2dd95SBruce Richardson } 25599a2dd95SBruce Richardson rte_pktmbuf_pool_init(mp, &mbp_priv); 25699a2dd95SBruce Richardson 25799a2dd95SBruce Richardson ret = rte_mempool_populate_default(mp); 25899a2dd95SBruce Richardson if (ret < 0) { 25999a2dd95SBruce Richardson rte_mempool_free(mp); 26099a2dd95SBruce Richardson rte_errno = -ret; 26199a2dd95SBruce Richardson return NULL; 26299a2dd95SBruce Richardson } 26399a2dd95SBruce Richardson 26499a2dd95SBruce Richardson rte_mempool_obj_iter(mp, rte_pktmbuf_init, NULL); 26599a2dd95SBruce Richardson 26699a2dd95SBruce Richardson return mp; 26799a2dd95SBruce Richardson } 26899a2dd95SBruce Richardson 26999a2dd95SBruce Richardson /* helper to create a mbuf pool */ 27099a2dd95SBruce Richardson struct rte_mempool * 27199a2dd95SBruce Richardson rte_pktmbuf_pool_create(const char *name, unsigned int n, 27299a2dd95SBruce Richardson unsigned int cache_size, uint16_t priv_size, uint16_t data_room_size, 27399a2dd95SBruce Richardson int socket_id) 27499a2dd95SBruce Richardson { 27599a2dd95SBruce Richardson return rte_pktmbuf_pool_create_by_ops(name, n, cache_size, priv_size, 27699a2dd95SBruce Richardson data_room_size, socket_id, NULL); 27799a2dd95SBruce Richardson } 27899a2dd95SBruce Richardson 27999a2dd95SBruce Richardson /* Helper to create a mbuf pool with pinned external data buffers. */ 28099a2dd95SBruce Richardson struct rte_mempool * 28199a2dd95SBruce Richardson rte_pktmbuf_pool_create_extbuf(const char *name, unsigned int n, 28299a2dd95SBruce Richardson unsigned int cache_size, uint16_t priv_size, 28399a2dd95SBruce Richardson uint16_t data_room_size, int socket_id, 28499a2dd95SBruce Richardson const struct rte_pktmbuf_extmem *ext_mem, 28599a2dd95SBruce Richardson unsigned int ext_num) 28699a2dd95SBruce Richardson { 28799a2dd95SBruce Richardson struct rte_mempool *mp; 28899a2dd95SBruce Richardson struct rte_pktmbuf_pool_private mbp_priv; 28999a2dd95SBruce Richardson struct rte_pktmbuf_extmem_init_ctx init_ctx; 29099a2dd95SBruce Richardson const char *mp_ops_name; 29199a2dd95SBruce Richardson unsigned int elt_size; 29299a2dd95SBruce Richardson unsigned int i, n_elts = 0; 29399a2dd95SBruce Richardson int ret; 29499a2dd95SBruce Richardson 29599a2dd95SBruce Richardson if (RTE_ALIGN(priv_size, RTE_MBUF_PRIV_ALIGN) != priv_size) { 29699a2dd95SBruce Richardson RTE_LOG(ERR, MBUF, "mbuf priv_size=%u is not aligned\n", 29799a2dd95SBruce Richardson priv_size); 29899a2dd95SBruce Richardson rte_errno = EINVAL; 29999a2dd95SBruce Richardson return NULL; 30099a2dd95SBruce Richardson } 30199a2dd95SBruce Richardson /* Check the external memory descriptors. */ 30299a2dd95SBruce Richardson for (i = 0; i < ext_num; i++) { 30399a2dd95SBruce Richardson const struct rte_pktmbuf_extmem *extm = ext_mem + i; 30499a2dd95SBruce Richardson 30599a2dd95SBruce Richardson if (!extm->elt_size || !extm->buf_len || !extm->buf_ptr) { 30699a2dd95SBruce Richardson RTE_LOG(ERR, MBUF, "invalid extmem descriptor\n"); 30799a2dd95SBruce Richardson rte_errno = EINVAL; 30899a2dd95SBruce Richardson return NULL; 30999a2dd95SBruce Richardson } 31099a2dd95SBruce Richardson if (data_room_size > extm->elt_size) { 31199a2dd95SBruce Richardson RTE_LOG(ERR, MBUF, "ext elt_size=%u is too small\n", 31299a2dd95SBruce Richardson priv_size); 31399a2dd95SBruce Richardson rte_errno = EINVAL; 31499a2dd95SBruce Richardson return NULL; 31599a2dd95SBruce Richardson } 31699a2dd95SBruce Richardson n_elts += extm->buf_len / extm->elt_size; 31799a2dd95SBruce Richardson } 31899a2dd95SBruce Richardson /* Check whether enough external memory provided. */ 31999a2dd95SBruce Richardson if (n_elts < n) { 32099a2dd95SBruce Richardson RTE_LOG(ERR, MBUF, "not enough extmem\n"); 32199a2dd95SBruce Richardson rte_errno = ENOMEM; 32299a2dd95SBruce Richardson return NULL; 32399a2dd95SBruce Richardson } 32499a2dd95SBruce Richardson elt_size = sizeof(struct rte_mbuf) + 32599a2dd95SBruce Richardson (unsigned int)priv_size + 32699a2dd95SBruce Richardson sizeof(struct rte_mbuf_ext_shared_info); 32799a2dd95SBruce Richardson 32899a2dd95SBruce Richardson memset(&mbp_priv, 0, sizeof(mbp_priv)); 32999a2dd95SBruce Richardson mbp_priv.mbuf_data_room_size = data_room_size; 33099a2dd95SBruce Richardson mbp_priv.mbuf_priv_size = priv_size; 33199a2dd95SBruce Richardson mbp_priv.flags = RTE_PKTMBUF_POOL_F_PINNED_EXT_BUF; 33299a2dd95SBruce Richardson 33399a2dd95SBruce Richardson mp = rte_mempool_create_empty(name, n, elt_size, cache_size, 33499a2dd95SBruce Richardson sizeof(struct rte_pktmbuf_pool_private), socket_id, 0); 33599a2dd95SBruce Richardson if (mp == NULL) 33699a2dd95SBruce Richardson return NULL; 33799a2dd95SBruce Richardson 33899a2dd95SBruce Richardson mp_ops_name = rte_mbuf_best_mempool_ops(); 33999a2dd95SBruce Richardson ret = rte_mempool_set_ops_byname(mp, mp_ops_name, NULL); 34099a2dd95SBruce Richardson if (ret != 0) { 34199a2dd95SBruce Richardson RTE_LOG(ERR, MBUF, "error setting mempool handler\n"); 34299a2dd95SBruce Richardson rte_mempool_free(mp); 34399a2dd95SBruce Richardson rte_errno = -ret; 34499a2dd95SBruce Richardson return NULL; 34599a2dd95SBruce Richardson } 34699a2dd95SBruce Richardson rte_pktmbuf_pool_init(mp, &mbp_priv); 34799a2dd95SBruce Richardson 34899a2dd95SBruce Richardson ret = rte_mempool_populate_default(mp); 34999a2dd95SBruce Richardson if (ret < 0) { 35099a2dd95SBruce Richardson rte_mempool_free(mp); 35199a2dd95SBruce Richardson rte_errno = -ret; 35299a2dd95SBruce Richardson return NULL; 35399a2dd95SBruce Richardson } 35499a2dd95SBruce Richardson 35599a2dd95SBruce Richardson init_ctx = (struct rte_pktmbuf_extmem_init_ctx){ 35699a2dd95SBruce Richardson .ext_mem = ext_mem, 35799a2dd95SBruce Richardson .ext_num = ext_num, 35899a2dd95SBruce Richardson .ext = 0, 35999a2dd95SBruce Richardson .off = 0, 36099a2dd95SBruce Richardson }; 36199a2dd95SBruce Richardson rte_mempool_obj_iter(mp, __rte_pktmbuf_init_extmem, &init_ctx); 36299a2dd95SBruce Richardson 36399a2dd95SBruce Richardson return mp; 36499a2dd95SBruce Richardson } 36599a2dd95SBruce Richardson 36699a2dd95SBruce Richardson /* do some sanity checks on a mbuf: panic if it fails */ 36799a2dd95SBruce Richardson void 36899a2dd95SBruce Richardson rte_mbuf_sanity_check(const struct rte_mbuf *m, int is_header) 36999a2dd95SBruce Richardson { 37099a2dd95SBruce Richardson const char *reason; 37199a2dd95SBruce Richardson 37299a2dd95SBruce Richardson if (rte_mbuf_check(m, is_header, &reason)) 37399a2dd95SBruce Richardson rte_panic("%s\n", reason); 37499a2dd95SBruce Richardson } 37599a2dd95SBruce Richardson 37699a2dd95SBruce Richardson int rte_mbuf_check(const struct rte_mbuf *m, int is_header, 37799a2dd95SBruce Richardson const char **reason) 37899a2dd95SBruce Richardson { 37999a2dd95SBruce Richardson unsigned int nb_segs, pkt_len; 38099a2dd95SBruce Richardson 38199a2dd95SBruce Richardson if (m == NULL) { 38299a2dd95SBruce Richardson *reason = "mbuf is NULL"; 38399a2dd95SBruce Richardson return -1; 38499a2dd95SBruce Richardson } 38599a2dd95SBruce Richardson 38699a2dd95SBruce Richardson /* generic checks */ 38799a2dd95SBruce Richardson if (m->pool == NULL) { 38899a2dd95SBruce Richardson *reason = "bad mbuf pool"; 38999a2dd95SBruce Richardson return -1; 39099a2dd95SBruce Richardson } 391*e811e2d7SShijith Thotton if (rte_mbuf_iova_get(m) == 0) { 39299a2dd95SBruce Richardson *reason = "bad IO addr"; 39399a2dd95SBruce Richardson return -1; 39499a2dd95SBruce Richardson } 39599a2dd95SBruce Richardson if (m->buf_addr == NULL) { 39699a2dd95SBruce Richardson *reason = "bad virt addr"; 39799a2dd95SBruce Richardson return -1; 39899a2dd95SBruce Richardson } 39999a2dd95SBruce Richardson 40099a2dd95SBruce Richardson uint16_t cnt = rte_mbuf_refcnt_read(m); 40199a2dd95SBruce Richardson if ((cnt == 0) || (cnt == UINT16_MAX)) { 40299a2dd95SBruce Richardson *reason = "bad ref cnt"; 40399a2dd95SBruce Richardson return -1; 40499a2dd95SBruce Richardson } 40599a2dd95SBruce Richardson 40699a2dd95SBruce Richardson /* nothing to check for sub-segments */ 40799a2dd95SBruce Richardson if (is_header == 0) 40899a2dd95SBruce Richardson return 0; 40999a2dd95SBruce Richardson 41099a2dd95SBruce Richardson /* data_len is supposed to be not more than pkt_len */ 41199a2dd95SBruce Richardson if (m->data_len > m->pkt_len) { 41299a2dd95SBruce Richardson *reason = "bad data_len"; 41399a2dd95SBruce Richardson return -1; 41499a2dd95SBruce Richardson } 41599a2dd95SBruce Richardson 41699a2dd95SBruce Richardson nb_segs = m->nb_segs; 41799a2dd95SBruce Richardson pkt_len = m->pkt_len; 41899a2dd95SBruce Richardson 41999a2dd95SBruce Richardson do { 42099a2dd95SBruce Richardson if (m->data_off > m->buf_len) { 42199a2dd95SBruce Richardson *reason = "data offset too big in mbuf segment"; 42299a2dd95SBruce Richardson return -1; 42399a2dd95SBruce Richardson } 42499a2dd95SBruce Richardson if (m->data_off + m->data_len > m->buf_len) { 42599a2dd95SBruce Richardson *reason = "data length too big in mbuf segment"; 42699a2dd95SBruce Richardson return -1; 42799a2dd95SBruce Richardson } 42899a2dd95SBruce Richardson nb_segs -= 1; 42999a2dd95SBruce Richardson pkt_len -= m->data_len; 43099a2dd95SBruce Richardson } while ((m = m->next) != NULL); 43199a2dd95SBruce Richardson 43299a2dd95SBruce Richardson if (nb_segs) { 43399a2dd95SBruce Richardson *reason = "bad nb_segs"; 43499a2dd95SBruce Richardson return -1; 43599a2dd95SBruce Richardson } 43699a2dd95SBruce Richardson if (pkt_len) { 43799a2dd95SBruce Richardson *reason = "bad pkt_len"; 43899a2dd95SBruce Richardson return -1; 43999a2dd95SBruce Richardson } 44099a2dd95SBruce Richardson 44199a2dd95SBruce Richardson return 0; 44299a2dd95SBruce Richardson } 44399a2dd95SBruce Richardson 44499a2dd95SBruce Richardson /** 44599a2dd95SBruce Richardson * @internal helper function for freeing a bulk of packet mbuf segments 44699a2dd95SBruce Richardson * via an array holding the packet mbuf segments from the same mempool 44799a2dd95SBruce Richardson * pending to be freed. 44899a2dd95SBruce Richardson * 44999a2dd95SBruce Richardson * @param m 45099a2dd95SBruce Richardson * The packet mbuf segment to be freed. 45199a2dd95SBruce Richardson * @param pending 45299a2dd95SBruce Richardson * Pointer to the array of packet mbuf segments pending to be freed. 45399a2dd95SBruce Richardson * @param nb_pending 45499a2dd95SBruce Richardson * Pointer to the number of elements held in the array. 45599a2dd95SBruce Richardson * @param pending_sz 45699a2dd95SBruce Richardson * Number of elements the array can hold. 45799a2dd95SBruce Richardson * Note: The compiler should optimize this parameter away when using a 45899a2dd95SBruce Richardson * constant value, such as RTE_PKTMBUF_FREE_PENDING_SZ. 45999a2dd95SBruce Richardson */ 46099a2dd95SBruce Richardson static void 46199a2dd95SBruce Richardson __rte_pktmbuf_free_seg_via_array(struct rte_mbuf *m, 46299a2dd95SBruce Richardson struct rte_mbuf ** const pending, unsigned int * const nb_pending, 46399a2dd95SBruce Richardson const unsigned int pending_sz) 46499a2dd95SBruce Richardson { 46599a2dd95SBruce Richardson m = rte_pktmbuf_prefree_seg(m); 46699a2dd95SBruce Richardson if (likely(m != NULL)) { 46799a2dd95SBruce Richardson if (*nb_pending == pending_sz || 46899a2dd95SBruce Richardson (*nb_pending > 0 && m->pool != pending[0]->pool)) { 46999a2dd95SBruce Richardson rte_mempool_put_bulk(pending[0]->pool, 47099a2dd95SBruce Richardson (void **)pending, *nb_pending); 47199a2dd95SBruce Richardson *nb_pending = 0; 47299a2dd95SBruce Richardson } 47399a2dd95SBruce Richardson 47499a2dd95SBruce Richardson pending[(*nb_pending)++] = m; 47599a2dd95SBruce Richardson } 47699a2dd95SBruce Richardson } 47799a2dd95SBruce Richardson 47899a2dd95SBruce Richardson /** 47999a2dd95SBruce Richardson * Size of the array holding mbufs from the same mempool pending to be freed 48099a2dd95SBruce Richardson * in bulk. 48199a2dd95SBruce Richardson */ 48299a2dd95SBruce Richardson #define RTE_PKTMBUF_FREE_PENDING_SZ 64 48399a2dd95SBruce Richardson 48499a2dd95SBruce Richardson /* Free a bulk of packet mbufs back into their original mempools. */ 48599a2dd95SBruce Richardson void rte_pktmbuf_free_bulk(struct rte_mbuf **mbufs, unsigned int count) 48699a2dd95SBruce Richardson { 48799a2dd95SBruce Richardson struct rte_mbuf *m, *m_next, *pending[RTE_PKTMBUF_FREE_PENDING_SZ]; 48899a2dd95SBruce Richardson unsigned int idx, nb_pending = 0; 48999a2dd95SBruce Richardson 49099a2dd95SBruce Richardson for (idx = 0; idx < count; idx++) { 49199a2dd95SBruce Richardson m = mbufs[idx]; 49299a2dd95SBruce Richardson if (unlikely(m == NULL)) 49399a2dd95SBruce Richardson continue; 49499a2dd95SBruce Richardson 49599a2dd95SBruce Richardson __rte_mbuf_sanity_check(m, 1); 49699a2dd95SBruce Richardson 49799a2dd95SBruce Richardson do { 49899a2dd95SBruce Richardson m_next = m->next; 49999a2dd95SBruce Richardson __rte_pktmbuf_free_seg_via_array(m, 50099a2dd95SBruce Richardson pending, &nb_pending, 50199a2dd95SBruce Richardson RTE_PKTMBUF_FREE_PENDING_SZ); 50299a2dd95SBruce Richardson m = m_next; 50399a2dd95SBruce Richardson } while (m != NULL); 50499a2dd95SBruce Richardson } 50599a2dd95SBruce Richardson 50699a2dd95SBruce Richardson if (nb_pending > 0) 50799a2dd95SBruce Richardson rte_mempool_put_bulk(pending[0]->pool, (void **)pending, nb_pending); 50899a2dd95SBruce Richardson } 50999a2dd95SBruce Richardson 51099a2dd95SBruce Richardson /* Creates a shallow copy of mbuf */ 51199a2dd95SBruce Richardson struct rte_mbuf * 51299a2dd95SBruce Richardson rte_pktmbuf_clone(struct rte_mbuf *md, struct rte_mempool *mp) 51399a2dd95SBruce Richardson { 51499a2dd95SBruce Richardson struct rte_mbuf *mc, *mi, **prev; 51599a2dd95SBruce Richardson uint32_t pktlen; 51699a2dd95SBruce Richardson uint16_t nseg; 51799a2dd95SBruce Richardson 51899a2dd95SBruce Richardson mc = rte_pktmbuf_alloc(mp); 51999a2dd95SBruce Richardson if (unlikely(mc == NULL)) 52099a2dd95SBruce Richardson return NULL; 52199a2dd95SBruce Richardson 52299a2dd95SBruce Richardson mi = mc; 52399a2dd95SBruce Richardson prev = &mi->next; 52499a2dd95SBruce Richardson pktlen = md->pkt_len; 52599a2dd95SBruce Richardson nseg = 0; 52699a2dd95SBruce Richardson 52799a2dd95SBruce Richardson do { 52899a2dd95SBruce Richardson nseg++; 52999a2dd95SBruce Richardson rte_pktmbuf_attach(mi, md); 53099a2dd95SBruce Richardson *prev = mi; 53199a2dd95SBruce Richardson prev = &mi->next; 53299a2dd95SBruce Richardson } while ((md = md->next) != NULL && 53399a2dd95SBruce Richardson (mi = rte_pktmbuf_alloc(mp)) != NULL); 53499a2dd95SBruce Richardson 53599a2dd95SBruce Richardson *prev = NULL; 53699a2dd95SBruce Richardson mc->nb_segs = nseg; 53799a2dd95SBruce Richardson mc->pkt_len = pktlen; 53899a2dd95SBruce Richardson 53999a2dd95SBruce Richardson /* Allocation of new indirect segment failed */ 54099a2dd95SBruce Richardson if (unlikely(mi == NULL)) { 54199a2dd95SBruce Richardson rte_pktmbuf_free(mc); 54299a2dd95SBruce Richardson return NULL; 54399a2dd95SBruce Richardson } 54499a2dd95SBruce Richardson 54599a2dd95SBruce Richardson __rte_mbuf_sanity_check(mc, 1); 54699a2dd95SBruce Richardson return mc; 54799a2dd95SBruce Richardson } 54899a2dd95SBruce Richardson 54999a2dd95SBruce Richardson /* convert multi-segment mbuf to single mbuf */ 55099a2dd95SBruce Richardson int 55199a2dd95SBruce Richardson __rte_pktmbuf_linearize(struct rte_mbuf *mbuf) 55299a2dd95SBruce Richardson { 55399a2dd95SBruce Richardson size_t seg_len, copy_len; 55499a2dd95SBruce Richardson struct rte_mbuf *m; 55599a2dd95SBruce Richardson struct rte_mbuf *m_next; 55699a2dd95SBruce Richardson char *buffer; 55799a2dd95SBruce Richardson 55899a2dd95SBruce Richardson /* Extend first segment to the total packet length */ 55999a2dd95SBruce Richardson copy_len = rte_pktmbuf_pkt_len(mbuf) - rte_pktmbuf_data_len(mbuf); 56099a2dd95SBruce Richardson 56199a2dd95SBruce Richardson if (unlikely(copy_len > rte_pktmbuf_tailroom(mbuf))) 56299a2dd95SBruce Richardson return -1; 56399a2dd95SBruce Richardson 56499a2dd95SBruce Richardson buffer = rte_pktmbuf_mtod_offset(mbuf, char *, mbuf->data_len); 56599a2dd95SBruce Richardson mbuf->data_len = (uint16_t)(mbuf->pkt_len); 56699a2dd95SBruce Richardson 56799a2dd95SBruce Richardson /* Append data from next segments to the first one */ 56899a2dd95SBruce Richardson m = mbuf->next; 56999a2dd95SBruce Richardson while (m != NULL) { 57099a2dd95SBruce Richardson m_next = m->next; 57199a2dd95SBruce Richardson 57299a2dd95SBruce Richardson seg_len = rte_pktmbuf_data_len(m); 57399a2dd95SBruce Richardson rte_memcpy(buffer, rte_pktmbuf_mtod(m, char *), seg_len); 57499a2dd95SBruce Richardson buffer += seg_len; 57599a2dd95SBruce Richardson 57699a2dd95SBruce Richardson rte_pktmbuf_free_seg(m); 57799a2dd95SBruce Richardson m = m_next; 57899a2dd95SBruce Richardson } 57999a2dd95SBruce Richardson 58099a2dd95SBruce Richardson mbuf->next = NULL; 58199a2dd95SBruce Richardson mbuf->nb_segs = 1; 58299a2dd95SBruce Richardson 58399a2dd95SBruce Richardson return 0; 58499a2dd95SBruce Richardson } 58599a2dd95SBruce Richardson 58699a2dd95SBruce Richardson /* Create a deep copy of mbuf */ 58799a2dd95SBruce Richardson struct rte_mbuf * 58899a2dd95SBruce Richardson rte_pktmbuf_copy(const struct rte_mbuf *m, struct rte_mempool *mp, 58999a2dd95SBruce Richardson uint32_t off, uint32_t len) 59099a2dd95SBruce Richardson { 59199a2dd95SBruce Richardson const struct rte_mbuf *seg = m; 59299a2dd95SBruce Richardson struct rte_mbuf *mc, *m_last, **prev; 59399a2dd95SBruce Richardson 59499a2dd95SBruce Richardson /* garbage in check */ 59599a2dd95SBruce Richardson __rte_mbuf_sanity_check(m, 1); 59699a2dd95SBruce Richardson 59799a2dd95SBruce Richardson /* check for request to copy at offset past end of mbuf */ 59899a2dd95SBruce Richardson if (unlikely(off >= m->pkt_len)) 59999a2dd95SBruce Richardson return NULL; 60099a2dd95SBruce Richardson 60199a2dd95SBruce Richardson mc = rte_pktmbuf_alloc(mp); 60299a2dd95SBruce Richardson if (unlikely(mc == NULL)) 60399a2dd95SBruce Richardson return NULL; 60499a2dd95SBruce Richardson 60599a2dd95SBruce Richardson /* truncate requested length to available data */ 60699a2dd95SBruce Richardson if (len > m->pkt_len - off) 60799a2dd95SBruce Richardson len = m->pkt_len - off; 60899a2dd95SBruce Richardson 60999a2dd95SBruce Richardson __rte_pktmbuf_copy_hdr(mc, m); 61099a2dd95SBruce Richardson 61199a2dd95SBruce Richardson /* copied mbuf is not indirect or external */ 612daa02b5cSOlivier Matz mc->ol_flags = m->ol_flags & ~(RTE_MBUF_F_INDIRECT|RTE_MBUF_F_EXTERNAL); 61399a2dd95SBruce Richardson 61499a2dd95SBruce Richardson prev = &mc->next; 61599a2dd95SBruce Richardson m_last = mc; 61699a2dd95SBruce Richardson while (len > 0) { 61799a2dd95SBruce Richardson uint32_t copy_len; 61899a2dd95SBruce Richardson 61999a2dd95SBruce Richardson /* skip leading mbuf segments */ 62099a2dd95SBruce Richardson while (off >= seg->data_len) { 62199a2dd95SBruce Richardson off -= seg->data_len; 62299a2dd95SBruce Richardson seg = seg->next; 62399a2dd95SBruce Richardson } 62499a2dd95SBruce Richardson 62599a2dd95SBruce Richardson /* current buffer is full, chain a new one */ 62699a2dd95SBruce Richardson if (rte_pktmbuf_tailroom(m_last) == 0) { 62799a2dd95SBruce Richardson m_last = rte_pktmbuf_alloc(mp); 62899a2dd95SBruce Richardson if (unlikely(m_last == NULL)) { 62999a2dd95SBruce Richardson rte_pktmbuf_free(mc); 63099a2dd95SBruce Richardson return NULL; 63199a2dd95SBruce Richardson } 63299a2dd95SBruce Richardson ++mc->nb_segs; 63399a2dd95SBruce Richardson *prev = m_last; 63499a2dd95SBruce Richardson prev = &m_last->next; 63599a2dd95SBruce Richardson } 63699a2dd95SBruce Richardson 63799a2dd95SBruce Richardson /* 63899a2dd95SBruce Richardson * copy the min of data in input segment (seg) 63999a2dd95SBruce Richardson * vs space available in output (m_last) 64099a2dd95SBruce Richardson */ 64199a2dd95SBruce Richardson copy_len = RTE_MIN(seg->data_len - off, len); 64299a2dd95SBruce Richardson if (copy_len > rte_pktmbuf_tailroom(m_last)) 64399a2dd95SBruce Richardson copy_len = rte_pktmbuf_tailroom(m_last); 64499a2dd95SBruce Richardson 64599a2dd95SBruce Richardson /* append from seg to m_last */ 64699a2dd95SBruce Richardson rte_memcpy(rte_pktmbuf_mtod_offset(m_last, char *, 64799a2dd95SBruce Richardson m_last->data_len), 64899a2dd95SBruce Richardson rte_pktmbuf_mtod_offset(seg, char *, off), 64999a2dd95SBruce Richardson copy_len); 65099a2dd95SBruce Richardson 65199a2dd95SBruce Richardson /* update offsets and lengths */ 65299a2dd95SBruce Richardson m_last->data_len += copy_len; 65399a2dd95SBruce Richardson mc->pkt_len += copy_len; 65499a2dd95SBruce Richardson off += copy_len; 65599a2dd95SBruce Richardson len -= copy_len; 65699a2dd95SBruce Richardson } 65799a2dd95SBruce Richardson 65899a2dd95SBruce Richardson /* garbage out check */ 65999a2dd95SBruce Richardson __rte_mbuf_sanity_check(mc, 1); 66099a2dd95SBruce Richardson return mc; 66199a2dd95SBruce Richardson } 66299a2dd95SBruce Richardson 66399a2dd95SBruce Richardson /* dump a mbuf on console */ 66499a2dd95SBruce Richardson void 66599a2dd95SBruce Richardson rte_pktmbuf_dump(FILE *f, const struct rte_mbuf *m, unsigned dump_len) 66699a2dd95SBruce Richardson { 66799a2dd95SBruce Richardson unsigned int len; 66899a2dd95SBruce Richardson unsigned int nb_segs; 66999a2dd95SBruce Richardson 67099a2dd95SBruce Richardson __rte_mbuf_sanity_check(m, 1); 67199a2dd95SBruce Richardson 672*e811e2d7SShijith Thotton fprintf(f, "dump mbuf at %p, iova=%#" PRIx64 ", buf_len=%u\n", m, rte_mbuf_iova_get(m), 673*e811e2d7SShijith Thotton m->buf_len); 67499a2dd95SBruce Richardson fprintf(f, " pkt_len=%u, ol_flags=%#"PRIx64", nb_segs=%u, port=%u", 67599a2dd95SBruce Richardson m->pkt_len, m->ol_flags, m->nb_segs, m->port); 67699a2dd95SBruce Richardson 6774d75f3fcSBen Magistro if (m->ol_flags & (RTE_MBUF_F_RX_QINQ | RTE_MBUF_F_TX_QINQ)) 6784d75f3fcSBen Magistro fprintf(f, ", vlan_tci_outer=%u", m->vlan_tci_outer); 6794d75f3fcSBen Magistro 680daa02b5cSOlivier Matz if (m->ol_flags & (RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_TX_VLAN)) 68199a2dd95SBruce Richardson fprintf(f, ", vlan_tci=%u", m->vlan_tci); 68299a2dd95SBruce Richardson 68399a2dd95SBruce Richardson fprintf(f, ", ptype=%#"PRIx32"\n", m->packet_type); 68499a2dd95SBruce Richardson 68599a2dd95SBruce Richardson nb_segs = m->nb_segs; 68699a2dd95SBruce Richardson 68799a2dd95SBruce Richardson while (m && nb_segs != 0) { 68899a2dd95SBruce Richardson __rte_mbuf_sanity_check(m, 0); 68999a2dd95SBruce Richardson 69099a2dd95SBruce Richardson fprintf(f, " segment at %p, data=%p, len=%u, off=%u, refcnt=%u\n", 69199a2dd95SBruce Richardson m, rte_pktmbuf_mtod(m, void *), 69299a2dd95SBruce Richardson m->data_len, m->data_off, rte_mbuf_refcnt_read(m)); 69399a2dd95SBruce Richardson 69499a2dd95SBruce Richardson len = dump_len; 69599a2dd95SBruce Richardson if (len > m->data_len) 69699a2dd95SBruce Richardson len = m->data_len; 69799a2dd95SBruce Richardson if (len != 0) 69899a2dd95SBruce Richardson rte_hexdump(f, NULL, rte_pktmbuf_mtod(m, void *), len); 69999a2dd95SBruce Richardson dump_len -= len; 70099a2dd95SBruce Richardson m = m->next; 70199a2dd95SBruce Richardson nb_segs --; 70299a2dd95SBruce Richardson } 70399a2dd95SBruce Richardson } 70499a2dd95SBruce Richardson 70599a2dd95SBruce Richardson /* read len data bytes in a mbuf at specified offset (internal) */ 70699a2dd95SBruce Richardson const void *__rte_pktmbuf_read(const struct rte_mbuf *m, uint32_t off, 70799a2dd95SBruce Richardson uint32_t len, void *buf) 70899a2dd95SBruce Richardson { 70999a2dd95SBruce Richardson const struct rte_mbuf *seg = m; 71099a2dd95SBruce Richardson uint32_t buf_off = 0, copy_len; 71199a2dd95SBruce Richardson 71299a2dd95SBruce Richardson if (off + len > rte_pktmbuf_pkt_len(m)) 71399a2dd95SBruce Richardson return NULL; 71499a2dd95SBruce Richardson 71599a2dd95SBruce Richardson while (off >= rte_pktmbuf_data_len(seg)) { 71699a2dd95SBruce Richardson off -= rte_pktmbuf_data_len(seg); 71799a2dd95SBruce Richardson seg = seg->next; 71899a2dd95SBruce Richardson } 71999a2dd95SBruce Richardson 72099a2dd95SBruce Richardson if (off + len <= rte_pktmbuf_data_len(seg)) 72199a2dd95SBruce Richardson return rte_pktmbuf_mtod_offset(seg, char *, off); 72299a2dd95SBruce Richardson 72399a2dd95SBruce Richardson /* rare case: header is split among several segments */ 72499a2dd95SBruce Richardson while (len > 0) { 72599a2dd95SBruce Richardson copy_len = rte_pktmbuf_data_len(seg) - off; 72699a2dd95SBruce Richardson if (copy_len > len) 72799a2dd95SBruce Richardson copy_len = len; 72899a2dd95SBruce Richardson rte_memcpy((char *)buf + buf_off, 72999a2dd95SBruce Richardson rte_pktmbuf_mtod_offset(seg, char *, off), copy_len); 73099a2dd95SBruce Richardson off = 0; 73199a2dd95SBruce Richardson buf_off += copy_len; 73299a2dd95SBruce Richardson len -= copy_len; 73399a2dd95SBruce Richardson seg = seg->next; 73499a2dd95SBruce Richardson } 73599a2dd95SBruce Richardson 73699a2dd95SBruce Richardson return buf; 73799a2dd95SBruce Richardson } 73899a2dd95SBruce Richardson 73999a2dd95SBruce Richardson /* 74099a2dd95SBruce Richardson * Get the name of a RX offload flag. Must be kept synchronized with flag 74199a2dd95SBruce Richardson * definitions in rte_mbuf.h. 74299a2dd95SBruce Richardson */ 74399a2dd95SBruce Richardson const char *rte_get_rx_ol_flag_name(uint64_t mask) 74499a2dd95SBruce Richardson { 74599a2dd95SBruce Richardson switch (mask) { 746daa02b5cSOlivier Matz case RTE_MBUF_F_RX_VLAN: return "RTE_MBUF_F_RX_VLAN"; 747daa02b5cSOlivier Matz case RTE_MBUF_F_RX_RSS_HASH: return "RTE_MBUF_F_RX_RSS_HASH"; 748daa02b5cSOlivier Matz case RTE_MBUF_F_RX_FDIR: return "RTE_MBUF_F_RX_FDIR"; 749daa02b5cSOlivier Matz case RTE_MBUF_F_RX_L4_CKSUM_BAD: return "RTE_MBUF_F_RX_L4_CKSUM_BAD"; 750daa02b5cSOlivier Matz case RTE_MBUF_F_RX_L4_CKSUM_GOOD: return "RTE_MBUF_F_RX_L4_CKSUM_GOOD"; 751daa02b5cSOlivier Matz case RTE_MBUF_F_RX_L4_CKSUM_NONE: return "RTE_MBUF_F_RX_L4_CKSUM_NONE"; 752daa02b5cSOlivier Matz case RTE_MBUF_F_RX_IP_CKSUM_BAD: return "RTE_MBUF_F_RX_IP_CKSUM_BAD"; 753daa02b5cSOlivier Matz case RTE_MBUF_F_RX_IP_CKSUM_GOOD: return "RTE_MBUF_F_RX_IP_CKSUM_GOOD"; 754daa02b5cSOlivier Matz case RTE_MBUF_F_RX_IP_CKSUM_NONE: return "RTE_MBUF_F_RX_IP_CKSUM_NONE"; 755daa02b5cSOlivier Matz case RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD: return "RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD"; 756daa02b5cSOlivier Matz case RTE_MBUF_F_RX_VLAN_STRIPPED: return "RTE_MBUF_F_RX_VLAN_STRIPPED"; 757daa02b5cSOlivier Matz case RTE_MBUF_F_RX_IEEE1588_PTP: return "RTE_MBUF_F_RX_IEEE1588_PTP"; 758daa02b5cSOlivier Matz case RTE_MBUF_F_RX_IEEE1588_TMST: return "RTE_MBUF_F_RX_IEEE1588_TMST"; 759daa02b5cSOlivier Matz case RTE_MBUF_F_RX_FDIR_ID: return "RTE_MBUF_F_RX_FDIR_ID"; 760daa02b5cSOlivier Matz case RTE_MBUF_F_RX_FDIR_FLX: return "RTE_MBUF_F_RX_FDIR_FLX"; 761daa02b5cSOlivier Matz case RTE_MBUF_F_RX_QINQ_STRIPPED: return "RTE_MBUF_F_RX_QINQ_STRIPPED"; 762daa02b5cSOlivier Matz case RTE_MBUF_F_RX_QINQ: return "RTE_MBUF_F_RX_QINQ"; 763daa02b5cSOlivier Matz case RTE_MBUF_F_RX_LRO: return "RTE_MBUF_F_RX_LRO"; 764daa02b5cSOlivier Matz case RTE_MBUF_F_RX_SEC_OFFLOAD: return "RTE_MBUF_F_RX_SEC_OFFLOAD"; 765daa02b5cSOlivier Matz case RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED: return "RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED"; 766daa02b5cSOlivier Matz case RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD: return "RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD"; 767daa02b5cSOlivier Matz case RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD: return "RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD"; 768daa02b5cSOlivier Matz case RTE_MBUF_F_RX_OUTER_L4_CKSUM_INVALID: 769daa02b5cSOlivier Matz return "RTE_MBUF_F_RX_OUTER_L4_CKSUM_INVALID"; 77099a2dd95SBruce Richardson 77199a2dd95SBruce Richardson default: return NULL; 77299a2dd95SBruce Richardson } 77399a2dd95SBruce Richardson } 77499a2dd95SBruce Richardson 77599a2dd95SBruce Richardson struct flag_mask { 77699a2dd95SBruce Richardson uint64_t flag; 77799a2dd95SBruce Richardson uint64_t mask; 77899a2dd95SBruce Richardson const char *default_name; 77999a2dd95SBruce Richardson }; 78099a2dd95SBruce Richardson 78199a2dd95SBruce Richardson /* write the list of rx ol flags in buffer buf */ 78299a2dd95SBruce Richardson int 78399a2dd95SBruce Richardson rte_get_rx_ol_flag_list(uint64_t mask, char *buf, size_t buflen) 78499a2dd95SBruce Richardson { 78599a2dd95SBruce Richardson const struct flag_mask rx_flags[] = { 786daa02b5cSOlivier Matz { RTE_MBUF_F_RX_VLAN, RTE_MBUF_F_RX_VLAN, NULL }, 787daa02b5cSOlivier Matz { RTE_MBUF_F_RX_RSS_HASH, RTE_MBUF_F_RX_RSS_HASH, NULL }, 788daa02b5cSOlivier Matz { RTE_MBUF_F_RX_FDIR, RTE_MBUF_F_RX_FDIR, NULL }, 789daa02b5cSOlivier Matz { RTE_MBUF_F_RX_L4_CKSUM_BAD, RTE_MBUF_F_RX_L4_CKSUM_MASK, NULL }, 790daa02b5cSOlivier Matz { RTE_MBUF_F_RX_L4_CKSUM_GOOD, RTE_MBUF_F_RX_L4_CKSUM_MASK, NULL }, 791daa02b5cSOlivier Matz { RTE_MBUF_F_RX_L4_CKSUM_NONE, RTE_MBUF_F_RX_L4_CKSUM_MASK, NULL }, 792daa02b5cSOlivier Matz { RTE_MBUF_F_RX_L4_CKSUM_UNKNOWN, RTE_MBUF_F_RX_L4_CKSUM_MASK, 793daa02b5cSOlivier Matz "RTE_MBUF_F_RX_L4_CKSUM_UNKNOWN" }, 794daa02b5cSOlivier Matz { RTE_MBUF_F_RX_IP_CKSUM_BAD, RTE_MBUF_F_RX_IP_CKSUM_MASK, NULL }, 795daa02b5cSOlivier Matz { RTE_MBUF_F_RX_IP_CKSUM_GOOD, RTE_MBUF_F_RX_IP_CKSUM_MASK, NULL }, 796daa02b5cSOlivier Matz { RTE_MBUF_F_RX_IP_CKSUM_NONE, RTE_MBUF_F_RX_IP_CKSUM_MASK, NULL }, 797daa02b5cSOlivier Matz { RTE_MBUF_F_RX_IP_CKSUM_UNKNOWN, RTE_MBUF_F_RX_IP_CKSUM_MASK, 798daa02b5cSOlivier Matz "RTE_MBUF_F_RX_IP_CKSUM_UNKNOWN" }, 799daa02b5cSOlivier Matz { RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD, RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD, NULL }, 800daa02b5cSOlivier Matz { RTE_MBUF_F_RX_VLAN_STRIPPED, RTE_MBUF_F_RX_VLAN_STRIPPED, NULL }, 801daa02b5cSOlivier Matz { RTE_MBUF_F_RX_IEEE1588_PTP, RTE_MBUF_F_RX_IEEE1588_PTP, NULL }, 802daa02b5cSOlivier Matz { RTE_MBUF_F_RX_IEEE1588_TMST, RTE_MBUF_F_RX_IEEE1588_TMST, NULL }, 803daa02b5cSOlivier Matz { RTE_MBUF_F_RX_FDIR_ID, RTE_MBUF_F_RX_FDIR_ID, NULL }, 804daa02b5cSOlivier Matz { RTE_MBUF_F_RX_FDIR_FLX, RTE_MBUF_F_RX_FDIR_FLX, NULL }, 805daa02b5cSOlivier Matz { RTE_MBUF_F_RX_QINQ_STRIPPED, RTE_MBUF_F_RX_QINQ_STRIPPED, NULL }, 806daa02b5cSOlivier Matz { RTE_MBUF_F_RX_LRO, RTE_MBUF_F_RX_LRO, NULL }, 807daa02b5cSOlivier Matz { RTE_MBUF_F_RX_SEC_OFFLOAD, RTE_MBUF_F_RX_SEC_OFFLOAD, NULL }, 808daa02b5cSOlivier Matz { RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED, RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED, NULL }, 809daa02b5cSOlivier Matz { RTE_MBUF_F_RX_QINQ, RTE_MBUF_F_RX_QINQ, NULL }, 810daa02b5cSOlivier Matz { RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD, RTE_MBUF_F_RX_OUTER_L4_CKSUM_MASK, NULL }, 811daa02b5cSOlivier Matz { RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD, RTE_MBUF_F_RX_OUTER_L4_CKSUM_MASK, 81299a2dd95SBruce Richardson NULL }, 813daa02b5cSOlivier Matz { RTE_MBUF_F_RX_OUTER_L4_CKSUM_INVALID, RTE_MBUF_F_RX_OUTER_L4_CKSUM_MASK, 81499a2dd95SBruce Richardson NULL }, 815daa02b5cSOlivier Matz { RTE_MBUF_F_RX_OUTER_L4_CKSUM_UNKNOWN, RTE_MBUF_F_RX_OUTER_L4_CKSUM_MASK, 816daa02b5cSOlivier Matz "RTE_MBUF_F_RX_OUTER_L4_CKSUM_UNKNOWN" }, 81799a2dd95SBruce Richardson }; 81899a2dd95SBruce Richardson const char *name; 81999a2dd95SBruce Richardson unsigned int i; 82099a2dd95SBruce Richardson int ret; 82199a2dd95SBruce Richardson 82299a2dd95SBruce Richardson if (buflen == 0) 82399a2dd95SBruce Richardson return -1; 82499a2dd95SBruce Richardson 82599a2dd95SBruce Richardson buf[0] = '\0'; 82699a2dd95SBruce Richardson for (i = 0; i < RTE_DIM(rx_flags); i++) { 82799a2dd95SBruce Richardson if ((mask & rx_flags[i].mask) != rx_flags[i].flag) 82899a2dd95SBruce Richardson continue; 82999a2dd95SBruce Richardson name = rte_get_rx_ol_flag_name(rx_flags[i].flag); 83099a2dd95SBruce Richardson if (name == NULL) 83199a2dd95SBruce Richardson name = rx_flags[i].default_name; 83299a2dd95SBruce Richardson ret = snprintf(buf, buflen, "%s ", name); 83399a2dd95SBruce Richardson if (ret < 0) 83499a2dd95SBruce Richardson return -1; 83599a2dd95SBruce Richardson if ((size_t)ret >= buflen) 83699a2dd95SBruce Richardson return -1; 83799a2dd95SBruce Richardson buf += ret; 83899a2dd95SBruce Richardson buflen -= ret; 83999a2dd95SBruce Richardson } 84099a2dd95SBruce Richardson 84199a2dd95SBruce Richardson return 0; 84299a2dd95SBruce Richardson } 84399a2dd95SBruce Richardson 84499a2dd95SBruce Richardson /* 84599a2dd95SBruce Richardson * Get the name of a TX offload flag. Must be kept synchronized with flag 84699a2dd95SBruce Richardson * definitions in rte_mbuf.h. 84799a2dd95SBruce Richardson */ 84899a2dd95SBruce Richardson const char *rte_get_tx_ol_flag_name(uint64_t mask) 84999a2dd95SBruce Richardson { 85099a2dd95SBruce Richardson switch (mask) { 851daa02b5cSOlivier Matz case RTE_MBUF_F_TX_VLAN: return "RTE_MBUF_F_TX_VLAN"; 852daa02b5cSOlivier Matz case RTE_MBUF_F_TX_IP_CKSUM: return "RTE_MBUF_F_TX_IP_CKSUM"; 853daa02b5cSOlivier Matz case RTE_MBUF_F_TX_TCP_CKSUM: return "RTE_MBUF_F_TX_TCP_CKSUM"; 854daa02b5cSOlivier Matz case RTE_MBUF_F_TX_SCTP_CKSUM: return "RTE_MBUF_F_TX_SCTP_CKSUM"; 855daa02b5cSOlivier Matz case RTE_MBUF_F_TX_UDP_CKSUM: return "RTE_MBUF_F_TX_UDP_CKSUM"; 856daa02b5cSOlivier Matz case RTE_MBUF_F_TX_IEEE1588_TMST: return "RTE_MBUF_F_TX_IEEE1588_TMST"; 857daa02b5cSOlivier Matz case RTE_MBUF_F_TX_TCP_SEG: return "RTE_MBUF_F_TX_TCP_SEG"; 858daa02b5cSOlivier Matz case RTE_MBUF_F_TX_IPV4: return "RTE_MBUF_F_TX_IPV4"; 859daa02b5cSOlivier Matz case RTE_MBUF_F_TX_IPV6: return "RTE_MBUF_F_TX_IPV6"; 860daa02b5cSOlivier Matz case RTE_MBUF_F_TX_OUTER_IP_CKSUM: return "RTE_MBUF_F_TX_OUTER_IP_CKSUM"; 861daa02b5cSOlivier Matz case RTE_MBUF_F_TX_OUTER_IPV4: return "RTE_MBUF_F_TX_OUTER_IPV4"; 862daa02b5cSOlivier Matz case RTE_MBUF_F_TX_OUTER_IPV6: return "RTE_MBUF_F_TX_OUTER_IPV6"; 863daa02b5cSOlivier Matz case RTE_MBUF_F_TX_TUNNEL_VXLAN: return "RTE_MBUF_F_TX_TUNNEL_VXLAN"; 864daa02b5cSOlivier Matz case RTE_MBUF_F_TX_TUNNEL_GTP: return "RTE_MBUF_F_TX_TUNNEL_GTP"; 865daa02b5cSOlivier Matz case RTE_MBUF_F_TX_TUNNEL_GRE: return "RTE_MBUF_F_TX_TUNNEL_GRE"; 866daa02b5cSOlivier Matz case RTE_MBUF_F_TX_TUNNEL_IPIP: return "RTE_MBUF_F_TX_TUNNEL_IPIP"; 867daa02b5cSOlivier Matz case RTE_MBUF_F_TX_TUNNEL_GENEVE: return "RTE_MBUF_F_TX_TUNNEL_GENEVE"; 868daa02b5cSOlivier Matz case RTE_MBUF_F_TX_TUNNEL_MPLSINUDP: return "RTE_MBUF_F_TX_TUNNEL_MPLSINUDP"; 869daa02b5cSOlivier Matz case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE: return "RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE"; 870daa02b5cSOlivier Matz case RTE_MBUF_F_TX_TUNNEL_IP: return "RTE_MBUF_F_TX_TUNNEL_IP"; 871daa02b5cSOlivier Matz case RTE_MBUF_F_TX_TUNNEL_UDP: return "RTE_MBUF_F_TX_TUNNEL_UDP"; 872daa02b5cSOlivier Matz case RTE_MBUF_F_TX_QINQ: return "RTE_MBUF_F_TX_QINQ"; 873daa02b5cSOlivier Matz case RTE_MBUF_F_TX_MACSEC: return "RTE_MBUF_F_TX_MACSEC"; 874daa02b5cSOlivier Matz case RTE_MBUF_F_TX_SEC_OFFLOAD: return "RTE_MBUF_F_TX_SEC_OFFLOAD"; 875daa02b5cSOlivier Matz case RTE_MBUF_F_TX_UDP_SEG: return "RTE_MBUF_F_TX_UDP_SEG"; 876daa02b5cSOlivier Matz case RTE_MBUF_F_TX_OUTER_UDP_CKSUM: return "RTE_MBUF_F_TX_OUTER_UDP_CKSUM"; 87799a2dd95SBruce Richardson default: return NULL; 87899a2dd95SBruce Richardson } 87999a2dd95SBruce Richardson } 88099a2dd95SBruce Richardson 88199a2dd95SBruce Richardson /* write the list of tx ol flags in buffer buf */ 88299a2dd95SBruce Richardson int 88399a2dd95SBruce Richardson rte_get_tx_ol_flag_list(uint64_t mask, char *buf, size_t buflen) 88499a2dd95SBruce Richardson { 88599a2dd95SBruce Richardson const struct flag_mask tx_flags[] = { 886daa02b5cSOlivier Matz { RTE_MBUF_F_TX_VLAN, RTE_MBUF_F_TX_VLAN, NULL }, 887daa02b5cSOlivier Matz { RTE_MBUF_F_TX_IP_CKSUM, RTE_MBUF_F_TX_IP_CKSUM, NULL }, 888daa02b5cSOlivier Matz { RTE_MBUF_F_TX_TCP_CKSUM, RTE_MBUF_F_TX_L4_MASK, NULL }, 889daa02b5cSOlivier Matz { RTE_MBUF_F_TX_SCTP_CKSUM, RTE_MBUF_F_TX_L4_MASK, NULL }, 890daa02b5cSOlivier Matz { RTE_MBUF_F_TX_UDP_CKSUM, RTE_MBUF_F_TX_L4_MASK, NULL }, 891daa02b5cSOlivier Matz { RTE_MBUF_F_TX_L4_NO_CKSUM, RTE_MBUF_F_TX_L4_MASK, "RTE_MBUF_F_TX_L4_NO_CKSUM" }, 892daa02b5cSOlivier Matz { RTE_MBUF_F_TX_IEEE1588_TMST, RTE_MBUF_F_TX_IEEE1588_TMST, NULL }, 893daa02b5cSOlivier Matz { RTE_MBUF_F_TX_TCP_SEG, RTE_MBUF_F_TX_TCP_SEG, NULL }, 894daa02b5cSOlivier Matz { RTE_MBUF_F_TX_IPV4, RTE_MBUF_F_TX_IPV4, NULL }, 895daa02b5cSOlivier Matz { RTE_MBUF_F_TX_IPV6, RTE_MBUF_F_TX_IPV6, NULL }, 896daa02b5cSOlivier Matz { RTE_MBUF_F_TX_OUTER_IP_CKSUM, RTE_MBUF_F_TX_OUTER_IP_CKSUM, NULL }, 897daa02b5cSOlivier Matz { RTE_MBUF_F_TX_OUTER_IPV4, RTE_MBUF_F_TX_OUTER_IPV4, NULL }, 898daa02b5cSOlivier Matz { RTE_MBUF_F_TX_OUTER_IPV6, RTE_MBUF_F_TX_OUTER_IPV6, NULL }, 899daa02b5cSOlivier Matz { RTE_MBUF_F_TX_TUNNEL_VXLAN, RTE_MBUF_F_TX_TUNNEL_MASK, NULL }, 900daa02b5cSOlivier Matz { RTE_MBUF_F_TX_TUNNEL_GTP, RTE_MBUF_F_TX_TUNNEL_MASK, NULL }, 901daa02b5cSOlivier Matz { RTE_MBUF_F_TX_TUNNEL_GRE, RTE_MBUF_F_TX_TUNNEL_MASK, NULL }, 902daa02b5cSOlivier Matz { RTE_MBUF_F_TX_TUNNEL_IPIP, RTE_MBUF_F_TX_TUNNEL_MASK, NULL }, 903daa02b5cSOlivier Matz { RTE_MBUF_F_TX_TUNNEL_GENEVE, RTE_MBUF_F_TX_TUNNEL_MASK, NULL }, 904daa02b5cSOlivier Matz { RTE_MBUF_F_TX_TUNNEL_MPLSINUDP, RTE_MBUF_F_TX_TUNNEL_MASK, NULL }, 905daa02b5cSOlivier Matz { RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE, RTE_MBUF_F_TX_TUNNEL_MASK, NULL }, 906daa02b5cSOlivier Matz { RTE_MBUF_F_TX_TUNNEL_IP, RTE_MBUF_F_TX_TUNNEL_MASK, NULL }, 907daa02b5cSOlivier Matz { RTE_MBUF_F_TX_TUNNEL_UDP, RTE_MBUF_F_TX_TUNNEL_MASK, NULL }, 908daa02b5cSOlivier Matz { RTE_MBUF_F_TX_QINQ, RTE_MBUF_F_TX_QINQ, NULL }, 909daa02b5cSOlivier Matz { RTE_MBUF_F_TX_MACSEC, RTE_MBUF_F_TX_MACSEC, NULL }, 910daa02b5cSOlivier Matz { RTE_MBUF_F_TX_SEC_OFFLOAD, RTE_MBUF_F_TX_SEC_OFFLOAD, NULL }, 911daa02b5cSOlivier Matz { RTE_MBUF_F_TX_UDP_SEG, RTE_MBUF_F_TX_UDP_SEG, NULL }, 912daa02b5cSOlivier Matz { RTE_MBUF_F_TX_OUTER_UDP_CKSUM, RTE_MBUF_F_TX_OUTER_UDP_CKSUM, NULL }, 91399a2dd95SBruce Richardson }; 91499a2dd95SBruce Richardson const char *name; 91599a2dd95SBruce Richardson unsigned int i; 91699a2dd95SBruce Richardson int ret; 91799a2dd95SBruce Richardson 91899a2dd95SBruce Richardson if (buflen == 0) 91999a2dd95SBruce Richardson return -1; 92099a2dd95SBruce Richardson 92199a2dd95SBruce Richardson buf[0] = '\0'; 92299a2dd95SBruce Richardson for (i = 0; i < RTE_DIM(tx_flags); i++) { 92399a2dd95SBruce Richardson if ((mask & tx_flags[i].mask) != tx_flags[i].flag) 92499a2dd95SBruce Richardson continue; 92599a2dd95SBruce Richardson name = rte_get_tx_ol_flag_name(tx_flags[i].flag); 92699a2dd95SBruce Richardson if (name == NULL) 92799a2dd95SBruce Richardson name = tx_flags[i].default_name; 92899a2dd95SBruce Richardson ret = snprintf(buf, buflen, "%s ", name); 92999a2dd95SBruce Richardson if (ret < 0) 93099a2dd95SBruce Richardson return -1; 93199a2dd95SBruce Richardson if ((size_t)ret >= buflen) 93299a2dd95SBruce Richardson return -1; 93399a2dd95SBruce Richardson buf += ret; 93499a2dd95SBruce Richardson buflen -= ret; 93599a2dd95SBruce Richardson } 93699a2dd95SBruce Richardson 93799a2dd95SBruce Richardson return 0; 93899a2dd95SBruce Richardson } 939