0%

周谈(54)- DPDK dmadev lib学习

前言

dmadev lib顾名思义就是用来使用dma设备的框架,伴随着摩尔定律的失效,现在CPU的性能几乎很难进行提升了。那么提高性能的方式就只能是软件不够硬件来凑了,让许多工作从CPU卸载到硬件去。
dmadev lib库是DPDK中的一个软件库,提供管理和配置DMA poll mode drivers的软件,定义了统一的操作接口。支持一系列不同的DMA操作。

功能介绍

设计约束

库支持物理的(硬件)和虚拟的(软件)DMA设备。

dmadev_arch

DMA框架的组成如上图所示:

  1. DMA控制器有多个硬件的DMA通道(队列),每个硬件DMA通道呈现为一个dmadev。
  2. dmadev可以创建多个虚拟的DMA通道,每个虚拟DMA通道呈现为不通的transfer context, 比如virtual DMA channel 0 用作memory-to-memory场景,而virtual dma channel 1用作 memory-to-device场景。
  3. DMA操作必须提交给虚拟DMA通道。

设备管理

设备创建

物理的DMA controller在DPDK初始化时,由PCI扫描枚举出来,基于设备的BDF(bus、device、function)。其他物理DMA controller可以在DPDK命令行中指定。
dmadev由rte_dma_pmd_allocate函数根据物理DMA channel的个数创建。

设备标识

每个DMA(不论是物理还是虚拟的)设备由2个id唯一标识。

  1. 一个唯一的设备索引,用在DMA API接口中指派dma设备。
  2. 一个设备名,用在串口信息或者管理调试。

设备特性和能力

不同的dma设备可能支持不一样的特性,rte_dma_info_get API可以获取设备信息和支持的特性。
Silent mode是一种特殊的设备能力,这种设备不需要应用调用dequeue APIs。

出入队接口

DPDK主要基于轮询的方式操作,因此所有的pmd都会有出入队的接口。
Enqueue API 可以把操作传递到设备,这样的接口有rte_dma_copy和rte_dma_fill。如果入队成功,会返回一个ring_idx。ring_idx可以让应用知道到其环中定为操作的元信息。如果入队失败ring_idx是一个负值。
rte_dma_submit用于发送一个doorbell通知硬件。也可以在入队的时候,带上RTE_DMA_OP_FLAG_SUBMIT 标记自动发送doorbell通知硬件。

下面的代码描述如何入队多个拷贝操作到设备,并启动硬件进行操作。

1
2
3
4
5
6
7
8
9
10
11
struct rte_mbuf *srcs[DMA_BURST_SZ], *dsts[DMA_BURST_SZ];
unsigned int i;

for (i = 0; i < RTE_DIM(srcs); i++) {
if (rte_dma_copy(dev_id, vchan, rte_pktmbuf_iova(srcs[i]),
rte_pktmbuf_iova(dsts[i]), COPY_LEN, 0) < 0) {
PRINT_ERR("Error with rte_dma_copy for buffer %u\n", i);
return -1;
}
}
rte_dma_submit(dev_id, vchan);

rte_dma_completed 和rte_dma_completed_status接口用于出队获取操作的结果。rte_dma_completed用于获取成功的个数,rte_dma_completed_status返回个数以及每个操作的执行状态(存放到一个status数组中)。这两个接口还会返回最后一个操作的ring_idx。

查询设备统计

使用rte_dma_stats_get()接口获取dmadev的统计信息,包含每个设备的如下数据:
Submitted: 提交的操作数量
Completed:已完成的操作数量(包含成功的和失败的)
Errors:完成发送错误的数量
库也支持调试接口显示相关信息:

dmadev_stats

注意点

设备使用前需要进行配置,然后再开始使用:

1
2
3
rte_dma_configure()
rte_dma_vchan_setup()
rte_dma_start()

修改配置

可以调用rte_dma_configure() or rte_dma_vchan_setup(), 但前提要先调用rte_dma_stop(),配置完后rte_dma_start()开始。设备停止状态下,不要往设备发送操作。

关闭设备

使用完毕需要调用rte_dma_close关闭设备。

提交操作

先入队再发送doorbell给硬件。

1
2
3
4
5
rte_dma_copy()
rte_dma_copy_sg(
rte_dma_fill()
rte_dma_submit()

ring_idx说明

    1. 每个virtual dma channel的ring_idx是独立的
    1. ring_idx是单调递增的数,直到UINT16_MAX才回到0
    1. ring_idx初始时是0,如果设备停止了,需要重置ring_idx

操作地址

操作内部的地址类型为rte_iova_t。
dmadev支持两种类型的地址: 内存地址和设备地址。

    1. 内存地址:memory-to-memory操作的源目地址,memory-to-device的源地址, device-to-memory操作的目的地址,如果设备支持SVA,那么这种地址可以是VA,否则必须是IOVA。
    1. 设备地址:memory-to-device的目的地址,device-to-memory操作的源地址

其他

所有的API都是不加锁的,不支持多个线程并发访问,不考虑多个同时调用同一个dmadev。
同一个dmadev的virtual dma channel也不支持同时调用,因为这些channel共用同一个硬件的dma channel。

更多

初步了解一下dma引擎在DPDK中的使用框架。很多公司已经实现了其dma引擎,在大数据、虚拟化等方面开始应用了。


行动,才不会被动!

欢迎关注个人公众号 微信 -> 搜索 -> fishmwei,沟通交流。

欢迎关注

博客地址: https://fishmwei.github.io

掘金主页: https://juejin.cn/user/2084329776486919