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 #ifndef _RTE_MBUF_H_ 799a2dd95SBruce Richardson #define _RTE_MBUF_H_ 899a2dd95SBruce Richardson 999a2dd95SBruce Richardson /** 1099a2dd95SBruce Richardson * @file 1199a2dd95SBruce Richardson * RTE Mbuf 1299a2dd95SBruce Richardson * 1399a2dd95SBruce Richardson * The mbuf library provides the ability to create and destroy buffers 1499a2dd95SBruce Richardson * that may be used by the RTE application to store message 1599a2dd95SBruce Richardson * buffers. The message buffers are stored in a mempool, using the 1699a2dd95SBruce Richardson * RTE mempool library. 1799a2dd95SBruce Richardson * 1899a2dd95SBruce Richardson * The preferred way to create a mbuf pool is to use 1999a2dd95SBruce Richardson * rte_pktmbuf_pool_create(). However, in some situations, an 2099a2dd95SBruce Richardson * application may want to have more control (ex: populate the pool with 2199a2dd95SBruce Richardson * specific memory), in this case it is possible to use functions from 2299a2dd95SBruce Richardson * rte_mempool. See how rte_pktmbuf_pool_create() is implemented for 2399a2dd95SBruce Richardson * details. 2499a2dd95SBruce Richardson * 2599a2dd95SBruce Richardson * This library provides an API to allocate/free packet mbufs, which are 2699a2dd95SBruce Richardson * used to carry network packets. 2799a2dd95SBruce Richardson * 2899a2dd95SBruce Richardson * To understand the concepts of packet buffers or mbufs, you 2999a2dd95SBruce Richardson * should read "TCP/IP Illustrated, Volume 2: The Implementation, 3099a2dd95SBruce Richardson * Addison-Wesley, 1995, ISBN 0-201-63354-X from Richard Stevens" 3199a2dd95SBruce Richardson * http://www.kohala.com/start/tcpipiv2.html 3299a2dd95SBruce Richardson */ 3399a2dd95SBruce Richardson 3499a2dd95SBruce Richardson #include <stdint.h> 35e189cb53SStephen Hemminger 3699a2dd95SBruce Richardson #include <rte_common.h> 3799a2dd95SBruce Richardson #include <rte_config.h> 3899a2dd95SBruce Richardson #include <rte_mempool.h> 3999a2dd95SBruce Richardson #include <rte_prefetch.h> 4099a2dd95SBruce Richardson #include <rte_branch_prediction.h> 4199a2dd95SBruce Richardson #include <rte_mbuf_ptype.h> 4299a2dd95SBruce Richardson #include <rte_mbuf_core.h> 4399a2dd95SBruce Richardson 4499a2dd95SBruce Richardson #ifdef __cplusplus 4599a2dd95SBruce Richardson extern "C" { 4699a2dd95SBruce Richardson #endif 4799a2dd95SBruce Richardson 4899a2dd95SBruce Richardson /** 4999a2dd95SBruce Richardson * Get the name of a RX offload flag 5099a2dd95SBruce Richardson * 5199a2dd95SBruce Richardson * @param mask 5299a2dd95SBruce Richardson * The mask describing the flag. 5399a2dd95SBruce Richardson * @return 5499a2dd95SBruce Richardson * The name of this flag, or NULL if it's not a valid RX flag. 5599a2dd95SBruce Richardson */ 5699a2dd95SBruce Richardson const char *rte_get_rx_ol_flag_name(uint64_t mask); 5799a2dd95SBruce Richardson 5899a2dd95SBruce Richardson /** 5999a2dd95SBruce Richardson * Dump the list of RX offload flags in a buffer 6099a2dd95SBruce Richardson * 6199a2dd95SBruce Richardson * @param mask 6299a2dd95SBruce Richardson * The mask describing the RX flags. 6399a2dd95SBruce Richardson * @param buf 6499a2dd95SBruce Richardson * The output buffer. 6599a2dd95SBruce Richardson * @param buflen 6699a2dd95SBruce Richardson * The length of the buffer. 6799a2dd95SBruce Richardson * @return 6899a2dd95SBruce Richardson * 0 on success, (-1) on error. 6999a2dd95SBruce Richardson */ 7099a2dd95SBruce Richardson int rte_get_rx_ol_flag_list(uint64_t mask, char *buf, size_t buflen); 7199a2dd95SBruce Richardson 7299a2dd95SBruce Richardson /** 7399a2dd95SBruce Richardson * Get the name of a TX offload flag 7499a2dd95SBruce Richardson * 7599a2dd95SBruce Richardson * @param mask 7699a2dd95SBruce Richardson * The mask describing the flag. Usually only one bit must be set. 7799a2dd95SBruce Richardson * Several bits can be given if they belong to the same mask. 78daa02b5cSOlivier Matz * Ex: RTE_MBUF_F_TX_L4_MASK. 7999a2dd95SBruce Richardson * @return 8099a2dd95SBruce Richardson * The name of this flag, or NULL if it's not a valid TX flag. 8199a2dd95SBruce Richardson */ 8299a2dd95SBruce Richardson const char *rte_get_tx_ol_flag_name(uint64_t mask); 8399a2dd95SBruce Richardson 8499a2dd95SBruce Richardson /** 8599a2dd95SBruce Richardson * Dump the list of TX offload flags in a buffer 8699a2dd95SBruce Richardson * 8799a2dd95SBruce Richardson * @param mask 8899a2dd95SBruce Richardson * The mask describing the TX flags. 8999a2dd95SBruce Richardson * @param buf 9099a2dd95SBruce Richardson * The output buffer. 9199a2dd95SBruce Richardson * @param buflen 9299a2dd95SBruce Richardson * The length of the buffer. 9399a2dd95SBruce Richardson * @return 9499a2dd95SBruce Richardson * 0 on success, (-1) on error. 9599a2dd95SBruce Richardson */ 9699a2dd95SBruce Richardson int rte_get_tx_ol_flag_list(uint64_t mask, char *buf, size_t buflen); 9799a2dd95SBruce Richardson 9899a2dd95SBruce Richardson /** 9999a2dd95SBruce Richardson * Prefetch the first part of the mbuf 10099a2dd95SBruce Richardson * 10199a2dd95SBruce Richardson * The first 64 bytes of the mbuf corresponds to fields that are used early 10299a2dd95SBruce Richardson * in the receive path. If the cache line of the architecture is higher than 10399a2dd95SBruce Richardson * 64B, the second part will also be prefetched. 10499a2dd95SBruce Richardson * 10599a2dd95SBruce Richardson * @param m 10699a2dd95SBruce Richardson * The pointer to the mbuf. 10799a2dd95SBruce Richardson */ 10899a2dd95SBruce Richardson static inline void 10999a2dd95SBruce Richardson rte_mbuf_prefetch_part1(struct rte_mbuf *m) 11099a2dd95SBruce Richardson { 1119e152e67STyler Retzlaff rte_prefetch0(m); 11299a2dd95SBruce Richardson } 11399a2dd95SBruce Richardson 11499a2dd95SBruce Richardson /** 11599a2dd95SBruce Richardson * Prefetch the second part of the mbuf 11699a2dd95SBruce Richardson * 11799a2dd95SBruce Richardson * The next 64 bytes of the mbuf corresponds to fields that are used in the 11899a2dd95SBruce Richardson * transmit path. If the cache line of the architecture is higher than 64B, 11999a2dd95SBruce Richardson * this function does nothing as it is expected that the full mbuf is 12099a2dd95SBruce Richardson * already in cache. 12199a2dd95SBruce Richardson * 12299a2dd95SBruce Richardson * @param m 12399a2dd95SBruce Richardson * The pointer to the mbuf. 12499a2dd95SBruce Richardson */ 12599a2dd95SBruce Richardson static inline void 12699a2dd95SBruce Richardson rte_mbuf_prefetch_part2(struct rte_mbuf *m) 12799a2dd95SBruce Richardson { 12899a2dd95SBruce Richardson #if RTE_CACHE_LINE_SIZE == 64 1299e152e67STyler Retzlaff rte_prefetch0(RTE_PTR_ADD(m, RTE_CACHE_LINE_MIN_SIZE)); 13099a2dd95SBruce Richardson #else 13199a2dd95SBruce Richardson RTE_SET_USED(m); 13299a2dd95SBruce Richardson #endif 13399a2dd95SBruce Richardson } 13499a2dd95SBruce Richardson 13599a2dd95SBruce Richardson 13699a2dd95SBruce Richardson static inline uint16_t rte_pktmbuf_priv_size(struct rte_mempool *mp); 13799a2dd95SBruce Richardson 13899a2dd95SBruce Richardson /** 139e811e2d7SShijith Thotton * Get the IOVA address of the mbuf data buffer. 140e811e2d7SShijith Thotton * 141e811e2d7SShijith Thotton * @param m 142e811e2d7SShijith Thotton * The pointer to the mbuf. 143e811e2d7SShijith Thotton * @return 144e811e2d7SShijith Thotton * The IOVA address of the mbuf. 145e811e2d7SShijith Thotton */ 146e811e2d7SShijith Thotton static inline rte_iova_t 147e811e2d7SShijith Thotton rte_mbuf_iova_get(const struct rte_mbuf *m) 148e811e2d7SShijith Thotton { 149d5d9e8feSThomas Monjalon #if RTE_IOVA_IN_MBUF 150e811e2d7SShijith Thotton return m->buf_iova; 151a986c2b7SShijith Thotton #else 152a986c2b7SShijith Thotton return (rte_iova_t)m->buf_addr; 153a986c2b7SShijith Thotton #endif 154e811e2d7SShijith Thotton } 155e811e2d7SShijith Thotton 156e811e2d7SShijith Thotton /** 157e811e2d7SShijith Thotton * Set the IOVA address of the mbuf data buffer. 158e811e2d7SShijith Thotton * 159e811e2d7SShijith Thotton * @param m 160e811e2d7SShijith Thotton * The pointer to the mbuf. 161e811e2d7SShijith Thotton * @param iova 162e811e2d7SShijith Thotton * Value to set as IOVA address of the mbuf. 163e811e2d7SShijith Thotton */ 164e811e2d7SShijith Thotton static inline void 165e811e2d7SShijith Thotton rte_mbuf_iova_set(struct rte_mbuf *m, rte_iova_t iova) 166e811e2d7SShijith Thotton { 167d5d9e8feSThomas Monjalon #if RTE_IOVA_IN_MBUF 168e811e2d7SShijith Thotton m->buf_iova = iova; 169a986c2b7SShijith Thotton #else 170a986c2b7SShijith Thotton RTE_SET_USED(m); 171a986c2b7SShijith Thotton RTE_SET_USED(iova); 172a986c2b7SShijith Thotton #endif 173e811e2d7SShijith Thotton } 174e811e2d7SShijith Thotton 175e811e2d7SShijith Thotton /** 17699a2dd95SBruce Richardson * Return the IO address of the beginning of the mbuf data 17799a2dd95SBruce Richardson * 17899a2dd95SBruce Richardson * @param mb 17999a2dd95SBruce Richardson * The pointer to the mbuf. 18099a2dd95SBruce Richardson * @return 18199a2dd95SBruce Richardson * The IO address of the beginning of the mbuf data 18299a2dd95SBruce Richardson */ 18399a2dd95SBruce Richardson static inline rte_iova_t 18499a2dd95SBruce Richardson rte_mbuf_data_iova(const struct rte_mbuf *mb) 18599a2dd95SBruce Richardson { 186e811e2d7SShijith Thotton return rte_mbuf_iova_get(mb) + mb->data_off; 18799a2dd95SBruce Richardson } 18899a2dd95SBruce Richardson 18999a2dd95SBruce Richardson /** 19099a2dd95SBruce Richardson * Return the default IO address of the beginning of the mbuf data 19199a2dd95SBruce Richardson * 19299a2dd95SBruce Richardson * This function is used by drivers in their receive function, as it 19399a2dd95SBruce Richardson * returns the location where data should be written by the NIC, taking 19499a2dd95SBruce Richardson * the default headroom in account. 19599a2dd95SBruce Richardson * 19699a2dd95SBruce Richardson * @param mb 19799a2dd95SBruce Richardson * The pointer to the mbuf. 19899a2dd95SBruce Richardson * @return 19999a2dd95SBruce Richardson * The IO address of the beginning of the mbuf data 20099a2dd95SBruce Richardson */ 20199a2dd95SBruce Richardson static inline rte_iova_t 20299a2dd95SBruce Richardson rte_mbuf_data_iova_default(const struct rte_mbuf *mb) 20399a2dd95SBruce Richardson { 204e811e2d7SShijith Thotton return rte_mbuf_iova_get(mb) + RTE_PKTMBUF_HEADROOM; 20599a2dd95SBruce Richardson } 20699a2dd95SBruce Richardson 20799a2dd95SBruce Richardson /** 20899a2dd95SBruce Richardson * Return the mbuf owning the data buffer address of an indirect mbuf. 20999a2dd95SBruce Richardson * 21099a2dd95SBruce Richardson * @param mi 21199a2dd95SBruce Richardson * The pointer to the indirect mbuf. 21299a2dd95SBruce Richardson * @return 21399a2dd95SBruce Richardson * The address of the direct mbuf corresponding to buffer_addr. 21499a2dd95SBruce Richardson */ 21599a2dd95SBruce Richardson static inline struct rte_mbuf * 21699a2dd95SBruce Richardson rte_mbuf_from_indirect(struct rte_mbuf *mi) 21799a2dd95SBruce Richardson { 21899a2dd95SBruce Richardson return (struct rte_mbuf *)RTE_PTR_SUB(mi->buf_addr, sizeof(*mi) + mi->priv_size); 21999a2dd95SBruce Richardson } 22099a2dd95SBruce Richardson 22199a2dd95SBruce Richardson /** 22299a2dd95SBruce Richardson * Return address of buffer embedded in the given mbuf. 22399a2dd95SBruce Richardson * 22499a2dd95SBruce Richardson * The return value shall be same as mb->buf_addr if the mbuf is already 22599a2dd95SBruce Richardson * initialized and direct. However, this API is useful if mempool of the 22699a2dd95SBruce Richardson * mbuf is already known because it doesn't need to access mbuf contents in 22799a2dd95SBruce Richardson * order to get the mempool pointer. 22899a2dd95SBruce Richardson * 22999a2dd95SBruce Richardson * @param mb 23099a2dd95SBruce Richardson * The pointer to the mbuf. 23199a2dd95SBruce Richardson * @param mp 23299a2dd95SBruce Richardson * The pointer to the mempool of the mbuf. 23399a2dd95SBruce Richardson * @return 23499a2dd95SBruce Richardson * The pointer of the mbuf buffer. 23599a2dd95SBruce Richardson */ 23699a2dd95SBruce Richardson static inline char * 23799a2dd95SBruce Richardson rte_mbuf_buf_addr(struct rte_mbuf *mb, struct rte_mempool *mp) 23899a2dd95SBruce Richardson { 23999a2dd95SBruce Richardson return (char *)mb + sizeof(*mb) + rte_pktmbuf_priv_size(mp); 24099a2dd95SBruce Richardson } 24199a2dd95SBruce Richardson 24299a2dd95SBruce Richardson /** 24399a2dd95SBruce Richardson * Return the default address of the beginning of the mbuf data. 24499a2dd95SBruce Richardson * 24599a2dd95SBruce Richardson * @param mb 24699a2dd95SBruce Richardson * The pointer to the mbuf. 24799a2dd95SBruce Richardson * @return 24899a2dd95SBruce Richardson * The pointer of the beginning of the mbuf data. 24999a2dd95SBruce Richardson */ 25099a2dd95SBruce Richardson static inline char * 2518d2a436dSDavid Marchand rte_mbuf_data_addr_default(struct rte_mbuf *mb) 25299a2dd95SBruce Richardson { 25399a2dd95SBruce Richardson return rte_mbuf_buf_addr(mb, mb->pool) + RTE_PKTMBUF_HEADROOM; 25499a2dd95SBruce Richardson } 25599a2dd95SBruce Richardson 25699a2dd95SBruce Richardson /** 25799a2dd95SBruce Richardson * Return address of buffer embedded in the given mbuf. 25899a2dd95SBruce Richardson * 25999a2dd95SBruce Richardson * @note: Accessing mempool pointer of a mbuf is expensive because the 26099a2dd95SBruce Richardson * pointer is stored in the 2nd cache line of mbuf. If mempool is known, it 26199a2dd95SBruce Richardson * is better not to reference the mempool pointer in mbuf but calling 26299a2dd95SBruce Richardson * rte_mbuf_buf_addr() would be more efficient. 26399a2dd95SBruce Richardson * 26499a2dd95SBruce Richardson * @param md 26599a2dd95SBruce Richardson * The pointer to the mbuf. 26699a2dd95SBruce Richardson * @return 26799a2dd95SBruce Richardson * The address of the data buffer owned by the mbuf. 26899a2dd95SBruce Richardson */ 26999a2dd95SBruce Richardson static inline char * 27099a2dd95SBruce Richardson rte_mbuf_to_baddr(struct rte_mbuf *md) 27199a2dd95SBruce Richardson { 27299a2dd95SBruce Richardson return rte_mbuf_buf_addr(md, md->pool); 27399a2dd95SBruce Richardson } 27499a2dd95SBruce Richardson 27599a2dd95SBruce Richardson /** 27699a2dd95SBruce Richardson * Return the starting address of the private data area embedded in 27799a2dd95SBruce Richardson * the given mbuf. 27899a2dd95SBruce Richardson * 27999a2dd95SBruce Richardson * Note that no check is made to ensure that a private data area 28099a2dd95SBruce Richardson * actually exists in the supplied mbuf. 28199a2dd95SBruce Richardson * 28299a2dd95SBruce Richardson * @param m 28399a2dd95SBruce Richardson * The pointer to the mbuf. 28499a2dd95SBruce Richardson * @return 28599a2dd95SBruce Richardson * The starting address of the private data area of the given mbuf. 28699a2dd95SBruce Richardson */ 28799a2dd95SBruce Richardson static inline void * 28899a2dd95SBruce Richardson rte_mbuf_to_priv(struct rte_mbuf *m) 28999a2dd95SBruce Richardson { 29099a2dd95SBruce Richardson return RTE_PTR_ADD(m, sizeof(struct rte_mbuf)); 29199a2dd95SBruce Richardson } 29299a2dd95SBruce Richardson 29399a2dd95SBruce Richardson /** 29499a2dd95SBruce Richardson * Private data in case of pktmbuf pool. 29599a2dd95SBruce Richardson * 29699a2dd95SBruce Richardson * A structure that contains some pktmbuf_pool-specific data that are 29799a2dd95SBruce Richardson * appended after the mempool structure (in private data). 29899a2dd95SBruce Richardson */ 29999a2dd95SBruce Richardson struct rte_pktmbuf_pool_private { 30099a2dd95SBruce Richardson uint16_t mbuf_data_room_size; /**< Size of data space in each mbuf. */ 30199a2dd95SBruce Richardson uint16_t mbuf_priv_size; /**< Size of private area in each mbuf. */ 30299a2dd95SBruce Richardson uint32_t flags; /**< reserved for future use. */ 30399a2dd95SBruce Richardson }; 30499a2dd95SBruce Richardson 30599a2dd95SBruce Richardson /** 30699a2dd95SBruce Richardson * Return the flags from private data in an mempool structure. 30799a2dd95SBruce Richardson * 30899a2dd95SBruce Richardson * @param mp 30999a2dd95SBruce Richardson * A pointer to the mempool structure. 31099a2dd95SBruce Richardson * @return 31199a2dd95SBruce Richardson * The flags from the private data structure. 31299a2dd95SBruce Richardson */ 31399a2dd95SBruce Richardson static inline uint32_t 31499a2dd95SBruce Richardson rte_pktmbuf_priv_flags(struct rte_mempool *mp) 31599a2dd95SBruce Richardson { 31699a2dd95SBruce Richardson struct rte_pktmbuf_pool_private *mbp_priv; 31799a2dd95SBruce Richardson 31899a2dd95SBruce Richardson mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(mp); 31999a2dd95SBruce Richardson return mbp_priv->flags; 32099a2dd95SBruce Richardson } 32199a2dd95SBruce Richardson 32299a2dd95SBruce Richardson /** 32399a2dd95SBruce Richardson * When set, pktmbuf mempool will hold only mbufs with pinned external 32499a2dd95SBruce Richardson * buffer. The external buffer will be attached to the mbuf at the 32599a2dd95SBruce Richardson * memory pool creation and will never be detached by the mbuf free calls. 32699a2dd95SBruce Richardson * mbuf should not contain any room for data after the mbuf structure. 32799a2dd95SBruce Richardson */ 32899a2dd95SBruce Richardson #define RTE_PKTMBUF_POOL_F_PINNED_EXT_BUF (1 << 0) 32999a2dd95SBruce Richardson 33099a2dd95SBruce Richardson /** 33199a2dd95SBruce Richardson * Returns non zero if given mbuf has a pinned external buffer, or zero 33299a2dd95SBruce Richardson * otherwise. The pinned external buffer is allocated at pool creation 33399a2dd95SBruce Richardson * time and should not be freed on mbuf freeing. 33499a2dd95SBruce Richardson * 33599a2dd95SBruce Richardson * External buffer is a user-provided anonymous buffer. 33699a2dd95SBruce Richardson */ 33799a2dd95SBruce Richardson #define RTE_MBUF_HAS_PINNED_EXTBUF(mb) \ 33899a2dd95SBruce Richardson (rte_pktmbuf_priv_flags(mb->pool) & RTE_PKTMBUF_POOL_F_PINNED_EXT_BUF) 33999a2dd95SBruce Richardson 34099a2dd95SBruce Richardson #ifdef RTE_LIBRTE_MBUF_DEBUG 34199a2dd95SBruce Richardson 34299a2dd95SBruce Richardson /** check mbuf type in debug mode */ 34399a2dd95SBruce Richardson #define __rte_mbuf_sanity_check(m, is_h) rte_mbuf_sanity_check(m, is_h) 34499a2dd95SBruce Richardson 34599a2dd95SBruce Richardson #else /* RTE_LIBRTE_MBUF_DEBUG */ 34699a2dd95SBruce Richardson 34799a2dd95SBruce Richardson /** check mbuf type in debug mode */ 34899a2dd95SBruce Richardson #define __rte_mbuf_sanity_check(m, is_h) do { } while (0) 34999a2dd95SBruce Richardson 35099a2dd95SBruce Richardson #endif /* RTE_LIBRTE_MBUF_DEBUG */ 35199a2dd95SBruce Richardson 35299a2dd95SBruce Richardson #ifdef RTE_MBUF_REFCNT_ATOMIC 35399a2dd95SBruce Richardson 35499a2dd95SBruce Richardson /** 35599a2dd95SBruce Richardson * Reads the value of an mbuf's refcnt. 35699a2dd95SBruce Richardson * @param m 35799a2dd95SBruce Richardson * Mbuf to read 35899a2dd95SBruce Richardson * @return 35999a2dd95SBruce Richardson * Reference count number. 36099a2dd95SBruce Richardson */ 36199a2dd95SBruce Richardson static inline uint16_t 36299a2dd95SBruce Richardson rte_mbuf_refcnt_read(const struct rte_mbuf *m) 36399a2dd95SBruce Richardson { 3649bcb34d4STyler Retzlaff return rte_atomic_load_explicit(&m->refcnt, rte_memory_order_relaxed); 36599a2dd95SBruce Richardson } 36699a2dd95SBruce Richardson 36799a2dd95SBruce Richardson /** 36899a2dd95SBruce Richardson * Sets an mbuf's refcnt to a defined value. 36999a2dd95SBruce Richardson * @param m 37099a2dd95SBruce Richardson * Mbuf to update 37199a2dd95SBruce Richardson * @param new_value 37299a2dd95SBruce Richardson * Value set 37399a2dd95SBruce Richardson */ 37499a2dd95SBruce Richardson static inline void 37599a2dd95SBruce Richardson rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value) 37699a2dd95SBruce Richardson { 3779bcb34d4STyler Retzlaff rte_atomic_store_explicit(&m->refcnt, new_value, rte_memory_order_relaxed); 37899a2dd95SBruce Richardson } 37999a2dd95SBruce Richardson 38099a2dd95SBruce Richardson /* internal */ 38199a2dd95SBruce Richardson static inline uint16_t 38299a2dd95SBruce Richardson __rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value) 38399a2dd95SBruce Richardson { 3849bcb34d4STyler Retzlaff return rte_atomic_fetch_add_explicit(&m->refcnt, value, 3859bcb34d4STyler Retzlaff rte_memory_order_acq_rel) + value; 38699a2dd95SBruce Richardson } 38799a2dd95SBruce Richardson 38899a2dd95SBruce Richardson /** 38999a2dd95SBruce Richardson * Adds given value to an mbuf's refcnt and returns its new value. 39099a2dd95SBruce Richardson * @param m 39199a2dd95SBruce Richardson * Mbuf to update 39299a2dd95SBruce Richardson * @param value 39399a2dd95SBruce Richardson * Value to add/subtract 39499a2dd95SBruce Richardson * @return 39599a2dd95SBruce Richardson * Updated value 39699a2dd95SBruce Richardson */ 39799a2dd95SBruce Richardson static inline uint16_t 39899a2dd95SBruce Richardson rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value) 39999a2dd95SBruce Richardson { 40099a2dd95SBruce Richardson /* 40199a2dd95SBruce Richardson * The atomic_add is an expensive operation, so we don't want to 40299a2dd95SBruce Richardson * call it in the case where we know we are the unique holder of 40399a2dd95SBruce Richardson * this mbuf (i.e. ref_cnt == 1). Otherwise, an atomic 40499a2dd95SBruce Richardson * operation has to be used because concurrent accesses on the 40599a2dd95SBruce Richardson * reference counter can occur. 40699a2dd95SBruce Richardson */ 40799a2dd95SBruce Richardson if (likely(rte_mbuf_refcnt_read(m) == 1)) { 40899a2dd95SBruce Richardson ++value; 40999a2dd95SBruce Richardson rte_mbuf_refcnt_set(m, (uint16_t)value); 41099a2dd95SBruce Richardson return (uint16_t)value; 41199a2dd95SBruce Richardson } 41299a2dd95SBruce Richardson 41399a2dd95SBruce Richardson return __rte_mbuf_refcnt_update(m, value); 41499a2dd95SBruce Richardson } 41599a2dd95SBruce Richardson 41699a2dd95SBruce Richardson #else /* ! RTE_MBUF_REFCNT_ATOMIC */ 41799a2dd95SBruce Richardson 41899a2dd95SBruce Richardson /* internal */ 41999a2dd95SBruce Richardson static inline uint16_t 42099a2dd95SBruce Richardson __rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value) 42199a2dd95SBruce Richardson { 42299a2dd95SBruce Richardson m->refcnt = (uint16_t)(m->refcnt + value); 42399a2dd95SBruce Richardson return m->refcnt; 42499a2dd95SBruce Richardson } 42599a2dd95SBruce Richardson 42699a2dd95SBruce Richardson /** 42799a2dd95SBruce Richardson * Adds given value to an mbuf's refcnt and returns its new value. 42899a2dd95SBruce Richardson */ 42999a2dd95SBruce Richardson static inline uint16_t 43099a2dd95SBruce Richardson rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value) 43199a2dd95SBruce Richardson { 43299a2dd95SBruce Richardson return __rte_mbuf_refcnt_update(m, value); 43399a2dd95SBruce Richardson } 43499a2dd95SBruce Richardson 43599a2dd95SBruce Richardson /** 43699a2dd95SBruce Richardson * Reads the value of an mbuf's refcnt. 43799a2dd95SBruce Richardson */ 43899a2dd95SBruce Richardson static inline uint16_t 43999a2dd95SBruce Richardson rte_mbuf_refcnt_read(const struct rte_mbuf *m) 44099a2dd95SBruce Richardson { 44199a2dd95SBruce Richardson return m->refcnt; 44299a2dd95SBruce Richardson } 44399a2dd95SBruce Richardson 44499a2dd95SBruce Richardson /** 44599a2dd95SBruce Richardson * Sets an mbuf's refcnt to the defined value. 44699a2dd95SBruce Richardson */ 44799a2dd95SBruce Richardson static inline void 44899a2dd95SBruce Richardson rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value) 44999a2dd95SBruce Richardson { 45099a2dd95SBruce Richardson m->refcnt = new_value; 45199a2dd95SBruce Richardson } 45299a2dd95SBruce Richardson 45399a2dd95SBruce Richardson #endif /* RTE_MBUF_REFCNT_ATOMIC */ 45499a2dd95SBruce Richardson 45599a2dd95SBruce Richardson /** 45699a2dd95SBruce Richardson * Reads the refcnt of an external buffer. 45799a2dd95SBruce Richardson * 45899a2dd95SBruce Richardson * @param shinfo 45999a2dd95SBruce Richardson * Shared data of the external buffer. 46099a2dd95SBruce Richardson * @return 46199a2dd95SBruce Richardson * Reference count number. 46299a2dd95SBruce Richardson */ 46399a2dd95SBruce Richardson static inline uint16_t 46499a2dd95SBruce Richardson rte_mbuf_ext_refcnt_read(const struct rte_mbuf_ext_shared_info *shinfo) 46599a2dd95SBruce Richardson { 4669bcb34d4STyler Retzlaff return rte_atomic_load_explicit(&shinfo->refcnt, rte_memory_order_relaxed); 46799a2dd95SBruce Richardson } 46899a2dd95SBruce Richardson 46999a2dd95SBruce Richardson /** 47099a2dd95SBruce Richardson * Set refcnt of an external buffer. 47199a2dd95SBruce Richardson * 47299a2dd95SBruce Richardson * @param shinfo 47399a2dd95SBruce Richardson * Shared data of the external buffer. 47499a2dd95SBruce Richardson * @param new_value 47599a2dd95SBruce Richardson * Value set 47699a2dd95SBruce Richardson */ 47799a2dd95SBruce Richardson static inline void 47899a2dd95SBruce Richardson rte_mbuf_ext_refcnt_set(struct rte_mbuf_ext_shared_info *shinfo, 47999a2dd95SBruce Richardson uint16_t new_value) 48099a2dd95SBruce Richardson { 4819bcb34d4STyler Retzlaff rte_atomic_store_explicit(&shinfo->refcnt, new_value, rte_memory_order_relaxed); 48299a2dd95SBruce Richardson } 48399a2dd95SBruce Richardson 48499a2dd95SBruce Richardson /** 48599a2dd95SBruce Richardson * Add given value to refcnt of an external buffer and return its new 48699a2dd95SBruce Richardson * value. 48799a2dd95SBruce Richardson * 48899a2dd95SBruce Richardson * @param shinfo 48999a2dd95SBruce Richardson * Shared data of the external buffer. 49099a2dd95SBruce Richardson * @param value 49199a2dd95SBruce Richardson * Value to add/subtract 49299a2dd95SBruce Richardson * @return 49399a2dd95SBruce Richardson * Updated value 49499a2dd95SBruce Richardson */ 49599a2dd95SBruce Richardson static inline uint16_t 49699a2dd95SBruce Richardson rte_mbuf_ext_refcnt_update(struct rte_mbuf_ext_shared_info *shinfo, 49799a2dd95SBruce Richardson int16_t value) 49899a2dd95SBruce Richardson { 49999a2dd95SBruce Richardson if (likely(rte_mbuf_ext_refcnt_read(shinfo) == 1)) { 50099a2dd95SBruce Richardson ++value; 50199a2dd95SBruce Richardson rte_mbuf_ext_refcnt_set(shinfo, (uint16_t)value); 50299a2dd95SBruce Richardson return (uint16_t)value; 50399a2dd95SBruce Richardson } 50499a2dd95SBruce Richardson 5059bcb34d4STyler Retzlaff return rte_atomic_fetch_add_explicit(&shinfo->refcnt, value, 5069bcb34d4STyler Retzlaff rte_memory_order_acq_rel) + value; 50799a2dd95SBruce Richardson } 50899a2dd95SBruce Richardson 50999a2dd95SBruce Richardson /** Mbuf prefetch */ 51099a2dd95SBruce Richardson #define RTE_MBUF_PREFETCH_TO_FREE(m) do { \ 51199a2dd95SBruce Richardson if ((m) != NULL) \ 51299a2dd95SBruce Richardson rte_prefetch0(m); \ 51399a2dd95SBruce Richardson } while (0) 51499a2dd95SBruce Richardson 51599a2dd95SBruce Richardson 51699a2dd95SBruce Richardson /** 51799a2dd95SBruce Richardson * Sanity checks on an mbuf. 51899a2dd95SBruce Richardson * 51999a2dd95SBruce Richardson * Check the consistency of the given mbuf. The function will cause a 52099a2dd95SBruce Richardson * panic if corruption is detected. 52199a2dd95SBruce Richardson * 52299a2dd95SBruce Richardson * @param m 52399a2dd95SBruce Richardson * The mbuf to be checked. 52499a2dd95SBruce Richardson * @param is_header 52599a2dd95SBruce Richardson * True if the mbuf is a packet header, false if it is a sub-segment 52699a2dd95SBruce Richardson * of a packet (in this case, some fields like nb_segs are not checked) 52799a2dd95SBruce Richardson */ 52899a2dd95SBruce Richardson void 52999a2dd95SBruce Richardson rte_mbuf_sanity_check(const struct rte_mbuf *m, int is_header); 53099a2dd95SBruce Richardson 53199a2dd95SBruce Richardson /** 53299a2dd95SBruce Richardson * Sanity checks on a mbuf. 53399a2dd95SBruce Richardson * 53499a2dd95SBruce Richardson * Almost like rte_mbuf_sanity_check(), but this function gives the reason 53599a2dd95SBruce Richardson * if corruption is detected rather than panic. 53699a2dd95SBruce Richardson * 53799a2dd95SBruce Richardson * @param m 53899a2dd95SBruce Richardson * The mbuf to be checked. 53999a2dd95SBruce Richardson * @param is_header 54099a2dd95SBruce Richardson * True if the mbuf is a packet header, false if it is a sub-segment 54199a2dd95SBruce Richardson * of a packet (in this case, some fields like nb_segs are not checked) 54299a2dd95SBruce Richardson * @param reason 54399a2dd95SBruce Richardson * A reference to a string pointer where to store the reason why a mbuf is 54499a2dd95SBruce Richardson * considered invalid. 54599a2dd95SBruce Richardson * @return 54699a2dd95SBruce Richardson * - 0 if no issue has been found, reason is left untouched. 54799a2dd95SBruce Richardson * - -1 if a problem is detected, reason then points to a string describing 54899a2dd95SBruce Richardson * the reason why the mbuf is deemed invalid. 54999a2dd95SBruce Richardson */ 55099a2dd95SBruce Richardson int rte_mbuf_check(const struct rte_mbuf *m, int is_header, 55199a2dd95SBruce Richardson const char **reason); 55299a2dd95SBruce Richardson 55399a2dd95SBruce Richardson /** 55499a2dd95SBruce Richardson * Sanity checks on a reinitialized mbuf in debug mode. 55599a2dd95SBruce Richardson * 55699a2dd95SBruce Richardson * Check the consistency of the given reinitialized mbuf. 55799a2dd95SBruce Richardson * The function will cause a panic if corruption is detected. 55899a2dd95SBruce Richardson * 55999a2dd95SBruce Richardson * Check that the mbuf is properly reinitialized (refcnt=1, next=NULL, 56099a2dd95SBruce Richardson * nb_segs=1), as done by rte_pktmbuf_prefree_seg(). 56199a2dd95SBruce Richardson * 56299a2dd95SBruce Richardson * @param m 56399a2dd95SBruce Richardson * The mbuf to be checked. 56499a2dd95SBruce Richardson */ 56599a2dd95SBruce Richardson static __rte_always_inline void 56699a2dd95SBruce Richardson __rte_mbuf_raw_sanity_check(__rte_unused const struct rte_mbuf *m) 56799a2dd95SBruce Richardson { 56899a2dd95SBruce Richardson RTE_ASSERT(rte_mbuf_refcnt_read(m) == 1); 56999a2dd95SBruce Richardson RTE_ASSERT(m->next == NULL); 57099a2dd95SBruce Richardson RTE_ASSERT(m->nb_segs == 1); 57199a2dd95SBruce Richardson __rte_mbuf_sanity_check(m, 0); 57299a2dd95SBruce Richardson } 57399a2dd95SBruce Richardson 57499a2dd95SBruce Richardson /** For backwards compatibility. */ 57599a2dd95SBruce Richardson #define MBUF_RAW_ALLOC_CHECK(m) __rte_mbuf_raw_sanity_check(m) 57699a2dd95SBruce Richardson 57799a2dd95SBruce Richardson /** 57899a2dd95SBruce Richardson * Allocate an uninitialized mbuf from mempool *mp*. 57999a2dd95SBruce Richardson * 58099a2dd95SBruce Richardson * This function can be used by PMDs (especially in RX functions) to 58199a2dd95SBruce Richardson * allocate an uninitialized mbuf. The driver is responsible of 58299a2dd95SBruce Richardson * initializing all the required fields. See rte_pktmbuf_reset(). 58399a2dd95SBruce Richardson * For standard needs, prefer rte_pktmbuf_alloc(). 58499a2dd95SBruce Richardson * 58599a2dd95SBruce Richardson * The caller can expect that the following fields of the mbuf structure 58699a2dd95SBruce Richardson * are initialized: buf_addr, buf_iova, buf_len, refcnt=1, nb_segs=1, 58799a2dd95SBruce Richardson * next=NULL, pool, priv_size. The other fields must be initialized 58899a2dd95SBruce Richardson * by the caller. 58999a2dd95SBruce Richardson * 59099a2dd95SBruce Richardson * @param mp 59199a2dd95SBruce Richardson * The mempool from which mbuf is allocated. 59299a2dd95SBruce Richardson * @return 59399a2dd95SBruce Richardson * - The pointer to the new mbuf on success. 59499a2dd95SBruce Richardson * - NULL if allocation failed. 59599a2dd95SBruce Richardson */ 59699a2dd95SBruce Richardson static inline struct rte_mbuf *rte_mbuf_raw_alloc(struct rte_mempool *mp) 59799a2dd95SBruce Richardson { 598*6011b12fSRobin Jarry union { 599*6011b12fSRobin Jarry void *ptr; 60099a2dd95SBruce Richardson struct rte_mbuf *m; 601*6011b12fSRobin Jarry } ret; 60299a2dd95SBruce Richardson 603*6011b12fSRobin Jarry if (rte_mempool_get(mp, &ret.ptr) < 0) 60499a2dd95SBruce Richardson return NULL; 605*6011b12fSRobin Jarry __rte_mbuf_raw_sanity_check(ret.m); 606*6011b12fSRobin Jarry return ret.m; 60799a2dd95SBruce Richardson } 60899a2dd95SBruce Richardson 60999a2dd95SBruce Richardson /** 61099a2dd95SBruce Richardson * Put mbuf back into its original mempool. 61199a2dd95SBruce Richardson * 61299a2dd95SBruce Richardson * The caller must ensure that the mbuf is direct and properly 61399a2dd95SBruce Richardson * reinitialized (refcnt=1, next=NULL, nb_segs=1), as done by 61499a2dd95SBruce Richardson * rte_pktmbuf_prefree_seg(). 61599a2dd95SBruce Richardson * 61699a2dd95SBruce Richardson * This function should be used with care, when optimization is 61799a2dd95SBruce Richardson * required. For standard needs, prefer rte_pktmbuf_free() or 61899a2dd95SBruce Richardson * rte_pktmbuf_free_seg(). 61999a2dd95SBruce Richardson * 62099a2dd95SBruce Richardson * @param m 62199a2dd95SBruce Richardson * The mbuf to be freed. 62299a2dd95SBruce Richardson */ 62399a2dd95SBruce Richardson static __rte_always_inline void 62499a2dd95SBruce Richardson rte_mbuf_raw_free(struct rte_mbuf *m) 62599a2dd95SBruce Richardson { 62699a2dd95SBruce Richardson RTE_ASSERT(!RTE_MBUF_CLONED(m) && 62799a2dd95SBruce Richardson (!RTE_MBUF_HAS_EXTBUF(m) || RTE_MBUF_HAS_PINNED_EXTBUF(m))); 62899a2dd95SBruce Richardson __rte_mbuf_raw_sanity_check(m); 62999a2dd95SBruce Richardson rte_mempool_put(m->pool, m); 63099a2dd95SBruce Richardson } 63199a2dd95SBruce Richardson 63299a2dd95SBruce Richardson /** 63399a2dd95SBruce Richardson * The packet mbuf constructor. 63499a2dd95SBruce Richardson * 63599a2dd95SBruce Richardson * This function initializes some fields in the mbuf structure that are 63699a2dd95SBruce Richardson * not modified by the user once created (origin pool, buffer start 63799a2dd95SBruce Richardson * address, and so on). This function is given as a callback function to 63899a2dd95SBruce Richardson * rte_mempool_obj_iter() or rte_mempool_create() at pool creation time. 63999a2dd95SBruce Richardson * 640bd611385SOlivier Matz * This function expects that the mempool private area was previously 641bd611385SOlivier Matz * initialized with rte_pktmbuf_pool_init(). 642bd611385SOlivier Matz * 64399a2dd95SBruce Richardson * @param mp 64499a2dd95SBruce Richardson * The mempool from which mbufs originate. 64599a2dd95SBruce Richardson * @param opaque_arg 64699a2dd95SBruce Richardson * A pointer that can be used by the user to retrieve useful information 64799a2dd95SBruce Richardson * for mbuf initialization. This pointer is the opaque argument passed to 64899a2dd95SBruce Richardson * rte_mempool_obj_iter() or rte_mempool_create(). 64999a2dd95SBruce Richardson * @param m 65099a2dd95SBruce Richardson * The mbuf to initialize. 65199a2dd95SBruce Richardson * @param i 65299a2dd95SBruce Richardson * The index of the mbuf in the pool table. 65399a2dd95SBruce Richardson */ 65499a2dd95SBruce Richardson void rte_pktmbuf_init(struct rte_mempool *mp, void *opaque_arg, 65599a2dd95SBruce Richardson void *m, unsigned i); 65699a2dd95SBruce Richardson 65799a2dd95SBruce Richardson /** 65899a2dd95SBruce Richardson * A packet mbuf pool constructor. 65999a2dd95SBruce Richardson * 66099a2dd95SBruce Richardson * This function initializes the mempool private data in the case of a 66199a2dd95SBruce Richardson * pktmbuf pool. This private data is needed by the driver. The 66299a2dd95SBruce Richardson * function must be called on the mempool before it is used, or it 66399a2dd95SBruce Richardson * can be given as a callback function to rte_mempool_create() at 66499a2dd95SBruce Richardson * pool creation. It can be extended by the user, for example, to 66599a2dd95SBruce Richardson * provide another packet size. 66699a2dd95SBruce Richardson * 667bd611385SOlivier Matz * The mempool private area size must be at least equal to 668bd611385SOlivier Matz * sizeof(struct rte_pktmbuf_pool_private). 669bd611385SOlivier Matz * 67099a2dd95SBruce Richardson * @param mp 67199a2dd95SBruce Richardson * The mempool from which mbufs originate. 67299a2dd95SBruce Richardson * @param opaque_arg 67399a2dd95SBruce Richardson * A pointer that can be used by the user to retrieve useful information 67499a2dd95SBruce Richardson * for mbuf initialization. This pointer is the opaque argument passed to 67599a2dd95SBruce Richardson * rte_mempool_create(). 67699a2dd95SBruce Richardson */ 67799a2dd95SBruce Richardson void rte_pktmbuf_pool_init(struct rte_mempool *mp, void *opaque_arg); 67899a2dd95SBruce Richardson 67999a2dd95SBruce Richardson /** 68099a2dd95SBruce Richardson * Create a mbuf pool. 68199a2dd95SBruce Richardson * 68299a2dd95SBruce Richardson * This function creates and initializes a packet mbuf pool. It is 68399a2dd95SBruce Richardson * a wrapper to rte_mempool functions. 68499a2dd95SBruce Richardson * 68599a2dd95SBruce Richardson * @param name 68699a2dd95SBruce Richardson * The name of the mbuf pool. 68799a2dd95SBruce Richardson * @param n 68899a2dd95SBruce Richardson * The number of elements in the mbuf pool. The optimum size (in terms 68999a2dd95SBruce Richardson * of memory usage) for a mempool is when n is a power of two minus one: 69099a2dd95SBruce Richardson * n = (2^q - 1). 69199a2dd95SBruce Richardson * @param cache_size 69299a2dd95SBruce Richardson * Size of the per-core object cache. See rte_mempool_create() for 69399a2dd95SBruce Richardson * details. 69499a2dd95SBruce Richardson * @param priv_size 69599a2dd95SBruce Richardson * Size of application private are between the rte_mbuf structure 69699a2dd95SBruce Richardson * and the data buffer. This value must be aligned to RTE_MBUF_PRIV_ALIGN. 69799a2dd95SBruce Richardson * @param data_room_size 69899a2dd95SBruce Richardson * Size of data buffer in each mbuf, including RTE_PKTMBUF_HEADROOM. 69999a2dd95SBruce Richardson * @param socket_id 70099a2dd95SBruce Richardson * The socket identifier where the memory should be allocated. The 70199a2dd95SBruce Richardson * value can be *SOCKET_ID_ANY* if there is no NUMA constraint for the 70299a2dd95SBruce Richardson * reserved zone. 70399a2dd95SBruce Richardson * @return 70499a2dd95SBruce Richardson * The pointer to the new allocated mempool, on success. NULL on error 70599a2dd95SBruce Richardson * with rte_errno set appropriately. Possible rte_errno values include: 70699a2dd95SBruce Richardson * - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure 70799a2dd95SBruce Richardson * - EINVAL - cache size provided is too large, or priv_size is not aligned. 70899a2dd95SBruce Richardson * - ENOSPC - the maximum number of memzones has already been allocated 70999a2dd95SBruce Richardson * - EEXIST - a memzone with the same name already exists 71099a2dd95SBruce Richardson * - ENOMEM - no appropriate memory area found in which to create memzone 71199a2dd95SBruce Richardson */ 71299a2dd95SBruce Richardson struct rte_mempool * 71399a2dd95SBruce Richardson rte_pktmbuf_pool_create(const char *name, unsigned n, 71499a2dd95SBruce Richardson unsigned cache_size, uint16_t priv_size, uint16_t data_room_size, 71599a2dd95SBruce Richardson int socket_id); 71699a2dd95SBruce Richardson 71799a2dd95SBruce Richardson /** 71899a2dd95SBruce Richardson * Create a mbuf pool with a given mempool ops name 71999a2dd95SBruce Richardson * 72099a2dd95SBruce Richardson * This function creates and initializes a packet mbuf pool. It is 72199a2dd95SBruce Richardson * a wrapper to rte_mempool functions. 72299a2dd95SBruce Richardson * 72399a2dd95SBruce Richardson * @param name 72499a2dd95SBruce Richardson * The name of the mbuf pool. 72599a2dd95SBruce Richardson * @param n 72699a2dd95SBruce Richardson * The number of elements in the mbuf pool. The optimum size (in terms 72799a2dd95SBruce Richardson * of memory usage) for a mempool is when n is a power of two minus one: 72899a2dd95SBruce Richardson * n = (2^q - 1). 72999a2dd95SBruce Richardson * @param cache_size 73099a2dd95SBruce Richardson * Size of the per-core object cache. See rte_mempool_create() for 73199a2dd95SBruce Richardson * details. 73299a2dd95SBruce Richardson * @param priv_size 73399a2dd95SBruce Richardson * Size of application private are between the rte_mbuf structure 73499a2dd95SBruce Richardson * and the data buffer. This value must be aligned to RTE_MBUF_PRIV_ALIGN. 73599a2dd95SBruce Richardson * @param data_room_size 73699a2dd95SBruce Richardson * Size of data buffer in each mbuf, including RTE_PKTMBUF_HEADROOM. 73799a2dd95SBruce Richardson * @param socket_id 73899a2dd95SBruce Richardson * The socket identifier where the memory should be allocated. The 73999a2dd95SBruce Richardson * value can be *SOCKET_ID_ANY* if there is no NUMA constraint for the 74099a2dd95SBruce Richardson * reserved zone. 74199a2dd95SBruce Richardson * @param ops_name 74299a2dd95SBruce Richardson * The mempool ops name to be used for this mempool instead of 74399a2dd95SBruce Richardson * default mempool. The value can be *NULL* to use default mempool. 74499a2dd95SBruce Richardson * @return 74599a2dd95SBruce Richardson * The pointer to the new allocated mempool, on success. NULL on error 74699a2dd95SBruce Richardson * with rte_errno set appropriately. Possible rte_errno values include: 74799a2dd95SBruce Richardson * - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure 74899a2dd95SBruce Richardson * - EINVAL - cache size provided is too large, or priv_size is not aligned. 74999a2dd95SBruce Richardson * - ENOSPC - the maximum number of memzones has already been allocated 75099a2dd95SBruce Richardson * - EEXIST - a memzone with the same name already exists 75199a2dd95SBruce Richardson * - ENOMEM - no appropriate memory area found in which to create memzone 75299a2dd95SBruce Richardson */ 75399a2dd95SBruce Richardson struct rte_mempool * 75499a2dd95SBruce Richardson rte_pktmbuf_pool_create_by_ops(const char *name, unsigned int n, 75599a2dd95SBruce Richardson unsigned int cache_size, uint16_t priv_size, uint16_t data_room_size, 75699a2dd95SBruce Richardson int socket_id, const char *ops_name); 75799a2dd95SBruce Richardson 75899a2dd95SBruce Richardson /** A structure that describes the pinned external buffer segment. */ 75999a2dd95SBruce Richardson struct rte_pktmbuf_extmem { 76099a2dd95SBruce Richardson void *buf_ptr; /**< The virtual address of data buffer. */ 76199a2dd95SBruce Richardson rte_iova_t buf_iova; /**< The IO address of the data buffer. */ 76299a2dd95SBruce Richardson size_t buf_len; /**< External buffer length in bytes. */ 76399a2dd95SBruce Richardson uint16_t elt_size; /**< mbuf element size in bytes. */ 76499a2dd95SBruce Richardson }; 76599a2dd95SBruce Richardson 76699a2dd95SBruce Richardson /** 76799a2dd95SBruce Richardson * Create a mbuf pool with external pinned data buffers. 76899a2dd95SBruce Richardson * 76999a2dd95SBruce Richardson * This function creates and initializes a packet mbuf pool that contains 77099a2dd95SBruce Richardson * only mbufs with external buffer. It is a wrapper to rte_mempool functions. 77199a2dd95SBruce Richardson * 77299a2dd95SBruce Richardson * @param name 77399a2dd95SBruce Richardson * The name of the mbuf pool. 77499a2dd95SBruce Richardson * @param n 77599a2dd95SBruce Richardson * The number of elements in the mbuf pool. The optimum size (in terms 77699a2dd95SBruce Richardson * of memory usage) for a mempool is when n is a power of two minus one: 77799a2dd95SBruce Richardson * n = (2^q - 1). 77899a2dd95SBruce Richardson * @param cache_size 77999a2dd95SBruce Richardson * Size of the per-core object cache. See rte_mempool_create() for 78099a2dd95SBruce Richardson * details. 78199a2dd95SBruce Richardson * @param priv_size 78299a2dd95SBruce Richardson * Size of application private are between the rte_mbuf structure 78399a2dd95SBruce Richardson * and the data buffer. This value must be aligned to RTE_MBUF_PRIV_ALIGN. 78499a2dd95SBruce Richardson * @param data_room_size 78599a2dd95SBruce Richardson * Size of data buffer in each mbuf, including RTE_PKTMBUF_HEADROOM. 78699a2dd95SBruce Richardson * @param socket_id 78799a2dd95SBruce Richardson * The socket identifier where the memory should be allocated. The 78899a2dd95SBruce Richardson * value can be *SOCKET_ID_ANY* if there is no NUMA constraint for the 78999a2dd95SBruce Richardson * reserved zone. 79099a2dd95SBruce Richardson * @param ext_mem 79199a2dd95SBruce Richardson * Pointer to the array of structures describing the external memory 79299a2dd95SBruce Richardson * for data buffers. It is caller responsibility to register this memory 79399a2dd95SBruce Richardson * with rte_extmem_register() (if needed), map this memory to appropriate 79499a2dd95SBruce Richardson * physical device, etc. 79599a2dd95SBruce Richardson * @param ext_num 79699a2dd95SBruce Richardson * Number of elements in the ext_mem array. 79799a2dd95SBruce Richardson * @return 79899a2dd95SBruce Richardson * The pointer to the new allocated mempool, on success. NULL on error 79999a2dd95SBruce Richardson * with rte_errno set appropriately. Possible rte_errno values include: 80099a2dd95SBruce Richardson * - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure 80199a2dd95SBruce Richardson * - EINVAL - cache size provided is too large, or priv_size is not aligned. 80299a2dd95SBruce Richardson * - ENOSPC - the maximum number of memzones has already been allocated 80399a2dd95SBruce Richardson * - EEXIST - a memzone with the same name already exists 80499a2dd95SBruce Richardson * - ENOMEM - no appropriate memory area found in which to create memzone 80599a2dd95SBruce Richardson */ 80699a2dd95SBruce Richardson struct rte_mempool * 80799a2dd95SBruce Richardson rte_pktmbuf_pool_create_extbuf(const char *name, unsigned int n, 80899a2dd95SBruce Richardson unsigned int cache_size, uint16_t priv_size, 80999a2dd95SBruce Richardson uint16_t data_room_size, int socket_id, 81099a2dd95SBruce Richardson const struct rte_pktmbuf_extmem *ext_mem, 81199a2dd95SBruce Richardson unsigned int ext_num); 81299a2dd95SBruce Richardson 81399a2dd95SBruce Richardson /** 81499a2dd95SBruce Richardson * Get the data room size of mbufs stored in a pktmbuf_pool 81599a2dd95SBruce Richardson * 81699a2dd95SBruce Richardson * The data room size is the amount of data that can be stored in a 81799a2dd95SBruce Richardson * mbuf including the headroom (RTE_PKTMBUF_HEADROOM). 81899a2dd95SBruce Richardson * 81999a2dd95SBruce Richardson * @param mp 82099a2dd95SBruce Richardson * The packet mbuf pool. 82199a2dd95SBruce Richardson * @return 82299a2dd95SBruce Richardson * The data room size of mbufs stored in this mempool. 82399a2dd95SBruce Richardson */ 82499a2dd95SBruce Richardson static inline uint16_t 82599a2dd95SBruce Richardson rte_pktmbuf_data_room_size(struct rte_mempool *mp) 82699a2dd95SBruce Richardson { 82799a2dd95SBruce Richardson struct rte_pktmbuf_pool_private *mbp_priv; 82899a2dd95SBruce Richardson 82999a2dd95SBruce Richardson mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(mp); 83099a2dd95SBruce Richardson return mbp_priv->mbuf_data_room_size; 83199a2dd95SBruce Richardson } 83299a2dd95SBruce Richardson 83399a2dd95SBruce Richardson /** 83499a2dd95SBruce Richardson * Get the application private size of mbufs stored in a pktmbuf_pool 83599a2dd95SBruce Richardson * 83699a2dd95SBruce Richardson * The private size of mbuf is a zone located between the rte_mbuf 83799a2dd95SBruce Richardson * structure and the data buffer where an application can store data 83899a2dd95SBruce Richardson * associated to a packet. 83999a2dd95SBruce Richardson * 84099a2dd95SBruce Richardson * @param mp 84199a2dd95SBruce Richardson * The packet mbuf pool. 84299a2dd95SBruce Richardson * @return 84399a2dd95SBruce Richardson * The private size of mbufs stored in this mempool. 84499a2dd95SBruce Richardson */ 84599a2dd95SBruce Richardson static inline uint16_t 84699a2dd95SBruce Richardson rte_pktmbuf_priv_size(struct rte_mempool *mp) 84799a2dd95SBruce Richardson { 84899a2dd95SBruce Richardson struct rte_pktmbuf_pool_private *mbp_priv; 84999a2dd95SBruce Richardson 85099a2dd95SBruce Richardson mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(mp); 85199a2dd95SBruce Richardson return mbp_priv->mbuf_priv_size; 85299a2dd95SBruce Richardson } 85399a2dd95SBruce Richardson 85499a2dd95SBruce Richardson /** 85599a2dd95SBruce Richardson * Reset the data_off field of a packet mbuf to its default value. 85699a2dd95SBruce Richardson * 85799a2dd95SBruce Richardson * The given mbuf must have only one segment, which should be empty. 85899a2dd95SBruce Richardson * 85999a2dd95SBruce Richardson * @param m 86099a2dd95SBruce Richardson * The packet mbuf's data_off field has to be reset. 86199a2dd95SBruce Richardson */ 86299a2dd95SBruce Richardson static inline void rte_pktmbuf_reset_headroom(struct rte_mbuf *m) 86399a2dd95SBruce Richardson { 86499a2dd95SBruce Richardson m->data_off = (uint16_t)RTE_MIN((uint16_t)RTE_PKTMBUF_HEADROOM, 86599a2dd95SBruce Richardson (uint16_t)m->buf_len); 86699a2dd95SBruce Richardson } 86799a2dd95SBruce Richardson 86899a2dd95SBruce Richardson /** 86999a2dd95SBruce Richardson * Reset the fields of a packet mbuf to their default values. 87099a2dd95SBruce Richardson * 87199a2dd95SBruce Richardson * The given mbuf must have only one segment. 87299a2dd95SBruce Richardson * 87399a2dd95SBruce Richardson * @param m 87499a2dd95SBruce Richardson * The packet mbuf to be reset. 87599a2dd95SBruce Richardson */ 87699a2dd95SBruce Richardson static inline void rte_pktmbuf_reset(struct rte_mbuf *m) 87799a2dd95SBruce Richardson { 87899a2dd95SBruce Richardson m->next = NULL; 87999a2dd95SBruce Richardson m->pkt_len = 0; 88099a2dd95SBruce Richardson m->tx_offload = 0; 88199a2dd95SBruce Richardson m->vlan_tci = 0; 88299a2dd95SBruce Richardson m->vlan_tci_outer = 0; 88399a2dd95SBruce Richardson m->nb_segs = 1; 88499a2dd95SBruce Richardson m->port = RTE_MBUF_PORT_INVALID; 88599a2dd95SBruce Richardson 886daa02b5cSOlivier Matz m->ol_flags &= RTE_MBUF_F_EXTERNAL; 88799a2dd95SBruce Richardson m->packet_type = 0; 88899a2dd95SBruce Richardson rte_pktmbuf_reset_headroom(m); 88999a2dd95SBruce Richardson 89099a2dd95SBruce Richardson m->data_len = 0; 89199a2dd95SBruce Richardson __rte_mbuf_sanity_check(m, 1); 89299a2dd95SBruce Richardson } 89399a2dd95SBruce Richardson 89499a2dd95SBruce Richardson /** 89599a2dd95SBruce Richardson * Allocate a new mbuf from a mempool. 89699a2dd95SBruce Richardson * 89799a2dd95SBruce Richardson * This new mbuf contains one segment, which has a length of 0. The pointer 89899a2dd95SBruce Richardson * to data is initialized to have some bytes of headroom in the buffer 89999a2dd95SBruce Richardson * (if buffer size allows). 90099a2dd95SBruce Richardson * 90199a2dd95SBruce Richardson * @param mp 90299a2dd95SBruce Richardson * The mempool from which the mbuf is allocated. 90399a2dd95SBruce Richardson * @return 90499a2dd95SBruce Richardson * - The pointer to the new mbuf on success. 90599a2dd95SBruce Richardson * - NULL if allocation failed. 90699a2dd95SBruce Richardson */ 90799a2dd95SBruce Richardson static inline struct rte_mbuf *rte_pktmbuf_alloc(struct rte_mempool *mp) 90899a2dd95SBruce Richardson { 90999a2dd95SBruce Richardson struct rte_mbuf *m; 91099a2dd95SBruce Richardson if ((m = rte_mbuf_raw_alloc(mp)) != NULL) 91199a2dd95SBruce Richardson rte_pktmbuf_reset(m); 91299a2dd95SBruce Richardson return m; 91399a2dd95SBruce Richardson } 91499a2dd95SBruce Richardson 91599a2dd95SBruce Richardson /** 91699a2dd95SBruce Richardson * Allocate a bulk of mbufs, initialize refcnt and reset the fields to default 91799a2dd95SBruce Richardson * values. 91899a2dd95SBruce Richardson * 91999a2dd95SBruce Richardson * @param pool 92099a2dd95SBruce Richardson * The mempool from which mbufs are allocated. 92199a2dd95SBruce Richardson * @param mbufs 92299a2dd95SBruce Richardson * Array of pointers to mbufs 92399a2dd95SBruce Richardson * @param count 92499a2dd95SBruce Richardson * Array size 92599a2dd95SBruce Richardson * @return 92699a2dd95SBruce Richardson * - 0: Success 92799a2dd95SBruce Richardson * - -ENOENT: Not enough entries in the mempool; no mbufs are retrieved. 92899a2dd95SBruce Richardson */ 92999a2dd95SBruce Richardson static inline int rte_pktmbuf_alloc_bulk(struct rte_mempool *pool, 93099a2dd95SBruce Richardson struct rte_mbuf **mbufs, unsigned count) 93199a2dd95SBruce Richardson { 93299a2dd95SBruce Richardson unsigned idx = 0; 93399a2dd95SBruce Richardson int rc; 93499a2dd95SBruce Richardson 93599a2dd95SBruce Richardson rc = rte_mempool_get_bulk(pool, (void **)mbufs, count); 93699a2dd95SBruce Richardson if (unlikely(rc)) 93799a2dd95SBruce Richardson return rc; 93899a2dd95SBruce Richardson 93999a2dd95SBruce Richardson /* To understand duff's device on loop unwinding optimization, see 94099a2dd95SBruce Richardson * https://en.wikipedia.org/wiki/Duff's_device. 94199a2dd95SBruce Richardson * Here while() loop is used rather than do() while{} to avoid extra 94299a2dd95SBruce Richardson * check if count is zero. 94399a2dd95SBruce Richardson */ 94499a2dd95SBruce Richardson switch (count % 4) { 94599a2dd95SBruce Richardson case 0: 94699a2dd95SBruce Richardson while (idx != count) { 94799a2dd95SBruce Richardson __rte_mbuf_raw_sanity_check(mbufs[idx]); 94899a2dd95SBruce Richardson rte_pktmbuf_reset(mbufs[idx]); 94999a2dd95SBruce Richardson idx++; 95099a2dd95SBruce Richardson /* fall-through */ 95199a2dd95SBruce Richardson case 3: 95299a2dd95SBruce Richardson __rte_mbuf_raw_sanity_check(mbufs[idx]); 95399a2dd95SBruce Richardson rte_pktmbuf_reset(mbufs[idx]); 95499a2dd95SBruce Richardson idx++; 95599a2dd95SBruce Richardson /* fall-through */ 95699a2dd95SBruce Richardson case 2: 95799a2dd95SBruce Richardson __rte_mbuf_raw_sanity_check(mbufs[idx]); 95899a2dd95SBruce Richardson rte_pktmbuf_reset(mbufs[idx]); 95999a2dd95SBruce Richardson idx++; 96099a2dd95SBruce Richardson /* fall-through */ 96199a2dd95SBruce Richardson case 1: 96299a2dd95SBruce Richardson __rte_mbuf_raw_sanity_check(mbufs[idx]); 96399a2dd95SBruce Richardson rte_pktmbuf_reset(mbufs[idx]); 96499a2dd95SBruce Richardson idx++; 96599a2dd95SBruce Richardson /* fall-through */ 96699a2dd95SBruce Richardson } 96799a2dd95SBruce Richardson } 96899a2dd95SBruce Richardson return 0; 96999a2dd95SBruce Richardson } 97099a2dd95SBruce Richardson 97199a2dd95SBruce Richardson /** 97299a2dd95SBruce Richardson * Initialize shared data at the end of an external buffer before attaching 97399a2dd95SBruce Richardson * to a mbuf by ``rte_pktmbuf_attach_extbuf()``. This is not a mandatory 97499a2dd95SBruce Richardson * initialization but a helper function to simply spare a few bytes at the 97599a2dd95SBruce Richardson * end of the buffer for shared data. If shared data is allocated 97699a2dd95SBruce Richardson * separately, this should not be called but application has to properly 97799a2dd95SBruce Richardson * initialize the shared data according to its need. 97899a2dd95SBruce Richardson * 97999a2dd95SBruce Richardson * Free callback and its argument is saved and the refcnt is set to 1. 98099a2dd95SBruce Richardson * 98199a2dd95SBruce Richardson * @warning 98299a2dd95SBruce Richardson * The value of buf_len will be reduced to RTE_PTR_DIFF(shinfo, buf_addr) 98399a2dd95SBruce Richardson * after this initialization. This shall be used for 98499a2dd95SBruce Richardson * ``rte_pktmbuf_attach_extbuf()`` 98599a2dd95SBruce Richardson * 98699a2dd95SBruce Richardson * @param buf_addr 98799a2dd95SBruce Richardson * The pointer to the external buffer. 98899a2dd95SBruce Richardson * @param [in,out] buf_len 98999a2dd95SBruce Richardson * The pointer to length of the external buffer. Input value must be 99099a2dd95SBruce Richardson * larger than the size of ``struct rte_mbuf_ext_shared_info`` and 99199a2dd95SBruce Richardson * padding for alignment. If not enough, this function will return NULL. 99299a2dd95SBruce Richardson * Adjusted buffer length will be returned through this pointer. 99399a2dd95SBruce Richardson * @param free_cb 99499a2dd95SBruce Richardson * Free callback function to call when the external buffer needs to be 99599a2dd95SBruce Richardson * freed. 99699a2dd95SBruce Richardson * @param fcb_opaque 99799a2dd95SBruce Richardson * Argument for the free callback function. 99899a2dd95SBruce Richardson * 99999a2dd95SBruce Richardson * @return 100099a2dd95SBruce Richardson * A pointer to the initialized shared data on success, return NULL 100199a2dd95SBruce Richardson * otherwise. 100299a2dd95SBruce Richardson */ 100399a2dd95SBruce Richardson static inline struct rte_mbuf_ext_shared_info * 100499a2dd95SBruce Richardson rte_pktmbuf_ext_shinfo_init_helper(void *buf_addr, uint16_t *buf_len, 100599a2dd95SBruce Richardson rte_mbuf_extbuf_free_callback_t free_cb, void *fcb_opaque) 100699a2dd95SBruce Richardson { 100799a2dd95SBruce Richardson struct rte_mbuf_ext_shared_info *shinfo; 100899a2dd95SBruce Richardson void *buf_end = RTE_PTR_ADD(buf_addr, *buf_len); 100999a2dd95SBruce Richardson void *addr; 101099a2dd95SBruce Richardson 101199a2dd95SBruce Richardson addr = RTE_PTR_ALIGN_FLOOR(RTE_PTR_SUB(buf_end, sizeof(*shinfo)), 101299a2dd95SBruce Richardson sizeof(uintptr_t)); 101399a2dd95SBruce Richardson if (addr <= buf_addr) 101499a2dd95SBruce Richardson return NULL; 101599a2dd95SBruce Richardson 101699a2dd95SBruce Richardson shinfo = (struct rte_mbuf_ext_shared_info *)addr; 101799a2dd95SBruce Richardson shinfo->free_cb = free_cb; 101899a2dd95SBruce Richardson shinfo->fcb_opaque = fcb_opaque; 101999a2dd95SBruce Richardson rte_mbuf_ext_refcnt_set(shinfo, 1); 102099a2dd95SBruce Richardson 102199a2dd95SBruce Richardson *buf_len = (uint16_t)RTE_PTR_DIFF(shinfo, buf_addr); 102299a2dd95SBruce Richardson return shinfo; 102399a2dd95SBruce Richardson } 102499a2dd95SBruce Richardson 102599a2dd95SBruce Richardson /** 102699a2dd95SBruce Richardson * Attach an external buffer to a mbuf. 102799a2dd95SBruce Richardson * 102899a2dd95SBruce Richardson * User-managed anonymous buffer can be attached to an mbuf. When attaching 102999a2dd95SBruce Richardson * it, corresponding free callback function and its argument should be 103099a2dd95SBruce Richardson * provided via shinfo. This callback function will be called once all the 103199a2dd95SBruce Richardson * mbufs are detached from the buffer (refcnt becomes zero). 103299a2dd95SBruce Richardson * 103399a2dd95SBruce Richardson * The headroom length of the attaching mbuf will be set to zero and this 103499a2dd95SBruce Richardson * can be properly adjusted after attachment. For example, ``rte_pktmbuf_adj()`` 103599a2dd95SBruce Richardson * or ``rte_pktmbuf_reset_headroom()`` might be used. 103699a2dd95SBruce Richardson * 103799a2dd95SBruce Richardson * Similarly, the packet length is initialized to 0. If the buffer contains 103899a2dd95SBruce Richardson * data, the user has to adjust ``data_len`` and the ``pkt_len`` field of 103999a2dd95SBruce Richardson * the mbuf accordingly. 104099a2dd95SBruce Richardson * 104199a2dd95SBruce Richardson * More mbufs can be attached to the same external buffer by 104299a2dd95SBruce Richardson * ``rte_pktmbuf_attach()`` once the external buffer has been attached by 104399a2dd95SBruce Richardson * this API. 104499a2dd95SBruce Richardson * 104599a2dd95SBruce Richardson * Detachment can be done by either ``rte_pktmbuf_detach_extbuf()`` or 104699a2dd95SBruce Richardson * ``rte_pktmbuf_detach()``. 104799a2dd95SBruce Richardson * 104899a2dd95SBruce Richardson * Memory for shared data must be provided and user must initialize all of 104999a2dd95SBruce Richardson * the content properly, especially free callback and refcnt. The pointer 105099a2dd95SBruce Richardson * of shared data will be stored in m->shinfo. 105199a2dd95SBruce Richardson * ``rte_pktmbuf_ext_shinfo_init_helper`` can help to simply spare a few 105299a2dd95SBruce Richardson * bytes at the end of buffer for the shared data, store free callback and 105399a2dd95SBruce Richardson * its argument and set the refcnt to 1. The following is an example: 105499a2dd95SBruce Richardson * 105599a2dd95SBruce Richardson * struct rte_mbuf_ext_shared_info *shinfo = 105699a2dd95SBruce Richardson * rte_pktmbuf_ext_shinfo_init_helper(buf_addr, &buf_len, 105799a2dd95SBruce Richardson * free_cb, fcb_arg); 105899a2dd95SBruce Richardson * rte_pktmbuf_attach_extbuf(m, buf_addr, buf_iova, buf_len, shinfo); 105999a2dd95SBruce Richardson * rte_pktmbuf_reset_headroom(m); 106099a2dd95SBruce Richardson * rte_pktmbuf_adj(m, data_len); 106199a2dd95SBruce Richardson * 106299a2dd95SBruce Richardson * Attaching an external buffer is quite similar to mbuf indirection in 106399a2dd95SBruce Richardson * replacing buffer addresses and length of a mbuf, but a few differences: 106499a2dd95SBruce Richardson * - When an indirect mbuf is attached, refcnt of the direct mbuf would be 106599a2dd95SBruce Richardson * 2 as long as the direct mbuf itself isn't freed after the attachment. 106699a2dd95SBruce Richardson * In such cases, the buffer area of a direct mbuf must be read-only. But 106799a2dd95SBruce Richardson * external buffer has its own refcnt and it starts from 1. Unless 106899a2dd95SBruce Richardson * multiple mbufs are attached to a mbuf having an external buffer, the 106999a2dd95SBruce Richardson * external buffer is writable. 107099a2dd95SBruce Richardson * - There's no need to allocate buffer from a mempool. Any buffer can be 107199a2dd95SBruce Richardson * attached with appropriate free callback and its IO address. 107299a2dd95SBruce Richardson * - Smaller metadata is required to maintain shared data such as refcnt. 107399a2dd95SBruce Richardson * 107499a2dd95SBruce Richardson * @param m 107599a2dd95SBruce Richardson * The pointer to the mbuf. 107699a2dd95SBruce Richardson * @param buf_addr 107799a2dd95SBruce Richardson * The pointer to the external buffer. 107899a2dd95SBruce Richardson * @param buf_iova 107999a2dd95SBruce Richardson * IO address of the external buffer. 108099a2dd95SBruce Richardson * @param buf_len 108199a2dd95SBruce Richardson * The size of the external buffer. 108299a2dd95SBruce Richardson * @param shinfo 108399a2dd95SBruce Richardson * User-provided memory for shared data of the external buffer. 108499a2dd95SBruce Richardson */ 108599a2dd95SBruce Richardson static inline void 108699a2dd95SBruce Richardson rte_pktmbuf_attach_extbuf(struct rte_mbuf *m, void *buf_addr, 108799a2dd95SBruce Richardson rte_iova_t buf_iova, uint16_t buf_len, 108899a2dd95SBruce Richardson struct rte_mbuf_ext_shared_info *shinfo) 108999a2dd95SBruce Richardson { 109099a2dd95SBruce Richardson /* mbuf should not be read-only */ 109199a2dd95SBruce Richardson RTE_ASSERT(RTE_MBUF_DIRECT(m) && rte_mbuf_refcnt_read(m) == 1); 109299a2dd95SBruce Richardson RTE_ASSERT(shinfo->free_cb != NULL); 109399a2dd95SBruce Richardson 109499a2dd95SBruce Richardson m->buf_addr = buf_addr; 1095e811e2d7SShijith Thotton rte_mbuf_iova_set(m, buf_iova); 109699a2dd95SBruce Richardson m->buf_len = buf_len; 109799a2dd95SBruce Richardson 109899a2dd95SBruce Richardson m->data_len = 0; 109999a2dd95SBruce Richardson m->data_off = 0; 110099a2dd95SBruce Richardson 1101daa02b5cSOlivier Matz m->ol_flags |= RTE_MBUF_F_EXTERNAL; 110299a2dd95SBruce Richardson m->shinfo = shinfo; 110399a2dd95SBruce Richardson } 110499a2dd95SBruce Richardson 110599a2dd95SBruce Richardson /** 110699a2dd95SBruce Richardson * Detach the external buffer attached to a mbuf, same as 110799a2dd95SBruce Richardson * ``rte_pktmbuf_detach()`` 110899a2dd95SBruce Richardson * 110999a2dd95SBruce Richardson * @param m 111099a2dd95SBruce Richardson * The mbuf having external buffer. 111199a2dd95SBruce Richardson */ 111299a2dd95SBruce Richardson #define rte_pktmbuf_detach_extbuf(m) rte_pktmbuf_detach(m) 111399a2dd95SBruce Richardson 111499a2dd95SBruce Richardson /** 111599a2dd95SBruce Richardson * Copy dynamic fields from msrc to mdst. 111699a2dd95SBruce Richardson * 111799a2dd95SBruce Richardson * @param mdst 111899a2dd95SBruce Richardson * The destination mbuf. 111999a2dd95SBruce Richardson * @param msrc 112099a2dd95SBruce Richardson * The source mbuf. 112199a2dd95SBruce Richardson */ 112299a2dd95SBruce Richardson static inline void 112399a2dd95SBruce Richardson rte_mbuf_dynfield_copy(struct rte_mbuf *mdst, const struct rte_mbuf *msrc) 112499a2dd95SBruce Richardson { 112595bea772SShijith Thotton #if !RTE_IOVA_IN_MBUF 112695bea772SShijith Thotton mdst->dynfield2 = msrc->dynfield2; 112795bea772SShijith Thotton #endif 112899a2dd95SBruce Richardson memcpy(&mdst->dynfield1, msrc->dynfield1, sizeof(mdst->dynfield1)); 112999a2dd95SBruce Richardson } 113099a2dd95SBruce Richardson 113199a2dd95SBruce Richardson /* internal */ 113299a2dd95SBruce Richardson static inline void 113399a2dd95SBruce Richardson __rte_pktmbuf_copy_hdr(struct rte_mbuf *mdst, const struct rte_mbuf *msrc) 113499a2dd95SBruce Richardson { 113599a2dd95SBruce Richardson mdst->port = msrc->port; 113699a2dd95SBruce Richardson mdst->vlan_tci = msrc->vlan_tci; 113799a2dd95SBruce Richardson mdst->vlan_tci_outer = msrc->vlan_tci_outer; 113899a2dd95SBruce Richardson mdst->tx_offload = msrc->tx_offload; 113999a2dd95SBruce Richardson mdst->hash = msrc->hash; 114099a2dd95SBruce Richardson mdst->packet_type = msrc->packet_type; 114199a2dd95SBruce Richardson rte_mbuf_dynfield_copy(mdst, msrc); 114299a2dd95SBruce Richardson } 114399a2dd95SBruce Richardson 114499a2dd95SBruce Richardson /** 114599a2dd95SBruce Richardson * Attach packet mbuf to another packet mbuf. 114699a2dd95SBruce Richardson * 114799a2dd95SBruce Richardson * If the mbuf we are attaching to isn't a direct buffer and is attached to 114899a2dd95SBruce Richardson * an external buffer, the mbuf being attached will be attached to the 114999a2dd95SBruce Richardson * external buffer instead of mbuf indirection. 115099a2dd95SBruce Richardson * 115199a2dd95SBruce Richardson * Otherwise, the mbuf will be indirectly attached. After attachment we 115299a2dd95SBruce Richardson * refer the mbuf we attached as 'indirect', while mbuf we attached to as 115399a2dd95SBruce Richardson * 'direct'. The direct mbuf's reference counter is incremented. 115499a2dd95SBruce Richardson * 115599a2dd95SBruce Richardson * Right now, not supported: 115699a2dd95SBruce Richardson * - attachment for already indirect mbuf (e.g. - mi has to be direct). 115799a2dd95SBruce Richardson * - mbuf we trying to attach (mi) is used by someone else 115899a2dd95SBruce Richardson * e.g. it's reference counter is greater then 1. 115999a2dd95SBruce Richardson * 116099a2dd95SBruce Richardson * @param mi 116199a2dd95SBruce Richardson * The indirect packet mbuf. 116299a2dd95SBruce Richardson * @param m 116399a2dd95SBruce Richardson * The packet mbuf we're attaching to. 116499a2dd95SBruce Richardson */ 116599a2dd95SBruce Richardson static inline void rte_pktmbuf_attach(struct rte_mbuf *mi, struct rte_mbuf *m) 116699a2dd95SBruce Richardson { 116799a2dd95SBruce Richardson RTE_ASSERT(RTE_MBUF_DIRECT(mi) && 116899a2dd95SBruce Richardson rte_mbuf_refcnt_read(mi) == 1); 116999a2dd95SBruce Richardson 117099a2dd95SBruce Richardson if (RTE_MBUF_HAS_EXTBUF(m)) { 117199a2dd95SBruce Richardson rte_mbuf_ext_refcnt_update(m->shinfo, 1); 117299a2dd95SBruce Richardson mi->ol_flags = m->ol_flags; 117399a2dd95SBruce Richardson mi->shinfo = m->shinfo; 117499a2dd95SBruce Richardson } else { 117599a2dd95SBruce Richardson /* if m is not direct, get the mbuf that embeds the data */ 117699a2dd95SBruce Richardson rte_mbuf_refcnt_update(rte_mbuf_from_indirect(m), 1); 117799a2dd95SBruce Richardson mi->priv_size = m->priv_size; 1178daa02b5cSOlivier Matz mi->ol_flags = m->ol_flags | RTE_MBUF_F_INDIRECT; 117999a2dd95SBruce Richardson } 118099a2dd95SBruce Richardson 118199a2dd95SBruce Richardson __rte_pktmbuf_copy_hdr(mi, m); 118299a2dd95SBruce Richardson 118399a2dd95SBruce Richardson mi->data_off = m->data_off; 118499a2dd95SBruce Richardson mi->data_len = m->data_len; 1185e811e2d7SShijith Thotton rte_mbuf_iova_set(mi, rte_mbuf_iova_get(m)); 118699a2dd95SBruce Richardson mi->buf_addr = m->buf_addr; 118799a2dd95SBruce Richardson mi->buf_len = m->buf_len; 118899a2dd95SBruce Richardson 118999a2dd95SBruce Richardson mi->next = NULL; 119099a2dd95SBruce Richardson mi->pkt_len = mi->data_len; 119199a2dd95SBruce Richardson mi->nb_segs = 1; 119299a2dd95SBruce Richardson 119399a2dd95SBruce Richardson __rte_mbuf_sanity_check(mi, 1); 119499a2dd95SBruce Richardson __rte_mbuf_sanity_check(m, 0); 119599a2dd95SBruce Richardson } 119699a2dd95SBruce Richardson 119799a2dd95SBruce Richardson /** 119899a2dd95SBruce Richardson * @internal used by rte_pktmbuf_detach(). 119999a2dd95SBruce Richardson * 120099a2dd95SBruce Richardson * Decrement the reference counter of the external buffer. When the 120199a2dd95SBruce Richardson * reference counter becomes 0, the buffer is freed by pre-registered 120299a2dd95SBruce Richardson * callback. 120399a2dd95SBruce Richardson */ 120499a2dd95SBruce Richardson static inline void 120599a2dd95SBruce Richardson __rte_pktmbuf_free_extbuf(struct rte_mbuf *m) 120699a2dd95SBruce Richardson { 120799a2dd95SBruce Richardson RTE_ASSERT(RTE_MBUF_HAS_EXTBUF(m)); 120899a2dd95SBruce Richardson RTE_ASSERT(m->shinfo != NULL); 120999a2dd95SBruce Richardson 121099a2dd95SBruce Richardson if (rte_mbuf_ext_refcnt_update(m->shinfo, -1) == 0) 121199a2dd95SBruce Richardson m->shinfo->free_cb(m->buf_addr, m->shinfo->fcb_opaque); 121299a2dd95SBruce Richardson } 121399a2dd95SBruce Richardson 121499a2dd95SBruce Richardson /** 121599a2dd95SBruce Richardson * @internal used by rte_pktmbuf_detach(). 121699a2dd95SBruce Richardson * 121799a2dd95SBruce Richardson * Decrement the direct mbuf's reference counter. When the reference 121899a2dd95SBruce Richardson * counter becomes 0, the direct mbuf is freed. 121999a2dd95SBruce Richardson */ 122099a2dd95SBruce Richardson static inline void 122199a2dd95SBruce Richardson __rte_pktmbuf_free_direct(struct rte_mbuf *m) 122299a2dd95SBruce Richardson { 122399a2dd95SBruce Richardson struct rte_mbuf *md; 122499a2dd95SBruce Richardson 122599a2dd95SBruce Richardson RTE_ASSERT(RTE_MBUF_CLONED(m)); 122699a2dd95SBruce Richardson 122799a2dd95SBruce Richardson md = rte_mbuf_from_indirect(m); 122899a2dd95SBruce Richardson 122999a2dd95SBruce Richardson if (rte_mbuf_refcnt_update(md, -1) == 0) { 123099a2dd95SBruce Richardson md->next = NULL; 123199a2dd95SBruce Richardson md->nb_segs = 1; 123299a2dd95SBruce Richardson rte_mbuf_refcnt_set(md, 1); 123399a2dd95SBruce Richardson rte_mbuf_raw_free(md); 123499a2dd95SBruce Richardson } 123599a2dd95SBruce Richardson } 123699a2dd95SBruce Richardson 123799a2dd95SBruce Richardson /** 123899a2dd95SBruce Richardson * Detach a packet mbuf from external buffer or direct buffer. 123999a2dd95SBruce Richardson * 124099a2dd95SBruce Richardson * - decrement refcnt and free the external/direct buffer if refcnt 124199a2dd95SBruce Richardson * becomes zero. 124299a2dd95SBruce Richardson * - restore original mbuf address and length values. 124399a2dd95SBruce Richardson * - reset pktmbuf data and data_len to their default values. 124499a2dd95SBruce Richardson * 124599a2dd95SBruce Richardson * All other fields of the given packet mbuf will be left intact. 124699a2dd95SBruce Richardson * 124799a2dd95SBruce Richardson * If the packet mbuf was allocated from the pool with pinned 124899a2dd95SBruce Richardson * external buffers the rte_pktmbuf_detach does nothing with the 124999a2dd95SBruce Richardson * mbuf of this kind, because the pinned buffers are not supposed 125099a2dd95SBruce Richardson * to be detached. 125199a2dd95SBruce Richardson * 125299a2dd95SBruce Richardson * @param m 125399a2dd95SBruce Richardson * The indirect attached packet mbuf. 125499a2dd95SBruce Richardson */ 125599a2dd95SBruce Richardson static inline void rte_pktmbuf_detach(struct rte_mbuf *m) 125699a2dd95SBruce Richardson { 125799a2dd95SBruce Richardson struct rte_mempool *mp = m->pool; 125899a2dd95SBruce Richardson uint32_t mbuf_size, buf_len; 125999a2dd95SBruce Richardson uint16_t priv_size; 126099a2dd95SBruce Richardson 126199a2dd95SBruce Richardson if (RTE_MBUF_HAS_EXTBUF(m)) { 126299a2dd95SBruce Richardson /* 126399a2dd95SBruce Richardson * The mbuf has the external attached buffer, 126499a2dd95SBruce Richardson * we should check the type of the memory pool where 126599a2dd95SBruce Richardson * the mbuf was allocated from to detect the pinned 126699a2dd95SBruce Richardson * external buffer. 126799a2dd95SBruce Richardson */ 126899a2dd95SBruce Richardson uint32_t flags = rte_pktmbuf_priv_flags(mp); 126999a2dd95SBruce Richardson 127099a2dd95SBruce Richardson if (flags & RTE_PKTMBUF_POOL_F_PINNED_EXT_BUF) { 127199a2dd95SBruce Richardson /* 127299a2dd95SBruce Richardson * The pinned external buffer should not be 127399a2dd95SBruce Richardson * detached from its backing mbuf, just exit. 127499a2dd95SBruce Richardson */ 127599a2dd95SBruce Richardson return; 127699a2dd95SBruce Richardson } 127799a2dd95SBruce Richardson __rte_pktmbuf_free_extbuf(m); 127899a2dd95SBruce Richardson } else { 127999a2dd95SBruce Richardson __rte_pktmbuf_free_direct(m); 128099a2dd95SBruce Richardson } 128199a2dd95SBruce Richardson priv_size = rte_pktmbuf_priv_size(mp); 128299a2dd95SBruce Richardson mbuf_size = (uint32_t)(sizeof(struct rte_mbuf) + priv_size); 128399a2dd95SBruce Richardson buf_len = rte_pktmbuf_data_room_size(mp); 128499a2dd95SBruce Richardson 128599a2dd95SBruce Richardson m->priv_size = priv_size; 128699a2dd95SBruce Richardson m->buf_addr = (char *)m + mbuf_size; 1287e811e2d7SShijith Thotton rte_mbuf_iova_set(m, rte_mempool_virt2iova(m) + mbuf_size); 128899a2dd95SBruce Richardson m->buf_len = (uint16_t)buf_len; 128999a2dd95SBruce Richardson rte_pktmbuf_reset_headroom(m); 129099a2dd95SBruce Richardson m->data_len = 0; 129199a2dd95SBruce Richardson m->ol_flags = 0; 129299a2dd95SBruce Richardson } 129399a2dd95SBruce Richardson 129499a2dd95SBruce Richardson /** 129599a2dd95SBruce Richardson * @internal Handle the packet mbufs with attached pinned external buffer 129699a2dd95SBruce Richardson * on the mbuf freeing: 129799a2dd95SBruce Richardson * 129899a2dd95SBruce Richardson * - return zero if reference counter in shinfo is one. It means there is 129999a2dd95SBruce Richardson * no more reference to this pinned buffer and mbuf can be returned to 130099a2dd95SBruce Richardson * the pool 130199a2dd95SBruce Richardson * 130299a2dd95SBruce Richardson * - otherwise (if reference counter is not one), decrement reference 130399a2dd95SBruce Richardson * counter and return non-zero value to prevent freeing the backing mbuf. 130499a2dd95SBruce Richardson * 130599a2dd95SBruce Richardson * Returns non zero if mbuf should not be freed. 130699a2dd95SBruce Richardson */ 130799a2dd95SBruce Richardson static inline int __rte_pktmbuf_pinned_extbuf_decref(struct rte_mbuf *m) 130899a2dd95SBruce Richardson { 130999a2dd95SBruce Richardson struct rte_mbuf_ext_shared_info *shinfo; 131099a2dd95SBruce Richardson 131199a2dd95SBruce Richardson /* Clear flags, mbuf is being freed. */ 1312daa02b5cSOlivier Matz m->ol_flags = RTE_MBUF_F_EXTERNAL; 131399a2dd95SBruce Richardson shinfo = m->shinfo; 131499a2dd95SBruce Richardson 131599a2dd95SBruce Richardson /* Optimize for performance - do not dec/reinit */ 131699a2dd95SBruce Richardson if (likely(rte_mbuf_ext_refcnt_read(shinfo) == 1)) 131799a2dd95SBruce Richardson return 0; 131899a2dd95SBruce Richardson 131999a2dd95SBruce Richardson /* 132099a2dd95SBruce Richardson * Direct usage of add primitive to avoid 132199a2dd95SBruce Richardson * duplication of comparing with one. 132299a2dd95SBruce Richardson */ 13239bcb34d4STyler Retzlaff if (likely(rte_atomic_fetch_add_explicit(&shinfo->refcnt, -1, 13249bcb34d4STyler Retzlaff rte_memory_order_acq_rel) - 1)) 132599a2dd95SBruce Richardson return 1; 132699a2dd95SBruce Richardson 132799a2dd95SBruce Richardson /* Reinitialize counter before mbuf freeing. */ 132899a2dd95SBruce Richardson rte_mbuf_ext_refcnt_set(shinfo, 1); 132999a2dd95SBruce Richardson return 0; 133099a2dd95SBruce Richardson } 133199a2dd95SBruce Richardson 133299a2dd95SBruce Richardson /** 133399a2dd95SBruce Richardson * Decrease reference counter and unlink a mbuf segment 133499a2dd95SBruce Richardson * 133599a2dd95SBruce Richardson * This function does the same than a free, except that it does not 133699a2dd95SBruce Richardson * return the segment to its pool. 133799a2dd95SBruce Richardson * It decreases the reference counter, and if it reaches 0, it is 133899a2dd95SBruce Richardson * detached from its parent for an indirect mbuf. 133999a2dd95SBruce Richardson * 134099a2dd95SBruce Richardson * @param m 134199a2dd95SBruce Richardson * The mbuf to be unlinked 134299a2dd95SBruce Richardson * @return 134399a2dd95SBruce Richardson * - (m) if it is the last reference. It can be recycled or freed. 134499a2dd95SBruce Richardson * - (NULL) if the mbuf still has remaining references on it. 134599a2dd95SBruce Richardson */ 134699a2dd95SBruce Richardson static __rte_always_inline struct rte_mbuf * 134799a2dd95SBruce Richardson rte_pktmbuf_prefree_seg(struct rte_mbuf *m) 134899a2dd95SBruce Richardson { 134999a2dd95SBruce Richardson __rte_mbuf_sanity_check(m, 0); 135099a2dd95SBruce Richardson 135199a2dd95SBruce Richardson if (likely(rte_mbuf_refcnt_read(m) == 1)) { 135299a2dd95SBruce Richardson 135399a2dd95SBruce Richardson if (!RTE_MBUF_DIRECT(m)) { 135499a2dd95SBruce Richardson rte_pktmbuf_detach(m); 135599a2dd95SBruce Richardson if (RTE_MBUF_HAS_EXTBUF(m) && 135699a2dd95SBruce Richardson RTE_MBUF_HAS_PINNED_EXTBUF(m) && 135799a2dd95SBruce Richardson __rte_pktmbuf_pinned_extbuf_decref(m)) 135899a2dd95SBruce Richardson return NULL; 135999a2dd95SBruce Richardson } 136099a2dd95SBruce Richardson 1361efc6f910SOlivier Matz if (m->next != NULL) 136299a2dd95SBruce Richardson m->next = NULL; 1363efc6f910SOlivier Matz if (m->nb_segs != 1) 136499a2dd95SBruce Richardson m->nb_segs = 1; 136599a2dd95SBruce Richardson 136699a2dd95SBruce Richardson return m; 136799a2dd95SBruce Richardson 136899a2dd95SBruce Richardson } else if (__rte_mbuf_refcnt_update(m, -1) == 0) { 136999a2dd95SBruce Richardson 137099a2dd95SBruce Richardson if (!RTE_MBUF_DIRECT(m)) { 137199a2dd95SBruce Richardson rte_pktmbuf_detach(m); 137299a2dd95SBruce Richardson if (RTE_MBUF_HAS_EXTBUF(m) && 137399a2dd95SBruce Richardson RTE_MBUF_HAS_PINNED_EXTBUF(m) && 137499a2dd95SBruce Richardson __rte_pktmbuf_pinned_extbuf_decref(m)) 137599a2dd95SBruce Richardson return NULL; 137699a2dd95SBruce Richardson } 137799a2dd95SBruce Richardson 1378efc6f910SOlivier Matz if (m->next != NULL) 137999a2dd95SBruce Richardson m->next = NULL; 1380efc6f910SOlivier Matz if (m->nb_segs != 1) 138199a2dd95SBruce Richardson m->nb_segs = 1; 138299a2dd95SBruce Richardson rte_mbuf_refcnt_set(m, 1); 138399a2dd95SBruce Richardson 138499a2dd95SBruce Richardson return m; 138599a2dd95SBruce Richardson } 138699a2dd95SBruce Richardson return NULL; 138799a2dd95SBruce Richardson } 138899a2dd95SBruce Richardson 138999a2dd95SBruce Richardson /** 139099a2dd95SBruce Richardson * Free a segment of a packet mbuf into its original mempool. 139199a2dd95SBruce Richardson * 139299a2dd95SBruce Richardson * Free an mbuf, without parsing other segments in case of chained 139399a2dd95SBruce Richardson * buffers. 139499a2dd95SBruce Richardson * 139599a2dd95SBruce Richardson * @param m 139699a2dd95SBruce Richardson * The packet mbuf segment to be freed. 139799a2dd95SBruce Richardson */ 139899a2dd95SBruce Richardson static __rte_always_inline void 139999a2dd95SBruce Richardson rte_pktmbuf_free_seg(struct rte_mbuf *m) 140099a2dd95SBruce Richardson { 140199a2dd95SBruce Richardson m = rte_pktmbuf_prefree_seg(m); 140299a2dd95SBruce Richardson if (likely(m != NULL)) 140399a2dd95SBruce Richardson rte_mbuf_raw_free(m); 140499a2dd95SBruce Richardson } 140599a2dd95SBruce Richardson 140699a2dd95SBruce Richardson /** 140799a2dd95SBruce Richardson * Free a packet mbuf back into its original mempool. 140899a2dd95SBruce Richardson * 140999a2dd95SBruce Richardson * Free an mbuf, and all its segments in case of chained buffers. Each 141099a2dd95SBruce Richardson * segment is added back into its original mempool. 141199a2dd95SBruce Richardson * 141299a2dd95SBruce Richardson * @param m 141399a2dd95SBruce Richardson * The packet mbuf to be freed. If NULL, the function does nothing. 141499a2dd95SBruce Richardson */ 141599a2dd95SBruce Richardson static inline void rte_pktmbuf_free(struct rte_mbuf *m) 141699a2dd95SBruce Richardson { 141799a2dd95SBruce Richardson struct rte_mbuf *m_next; 141899a2dd95SBruce Richardson 141999a2dd95SBruce Richardson if (m != NULL) 142099a2dd95SBruce Richardson __rte_mbuf_sanity_check(m, 1); 142199a2dd95SBruce Richardson 142299a2dd95SBruce Richardson while (m != NULL) { 142399a2dd95SBruce Richardson m_next = m->next; 142499a2dd95SBruce Richardson rte_pktmbuf_free_seg(m); 142599a2dd95SBruce Richardson m = m_next; 142699a2dd95SBruce Richardson } 142799a2dd95SBruce Richardson } 142899a2dd95SBruce Richardson 142999a2dd95SBruce Richardson /** 143099a2dd95SBruce Richardson * Free a bulk of packet mbufs back into their original mempools. 143199a2dd95SBruce Richardson * 143299a2dd95SBruce Richardson * Free a bulk of mbufs, and all their segments in case of chained buffers. 143399a2dd95SBruce Richardson * Each segment is added back into its original mempool. 143499a2dd95SBruce Richardson * 143599a2dd95SBruce Richardson * @param mbufs 143699a2dd95SBruce Richardson * Array of pointers to packet mbufs. 143799a2dd95SBruce Richardson * The array may contain NULL pointers. 143899a2dd95SBruce Richardson * @param count 143999a2dd95SBruce Richardson * Array size. 144099a2dd95SBruce Richardson */ 144199a2dd95SBruce Richardson void rte_pktmbuf_free_bulk(struct rte_mbuf **mbufs, unsigned int count); 144299a2dd95SBruce Richardson 144399a2dd95SBruce Richardson /** 144499a2dd95SBruce Richardson * Create a "clone" of the given packet mbuf. 144599a2dd95SBruce Richardson * 144699a2dd95SBruce Richardson * Walks through all segments of the given packet mbuf, and for each of them: 144799a2dd95SBruce Richardson * - Creates a new packet mbuf from the given pool. 144899a2dd95SBruce Richardson * - Attaches newly created mbuf to the segment. 144999a2dd95SBruce Richardson * Then updates pkt_len and nb_segs of the "clone" packet mbuf to match values 145099a2dd95SBruce Richardson * from the original packet mbuf. 145199a2dd95SBruce Richardson * 145299a2dd95SBruce Richardson * @param md 145399a2dd95SBruce Richardson * The packet mbuf to be cloned. 145499a2dd95SBruce Richardson * @param mp 145599a2dd95SBruce Richardson * The mempool from which the "clone" mbufs are allocated. 145699a2dd95SBruce Richardson * @return 145799a2dd95SBruce Richardson * - The pointer to the new "clone" mbuf on success. 145899a2dd95SBruce Richardson * - NULL if allocation fails. 145999a2dd95SBruce Richardson */ 146099a2dd95SBruce Richardson struct rte_mbuf * 146199a2dd95SBruce Richardson rte_pktmbuf_clone(struct rte_mbuf *md, struct rte_mempool *mp); 146299a2dd95SBruce Richardson 146399a2dd95SBruce Richardson /** 146499a2dd95SBruce Richardson * Create a full copy of a given packet mbuf. 146599a2dd95SBruce Richardson * 146699a2dd95SBruce Richardson * Copies all the data from a given packet mbuf to a newly allocated 146799a2dd95SBruce Richardson * set of mbufs. The private data are is not copied. 146899a2dd95SBruce Richardson * 146999a2dd95SBruce Richardson * @param m 1470d75eed0fSStephen Hemminger * The packet mbuf to be copied. 147199a2dd95SBruce Richardson * @param mp 147299a2dd95SBruce Richardson * The mempool from which the "clone" mbufs are allocated. 147399a2dd95SBruce Richardson * @param offset 147499a2dd95SBruce Richardson * The number of bytes to skip before copying. 147599a2dd95SBruce Richardson * If the mbuf does not have that many bytes, it is an error 147699a2dd95SBruce Richardson * and NULL is returned. 147799a2dd95SBruce Richardson * @param length 147899a2dd95SBruce Richardson * The upper limit on bytes to copy. Passing UINT32_MAX 147999a2dd95SBruce Richardson * means all data (after offset). 148099a2dd95SBruce Richardson * @return 148199a2dd95SBruce Richardson * - The pointer to the new "clone" mbuf on success. 148299a2dd95SBruce Richardson * - NULL if allocation fails. 148399a2dd95SBruce Richardson */ 148499a2dd95SBruce Richardson struct rte_mbuf * 148599a2dd95SBruce Richardson rte_pktmbuf_copy(const struct rte_mbuf *m, struct rte_mempool *mp, 148699a2dd95SBruce Richardson uint32_t offset, uint32_t length); 148799a2dd95SBruce Richardson 148899a2dd95SBruce Richardson /** 148999a2dd95SBruce Richardson * Adds given value to the refcnt of all packet mbuf segments. 149099a2dd95SBruce Richardson * 149199a2dd95SBruce Richardson * Walks through all segments of given packet mbuf and for each of them 149299a2dd95SBruce Richardson * invokes rte_mbuf_refcnt_update(). 149399a2dd95SBruce Richardson * 149499a2dd95SBruce Richardson * @param m 149599a2dd95SBruce Richardson * The packet mbuf whose refcnt to be updated. 149699a2dd95SBruce Richardson * @param v 149799a2dd95SBruce Richardson * The value to add to the mbuf's segments refcnt. 149899a2dd95SBruce Richardson */ 149999a2dd95SBruce Richardson static inline void rte_pktmbuf_refcnt_update(struct rte_mbuf *m, int16_t v) 150099a2dd95SBruce Richardson { 150199a2dd95SBruce Richardson __rte_mbuf_sanity_check(m, 1); 150299a2dd95SBruce Richardson 150399a2dd95SBruce Richardson do { 150499a2dd95SBruce Richardson rte_mbuf_refcnt_update(m, v); 150599a2dd95SBruce Richardson } while ((m = m->next) != NULL); 150699a2dd95SBruce Richardson } 150799a2dd95SBruce Richardson 150899a2dd95SBruce Richardson /** 150999a2dd95SBruce Richardson * Get the headroom in a packet mbuf. 151099a2dd95SBruce Richardson * 151199a2dd95SBruce Richardson * @param m 151299a2dd95SBruce Richardson * The packet mbuf. 151399a2dd95SBruce Richardson * @return 151499a2dd95SBruce Richardson * The length of the headroom. 151599a2dd95SBruce Richardson */ 151699a2dd95SBruce Richardson static inline uint16_t rte_pktmbuf_headroom(const struct rte_mbuf *m) 151799a2dd95SBruce Richardson { 151899a2dd95SBruce Richardson __rte_mbuf_sanity_check(m, 0); 151999a2dd95SBruce Richardson return m->data_off; 152099a2dd95SBruce Richardson } 152199a2dd95SBruce Richardson 152299a2dd95SBruce Richardson /** 152399a2dd95SBruce Richardson * Get the tailroom of a packet mbuf. 152499a2dd95SBruce Richardson * 152599a2dd95SBruce Richardson * @param m 152699a2dd95SBruce Richardson * The packet mbuf. 152799a2dd95SBruce Richardson * @return 152899a2dd95SBruce Richardson * The length of the tailroom. 152999a2dd95SBruce Richardson */ 153099a2dd95SBruce Richardson static inline uint16_t rte_pktmbuf_tailroom(const struct rte_mbuf *m) 153199a2dd95SBruce Richardson { 153299a2dd95SBruce Richardson __rte_mbuf_sanity_check(m, 0); 153399a2dd95SBruce Richardson return (uint16_t)(m->buf_len - rte_pktmbuf_headroom(m) - 153499a2dd95SBruce Richardson m->data_len); 153599a2dd95SBruce Richardson } 153699a2dd95SBruce Richardson 153799a2dd95SBruce Richardson /** 153899a2dd95SBruce Richardson * Get the last segment of the packet. 153999a2dd95SBruce Richardson * 154099a2dd95SBruce Richardson * @param m 154199a2dd95SBruce Richardson * The packet mbuf. 154299a2dd95SBruce Richardson * @return 154399a2dd95SBruce Richardson * The last segment of the given mbuf. 154499a2dd95SBruce Richardson */ 154599a2dd95SBruce Richardson static inline struct rte_mbuf *rte_pktmbuf_lastseg(struct rte_mbuf *m) 154699a2dd95SBruce Richardson { 154799a2dd95SBruce Richardson __rte_mbuf_sanity_check(m, 1); 154899a2dd95SBruce Richardson while (m->next != NULL) 154999a2dd95SBruce Richardson m = m->next; 155099a2dd95SBruce Richardson return m; 155199a2dd95SBruce Richardson } 155299a2dd95SBruce Richardson 155399a2dd95SBruce Richardson /** 155499a2dd95SBruce Richardson * A macro that returns the length of the packet. 155599a2dd95SBruce Richardson * 155699a2dd95SBruce Richardson * The value can be read or assigned. 155799a2dd95SBruce Richardson * 155899a2dd95SBruce Richardson * @param m 155999a2dd95SBruce Richardson * The packet mbuf. 156099a2dd95SBruce Richardson */ 156199a2dd95SBruce Richardson #define rte_pktmbuf_pkt_len(m) ((m)->pkt_len) 156299a2dd95SBruce Richardson 156399a2dd95SBruce Richardson /** 156499a2dd95SBruce Richardson * A macro that returns the length of the segment. 156599a2dd95SBruce Richardson * 156699a2dd95SBruce Richardson * The value can be read or assigned. 156799a2dd95SBruce Richardson * 156899a2dd95SBruce Richardson * @param m 156999a2dd95SBruce Richardson * The packet mbuf. 157099a2dd95SBruce Richardson */ 157199a2dd95SBruce Richardson #define rte_pktmbuf_data_len(m) ((m)->data_len) 157299a2dd95SBruce Richardson 157399a2dd95SBruce Richardson /** 157499a2dd95SBruce Richardson * Prepend len bytes to an mbuf data area. 157599a2dd95SBruce Richardson * 157699a2dd95SBruce Richardson * Returns a pointer to the new 157799a2dd95SBruce Richardson * data start address. If there is not enough headroom in the first 157899a2dd95SBruce Richardson * segment, the function will return NULL, without modifying the mbuf. 157999a2dd95SBruce Richardson * 158099a2dd95SBruce Richardson * @param m 158199a2dd95SBruce Richardson * The pkt mbuf. 158299a2dd95SBruce Richardson * @param len 158399a2dd95SBruce Richardson * The amount of data to prepend (in bytes). 158499a2dd95SBruce Richardson * @return 158599a2dd95SBruce Richardson * A pointer to the start of the newly prepended data, or 158699a2dd95SBruce Richardson * NULL if there is not enough headroom space in the first segment 158799a2dd95SBruce Richardson */ 158899a2dd95SBruce Richardson static inline char *rte_pktmbuf_prepend(struct rte_mbuf *m, 158999a2dd95SBruce Richardson uint16_t len) 159099a2dd95SBruce Richardson { 159199a2dd95SBruce Richardson __rte_mbuf_sanity_check(m, 1); 159299a2dd95SBruce Richardson 159399a2dd95SBruce Richardson if (unlikely(len > rte_pktmbuf_headroom(m))) 159499a2dd95SBruce Richardson return NULL; 159599a2dd95SBruce Richardson 159699a2dd95SBruce Richardson /* NB: elaborating the subtraction like this instead of using 159799a2dd95SBruce Richardson * -= allows us to ensure the result type is uint16_t 159899a2dd95SBruce Richardson * avoiding compiler warnings on gcc 8.1 at least */ 159999a2dd95SBruce Richardson m->data_off = (uint16_t)(m->data_off - len); 160099a2dd95SBruce Richardson m->data_len = (uint16_t)(m->data_len + len); 160199a2dd95SBruce Richardson m->pkt_len = (m->pkt_len + len); 160299a2dd95SBruce Richardson 160399a2dd95SBruce Richardson return (char *)m->buf_addr + m->data_off; 160499a2dd95SBruce Richardson } 160599a2dd95SBruce Richardson 160699a2dd95SBruce Richardson /** 160799a2dd95SBruce Richardson * Append len bytes to an mbuf. 160899a2dd95SBruce Richardson * 160999a2dd95SBruce Richardson * Append len bytes to an mbuf and return a pointer to the start address 161099a2dd95SBruce Richardson * of the added data. If there is not enough tailroom in the last 161199a2dd95SBruce Richardson * segment, the function will return NULL, without modifying the mbuf. 161299a2dd95SBruce Richardson * 161399a2dd95SBruce Richardson * @param m 161499a2dd95SBruce Richardson * The packet mbuf. 161599a2dd95SBruce Richardson * @param len 161699a2dd95SBruce Richardson * The amount of data to append (in bytes). 161799a2dd95SBruce Richardson * @return 161899a2dd95SBruce Richardson * A pointer to the start of the newly appended data, or 161999a2dd95SBruce Richardson * NULL if there is not enough tailroom space in the last segment 162099a2dd95SBruce Richardson */ 162199a2dd95SBruce Richardson static inline char *rte_pktmbuf_append(struct rte_mbuf *m, uint16_t len) 162299a2dd95SBruce Richardson { 162399a2dd95SBruce Richardson void *tail; 162499a2dd95SBruce Richardson struct rte_mbuf *m_last; 162599a2dd95SBruce Richardson 162699a2dd95SBruce Richardson __rte_mbuf_sanity_check(m, 1); 162799a2dd95SBruce Richardson 162899a2dd95SBruce Richardson m_last = rte_pktmbuf_lastseg(m); 162999a2dd95SBruce Richardson if (unlikely(len > rte_pktmbuf_tailroom(m_last))) 163099a2dd95SBruce Richardson return NULL; 163199a2dd95SBruce Richardson 163299a2dd95SBruce Richardson tail = (char *)m_last->buf_addr + m_last->data_off + m_last->data_len; 163399a2dd95SBruce Richardson m_last->data_len = (uint16_t)(m_last->data_len + len); 163499a2dd95SBruce Richardson m->pkt_len = (m->pkt_len + len); 163599a2dd95SBruce Richardson return (char*) tail; 163699a2dd95SBruce Richardson } 163799a2dd95SBruce Richardson 163899a2dd95SBruce Richardson /** 163999a2dd95SBruce Richardson * Remove len bytes at the beginning of an mbuf. 164099a2dd95SBruce Richardson * 164199a2dd95SBruce Richardson * Returns a pointer to the start address of the new data area. If the 164299a2dd95SBruce Richardson * length is greater than the length of the first segment, then the 164399a2dd95SBruce Richardson * function will fail and return NULL, without modifying the mbuf. 164499a2dd95SBruce Richardson * 164599a2dd95SBruce Richardson * @param m 164699a2dd95SBruce Richardson * The packet mbuf. 164799a2dd95SBruce Richardson * @param len 164899a2dd95SBruce Richardson * The amount of data to remove (in bytes). 164999a2dd95SBruce Richardson * @return 165099a2dd95SBruce Richardson * A pointer to the new start of the data. 165199a2dd95SBruce Richardson */ 165299a2dd95SBruce Richardson static inline char *rte_pktmbuf_adj(struct rte_mbuf *m, uint16_t len) 165399a2dd95SBruce Richardson { 165499a2dd95SBruce Richardson __rte_mbuf_sanity_check(m, 1); 165599a2dd95SBruce Richardson 165699a2dd95SBruce Richardson if (unlikely(len > m->data_len)) 165799a2dd95SBruce Richardson return NULL; 165899a2dd95SBruce Richardson 165999a2dd95SBruce Richardson /* NB: elaborating the addition like this instead of using 166099a2dd95SBruce Richardson * += allows us to ensure the result type is uint16_t 166199a2dd95SBruce Richardson * avoiding compiler warnings on gcc 8.1 at least */ 166299a2dd95SBruce Richardson m->data_len = (uint16_t)(m->data_len - len); 166399a2dd95SBruce Richardson m->data_off = (uint16_t)(m->data_off + len); 166499a2dd95SBruce Richardson m->pkt_len = (m->pkt_len - len); 166599a2dd95SBruce Richardson return (char *)m->buf_addr + m->data_off; 166699a2dd95SBruce Richardson } 166799a2dd95SBruce Richardson 166899a2dd95SBruce Richardson /** 166999a2dd95SBruce Richardson * Remove len bytes of data at the end of the mbuf. 167099a2dd95SBruce Richardson * 167199a2dd95SBruce Richardson * If the length is greater than the length of the last segment, the 167299a2dd95SBruce Richardson * function will fail and return -1 without modifying the mbuf. 167399a2dd95SBruce Richardson * 167499a2dd95SBruce Richardson * @param m 167599a2dd95SBruce Richardson * The packet mbuf. 167699a2dd95SBruce Richardson * @param len 167799a2dd95SBruce Richardson * The amount of data to remove (in bytes). 167899a2dd95SBruce Richardson * @return 167999a2dd95SBruce Richardson * - 0: On success. 168099a2dd95SBruce Richardson * - -1: On error. 168199a2dd95SBruce Richardson */ 168299a2dd95SBruce Richardson static inline int rte_pktmbuf_trim(struct rte_mbuf *m, uint16_t len) 168399a2dd95SBruce Richardson { 168499a2dd95SBruce Richardson struct rte_mbuf *m_last; 168599a2dd95SBruce Richardson 168699a2dd95SBruce Richardson __rte_mbuf_sanity_check(m, 1); 168799a2dd95SBruce Richardson 168899a2dd95SBruce Richardson m_last = rte_pktmbuf_lastseg(m); 168999a2dd95SBruce Richardson if (unlikely(len > m_last->data_len)) 169099a2dd95SBruce Richardson return -1; 169199a2dd95SBruce Richardson 169299a2dd95SBruce Richardson m_last->data_len = (uint16_t)(m_last->data_len - len); 169399a2dd95SBruce Richardson m->pkt_len = (m->pkt_len - len); 169499a2dd95SBruce Richardson return 0; 169599a2dd95SBruce Richardson } 169699a2dd95SBruce Richardson 169799a2dd95SBruce Richardson /** 169899a2dd95SBruce Richardson * Test if mbuf data is contiguous. 169999a2dd95SBruce Richardson * 170099a2dd95SBruce Richardson * @param m 170199a2dd95SBruce Richardson * The packet mbuf. 170299a2dd95SBruce Richardson * @return 170399a2dd95SBruce Richardson * - 1, if all data is contiguous (one segment). 170499a2dd95SBruce Richardson * - 0, if there is several segments. 170599a2dd95SBruce Richardson */ 170699a2dd95SBruce Richardson static inline int rte_pktmbuf_is_contiguous(const struct rte_mbuf *m) 170799a2dd95SBruce Richardson { 170899a2dd95SBruce Richardson __rte_mbuf_sanity_check(m, 1); 170999a2dd95SBruce Richardson return m->nb_segs == 1; 171099a2dd95SBruce Richardson } 171199a2dd95SBruce Richardson 171299a2dd95SBruce Richardson /** 171399a2dd95SBruce Richardson * @internal used by rte_pktmbuf_read(). 171499a2dd95SBruce Richardson */ 171599a2dd95SBruce Richardson const void *__rte_pktmbuf_read(const struct rte_mbuf *m, uint32_t off, 171699a2dd95SBruce Richardson uint32_t len, void *buf); 171799a2dd95SBruce Richardson 171899a2dd95SBruce Richardson /** 171999a2dd95SBruce Richardson * Read len data bytes in a mbuf at specified offset. 172099a2dd95SBruce Richardson * 172199a2dd95SBruce Richardson * If the data is contiguous, return the pointer in the mbuf data, else 172299a2dd95SBruce Richardson * copy the data in the buffer provided by the user and return its 172399a2dd95SBruce Richardson * pointer. 172499a2dd95SBruce Richardson * 172599a2dd95SBruce Richardson * @param m 172699a2dd95SBruce Richardson * The pointer to the mbuf. 172799a2dd95SBruce Richardson * @param off 172899a2dd95SBruce Richardson * The offset of the data in the mbuf. 172999a2dd95SBruce Richardson * @param len 173099a2dd95SBruce Richardson * The amount of bytes to read. 173199a2dd95SBruce Richardson * @param buf 173299a2dd95SBruce Richardson * The buffer where data is copied if it is not contiguous in mbuf 173399a2dd95SBruce Richardson * data. Its length should be at least equal to the len parameter. 173499a2dd95SBruce Richardson * @return 173599a2dd95SBruce Richardson * The pointer to the data, either in the mbuf if it is contiguous, 173699a2dd95SBruce Richardson * or in the user buffer. If mbuf is too small, NULL is returned. 173799a2dd95SBruce Richardson */ 173899a2dd95SBruce Richardson static inline const void *rte_pktmbuf_read(const struct rte_mbuf *m, 173999a2dd95SBruce Richardson uint32_t off, uint32_t len, void *buf) 174099a2dd95SBruce Richardson { 174199a2dd95SBruce Richardson if (likely(off + len <= rte_pktmbuf_data_len(m))) 174299a2dd95SBruce Richardson return rte_pktmbuf_mtod_offset(m, char *, off); 174399a2dd95SBruce Richardson else 174499a2dd95SBruce Richardson return __rte_pktmbuf_read(m, off, len, buf); 174599a2dd95SBruce Richardson } 174699a2dd95SBruce Richardson 174799a2dd95SBruce Richardson /** 174899a2dd95SBruce Richardson * Chain an mbuf to another, thereby creating a segmented packet. 174999a2dd95SBruce Richardson * 175099a2dd95SBruce Richardson * Note: The implementation will do a linear walk over the segments to find 175199a2dd95SBruce Richardson * the tail entry. For cases when there are many segments, it's better to 175299a2dd95SBruce Richardson * chain the entries manually. 175399a2dd95SBruce Richardson * 175499a2dd95SBruce Richardson * @param head 175599a2dd95SBruce Richardson * The head of the mbuf chain (the first packet) 175699a2dd95SBruce Richardson * @param tail 175799a2dd95SBruce Richardson * The mbuf to put last in the chain 175899a2dd95SBruce Richardson * 175999a2dd95SBruce Richardson * @return 176099a2dd95SBruce Richardson * - 0, on success. 176199a2dd95SBruce Richardson * - -EOVERFLOW, if the chain segment limit exceeded 176299a2dd95SBruce Richardson */ 176399a2dd95SBruce Richardson static inline int rte_pktmbuf_chain(struct rte_mbuf *head, struct rte_mbuf *tail) 176499a2dd95SBruce Richardson { 176599a2dd95SBruce Richardson struct rte_mbuf *cur_tail; 176699a2dd95SBruce Richardson 176799a2dd95SBruce Richardson /* Check for number-of-segments-overflow */ 176899a2dd95SBruce Richardson if (head->nb_segs + tail->nb_segs > RTE_MBUF_MAX_NB_SEGS) 176999a2dd95SBruce Richardson return -EOVERFLOW; 177099a2dd95SBruce Richardson 177199a2dd95SBruce Richardson /* Chain 'tail' onto the old tail */ 177299a2dd95SBruce Richardson cur_tail = rte_pktmbuf_lastseg(head); 177399a2dd95SBruce Richardson cur_tail->next = tail; 177499a2dd95SBruce Richardson 177599a2dd95SBruce Richardson /* accumulate number of segments and total length. 177699a2dd95SBruce Richardson * NB: elaborating the addition like this instead of using 177799a2dd95SBruce Richardson * -= allows us to ensure the result type is uint16_t 177899a2dd95SBruce Richardson * avoiding compiler warnings on gcc 8.1 at least */ 177999a2dd95SBruce Richardson head->nb_segs = (uint16_t)(head->nb_segs + tail->nb_segs); 178099a2dd95SBruce Richardson head->pkt_len += tail->pkt_len; 178199a2dd95SBruce Richardson 178299a2dd95SBruce Richardson /* pkt_len is only set in the head */ 178399a2dd95SBruce Richardson tail->pkt_len = tail->data_len; 178499a2dd95SBruce Richardson 178599a2dd95SBruce Richardson return 0; 178699a2dd95SBruce Richardson } 178799a2dd95SBruce Richardson 17888680efa0SStephen Hemminger /** 178999a2dd95SBruce Richardson * For given input values generate raw tx_offload value. 179099a2dd95SBruce Richardson * Note that it is caller responsibility to make sure that input parameters 179199a2dd95SBruce Richardson * don't exceed maximum bit-field values. 179299a2dd95SBruce Richardson * @param il2 179399a2dd95SBruce Richardson * l2_len value. 179499a2dd95SBruce Richardson * @param il3 179599a2dd95SBruce Richardson * l3_len value. 179699a2dd95SBruce Richardson * @param il4 179799a2dd95SBruce Richardson * l4_len value. 179899a2dd95SBruce Richardson * @param tso 179999a2dd95SBruce Richardson * tso_segsz value. 180099a2dd95SBruce Richardson * @param ol3 180199a2dd95SBruce Richardson * outer_l3_len value. 180299a2dd95SBruce Richardson * @param ol2 180399a2dd95SBruce Richardson * outer_l2_len value. 180499a2dd95SBruce Richardson * @param unused 180599a2dd95SBruce Richardson * unused value. 180699a2dd95SBruce Richardson * @return 180799a2dd95SBruce Richardson * raw tx_offload value. 180899a2dd95SBruce Richardson */ 180999a2dd95SBruce Richardson static __rte_always_inline uint64_t 181099a2dd95SBruce Richardson rte_mbuf_tx_offload(uint64_t il2, uint64_t il3, uint64_t il4, uint64_t tso, 181199a2dd95SBruce Richardson uint64_t ol3, uint64_t ol2, uint64_t unused) 181299a2dd95SBruce Richardson { 181399a2dd95SBruce Richardson return il2 << RTE_MBUF_L2_LEN_OFS | 181499a2dd95SBruce Richardson il3 << RTE_MBUF_L3_LEN_OFS | 181599a2dd95SBruce Richardson il4 << RTE_MBUF_L4_LEN_OFS | 181699a2dd95SBruce Richardson tso << RTE_MBUF_TSO_SEGSZ_OFS | 181799a2dd95SBruce Richardson ol3 << RTE_MBUF_OUTL3_LEN_OFS | 181899a2dd95SBruce Richardson ol2 << RTE_MBUF_OUTL2_LEN_OFS | 181999a2dd95SBruce Richardson unused << RTE_MBUF_TXOFLD_UNUSED_OFS; 182099a2dd95SBruce Richardson } 182199a2dd95SBruce Richardson 182299a2dd95SBruce Richardson /** 182399a2dd95SBruce Richardson * Validate general requirements for Tx offload in mbuf. 182499a2dd95SBruce Richardson * 182599a2dd95SBruce Richardson * This function checks correctness and completeness of Tx offload settings. 182699a2dd95SBruce Richardson * 182799a2dd95SBruce Richardson * @param m 182899a2dd95SBruce Richardson * The packet mbuf to be validated. 182999a2dd95SBruce Richardson * @return 183099a2dd95SBruce Richardson * 0 if packet is valid 183199a2dd95SBruce Richardson */ 183299a2dd95SBruce Richardson static inline int 183399a2dd95SBruce Richardson rte_validate_tx_offload(const struct rte_mbuf *m) 183499a2dd95SBruce Richardson { 183599a2dd95SBruce Richardson uint64_t ol_flags = m->ol_flags; 183699a2dd95SBruce Richardson 183799a2dd95SBruce Richardson /* Does packet set any of available offloads? */ 1838daa02b5cSOlivier Matz if (!(ol_flags & RTE_MBUF_F_TX_OFFLOAD_MASK)) 183999a2dd95SBruce Richardson return 0; 184099a2dd95SBruce Richardson 184199a2dd95SBruce Richardson /* IP checksum can be counted only for IPv4 packet */ 1842daa02b5cSOlivier Matz if ((ol_flags & RTE_MBUF_F_TX_IP_CKSUM) && (ol_flags & RTE_MBUF_F_TX_IPV6)) 184399a2dd95SBruce Richardson return -EINVAL; 184499a2dd95SBruce Richardson 184599a2dd95SBruce Richardson /* IP type not set when required */ 1846daa02b5cSOlivier Matz if (ol_flags & (RTE_MBUF_F_TX_L4_MASK | RTE_MBUF_F_TX_TCP_SEG)) 1847daa02b5cSOlivier Matz if (!(ol_flags & (RTE_MBUF_F_TX_IPV4 | RTE_MBUF_F_TX_IPV6))) 184899a2dd95SBruce Richardson return -EINVAL; 184999a2dd95SBruce Richardson 185099a2dd95SBruce Richardson /* Check requirements for TSO packet */ 1851daa02b5cSOlivier Matz if (ol_flags & RTE_MBUF_F_TX_TCP_SEG) 185299a2dd95SBruce Richardson if ((m->tso_segsz == 0) || 1853daa02b5cSOlivier Matz ((ol_flags & RTE_MBUF_F_TX_IPV4) && 1854daa02b5cSOlivier Matz !(ol_flags & RTE_MBUF_F_TX_IP_CKSUM))) 185599a2dd95SBruce Richardson return -EINVAL; 185699a2dd95SBruce Richardson 1857daa02b5cSOlivier Matz /* RTE_MBUF_F_TX_OUTER_IP_CKSUM set for non outer IPv4 packet. */ 1858daa02b5cSOlivier Matz if ((ol_flags & RTE_MBUF_F_TX_OUTER_IP_CKSUM) && 1859daa02b5cSOlivier Matz !(ol_flags & RTE_MBUF_F_TX_OUTER_IPV4)) 186099a2dd95SBruce Richardson return -EINVAL; 186199a2dd95SBruce Richardson 186299a2dd95SBruce Richardson return 0; 186399a2dd95SBruce Richardson } 186499a2dd95SBruce Richardson 186599a2dd95SBruce Richardson /** 186699a2dd95SBruce Richardson * @internal used by rte_pktmbuf_linearize(). 186799a2dd95SBruce Richardson */ 186899a2dd95SBruce Richardson int __rte_pktmbuf_linearize(struct rte_mbuf *mbuf); 186999a2dd95SBruce Richardson 187099a2dd95SBruce Richardson /** 187199a2dd95SBruce Richardson * Linearize data in mbuf. 187299a2dd95SBruce Richardson * 187399a2dd95SBruce Richardson * This function moves the mbuf data in the first segment if there is enough 187499a2dd95SBruce Richardson * tailroom. The subsequent segments are unchained and freed. 187599a2dd95SBruce Richardson * 187699a2dd95SBruce Richardson * @param mbuf 187799a2dd95SBruce Richardson * mbuf to linearize 187899a2dd95SBruce Richardson * @return 187999a2dd95SBruce Richardson * - 0, on success 188099a2dd95SBruce Richardson * - -1, on error 188199a2dd95SBruce Richardson */ 188299a2dd95SBruce Richardson static inline int 188399a2dd95SBruce Richardson rte_pktmbuf_linearize(struct rte_mbuf *mbuf) 188499a2dd95SBruce Richardson { 188599a2dd95SBruce Richardson if (rte_pktmbuf_is_contiguous(mbuf)) 188699a2dd95SBruce Richardson return 0; 188799a2dd95SBruce Richardson return __rte_pktmbuf_linearize(mbuf); 188899a2dd95SBruce Richardson } 188999a2dd95SBruce Richardson 189099a2dd95SBruce Richardson /** 189199a2dd95SBruce Richardson * Dump an mbuf structure to a file. 189299a2dd95SBruce Richardson * 189399a2dd95SBruce Richardson * Dump all fields for the given packet mbuf and all its associated 189499a2dd95SBruce Richardson * segments (in the case of a chained buffer). 189599a2dd95SBruce Richardson * 189699a2dd95SBruce Richardson * @param f 189799a2dd95SBruce Richardson * A pointer to a file for output 189899a2dd95SBruce Richardson * @param m 189999a2dd95SBruce Richardson * The packet mbuf. 190099a2dd95SBruce Richardson * @param dump_len 190199a2dd95SBruce Richardson * If dump_len != 0, also dump the "dump_len" first data bytes of 190299a2dd95SBruce Richardson * the packet. 190399a2dd95SBruce Richardson */ 190499a2dd95SBruce Richardson void rte_pktmbuf_dump(FILE *f, const struct rte_mbuf *m, unsigned dump_len); 190599a2dd95SBruce Richardson 190699a2dd95SBruce Richardson /** 190799a2dd95SBruce Richardson * Get the value of mbuf sched queue_id field. 190899a2dd95SBruce Richardson */ 190999a2dd95SBruce Richardson static inline uint32_t 191099a2dd95SBruce Richardson rte_mbuf_sched_queue_get(const struct rte_mbuf *m) 191199a2dd95SBruce Richardson { 191299a2dd95SBruce Richardson return m->hash.sched.queue_id; 191399a2dd95SBruce Richardson } 191499a2dd95SBruce Richardson 191599a2dd95SBruce Richardson /** 191699a2dd95SBruce Richardson * Get the value of mbuf sched traffic_class field. 191799a2dd95SBruce Richardson */ 191899a2dd95SBruce Richardson static inline uint8_t 191999a2dd95SBruce Richardson rte_mbuf_sched_traffic_class_get(const struct rte_mbuf *m) 192099a2dd95SBruce Richardson { 192199a2dd95SBruce Richardson return m->hash.sched.traffic_class; 192299a2dd95SBruce Richardson } 192399a2dd95SBruce Richardson 192499a2dd95SBruce Richardson /** 192599a2dd95SBruce Richardson * Get the value of mbuf sched color field. 192699a2dd95SBruce Richardson */ 192799a2dd95SBruce Richardson static inline uint8_t 192899a2dd95SBruce Richardson rte_mbuf_sched_color_get(const struct rte_mbuf *m) 192999a2dd95SBruce Richardson { 193099a2dd95SBruce Richardson return m->hash.sched.color; 193199a2dd95SBruce Richardson } 193299a2dd95SBruce Richardson 193399a2dd95SBruce Richardson /** 193499a2dd95SBruce Richardson * Get the values of mbuf sched queue_id, traffic_class and color. 193599a2dd95SBruce Richardson * 193699a2dd95SBruce Richardson * @param m 193799a2dd95SBruce Richardson * Mbuf to read 193899a2dd95SBruce Richardson * @param queue_id 193999a2dd95SBruce Richardson * Returns the queue id 194099a2dd95SBruce Richardson * @param traffic_class 194199a2dd95SBruce Richardson * Returns the traffic class id 194299a2dd95SBruce Richardson * @param color 194399a2dd95SBruce Richardson * Returns the colour id 194499a2dd95SBruce Richardson */ 194599a2dd95SBruce Richardson static inline void 194699a2dd95SBruce Richardson rte_mbuf_sched_get(const struct rte_mbuf *m, uint32_t *queue_id, 194799a2dd95SBruce Richardson uint8_t *traffic_class, 194899a2dd95SBruce Richardson uint8_t *color) 194999a2dd95SBruce Richardson { 195099a2dd95SBruce Richardson struct rte_mbuf_sched sched = m->hash.sched; 195199a2dd95SBruce Richardson 195299a2dd95SBruce Richardson *queue_id = sched.queue_id; 195399a2dd95SBruce Richardson *traffic_class = sched.traffic_class; 195499a2dd95SBruce Richardson *color = sched.color; 195599a2dd95SBruce Richardson } 195699a2dd95SBruce Richardson 195799a2dd95SBruce Richardson /** 195899a2dd95SBruce Richardson * Set the mbuf sched queue_id to the defined value. 195999a2dd95SBruce Richardson */ 196099a2dd95SBruce Richardson static inline void 196199a2dd95SBruce Richardson rte_mbuf_sched_queue_set(struct rte_mbuf *m, uint32_t queue_id) 196299a2dd95SBruce Richardson { 196399a2dd95SBruce Richardson m->hash.sched.queue_id = queue_id; 196499a2dd95SBruce Richardson } 196599a2dd95SBruce Richardson 196699a2dd95SBruce Richardson /** 196799a2dd95SBruce Richardson * Set the mbuf sched traffic_class id to the defined value. 196899a2dd95SBruce Richardson */ 196999a2dd95SBruce Richardson static inline void 197099a2dd95SBruce Richardson rte_mbuf_sched_traffic_class_set(struct rte_mbuf *m, uint8_t traffic_class) 197199a2dd95SBruce Richardson { 197299a2dd95SBruce Richardson m->hash.sched.traffic_class = traffic_class; 197399a2dd95SBruce Richardson } 197499a2dd95SBruce Richardson 197599a2dd95SBruce Richardson /** 197699a2dd95SBruce Richardson * Set the mbuf sched color id to the defined value. 197799a2dd95SBruce Richardson */ 197899a2dd95SBruce Richardson static inline void 197999a2dd95SBruce Richardson rte_mbuf_sched_color_set(struct rte_mbuf *m, uint8_t color) 198099a2dd95SBruce Richardson { 198199a2dd95SBruce Richardson m->hash.sched.color = color; 198299a2dd95SBruce Richardson } 198399a2dd95SBruce Richardson 198499a2dd95SBruce Richardson /** 198599a2dd95SBruce Richardson * Set the mbuf sched queue_id, traffic_class and color. 198699a2dd95SBruce Richardson * 198799a2dd95SBruce Richardson * @param m 198899a2dd95SBruce Richardson * Mbuf to set 198999a2dd95SBruce Richardson * @param queue_id 199099a2dd95SBruce Richardson * Queue id value to be set 199199a2dd95SBruce Richardson * @param traffic_class 199299a2dd95SBruce Richardson * Traffic class id value to be set 199399a2dd95SBruce Richardson * @param color 199499a2dd95SBruce Richardson * Color id to be set 199599a2dd95SBruce Richardson */ 199699a2dd95SBruce Richardson static inline void 199799a2dd95SBruce Richardson rte_mbuf_sched_set(struct rte_mbuf *m, uint32_t queue_id, 199899a2dd95SBruce Richardson uint8_t traffic_class, 199999a2dd95SBruce Richardson uint8_t color) 200099a2dd95SBruce Richardson { 200199a2dd95SBruce Richardson m->hash.sched = (struct rte_mbuf_sched){ 200299a2dd95SBruce Richardson .queue_id = queue_id, 200399a2dd95SBruce Richardson .traffic_class = traffic_class, 200499a2dd95SBruce Richardson .color = color, 200599a2dd95SBruce Richardson .reserved = 0, 200699a2dd95SBruce Richardson }; 200799a2dd95SBruce Richardson } 200899a2dd95SBruce Richardson 200999a2dd95SBruce Richardson #ifdef __cplusplus 201099a2dd95SBruce Richardson } 201199a2dd95SBruce Richardson #endif 201299a2dd95SBruce Richardson 201399a2dd95SBruce Richardson #endif /* _RTE_MBUF_H_ */ 2014