DPDK的几种buffer分配方式

在使用DPDK时,我们一般会用mbuf作为buffer,从mempool中分配。其实我们还可以直接用mempool的block作为buffer,或者memzone的block作为buffer,以及用rte_malloc的heap区作为buffer。但mbuf可以发送到以太网,其他方式分配的buffer,没有mbuf header,不能发送到网络。

基于mbuf的buffer

mbuf本身有最大64kB的buffer size限制。因为struct rte_mbuf中的字段uint16_t data_len;最大能表示64kB。https://elixir.bootlin.com/dpdk/latest/source/lib/mbuf/rte_mbuf_core.h#L656

使用mbuf有几种方式:普通alloc和快速alloc,其中快速alloc的性能更好,更推荐。

普通alloc

使用的步骤

  1. 创建mbuf的mempool,用rte_pktmbuf_pool_create_by_ops()分配mempool,同时指定pool的enq/deq方式。

  2. rte_mbuf_raw_alloc()分配mbuf,用rte_mbuf_raw_free()释放mbuf。注意这2个API适合在每个mbuf里加些字段,不适合直接使用,因为mbuf header里的很多字段,都还没有初始化。

  3. 通过rte_pktmbuf_reset()初始化mbuf的header内容,就可以使用了。payload地址需要通过函数rte_pktmbuf_mtod()来偏移。

    如无需初始化时标记每个buffer,那么直接调用rte_pktmbuf_alloc()也可以,步骤2,3合并为一步。

快速alloc

使用的步骤

  1. 分配mempool,通过rte_mempool_create_empty()创建空mempool,然后调用rte_mempool_set_ops_byname()配置enq/deq方式,rte_mempool_populate_default()在memzone中实际分配内存。

  2. 从mempool获得buffer,rte_mempool_get_bulk(rte_mempool,(void **)events, num);

  3. 通过rte_pktmbuf_reset(rte_mbuf)初始化mbuf header,为null或0等,就可使用mbuf了。如果跳过这一步,可能会导致mbuf使用时,出现莫名其妙的问题。

  4. 如果需要,还可以append一部分tailroom的空间,存需要的内容,rte_pktmbuf_append(mbuf, size)。

基于mempool的buffer

用mempool或memzone没有最大buffer大小为64kB的这个限制。而且因为不需要mbuf的header,可以节约一些内存,不需要填充mbuf的header内容,速度也会更快。

使用的步骤

  1. 创建一个空的mempool

    1. 通过API rte_mempool_create_empty()创建。

    2. 配置mempool的enq/deq方式,rte_mempool_set_ops_byname(),比如配置ring_mp_mc/ring_mt_rts/lf_stack。

    3. 在memzone分配内存。rte_mempool_populate_default()

  2. 分配buffer

    通过rte_mempool_get/rte_mempool_get_bulk()的API即可。分配出的obj指针,直接就指向payload地址,不需要像mbuf一样偏移后,才能得到payload地址。bulk可以一次性拿到n个buffer,拿不到就返回0。不像burst可能返回小于n的buffer个数。但dpdk目前只支持bulk的方式取buffer。

  3. 释放buffer

    通过rte_mempool_put/rte_mempool_put_bulk()。

注意,分配mempool的参数如下:

mp = rte_mempool_create_empty(name, n, block_sz, cache_sz, 0, SOCKET_ID_ANY, RTE_MEMPOOL_F_NO_IOVA_CONTIG);名称是参数name,总的buffer个数是n,每个buffer大小是block_sz,cache_sz是分配的cache大小。RTE_MEMPOOL_F_NO_IOVA_CONTIG表示可以基于非连续内存的分配,在IOVA=PA的环境下尤其有用,IOVA=PA表示硬件看到的实际物理地址是需要连续的。如果出现没有连续的物理内存,会导致没法分配buffer。

基于memzone的buffer

分配的步骤

  1. 先看这个名称的memzone是否被使用了,rte_memzone_lookup(name)。

  2. 如果名称没被使用,可以reserve。mz = rte_memzone_reserve_aligned(name, size, SOCKET_ID_ANY, 0, 64);

    注意返回的地址是mz->addr,而不是直接用mz。

释放的步骤

  1. 先看这个名称的memzone是否被使用了,rte_memzone_lookup(name);

  2. 释放这个memzone,rte_memzone_free(mz);

查找的步骤

rte_memzone_lookup(name);

基于DPDK heap的buffer

和linux的malloc/free类似。而且也可以使用非连续的内存。用的是memzone之外的内存。

分配的方式是:

*ptr = rte_zmalloc(NULL, size, 64);

释放的方式是:

rte_free(ptr);

原文链接:https://mp.weixin.qq.com/s/duqEGmu-fUWzoxRi0SnA_Q

 
学习更多dpdk视频

DPDK 学习资料、教学视频和学习路线图 :https://space.bilibili.com/1600631218
Dpdk/网络协议栈/ vpp /OvS/DDos/NFV/虚拟化/高性能专家 学习地址: https://ke.qq.com/course/5066203?flowToken=1043799
DPDK开发学习资料、教学视频和学习路线图分享有需要的可以自行添加学习交流q 君羊909332607备注(XMG) 获取

猜你喜欢

转载自blog.csdn.net/weixin_60043341/article/details/126608031