xref: /dpdk/lib/mbuf/rte_mbuf.h (revision 6011b12f52b60565d4dfcc3b382551ec1f53b3d4)
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