2012-09-04 12:54:00 +00:00
|
|
|
/*-
|
|
|
|
* BSD LICENSE
|
2014-06-03 23:42:50 +00:00
|
|
|
*
|
2014-02-10 11:46:50 +00:00
|
|
|
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
2012-09-04 12:54:00 +00:00
|
|
|
* All rights reserved.
|
2014-06-03 23:42:50 +00:00
|
|
|
*
|
2013-09-18 10:00:00 +00:00
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
2012-09-04 12:54:00 +00:00
|
|
|
* are met:
|
2014-06-03 23:42:50 +00:00
|
|
|
*
|
2013-09-18 10:00:00 +00:00
|
|
|
* * Redistributions of source code must retain the above copyright
|
2012-09-04 12:54:00 +00:00
|
|
|
* notice, this list of conditions and the following disclaimer.
|
2013-09-18 10:00:00 +00:00
|
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in
|
|
|
|
* the documentation and/or other materials provided with the
|
2012-09-04 12:54:00 +00:00
|
|
|
* distribution.
|
2013-09-18 10:00:00 +00:00
|
|
|
* * Neither the name of Intel Corporation nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived
|
2012-09-04 12:54:00 +00:00
|
|
|
* from this software without specific prior written permission.
|
2014-06-03 23:42:50 +00:00
|
|
|
*
|
2013-09-18 10:00:00 +00:00
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
2012-09-04 12:54:00 +00:00
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _RTE_MBUF_H_
|
|
|
|
#define _RTE_MBUF_H_
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @file
|
|
|
|
* RTE Mbuf
|
|
|
|
*
|
|
|
|
* The mbuf library provides the ability to create and destroy buffers
|
|
|
|
* that may be used by the RTE application to store message
|
|
|
|
* buffers. The message buffers are stored in a mempool, using the
|
|
|
|
* RTE mempool library.
|
|
|
|
*
|
2014-08-28 15:42:36 +00:00
|
|
|
* This library provide an API to allocate/free packet mbufs, which are
|
|
|
|
* used to carry network packets.
|
2012-09-04 12:54:00 +00:00
|
|
|
*
|
|
|
|
* To understand the concepts of packet buffers or mbufs, you
|
|
|
|
* should read "TCP/IP Illustrated, Volume 2: The Implementation,
|
|
|
|
* Addison-Wesley, 1995, ISBN 0-201-63354-X from Richard Stevens"
|
|
|
|
* http://www.kohala.com/start/tcpipiv2.html
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <rte_mempool.h>
|
|
|
|
#include <rte_atomic.h>
|
|
|
|
#include <rte_prefetch.h>
|
|
|
|
#include <rte_branch_prediction.h>
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2014-08-28 15:42:35 +00:00
|
|
|
/* deprecated feature, renamed in RTE_MBUF_REFCNT */
|
|
|
|
#pragma GCC poison RTE_MBUF_SCATTER_GATHER
|
|
|
|
|
2012-09-04 12:54:00 +00:00
|
|
|
/*
|
|
|
|
* Packet Offload Features Flags. It also carry packet type information.
|
|
|
|
* Critical resources. Both rx/tx shared these bits. Be cautious on any change
|
2014-10-03 15:36:50 +00:00
|
|
|
*
|
|
|
|
* - RX flags start at bit position zero, and get added to the left of previous
|
|
|
|
* flags.
|
|
|
|
* - The most-significant 8 bits are reserved for generic mbuf flags
|
|
|
|
* - TX flags therefore start at bit position 55 (i.e. 63-8), and new flags get
|
|
|
|
* added to the right of the previously defined flags
|
2012-09-04 12:54:00 +00:00
|
|
|
*/
|
|
|
|
#define PKT_RX_VLAN_PKT 0x0001 /**< RX packet is a 802.1q VLAN packet. */
|
|
|
|
#define PKT_RX_RSS_HASH 0x0002 /**< RX packet with RSS hash result. */
|
|
|
|
#define PKT_RX_FDIR 0x0004 /**< RX packet with FDIR infos. */
|
|
|
|
#define PKT_RX_L4_CKSUM_BAD 0x0008 /**< L4 cksum of RX pkt. is not OK. */
|
|
|
|
#define PKT_RX_IP_CKSUM_BAD 0x0010 /**< IP cksum of RX pkt. is not OK. */
|
2014-06-05 05:08:49 +00:00
|
|
|
#define PKT_RX_EIP_CKSUM_BAD 0x0000 /**< External IP header checksum error. */
|
|
|
|
#define PKT_RX_OVERSIZE 0x0000 /**< Num of desc of an RX pkt oversize. */
|
|
|
|
#define PKT_RX_HBUF_OVERFLOW 0x0000 /**< Header buffer overflow. */
|
|
|
|
#define PKT_RX_RECIP_ERR 0x0000 /**< Hardware processing error. */
|
|
|
|
#define PKT_RX_MAC_ERR 0x0000 /**< MAC error. */
|
2012-09-04 12:54:00 +00:00
|
|
|
#define PKT_RX_IPV4_HDR 0x0020 /**< RX packet with IPv4 header. */
|
|
|
|
#define PKT_RX_IPV4_HDR_EXT 0x0040 /**< RX packet with extended IPv4 header. */
|
|
|
|
#define PKT_RX_IPV6_HDR 0x0080 /**< RX packet with IPv6 header. */
|
|
|
|
#define PKT_RX_IPV6_HDR_EXT 0x0100 /**< RX packet with extended IPv6 header. */
|
|
|
|
#define PKT_RX_IEEE1588_PTP 0x0200 /**< RX IEEE1588 L2 Ethernet PT Packet. */
|
|
|
|
#define PKT_RX_IEEE1588_TMST 0x0400 /**< RX IEEE1588 L2/L4 timestamped packet.*/
|
|
|
|
|
2014-10-03 15:36:50 +00:00
|
|
|
#define PKT_TX_VLAN_PKT (1ULL << 55) /**< TX packet is a 802.1q VLAN packet. */
|
|
|
|
#define PKT_TX_IP_CKSUM (1ULL << 54) /**< IP cksum of TX pkt. computed by NIC. */
|
|
|
|
#define PKT_TX_IPV4_CSUM PKT_TX_IP_CKSUM /**< Alias of PKT_TX_IP_CKSUM. */
|
2014-06-05 05:08:49 +00:00
|
|
|
#define PKT_TX_IPV4 PKT_RX_IPV4_HDR /**< IPv4 with no IP checksum offload. */
|
|
|
|
#define PKT_TX_IPV6 PKT_RX_IPV6_HDR /**< IPv6 packet */
|
2014-09-11 13:15:38 +00:00
|
|
|
|
2012-09-04 12:54:00 +00:00
|
|
|
/*
|
2014-10-03 15:36:50 +00:00
|
|
|
* Bits 52+53 used for L4 packet type with checksum enabled.
|
2012-09-04 12:54:00 +00:00
|
|
|
* 00: Reserved
|
|
|
|
* 01: TCP checksum
|
|
|
|
* 10: SCTP checksum
|
|
|
|
* 11: UDP checksum
|
|
|
|
*/
|
2014-10-03 15:36:50 +00:00
|
|
|
#define PKT_TX_L4_NO_CKSUM (0ULL << 52) /**< Disable L4 cksum of TX pkt. */
|
|
|
|
#define PKT_TX_TCP_CKSUM (1ULL << 52) /**< TCP cksum of TX pkt. computed by NIC. */
|
|
|
|
#define PKT_TX_SCTP_CKSUM (2ULL << 52) /**< SCTP cksum of TX pkt. computed by NIC. */
|
|
|
|
#define PKT_TX_UDP_CKSUM (3ULL << 52) /**< UDP cksum of TX pkt. computed by NIC. */
|
|
|
|
#define PKT_TX_L4_MASK (3ULL << 52) /**< Mask for L4 cksum offload request. */
|
|
|
|
|
|
|
|
/* Bit 51 - IEEE1588*/
|
|
|
|
#define PKT_TX_IEEE1588_TMST (1ULL << 51) /**< TX IEEE1588 packet to timestamp. */
|
2012-09-04 12:54:00 +00:00
|
|
|
|
2014-09-11 13:15:38 +00:00
|
|
|
/* Use final bit of flags to indicate a control mbuf */
|
|
|
|
#define CTRL_MBUF_FLAG (1ULL << 63)
|
|
|
|
|
2012-09-04 12:54:00 +00:00
|
|
|
/**
|
|
|
|
* Bit Mask to indicate what bits required for building TX context
|
|
|
|
*/
|
|
|
|
#define PKT_TX_OFFLOAD_MASK (PKT_TX_VLAN_PKT | PKT_TX_IP_CKSUM | PKT_TX_L4_MASK)
|
|
|
|
|
2014-09-11 13:15:42 +00:00
|
|
|
/* define a set of marker types that can be used to refer to set points in the
|
|
|
|
* mbuf */
|
|
|
|
typedef void *MARKER[0]; /**< generic marker for a point in a structure */
|
|
|
|
typedef uint64_t MARKER64[0]; /**< marker that allows us to overwrite 8 bytes
|
|
|
|
* with a single assignment */
|
2012-09-04 12:54:00 +00:00
|
|
|
/**
|
2014-08-28 15:42:36 +00:00
|
|
|
* The generic rte_mbuf, containing a packet mbuf.
|
2012-09-04 12:54:00 +00:00
|
|
|
*/
|
|
|
|
struct rte_mbuf {
|
2014-09-11 13:15:42 +00:00
|
|
|
MARKER cacheline0;
|
|
|
|
|
2012-09-04 12:54:00 +00:00
|
|
|
void *buf_addr; /**< Virtual address of segment buffer. */
|
|
|
|
phys_addr_t buf_physaddr; /**< Physical address of segment buffer. */
|
2014-09-11 13:15:35 +00:00
|
|
|
|
2014-09-11 13:15:36 +00:00
|
|
|
/* next 8 bytes are initialised on RX descriptor rearm */
|
2014-09-11 13:15:42 +00:00
|
|
|
MARKER64 rearm_data;
|
2014-09-11 13:15:36 +00:00
|
|
|
uint16_t buf_len; /**< Length of segment buffer. */
|
2014-09-11 13:15:35 +00:00
|
|
|
uint16_t data_off;
|
|
|
|
|
2012-09-04 12:54:00 +00:00
|
|
|
/**
|
|
|
|
* 16-bit Reference counter.
|
|
|
|
* It should only be accessed using the following functions:
|
|
|
|
* rte_mbuf_refcnt_update(), rte_mbuf_refcnt_read(), and
|
|
|
|
* rte_mbuf_refcnt_set(). The functionality of these functions (atomic,
|
|
|
|
* or non-atomic) is controlled by the CONFIG_RTE_MBUF_REFCNT_ATOMIC
|
|
|
|
* config option.
|
|
|
|
*/
|
|
|
|
union {
|
2014-09-11 13:15:39 +00:00
|
|
|
#ifdef RTE_MBUF_REFCNT
|
|
|
|
rte_atomic16_t refcnt_atomic; /**< Atomically accessed refcnt */
|
|
|
|
uint16_t refcnt; /**< Non-atomically accessed refcnt */
|
2012-09-04 12:54:00 +00:00
|
|
|
#endif
|
2014-09-11 13:15:39 +00:00
|
|
|
uint16_t refcnt_reserved; /**< Do not use this field */
|
|
|
|
};
|
|
|
|
uint8_t nb_segs; /**< Number of segments. */
|
|
|
|
uint8_t port; /**< Input port. */
|
2014-08-28 15:42:37 +00:00
|
|
|
|
2014-09-11 13:15:39 +00:00
|
|
|
uint64_t ol_flags; /**< Offload features. */
|
2014-09-11 13:15:36 +00:00
|
|
|
|
|
|
|
/* remaining bytes are set on RX when pulling packet from descriptor */
|
2014-09-11 13:15:42 +00:00
|
|
|
MARKER rx_descriptor_fields1;
|
2014-09-11 13:15:39 +00:00
|
|
|
uint16_t reserved2; /**< Unused field. Required for padding */
|
|
|
|
uint16_t data_len; /**< Amount of data in segment buffer. */
|
|
|
|
uint32_t pkt_len; /**< Total pkt len: sum of all segments. */
|
|
|
|
uint16_t vlan_tci; /**< VLAN Tag Control Identifier (CPU order) */
|
2014-09-23 11:08:17 +00:00
|
|
|
uint16_t reserved;
|
2014-08-28 15:42:37 +00:00
|
|
|
union {
|
2014-09-11 13:15:39 +00:00
|
|
|
uint32_t rss; /**< RSS hash result if RSS enabled */
|
2014-08-28 15:42:37 +00:00
|
|
|
struct {
|
|
|
|
uint16_t hash;
|
|
|
|
uint16_t id;
|
2014-09-11 13:15:39 +00:00
|
|
|
} fdir; /**< Filter identifier if FDIR enabled */
|
|
|
|
uint32_t sched; /**< Hierarchical scheduler */
|
|
|
|
} hash; /**< hash information */
|
2014-06-04 18:08:18 +00:00
|
|
|
|
mbuf: split mbuf across two cache lines.
This change splits the mbuf in two to move the pool and next pointers to
the second cache line. This frees up 16 bytes in first cache line.
The reason for this change is that we believe that there is no possible
way that we can ever fit all the fields we need to fit into a 64-byte
mbuf, and so we need to start looking at a 128-byte mbuf instead. Examples
of new fields that need to fit in, include -
* 32-bits more for filter information for support for the new filters in
the i40e driver (and possibly other future drivers)
* an additional 2-4 bytes for storing info on a second vlan tag to allow
drivers to support double Vlan/QinQ
* 4-bytes for storing a sequence number to enable out of order packet
processing and subsequent packet reordering
as well as potentially a number of other fields or splitting out fields
that are superimposed over each other right now, e.g. for the qos scheduler.
We also want to allow space for use by other non-Intel NIC drivers that may
be open-sourced to dpdk.org in the future too, where they support fields
and offloads that currently supported hardware doesn't.
If we accept the fact of a 2-cache-line mbuf, then the issue becomes
how to rework things so that we spread our fields over the two
cache lines while causing the lowest slow-down possible. The general
approach that we are looking to take is to focus the first cache
line on fields that are updated on RX , so that receive only deals
with one cache line. The second cache line can be used for application
data and information that will only be used on the TX leg. This would
allow us to work on the first cache line in RX as now, and have the
second cache line being prefetched in the background so that it is
available when necessary. Hardware prefetches should help us out
here. We also may move rarely used, or slow-path RX fields e.g. such
as those for chained mbufs with jumbo frames, to the second
cache line, depending upon the performance impact and bytes savings
achieved.
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
Acked-by: Thomas Monjalon <thomas.monjalon@6wind.com>
2014-09-11 13:15:44 +00:00
|
|
|
/* second cache line - fields only used in slow path or on TX */
|
|
|
|
MARKER cacheline1 __rte_cache_aligned;
|
2014-09-23 11:08:16 +00:00
|
|
|
|
|
|
|
union {
|
|
|
|
void *userdata; /**< Can be used for external metadata */
|
|
|
|
uint64_t udata64; /**< Allow 8-byte userdata on 32-bit */
|
|
|
|
};
|
|
|
|
|
2014-09-11 13:15:36 +00:00
|
|
|
struct rte_mempool *pool; /**< Pool from which mbuf was allocated. */
|
|
|
|
struct rte_mbuf *next; /**< Next segment of scattered packet. */
|
|
|
|
|
2014-09-11 13:15:45 +00:00
|
|
|
/* fields to support TX offloads */
|
|
|
|
union {
|
|
|
|
uint16_t l2_l3_len; /**< combined l2/l3 lengths as single var */
|
|
|
|
struct {
|
|
|
|
uint16_t l3_len:9; /**< L3 (IP) Header Length. */
|
|
|
|
uint16_t l2_len:7; /**< L2 (MAC) Header Length. */
|
|
|
|
};
|
|
|
|
};
|
2012-09-04 12:54:00 +00:00
|
|
|
} __rte_cache_aligned;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Given the buf_addr returns the pointer to corresponding mbuf.
|
|
|
|
*/
|
|
|
|
#define RTE_MBUF_FROM_BADDR(ba) (((struct rte_mbuf *)(ba)) - 1)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Given the pointer to mbuf returns an address where it's buf_addr
|
|
|
|
* should point to.
|
|
|
|
*/
|
|
|
|
#define RTE_MBUF_TO_BADDR(mb) (((struct rte_mbuf *)(mb)) + 1)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns TRUE if given mbuf is indirect, or FALSE otherwise.
|
|
|
|
*/
|
|
|
|
#define RTE_MBUF_INDIRECT(mb) (RTE_MBUF_FROM_BADDR((mb)->buf_addr) != (mb))
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns TRUE if given mbuf is direct, or FALSE otherwise.
|
|
|
|
*/
|
|
|
|
#define RTE_MBUF_DIRECT(mb) (RTE_MBUF_FROM_BADDR((mb)->buf_addr) == (mb))
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Private data in case of pktmbuf pool.
|
|
|
|
*
|
|
|
|
* A structure that contains some pktmbuf_pool-specific data that are
|
|
|
|
* appended after the mempool structure (in private data).
|
|
|
|
*/
|
|
|
|
struct rte_pktmbuf_pool_private {
|
|
|
|
uint16_t mbuf_data_room_size; /**< Size of data space in each mbuf.*/
|
|
|
|
};
|
|
|
|
|
|
|
|
#ifdef RTE_LIBRTE_MBUF_DEBUG
|
|
|
|
|
|
|
|
/** check mbuf type in debug mode */
|
2014-08-28 15:42:36 +00:00
|
|
|
#define __rte_mbuf_sanity_check(m, is_h) rte_mbuf_sanity_check(m, is_h)
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
/** check mbuf type in debug mode if mbuf pointer is not null */
|
2014-08-28 15:42:36 +00:00
|
|
|
#define __rte_mbuf_sanity_check_raw(m, is_h) do { \
|
2012-09-04 12:54:00 +00:00
|
|
|
if ((m) != NULL) \
|
2014-08-28 15:42:36 +00:00
|
|
|
rte_mbuf_sanity_check(m, is_h); \
|
2012-09-04 12:54:00 +00:00
|
|
|
} while (0)
|
|
|
|
|
|
|
|
/** MBUF asserts in debug mode */
|
|
|
|
#define RTE_MBUF_ASSERT(exp) \
|
|
|
|
if (!(exp)) { \
|
|
|
|
rte_panic("line%d\tassert \"" #exp "\" failed\n", __LINE__); \
|
|
|
|
}
|
|
|
|
|
|
|
|
#else /* RTE_LIBRTE_MBUF_DEBUG */
|
|
|
|
|
|
|
|
/** check mbuf type in debug mode */
|
2014-08-28 15:42:36 +00:00
|
|
|
#define __rte_mbuf_sanity_check(m, is_h) do { } while (0)
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
/** check mbuf type in debug mode if mbuf pointer is not null */
|
2014-08-28 15:42:36 +00:00
|
|
|
#define __rte_mbuf_sanity_check_raw(m, is_h) do { } while (0)
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
/** MBUF asserts in debug mode */
|
2014-08-28 15:42:36 +00:00
|
|
|
#define RTE_MBUF_ASSERT(exp) do { } while (0)
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
#endif /* RTE_LIBRTE_MBUF_DEBUG */
|
|
|
|
|
2014-08-28 15:42:35 +00:00
|
|
|
#ifdef RTE_MBUF_REFCNT
|
2012-09-04 12:54:00 +00:00
|
|
|
#ifdef RTE_MBUF_REFCNT_ATOMIC
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds given value to an mbuf's refcnt and returns its new value.
|
|
|
|
* @param m
|
|
|
|
* Mbuf to update
|
|
|
|
* @param value
|
|
|
|
* Value to add/subtract
|
|
|
|
* @return
|
|
|
|
* Updated value
|
|
|
|
*/
|
|
|
|
static inline uint16_t
|
|
|
|
rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
|
|
|
|
{
|
|
|
|
return (uint16_t)(rte_atomic16_add_return(&m->refcnt_atomic, value));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reads the value of an mbuf's refcnt.
|
|
|
|
* @param m
|
|
|
|
* Mbuf to read
|
|
|
|
* @return
|
|
|
|
* Reference count number.
|
|
|
|
*/
|
|
|
|
static inline uint16_t
|
|
|
|
rte_mbuf_refcnt_read(const struct rte_mbuf *m)
|
|
|
|
{
|
|
|
|
return (uint16_t)(rte_atomic16_read(&m->refcnt_atomic));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets an mbuf's refcnt to a defined value.
|
|
|
|
* @param m
|
|
|
|
* Mbuf to update
|
|
|
|
* @param new_value
|
|
|
|
* Value set
|
|
|
|
*/
|
|
|
|
static inline void
|
|
|
|
rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value)
|
|
|
|
{
|
|
|
|
rte_atomic16_set(&m->refcnt_atomic, new_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
#else /* ! RTE_MBUF_REFCNT_ATOMIC */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds given value to an mbuf's refcnt and returns its new value.
|
|
|
|
*/
|
|
|
|
static inline uint16_t
|
|
|
|
rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
|
|
|
|
{
|
|
|
|
m->refcnt = (uint16_t)(m->refcnt + value);
|
|
|
|
return m->refcnt;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reads the value of an mbuf's refcnt.
|
|
|
|
*/
|
|
|
|
static inline uint16_t
|
|
|
|
rte_mbuf_refcnt_read(const struct rte_mbuf *m)
|
|
|
|
{
|
|
|
|
return m->refcnt;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets an mbuf's refcnt to the defined value.
|
|
|
|
*/
|
|
|
|
static inline void
|
|
|
|
rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value)
|
|
|
|
{
|
|
|
|
m->refcnt = new_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* RTE_MBUF_REFCNT_ATOMIC */
|
|
|
|
|
|
|
|
/** Mbuf prefetch */
|
|
|
|
#define RTE_MBUF_PREFETCH_TO_FREE(m) do { \
|
|
|
|
if ((m) != NULL) \
|
|
|
|
rte_prefetch0(m); \
|
|
|
|
} while (0)
|
|
|
|
|
2014-08-28 15:42:35 +00:00
|
|
|
#else /* ! RTE_MBUF_REFCNT */
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
/** Mbuf prefetch */
|
|
|
|
#define RTE_MBUF_PREFETCH_TO_FREE(m) do { } while(0)
|
|
|
|
|
2012-12-19 23:00:00 +00:00
|
|
|
#define rte_mbuf_refcnt_set(m,v) do { } while(0)
|
|
|
|
|
2014-08-28 15:42:35 +00:00
|
|
|
#endif /* RTE_MBUF_REFCNT */
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sanity checks on an mbuf.
|
|
|
|
*
|
|
|
|
* Check the consistency of the given mbuf. The function will cause a
|
|
|
|
* panic if corruption is detected.
|
|
|
|
*
|
|
|
|
* @param m
|
|
|
|
* The mbuf to be checked.
|
|
|
|
* @param is_header
|
|
|
|
* True if the mbuf is a packet header, false if it is a sub-segment
|
|
|
|
* of a packet (in this case, some fields like nb_segs are not checked)
|
|
|
|
*/
|
|
|
|
void
|
2014-08-28 15:42:36 +00:00
|
|
|
rte_mbuf_sanity_check(const struct rte_mbuf *m, int is_header);
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal Allocate a new mbuf from mempool *mp*.
|
|
|
|
* The use of that function is reserved for RTE internal needs.
|
2014-08-28 15:42:36 +00:00
|
|
|
* Please use rte_pktmbuf_alloc().
|
2012-09-04 12:54:00 +00:00
|
|
|
*
|
|
|
|
* @param mp
|
|
|
|
* The mempool from which mbuf is allocated.
|
|
|
|
* @return
|
|
|
|
* - The pointer to the new mbuf on success.
|
|
|
|
* - NULL if allocation failed.
|
|
|
|
*/
|
|
|
|
static inline struct rte_mbuf *__rte_mbuf_raw_alloc(struct rte_mempool *mp)
|
|
|
|
{
|
|
|
|
struct rte_mbuf *m;
|
|
|
|
void *mb = NULL;
|
|
|
|
if (rte_mempool_get(mp, &mb) < 0)
|
|
|
|
return NULL;
|
|
|
|
m = (struct rte_mbuf *)mb;
|
2014-08-28 15:42:35 +00:00
|
|
|
#ifdef RTE_MBUF_REFCNT
|
2012-09-04 12:54:00 +00:00
|
|
|
RTE_MBUF_ASSERT(rte_mbuf_refcnt_read(m) == 0);
|
|
|
|
rte_mbuf_refcnt_set(m, 1);
|
2014-08-28 15:42:35 +00:00
|
|
|
#endif /* RTE_MBUF_REFCNT */
|
2012-09-04 12:54:00 +00:00
|
|
|
return (m);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal Put mbuf back into its original mempool.
|
|
|
|
* The use of that function is reserved for RTE internal needs.
|
2014-08-28 15:42:36 +00:00
|
|
|
* Please use rte_pktmbuf_free().
|
2012-09-04 12:54:00 +00:00
|
|
|
*
|
|
|
|
* @param m
|
|
|
|
* The mbuf to be freed.
|
|
|
|
*/
|
2013-06-03 00:00:00 +00:00
|
|
|
static inline void __attribute__((always_inline))
|
|
|
|
__rte_mbuf_raw_free(struct rte_mbuf *m)
|
2012-09-04 12:54:00 +00:00
|
|
|
{
|
2014-08-28 15:42:35 +00:00
|
|
|
#ifdef RTE_MBUF_REFCNT
|
2012-09-04 12:54:00 +00:00
|
|
|
RTE_MBUF_ASSERT(rte_mbuf_refcnt_read(m) == 0);
|
2014-08-28 15:42:35 +00:00
|
|
|
#endif /* RTE_MBUF_REFCNT */
|
2012-09-04 12:54:00 +00:00
|
|
|
rte_mempool_put(m->pool, m);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Operations on ctrl mbuf */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The control mbuf constructor.
|
|
|
|
*
|
|
|
|
* This function initializes some fields in an mbuf structure that are
|
|
|
|
* not modified by the user once created (mbuf type, origin pool, buffer
|
|
|
|
* start address, and so on). This function is given as a callback function
|
|
|
|
* to rte_mempool_create() at pool creation time.
|
|
|
|
*
|
|
|
|
* @param mp
|
|
|
|
* The mempool from which the mbuf is allocated.
|
|
|
|
* @param opaque_arg
|
|
|
|
* A pointer that can be used by the user to retrieve useful information
|
|
|
|
* for mbuf initialization. This pointer comes from the ``init_arg``
|
|
|
|
* parameter of rte_mempool_create().
|
|
|
|
* @param m
|
|
|
|
* The mbuf to initialize.
|
|
|
|
* @param i
|
|
|
|
* The index of the mbuf in the pool table.
|
|
|
|
*/
|
|
|
|
void rte_ctrlmbuf_init(struct rte_mempool *mp, void *opaque_arg,
|
2014-08-28 15:42:36 +00:00
|
|
|
void *m, unsigned i);
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Allocate a new mbuf (type is ctrl) from mempool *mp*.
|
|
|
|
*
|
|
|
|
* This new mbuf is initialized with data pointing to the beginning of
|
|
|
|
* buffer, and with a length of zero.
|
|
|
|
*
|
|
|
|
* @param mp
|
|
|
|
* The mempool from which the mbuf is allocated.
|
|
|
|
* @return
|
|
|
|
* - The pointer to the new mbuf on success.
|
|
|
|
* - NULL if allocation failed.
|
|
|
|
*/
|
2014-08-28 15:42:36 +00:00
|
|
|
#define rte_ctrlmbuf_alloc(mp) rte_pktmbuf_alloc(mp)
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Free a control mbuf back into its original mempool.
|
|
|
|
*
|
|
|
|
* @param m
|
|
|
|
* The control mbuf to be freed.
|
|
|
|
*/
|
2014-08-28 15:42:36 +00:00
|
|
|
#define rte_ctrlmbuf_free(m) rte_pktmbuf_free(m)
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A macro that returns the pointer to the carried data.
|
|
|
|
*
|
|
|
|
* The value that can be read or assigned.
|
|
|
|
*
|
|
|
|
* @param m
|
|
|
|
* The control mbuf.
|
|
|
|
*/
|
2014-09-11 13:15:35 +00:00
|
|
|
#define rte_ctrlmbuf_data(m) ((char *)((m)->buf_addr) + (m)->data_off)
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A macro that returns the length of the carried data.
|
|
|
|
*
|
|
|
|
* The value that can be read or assigned.
|
|
|
|
*
|
|
|
|
* @param m
|
|
|
|
* The control mbuf.
|
|
|
|
*/
|
2014-08-28 15:42:36 +00:00
|
|
|
#define rte_ctrlmbuf_len(m) rte_pktmbuf_data_len(m)
|
2012-09-04 12:54:00 +00:00
|
|
|
|
2014-09-11 13:15:38 +00:00
|
|
|
/**
|
|
|
|
* Tests if an mbuf is a control mbuf
|
|
|
|
*
|
|
|
|
* @param m
|
|
|
|
* The mbuf to be tested
|
|
|
|
* @return
|
|
|
|
* - True (1) if the mbuf is a control mbuf
|
|
|
|
* - False(0) otherwise
|
|
|
|
*/
|
|
|
|
static inline int
|
|
|
|
rte_is_ctrlmbuf(struct rte_mbuf *m)
|
|
|
|
{
|
|
|
|
return (!!(m->ol_flags & CTRL_MBUF_FLAG));
|
|
|
|
}
|
|
|
|
|
2012-09-04 12:54:00 +00:00
|
|
|
/* Operations on pkt mbuf */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The packet mbuf constructor.
|
|
|
|
*
|
2014-08-28 15:42:36 +00:00
|
|
|
* This function initializes some fields in the mbuf structure that are
|
|
|
|
* not modified by the user once created (origin pool, buffer start
|
2012-09-04 12:54:00 +00:00
|
|
|
* address, and so on). This function is given as a callback function to
|
|
|
|
* rte_mempool_create() at pool creation time.
|
|
|
|
*
|
|
|
|
* @param mp
|
|
|
|
* The mempool from which mbufs originate.
|
|
|
|
* @param opaque_arg
|
|
|
|
* A pointer that can be used by the user to retrieve useful information
|
|
|
|
* for mbuf initialization. This pointer comes from the ``init_arg``
|
|
|
|
* parameter of rte_mempool_create().
|
|
|
|
* @param m
|
|
|
|
* The mbuf to initialize.
|
|
|
|
* @param i
|
|
|
|
* The index of the mbuf in the pool table.
|
|
|
|
*/
|
|
|
|
void rte_pktmbuf_init(struct rte_mempool *mp, void *opaque_arg,
|
|
|
|
void *m, unsigned i);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A packet mbuf pool constructor.
|
|
|
|
*
|
|
|
|
* This function initializes the mempool private data in the case of a
|
|
|
|
* pktmbuf pool. This private data is needed by the driver. The
|
|
|
|
* function is given as a callback function to rte_mempool_create() at
|
|
|
|
* pool creation. It can be extended by the user, for example, to
|
|
|
|
* provide another packet size.
|
|
|
|
*
|
|
|
|
* @param mp
|
|
|
|
* The mempool from which mbufs originate.
|
|
|
|
* @param opaque_arg
|
|
|
|
* A pointer that can be used by the user to retrieve useful information
|
|
|
|
* for mbuf initialization. This pointer comes from the ``init_arg``
|
|
|
|
* parameter of rte_mempool_create().
|
|
|
|
*/
|
|
|
|
void rte_pktmbuf_pool_init(struct rte_mempool *mp, void *opaque_arg);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reset the fields of a packet mbuf to their default values.
|
|
|
|
*
|
|
|
|
* The given mbuf must have only one segment.
|
|
|
|
*
|
|
|
|
* @param m
|
|
|
|
* The packet mbuf to be resetted.
|
|
|
|
*/
|
|
|
|
static inline void rte_pktmbuf_reset(struct rte_mbuf *m)
|
|
|
|
{
|
2014-08-28 15:42:37 +00:00
|
|
|
m->next = NULL;
|
|
|
|
m->pkt_len = 0;
|
2014-09-09 14:40:56 +00:00
|
|
|
m->l2_l3_len = 0;
|
|
|
|
m->vlan_tci = 0;
|
2014-08-28 15:42:37 +00:00
|
|
|
m->nb_segs = 1;
|
2014-08-28 15:42:38 +00:00
|
|
|
m->port = 0xff;
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
m->ol_flags = 0;
|
2014-09-11 13:15:35 +00:00
|
|
|
m->data_off = (RTE_PKTMBUF_HEADROOM <= m->buf_len) ?
|
2012-09-04 12:54:00 +00:00
|
|
|
RTE_PKTMBUF_HEADROOM : m->buf_len;
|
|
|
|
|
2014-08-28 15:42:37 +00:00
|
|
|
m->data_len = 0;
|
2014-08-28 15:42:36 +00:00
|
|
|
__rte_mbuf_sanity_check(m, 1);
|
2012-09-04 12:54:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2014-08-28 15:42:36 +00:00
|
|
|
* Allocate a new mbuf from a mempool.
|
2012-09-04 12:54:00 +00:00
|
|
|
*
|
|
|
|
* This new mbuf contains one segment, which has a length of 0. The pointer
|
|
|
|
* to data is initialized to have some bytes of headroom in the buffer
|
|
|
|
* (if buffer size allows).
|
|
|
|
*
|
|
|
|
* @param mp
|
|
|
|
* The mempool from which the mbuf is allocated.
|
|
|
|
* @return
|
|
|
|
* - The pointer to the new mbuf on success.
|
|
|
|
* - NULL if allocation failed.
|
|
|
|
*/
|
|
|
|
static inline struct rte_mbuf *rte_pktmbuf_alloc(struct rte_mempool *mp)
|
|
|
|
{
|
|
|
|
struct rte_mbuf *m;
|
|
|
|
if ((m = __rte_mbuf_raw_alloc(mp)) != NULL)
|
|
|
|
rte_pktmbuf_reset(m);
|
|
|
|
return (m);
|
|
|
|
}
|
|
|
|
|
2014-08-28 15:42:35 +00:00
|
|
|
#ifdef RTE_MBUF_REFCNT
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Attach packet mbuf to another packet mbuf.
|
|
|
|
* After attachment we refer the mbuf we attached as 'indirect',
|
|
|
|
* while mbuf we attached to as 'direct'.
|
|
|
|
* Right now, not supported:
|
|
|
|
* - attachment to indirect mbuf (e.g. - md has to be direct).
|
|
|
|
* - attachment for already indirect mbuf (e.g. - mi has to be direct).
|
|
|
|
* - mbuf we trying to attach (mi) is used by someone else
|
|
|
|
* e.g. it's reference counter is greater then 1.
|
|
|
|
*
|
|
|
|
* @param mi
|
|
|
|
* The indirect packet mbuf.
|
|
|
|
* @param md
|
|
|
|
* The direct packet mbuf.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static inline void rte_pktmbuf_attach(struct rte_mbuf *mi, struct rte_mbuf *md)
|
|
|
|
{
|
|
|
|
RTE_MBUF_ASSERT(RTE_MBUF_DIRECT(md) &&
|
|
|
|
RTE_MBUF_DIRECT(mi) &&
|
|
|
|
rte_mbuf_refcnt_read(mi) == 1);
|
|
|
|
|
|
|
|
rte_mbuf_refcnt_update(md, 1);
|
|
|
|
mi->buf_physaddr = md->buf_physaddr;
|
|
|
|
mi->buf_addr = md->buf_addr;
|
|
|
|
mi->buf_len = md->buf_len;
|
|
|
|
|
2014-08-28 15:42:37 +00:00
|
|
|
mi->next = md->next;
|
2014-09-11 13:15:35 +00:00
|
|
|
mi->data_off = md->data_off;
|
2014-08-28 15:42:37 +00:00
|
|
|
mi->data_len = md->data_len;
|
2014-08-28 15:42:38 +00:00
|
|
|
mi->port = md->port;
|
2014-09-09 14:40:56 +00:00
|
|
|
mi->vlan_tci = md->vlan_tci;
|
|
|
|
mi->l2_l3_len = md->l2_l3_len;
|
2014-08-28 15:42:37 +00:00
|
|
|
mi->hash = md->hash;
|
2012-09-04 12:54:00 +00:00
|
|
|
|
2014-08-28 15:42:37 +00:00
|
|
|
mi->next = NULL;
|
|
|
|
mi->pkt_len = mi->data_len;
|
|
|
|
mi->nb_segs = 1;
|
2014-03-07 18:13:36 +00:00
|
|
|
mi->ol_flags = md->ol_flags;
|
2012-09-04 12:54:00 +00:00
|
|
|
|
2014-08-28 15:42:36 +00:00
|
|
|
__rte_mbuf_sanity_check(mi, 1);
|
|
|
|
__rte_mbuf_sanity_check(md, 0);
|
2012-09-04 12:54:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Detach an indirect packet mbuf -
|
|
|
|
* - restore original mbuf address and length values.
|
|
|
|
* - reset pktmbuf data and data_len to their default values.
|
|
|
|
* All other fields of the given packet mbuf will be left intact.
|
|
|
|
*
|
|
|
|
* @param m
|
|
|
|
* The indirect attached packet mbuf.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static inline void rte_pktmbuf_detach(struct rte_mbuf *m)
|
|
|
|
{
|
|
|
|
const struct rte_mempool *mp = m->pool;
|
|
|
|
void *buf = RTE_MBUF_TO_BADDR(m);
|
|
|
|
uint32_t buf_len = mp->elt_size - sizeof(*m);
|
|
|
|
m->buf_physaddr = rte_mempool_virt2phy(mp, m) + sizeof (*m);
|
|
|
|
|
|
|
|
m->buf_addr = buf;
|
|
|
|
m->buf_len = (uint16_t)buf_len;
|
|
|
|
|
2014-09-11 13:15:35 +00:00
|
|
|
m->data_off = (RTE_PKTMBUF_HEADROOM <= m->buf_len) ?
|
2012-09-04 12:54:00 +00:00
|
|
|
RTE_PKTMBUF_HEADROOM : m->buf_len;
|
|
|
|
|
2014-08-28 15:42:37 +00:00
|
|
|
m->data_len = 0;
|
2012-09-04 12:54:00 +00:00
|
|
|
}
|
|
|
|
|
2014-08-28 15:42:35 +00:00
|
|
|
#endif /* RTE_MBUF_REFCNT */
|
2012-09-04 12:54:00 +00:00
|
|
|
|
2014-02-17 19:15:19 +00:00
|
|
|
|
|
|
|
static inline struct rte_mbuf* __attribute__((always_inline))
|
|
|
|
__rte_pktmbuf_prefree_seg(struct rte_mbuf *m)
|
2012-09-04 12:54:00 +00:00
|
|
|
{
|
2014-08-28 15:42:36 +00:00
|
|
|
__rte_mbuf_sanity_check(m, 0);
|
2012-09-04 12:54:00 +00:00
|
|
|
|
2014-08-28 15:42:35 +00:00
|
|
|
#ifdef RTE_MBUF_REFCNT
|
2012-09-04 12:54:00 +00:00
|
|
|
if (likely (rte_mbuf_refcnt_read(m) == 1) ||
|
|
|
|
likely (rte_mbuf_refcnt_update(m, -1) == 0)) {
|
|
|
|
struct rte_mbuf *md = RTE_MBUF_FROM_BADDR(m->buf_addr);
|
|
|
|
|
|
|
|
rte_mbuf_refcnt_set(m, 0);
|
|
|
|
|
|
|
|
/* if this is an indirect mbuf, then
|
|
|
|
* - detach mbuf
|
|
|
|
* - free attached mbuf segment
|
|
|
|
*/
|
|
|
|
if (unlikely (md != m)) {
|
|
|
|
rte_pktmbuf_detach(m);
|
|
|
|
if (rte_mbuf_refcnt_update(md, -1) == 0)
|
|
|
|
__rte_mbuf_raw_free(md);
|
|
|
|
}
|
|
|
|
#endif
|
2014-02-17 19:15:19 +00:00
|
|
|
return(m);
|
2014-08-28 15:42:35 +00:00
|
|
|
#ifdef RTE_MBUF_REFCNT
|
2012-09-04 12:54:00 +00:00
|
|
|
}
|
2014-02-17 19:15:19 +00:00
|
|
|
return (NULL);
|
2012-09-04 12:54:00 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-02-17 19:15:19 +00:00
|
|
|
/**
|
|
|
|
* Free a segment of a packet mbuf into its original mempool.
|
|
|
|
*
|
|
|
|
* Free an mbuf, without parsing other segments in case of chained
|
|
|
|
* buffers.
|
|
|
|
*
|
|
|
|
* @param m
|
|
|
|
* The packet mbuf segment to be freed.
|
|
|
|
*/
|
|
|
|
static inline void __attribute__((always_inline))
|
|
|
|
rte_pktmbuf_free_seg(struct rte_mbuf *m)
|
|
|
|
{
|
2014-09-23 11:08:13 +00:00
|
|
|
if (likely(NULL != (m = __rte_pktmbuf_prefree_seg(m)))) {
|
|
|
|
m->next = NULL;
|
2014-02-17 19:15:19 +00:00
|
|
|
__rte_mbuf_raw_free(m);
|
2014-09-23 11:08:13 +00:00
|
|
|
}
|
2014-02-17 19:15:19 +00:00
|
|
|
}
|
|
|
|
|
2012-09-04 12:54:00 +00:00
|
|
|
/**
|
|
|
|
* Free a packet mbuf back into its original mempool.
|
|
|
|
*
|
|
|
|
* Free an mbuf, and all its segments in case of chained buffers. Each
|
|
|
|
* segment is added back into its original mempool.
|
|
|
|
*
|
|
|
|
* @param m
|
|
|
|
* The packet mbuf to be freed.
|
|
|
|
*/
|
|
|
|
static inline void rte_pktmbuf_free(struct rte_mbuf *m)
|
|
|
|
{
|
|
|
|
struct rte_mbuf *m_next;
|
|
|
|
|
2014-08-28 15:42:36 +00:00
|
|
|
__rte_mbuf_sanity_check(m, 1);
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
while (m != NULL) {
|
2014-08-28 15:42:37 +00:00
|
|
|
m_next = m->next;
|
2012-09-04 12:54:00 +00:00
|
|
|
rte_pktmbuf_free_seg(m);
|
|
|
|
m = m_next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-28 15:42:35 +00:00
|
|
|
#ifdef RTE_MBUF_REFCNT
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a "clone" of the given packet mbuf.
|
|
|
|
*
|
|
|
|
* Walks through all segments of the given packet mbuf, and for each of them:
|
|
|
|
* - Creates a new packet mbuf from the given pool.
|
|
|
|
* - Attaches newly created mbuf to the segment.
|
|
|
|
* Then updates pkt_len and nb_segs of the "clone" packet mbuf to match values
|
|
|
|
* from the original packet mbuf.
|
|
|
|
*
|
|
|
|
* @param md
|
|
|
|
* The packet mbuf to be cloned.
|
|
|
|
* @param mp
|
|
|
|
* The mempool from which the "clone" mbufs are allocated.
|
|
|
|
* @return
|
|
|
|
* - The pointer to the new "clone" mbuf on success.
|
|
|
|
* - NULL if allocation fails.
|
|
|
|
*/
|
|
|
|
static inline struct rte_mbuf *rte_pktmbuf_clone(struct rte_mbuf *md,
|
|
|
|
struct rte_mempool *mp)
|
|
|
|
{
|
|
|
|
struct rte_mbuf *mc, *mi, **prev;
|
|
|
|
uint32_t pktlen;
|
|
|
|
uint8_t nseg;
|
|
|
|
|
|
|
|
if (unlikely ((mc = rte_pktmbuf_alloc(mp)) == NULL))
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
mi = mc;
|
2014-08-28 15:42:37 +00:00
|
|
|
prev = &mi->next;
|
|
|
|
pktlen = md->pkt_len;
|
2012-09-04 12:54:00 +00:00
|
|
|
nseg = 0;
|
|
|
|
|
|
|
|
do {
|
|
|
|
nseg++;
|
|
|
|
rte_pktmbuf_attach(mi, md);
|
|
|
|
*prev = mi;
|
2014-08-28 15:42:37 +00:00
|
|
|
prev = &mi->next;
|
|
|
|
} while ((md = md->next) != NULL &&
|
2012-09-04 12:54:00 +00:00
|
|
|
(mi = rte_pktmbuf_alloc(mp)) != NULL);
|
|
|
|
|
|
|
|
*prev = NULL;
|
2014-08-28 15:42:37 +00:00
|
|
|
mc->nb_segs = nseg;
|
|
|
|
mc->pkt_len = pktlen;
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
/* Allocation of new indirect segment failed */
|
|
|
|
if (unlikely (mi == NULL)) {
|
|
|
|
rte_pktmbuf_free(mc);
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
2014-08-28 15:42:36 +00:00
|
|
|
__rte_mbuf_sanity_check(mc, 1);
|
2012-09-04 12:54:00 +00:00
|
|
|
return (mc);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds given value to the refcnt of all packet mbuf segments.
|
|
|
|
*
|
|
|
|
* Walks through all segments of given packet mbuf and for each of them
|
|
|
|
* invokes rte_mbuf_refcnt_update().
|
|
|
|
*
|
|
|
|
* @param m
|
|
|
|
* The packet mbuf whose refcnt to be updated.
|
|
|
|
* @param v
|
|
|
|
* The value to add to the mbuf's segments refcnt.
|
|
|
|
*/
|
|
|
|
static inline void rte_pktmbuf_refcnt_update(struct rte_mbuf *m, int16_t v)
|
|
|
|
{
|
2014-08-28 15:42:36 +00:00
|
|
|
__rte_mbuf_sanity_check(m, 1);
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
do {
|
|
|
|
rte_mbuf_refcnt_update(m, v);
|
2014-08-28 15:42:37 +00:00
|
|
|
} while ((m = m->next) != NULL);
|
2012-09-04 12:54:00 +00:00
|
|
|
}
|
|
|
|
|
2014-08-28 15:42:35 +00:00
|
|
|
#endif /* RTE_MBUF_REFCNT */
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the headroom in a packet mbuf.
|
|
|
|
*
|
|
|
|
* @param m
|
|
|
|
* The packet mbuf.
|
|
|
|
* @return
|
|
|
|
* The length of the headroom.
|
|
|
|
*/
|
|
|
|
static inline uint16_t rte_pktmbuf_headroom(const struct rte_mbuf *m)
|
|
|
|
{
|
2014-08-28 15:42:36 +00:00
|
|
|
__rte_mbuf_sanity_check(m, 1);
|
2014-09-11 13:15:35 +00:00
|
|
|
return m->data_off;
|
2012-09-04 12:54:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the tailroom of a packet mbuf.
|
|
|
|
*
|
|
|
|
* @param m
|
|
|
|
* The packet mbuf.
|
|
|
|
* @return
|
|
|
|
* The length of the tailroom.
|
|
|
|
*/
|
|
|
|
static inline uint16_t rte_pktmbuf_tailroom(const struct rte_mbuf *m)
|
|
|
|
{
|
2014-08-28 15:42:36 +00:00
|
|
|
__rte_mbuf_sanity_check(m, 1);
|
2012-09-04 12:54:00 +00:00
|
|
|
return (uint16_t)(m->buf_len - rte_pktmbuf_headroom(m) -
|
2014-08-28 15:42:37 +00:00
|
|
|
m->data_len);
|
2012-09-04 12:54:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the last segment of the packet.
|
|
|
|
*
|
|
|
|
* @param m
|
|
|
|
* The packet mbuf.
|
|
|
|
* @return
|
|
|
|
* The last segment of the given mbuf.
|
|
|
|
*/
|
|
|
|
static inline struct rte_mbuf *rte_pktmbuf_lastseg(struct rte_mbuf *m)
|
|
|
|
{
|
|
|
|
struct rte_mbuf *m2 = (struct rte_mbuf *)m;
|
|
|
|
|
2014-08-28 15:42:36 +00:00
|
|
|
__rte_mbuf_sanity_check(m, 1);
|
2014-08-28 15:42:37 +00:00
|
|
|
while (m2->next != NULL)
|
|
|
|
m2 = m2->next;
|
2012-09-04 12:54:00 +00:00
|
|
|
return m2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A macro that points to the start of the data in the mbuf.
|
|
|
|
*
|
|
|
|
* The returned pointer is cast to type t. Before using this
|
|
|
|
* function, the user must ensure that m_headlen(m) is large enough to
|
|
|
|
* read its data.
|
|
|
|
*
|
|
|
|
* @param m
|
|
|
|
* The packet mbuf.
|
|
|
|
* @param t
|
|
|
|
* The type to cast the result into.
|
|
|
|
*/
|
2014-09-11 13:15:35 +00:00
|
|
|
#define rte_pktmbuf_mtod(m, t) ((t)((char *)(m)->buf_addr + (m)->data_off))
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A macro that returns the length of the packet.
|
|
|
|
*
|
|
|
|
* The value can be read or assigned.
|
|
|
|
*
|
|
|
|
* @param m
|
|
|
|
* The packet mbuf.
|
|
|
|
*/
|
2014-08-28 15:42:37 +00:00
|
|
|
#define rte_pktmbuf_pkt_len(m) ((m)->pkt_len)
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A macro that returns the length of the segment.
|
|
|
|
*
|
|
|
|
* The value can be read or assigned.
|
|
|
|
*
|
|
|
|
* @param m
|
|
|
|
* The packet mbuf.
|
|
|
|
*/
|
2014-08-28 15:42:37 +00:00
|
|
|
#define rte_pktmbuf_data_len(m) ((m)->data_len)
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Prepend len bytes to an mbuf data area.
|
|
|
|
*
|
|
|
|
* Returns a pointer to the new
|
|
|
|
* data start address. If there is not enough headroom in the first
|
|
|
|
* segment, the function will return NULL, without modifying the mbuf.
|
|
|
|
*
|
|
|
|
* @param m
|
|
|
|
* The pkt mbuf.
|
|
|
|
* @param len
|
|
|
|
* The amount of data to prepend (in bytes).
|
|
|
|
* @return
|
|
|
|
* A pointer to the start of the newly prepended data, or
|
|
|
|
* NULL if there is not enough headroom space in the first segment
|
|
|
|
*/
|
|
|
|
static inline char *rte_pktmbuf_prepend(struct rte_mbuf *m,
|
|
|
|
uint16_t len)
|
|
|
|
{
|
2014-08-28 15:42:36 +00:00
|
|
|
__rte_mbuf_sanity_check(m, 1);
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
if (unlikely(len > rte_pktmbuf_headroom(m)))
|
|
|
|
return NULL;
|
|
|
|
|
2014-09-11 13:15:35 +00:00
|
|
|
m->data_off -= len;
|
2014-08-28 15:42:37 +00:00
|
|
|
m->data_len = (uint16_t)(m->data_len + len);
|
|
|
|
m->pkt_len = (m->pkt_len + len);
|
2012-09-04 12:54:00 +00:00
|
|
|
|
2014-09-11 13:15:35 +00:00
|
|
|
return (char *)m->buf_addr + m->data_off;
|
2012-09-04 12:54:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Append len bytes to an mbuf.
|
|
|
|
*
|
|
|
|
* Append len bytes to an mbuf and return a pointer to the start address
|
|
|
|
* of the added data. If there is not enough tailroom in the last
|
|
|
|
* segment, the function will return NULL, without modifying the mbuf.
|
|
|
|
*
|
|
|
|
* @param m
|
|
|
|
* The packet mbuf.
|
|
|
|
* @param len
|
|
|
|
* The amount of data to append (in bytes).
|
|
|
|
* @return
|
|
|
|
* A pointer to the start of the newly appended data, or
|
|
|
|
* NULL if there is not enough tailroom space in the last segment
|
|
|
|
*/
|
|
|
|
static inline char *rte_pktmbuf_append(struct rte_mbuf *m, uint16_t len)
|
|
|
|
{
|
|
|
|
void *tail;
|
|
|
|
struct rte_mbuf *m_last;
|
|
|
|
|
2014-08-28 15:42:36 +00:00
|
|
|
__rte_mbuf_sanity_check(m, 1);
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
m_last = rte_pktmbuf_lastseg(m);
|
|
|
|
if (unlikely(len > rte_pktmbuf_tailroom(m_last)))
|
|
|
|
return NULL;
|
|
|
|
|
2014-09-11 13:15:35 +00:00
|
|
|
tail = (char *)m_last->buf_addr + m_last->data_off + m_last->data_len;
|
2014-08-28 15:42:37 +00:00
|
|
|
m_last->data_len = (uint16_t)(m_last->data_len + len);
|
|
|
|
m->pkt_len = (m->pkt_len + len);
|
2012-09-04 12:54:00 +00:00
|
|
|
return (char*) tail;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove len bytes at the beginning of an mbuf.
|
|
|
|
*
|
|
|
|
* Returns a pointer to the start address of the new data area. If the
|
|
|
|
* length is greater than the length of the first segment, then the
|
|
|
|
* function will fail and return NULL, without modifying the mbuf.
|
|
|
|
*
|
|
|
|
* @param m
|
|
|
|
* The packet mbuf.
|
|
|
|
* @param len
|
|
|
|
* The amount of data to remove (in bytes).
|
|
|
|
* @return
|
|
|
|
* A pointer to the new start of the data.
|
|
|
|
*/
|
|
|
|
static inline char *rte_pktmbuf_adj(struct rte_mbuf *m, uint16_t len)
|
|
|
|
{
|
2014-08-28 15:42:36 +00:00
|
|
|
__rte_mbuf_sanity_check(m, 1);
|
2012-09-04 12:54:00 +00:00
|
|
|
|
2014-08-28 15:42:37 +00:00
|
|
|
if (unlikely(len > m->data_len))
|
2012-09-04 12:54:00 +00:00
|
|
|
return NULL;
|
|
|
|
|
2014-08-28 15:42:37 +00:00
|
|
|
m->data_len = (uint16_t)(m->data_len - len);
|
2014-09-11 13:15:35 +00:00
|
|
|
m->data_off += len;
|
2014-08-28 15:42:37 +00:00
|
|
|
m->pkt_len = (m->pkt_len - len);
|
2014-09-11 13:15:35 +00:00
|
|
|
return (char *)m->buf_addr + m->data_off;
|
2012-09-04 12:54:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove len bytes of data at the end of the mbuf.
|
|
|
|
*
|
|
|
|
* If the length is greater than the length of the last segment, the
|
|
|
|
* function will fail and return -1 without modifying the mbuf.
|
|
|
|
*
|
|
|
|
* @param m
|
|
|
|
* The packet mbuf.
|
|
|
|
* @param len
|
|
|
|
* The amount of data to remove (in bytes).
|
|
|
|
* @return
|
|
|
|
* - 0: On success.
|
|
|
|
* - -1: On error.
|
|
|
|
*/
|
|
|
|
static inline int rte_pktmbuf_trim(struct rte_mbuf *m, uint16_t len)
|
|
|
|
{
|
|
|
|
struct rte_mbuf *m_last;
|
|
|
|
|
2014-08-28 15:42:36 +00:00
|
|
|
__rte_mbuf_sanity_check(m, 1);
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
m_last = rte_pktmbuf_lastseg(m);
|
2014-08-28 15:42:37 +00:00
|
|
|
if (unlikely(len > m_last->data_len))
|
2012-09-04 12:54:00 +00:00
|
|
|
return -1;
|
|
|
|
|
2014-08-28 15:42:37 +00:00
|
|
|
m_last->data_len = (uint16_t)(m_last->data_len - len);
|
|
|
|
m->pkt_len = (m->pkt_len - len);
|
2012-09-04 12:54:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test if mbuf data is contiguous.
|
|
|
|
*
|
|
|
|
* @param m
|
|
|
|
* The packet mbuf.
|
|
|
|
* @return
|
|
|
|
* - 1, if all data is contiguous (one segment).
|
|
|
|
* - 0, if there is several segments.
|
|
|
|
*/
|
|
|
|
static inline int rte_pktmbuf_is_contiguous(const struct rte_mbuf *m)
|
|
|
|
{
|
2014-08-28 15:42:36 +00:00
|
|
|
__rte_mbuf_sanity_check(m, 1);
|
2014-08-28 15:42:37 +00:00
|
|
|
return !!(m->nb_segs == 1);
|
2012-09-04 12:54:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Dump an mbuf structure to the console.
|
|
|
|
*
|
|
|
|
* Dump all fields for the given packet mbuf and all its associated
|
|
|
|
* segments (in the case of a chained buffer).
|
|
|
|
*
|
2014-05-02 23:42:56 +00:00
|
|
|
* @param f
|
|
|
|
* A pointer to a file for output
|
2012-09-04 12:54:00 +00:00
|
|
|
* @param m
|
|
|
|
* The packet mbuf.
|
|
|
|
* @param dump_len
|
|
|
|
* If dump_len != 0, also dump the "dump_len" first data bytes of
|
|
|
|
* the packet.
|
|
|
|
*/
|
2014-05-02 23:42:56 +00:00
|
|
|
void rte_pktmbuf_dump(FILE *f, const struct rte_mbuf *m, unsigned dump_len);
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* _RTE_MBUF_H_ */
|