DPDK dmadev lib学习

前言

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

功能介绍

设计约束

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

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通知硬件。

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

c 复制代码
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:完成发送错误的数量 库也支持调试接口显示相关信息:

注意点

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

c 复制代码
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给硬件。

c 复制代码
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,沟通交流。

博客地址: fishmwei.github.io

掘金主页: juejin.cn/user/208432...


相关推荐
Java水解1 分钟前
Java 中间件:Dubbo 服务降级(Mock 机制)
java·后端
千寻girling4 分钟前
一份不可多得的 《 Python 》语言教程
人工智能·后端·python
南风9995 分钟前
Claude code安装使用保姆级教程
后端
爱泡脚的鸡腿6 分钟前
Node.js 拓展
前端·后端
蚂蚁背大象1 小时前
Rust 所有权系统是为了解决什么问题
后端·rust
子玖3 小时前
go实现通过ip解析城市
后端·go
Java不加班3 小时前
Java 后端定时任务实现方案与工程化指南
后端
心在飞扬3 小时前
RAG 进阶检索学习笔记
后端
Moment3 小时前
想要长期陪伴你的助理?先从部署一个 OpenClaw 开始 😍😍😍
前端·后端·github