dpdk mbuf之代码流程

创建mbuf的内存池

当我们要使用mbuf的时候,需要先创建一个mbuf的内存池,然后每次都从mp里面alloc和free即可。
相对dpdk提供的mbuf库来说,使用比较简单,具体代码在:dpdk/lib/librte_mbuf 目录里面

struct rte_mempool *
rte_pktmbuf_pool_create(const char *name, unsigned int n,
	unsigned int cache_size, uint16_t priv_size, uint16_t data_room_size,
	int socket_id)
{
	return rte_pktmbuf_pool_create_by_ops(name, n, cache_size, priv_size,
			data_room_size, socket_id, NULL);
}

具体输入参数:
const char *name 创建mp需要的名字
unsigned int n mp里面obj的数量,在这里表示mbuf的数量,如果你的代码缓存mbuf比较多,这里就需要设置大一些,防止不够用
unsigned int cache_size mp里面cache的数量
uint16_t priv_size 每一个mbuf私有数据空间的大小,不需要直接设置为0即可
uint16_t data_room_size mbuf的数据报文的大小,理论上需要加上room head的大小,建议使用默认值RTE_MBUF_DEFAULT_BUF_SIZE
int socket_id 申请内存的socket,不清楚设置那个的直接使用rte_socket_id()即可。

rte_pktmbuf_pool_create主要分为以下几步:

  1. 创建一个空的mp使用rte_mempool_create_empty

  2. 根据ops name选择相应的mp 的ops操作库,如果有自己定义的ops 操作库,则直接使用rte_pktmbuf_pool_create_by_ops,否则就使用rte_pktmbuf_pool_create创建mbuf的mp即可

  3. 如果没有指定ops name的话,系统默认rte_mbuf_best_mempool_ops

    这里说一下dpdk提供的ops类型,主要分为三种:
    ①、用户自定义
    ②、硬件平台相关,这里运行不同nic自己设计内存buf,主要用到的主要有nxp的dpaa和cavium的octeontx
    ③、默认ring_mp_mc
    优先级也是① > ② > ③

  4. 初始化mp rte_pktmbuf_pool_init

void
rte_pktmbuf_pool_init(struct rte_mempool *mp, void *opaque_arg)
{
	struct rte_pktmbuf_pool_private *user_mbp_priv, *mbp_priv;
	struct rte_pktmbuf_pool_private default_mbp_priv;
	uint16_t roomsz;

	RTE_ASSERT(mp->elt_size >= sizeof(struct rte_mbuf));

	/* if no structure is provided, assume no mbuf private area */
	user_mbp_priv = opaque_arg;
	if (user_mbp_priv == NULL) {
		default_mbp_priv.mbuf_priv_size = 0;
		if (mp->elt_size > sizeof(struct rte_mbuf))
			roomsz = mp->elt_size - sizeof(struct rte_mbuf);
		else
			roomsz = 0;
		default_mbp_priv.mbuf_data_room_size = roomsz;
		user_mbp_priv = &default_mbp_priv;
	}

	RTE_ASSERT(mp->elt_size >= sizeof(struct rte_mbuf) +
		user_mbp_priv->mbuf_data_room_size +
		user_mbp_priv->mbuf_priv_size);

	mbp_priv = rte_mempool_get_priv(mp);
	memcpy(mbp_priv, user_mbp_priv, sizeof(*mbp_priv));
}
  1. 申请n个mbuf内存rte_mempool_populate_default
  2. 初始化每一个mbuf
void
rte_pktmbuf_init(struct rte_mempool *mp,
		 __attribute__((unused)) void *opaque_arg,
		 void *_m,
		 __attribute__((unused)) unsigned i)
{
	struct rte_mbuf *m = _m;
	uint32_t mbuf_size, buf_len, priv_size;

	priv_size = rte_pktmbuf_priv_size(mp);
	mbuf_size = sizeof(struct rte_mbuf) + priv_size;
	buf_len = rte_pktmbuf_data_room_size(mp);

	RTE_ASSERT(RTE_ALIGN(priv_size, RTE_MBUF_PRIV_ALIGN) == priv_size);
	RTE_ASSERT(mp->elt_size >= mbuf_size);
	RTE_ASSERT(buf_len <= UINT16_MAX);

	memset(m, 0, mbuf_size);
	/* start of buffer is after mbuf structure and priv data */
	m->priv_size = priv_size;
	m->buf_addr = (char *)m + mbuf_size;
	m->buf_iova = rte_mempool_virt2iova(m) + mbuf_size;
	m->buf_len = (uint16_t)buf_len;

	/* keep some headroom between start of buffer and data */
	m->data_off = RTE_MIN(RTE_PKTMBUF_HEADROOM, (uint16_t)m->buf_len);

	/* init some constant fields */
	m->pool = mp;
	m->nb_segs = 1;
	m->port = MBUF_INVALID_PORT;
	rte_mbuf_refcnt_set(m, 1);
	m->next = NULL;
}

到此为止mbuf的内存池已经初始化完成.

相关api

  1. 申请mbuf
    rte_mbuf_raw_alloc 从mp里面申请一块mbuf,不做初始化
    rte_pktmbuf_alloc 从mp里面申请一块mbuf,同时对mbuf做初始化rte_pktmbuf_reset,对mbuf的变量重置为初始值
    rte_pktmbuf_alloc_bulk 从mp里面一次申请多个mbuf并做reset操作
    rte_pktmbuf_reset 复位mbuf控制块的信息
  2. 释放mbuf
    rte_pktmbuf_free 释放mbuf到mp里面,如果mbuf属于多段buf,同时释放所有mbuf
  3. 获取mbuf报文位置指针
    rte_pktmbuf_mtod 获取报文开始的虚拟地址
    rte_pktmbuf_iova 获取报文开始的物理地址
  4. 获取mbuf相关长度
    rte_pktmbuf_pkt_len 获取报文总的长度
    rte_pktmbuf_data_len 获取报文当前段的长度
  5. mbuf数据插入删除操作
    rte_pktmbuf_prepend 在帧数据前插入一段内容
    rte_pktmbuf_append 在帧数据后增加一段内容
    rte_pktmbuf_adj 在帧数据前删除一段内容
    rte_pktmbuf_trim 将帧数据后截掉一段内容
    6、连接分离两段mbuf缓存
    rte_pktmbuf_attach 此函数会连接两段属于不同缓存区的缓存, 称为间接缓存(indirect buffer) 。 对间接缓存的访
    问效率低于直接缓存(意为一段缓存包含完整Mbuf结构和帧数据),也就是说,把mbuf1的buf_addr等信息替换为mbuf2里面的,如果要分离的话,需要重新从mbuf头部计算一下buf_addr等变量的值。
    rte_pktmbuf_detach 分离两点缓存,和attach相反操作。
  6. 克隆mbuf
    rte_pktmbuf_clone 此函数作为rte_pktmbuf_attach的更高一级抽象, 将正确设置连接后Mbuf的各个参数, 相对rte_pktmbuf_attach更为安全

你可能感兴趣的:(dpdk)