mbuf图解
![](https://img-blog.csdnimg.cn/2021011716185735.png)
![](https://img-blog.csdnimg.cn/20210117161628857.png)
mbuf分为4部分:mbuf + priv + headroom + data
(1)mbuf长度为sizeof(struct rte_mbuf) = 128
(2)priv长度在创建pool时指定(priv_size)
(3)headroom长度为RTE_PKTMBUF_HEADROOM(CONFIG_RTE_PKTMBUF_HEADROOM)
(4)data长度在创建pool时指定(data_room_size - RTE_PKTMBUF_HEADROOM)
data根据实际情况又分为2部分:data(有效长度)+ tailroom(空闲长度)
![](https://img-blog.csdnimg.cn/20210117162740998.png)
主要成员
buf_addr:headroom首地址
buf_len:headroom长度 + data长度 + tailroom长度
data_off:headroom长度,data相对buf_addr的偏移
data_len:data长度
pkt_len:data_len长度和(多个segment)
![](https://img-blog.csdnimg.cn/2021011718493991.png)
![](https://img-blog.csdnimg.cn/20210117185017717.png)
rte_pktmbuf_headroom:headroom长度
rte_pktmbuf_tailroom:tailroom长度
rte_pktmbuf_mtod:data首地址
static inline uint16_t rte_pktmbuf_headroom(const struct rte_mbuf *m)
{
__rte_mbuf_sanity_check(m, 0);
return m->data_off;
}
static inline uint16_t rte_pktmbuf_tailroom(const struct rte_mbuf *m)
{
__rte_mbuf_sanity_check(m, 0);
return (uint16_t)(m->buf_len - rte_pktmbuf_headroom(m) -
m->data_len);
}
#define rte_pktmbuf_mtod_offset(m, t, o) \
((t)((char *)(m)->buf_addr + (m)->data_off + (o)))
#define rte_pktmbuf_mtod(m, t) rte_pktmbuf_mtod_offset(m, t, 0)
rte_pktmbuf_prepend:在data前增加一段内容(headroom-)
rte_pktmbuf_append:在data后增加一段内容(tailroom-)
rte_pktmbuf_adj:在data前删除一段内容(headroom+)
rte_pktmbuf_trim:在data后删除一段内容(tailroom+)
static inline char *rte_pktmbuf_prepend(struct rte_mbuf *m,
uint16_t len)
{
__rte_mbuf_sanity_check(m, 1);
if (unlikely(len > rte_pktmbuf_headroom(m)))
return NULL;
m->data_off -= len;
m->data_len = (uint16_t)(m->data_len + len);
m->pkt_len = (m->pkt_len + len);
return (char *)m->buf_addr + m->data_off;
}
static inline char *rte_pktmbuf_append(struct rte_mbuf *m, uint16_t len)
{
void *tail;
struct rte_mbuf *m_last;
__rte_mbuf_sanity_check(m, 1);
m_last = rte_pktmbuf_lastseg(m);
if (unlikely(len > rte_pktmbuf_tailroom(m_last)))
return NULL;
tail = (char *)m_last->buf_addr + m_last->data_off + m_last->data_len;
m_last->data_len = (uint16_t)(m_last->data_len + len);
m->pkt_len = (m->pkt_len + len);
return (char*) tail;
}
static inline char *rte_pktmbuf_adj(struct rte_mbuf *m, uint16_t len)
{
__rte_mbuf_sanity_check(m, 1);
if (unlikely(len > m->data_len))
return NULL;
m->data_len = (uint16_t)(m->data_len - len);
m->data_off += len;
m->pkt_len = (m->pkt_len - len);
return (char *)m->buf_addr + m->data_off;
}
static inline int rte_pktmbuf_trim(struct rte_mbuf *m, uint16_t len)
{
struct rte_mbuf *m_last;
__rte_mbuf_sanity_check(m, 1);
m_last = rte_pktmbuf_lastseg(m);
if (unlikely(len > m_last->data_len))
return -1;
m_last->data_len = (uint16_t)(m_last->data_len - len);
m->pkt_len = (m->pkt_len - len);
return 0;
}
mbuf定义
struct rte_mbuf {
MARKER cacheline0;
void *buf_addr; /**< Virtual address of segment buffer. */
/**
* Physical address of segment buffer.
* Force alignment to 8-bytes, so as to ensure we have the exact
* same mbuf cacheline0 layout for 32-bit and 64-bit. This makes
* working on vector drivers easier.
*/
RTE_STD_C11
union {
rte_iova_t buf_iova;
rte_iova_t buf_physaddr; /**< deprecated */
} __rte_aligned(sizeof(rte_iova_t));
/* next 8 bytes are initialised on RX descriptor rearm */
MARKER64 rearm_data;
uint16_t data_off;
/**
* Reference counter. Its size should at least equal to the size
* of port field (16 bits), to support zero-copy broadcast.
* 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.
*/
RTE_STD_C11
union {
rte_atomic16_t refcnt_atomic; /**< Atomically accessed refcnt */
uint16_t refcnt; /**< Non-atomically accessed refcnt */
};
uint16_t nb_segs; /**< Number of segments. */
/** Input port (16 bits to support more than 256 virtual ports). */
uint16_t port;
uint64_t ol_flags; /**< Offload features. */
/* remaining bytes are set on RX when pulling packet from descriptor */
MARKER rx_descriptor_fields1;
/*
* The packet type, which is the combination of outer/inner L2, L3, L4
* and tunnel types. The packet_type is about data really present in the
* mbuf. Example: if vlan stripping is enabled, a received vlan packet
* would have RTE_PTYPE_L2_ETHER and not RTE_PTYPE_L2_VLAN because the
* vlan is stripped from the data.
*/
RTE_STD_C11
union {
uint32_t packet_type; /**< L2/L3/L4 and tunnel information. */
struct {
uint32_t l2_type:4; /**< (Outer) L2 type. */
uint32_t l3_type:4; /**< (Outer) L3 type. */
uint32_t l4_type:4; /**< (Outer) L4 type. */
uint32_t tun_type:4; /**< Tunnel type. */
RTE_STD_C11
union {
uint8_t inner_esp_next_proto;
/**< ESP next protocol type, valid if
* RTE_PTYPE_TUNNEL_ESP tunnel type is set
* on both Tx and Rx.
*/
__extension__
struct {
uint8_t inner_l2_type:4;
/**< Inner L2 type. */
uint8_t inner_l3_type:4;
/**< Inner L3 type. */
};
};
uint32_t inner_l4_type:4; /**< Inner L4 type. */
};
};
uint32_t pkt_len; /**< Total pkt len: sum of all segments. */
uint16_t data_len; /**< Amount of data in segment buffer. */
/** VLAN TCI (CPU order), valid if PKT_RX_VLAN_STRIPPED is set. */
uint16_t vlan_tci;
union {
uint32_t rss; /**< RSS hash result if RSS enabled */
struct {
RTE_STD_C11
union {
struct {
uint16_t hash;
uint16_t id;
};
uint32_t lo;
/**< Second 4 flexible bytes */
};
uint32_t hi;
/**< First 4 flexible bytes or FD ID, dependent on
PKT_RX_FDIR_* flag in ol_flags. */
} fdir; /**< Filter identifier if FDIR enabled */
struct {
uint32_t lo;
uint32_t hi;
} sched; /**< Hierarchical scheduler */
uint32_t usr; /**< User defined tags. See rte_distributor_process() */
} hash; /**< hash information */
/** Outer VLAN TCI (CPU order), valid if PKT_RX_QINQ_STRIPPED is set. */
uint16_t vlan_tci_outer;
uint16_t buf_len; /**< Length of segment buffer. */
/** Valid if PKT_RX_TIMESTAMP is set. The unit and time reference
* are not normalized but are always the same for a given port.
*/
uint64_t timestamp;
/* second cache line - fields only used in slow path or on TX */
MARKER cacheline1 __rte_cache_min_aligned;
RTE_STD_C11
union {
void *userdata; /**< Can be used for external metadata */
uint64_t udata64; /**< Allow 8-byte userdata on 32-bit */
};
struct rte_mempool *pool; /**< Pool from which mbuf was allocated. */
struct rte_mbuf *next; /**< Next segment of scattered packet. */
/* fields to support TX offloads */
RTE_STD_C11
union {
uint64_t tx_offload; /**< combined for easy fetch */
__extension__
struct {
uint64_t l2_len:7;
/**< L2 (MAC) Header Length for non-tunneling pkt.
* Outer_L4_len + ... + Inner_L2_len for tunneling pkt.
*/
uint64_t l3_len:9; /**< L3 (IP) Header Length. */
uint64_t l4_len:8; /**< L4 (TCP/UDP) Header Length. */
uint64_t tso_segsz:16; /**< TCP TSO segment size */
/* fields for TX offloading of tunnels */
uint64_t outer_l3_len:9; /**< Outer L3 (IP) Hdr Length. */
uint64_t outer_l2_len:7; /**< Outer L2 (MAC) Hdr Length. */
/* uint64_t unused:8; */
};
};
/** Size of the application private data. In case of an indirect
* mbuf, it stores the direct mbuf private data size. */
uint16_t priv_size;
/** Timesync flags for use with IEEE1588. */
uint16_t timesync;
/** Sequence number. See also rte_reorder_insert(). */
uint32_t seqn;
} __rte_cache_aligned;
rte_mbuf是按cache line对齐的,查看cache line:cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size
MARKER为零长度数组(柔性数组)
__extension__
typedef void *MARKER[0]; /**< generic marker for a point in a structure */
参考
https://zzqcn.github.io/opensource/dpdk/code-analysis/mbuf.html
https://doc.dpdk.org/guides/prog_guide/mbuf_lib.html