目录

文章目录

  • 目录
  • 前文列表
  • PMD,DPDK 的核心优化
  • PMD 与 UIP 的交互实现
  • PMD 的应用层实现
  • 参考文章

前文列表

《DPDK — 安装部署》
《DPDK — 数据平面开发技术》
《DPDK — 架构解析》
《DPDK — IGB_UIO,与 UIO Framework 进行交互的内核模块》

PMD,DPDK 的核心优化

我们知道,Linux 内核在收包时有两种方式可供选择,一种是中断方式,另外一种是轮询方式。

从哲学的角度来说,中断是外界强加给你的信号,你必须被动应对,而轮询则是你主动地处理事情。前者最大的影响就是打断你当前工作的连续性,而后者则不会,事务的安排自在掌握。

中断对性能的影响有多大?在 x86 体系结构中,一次中断处理需要将 CPU 的状态寄存器保存到堆栈,并运行中断服务程序,最后再将保存的状态寄存器信息从堆栈中恢复。整个过程需要至少 300 个处理器时钟周期。

轮询对性能的提升有多大?网卡收到报文后,可以借助 DDIO(Direct Data I/O)技术直接将报文保存到 CPU 的 Cache 中,或者保存到内存中(没有 DDIO 技术的情况下),并设置报文到达的标志位。应用程序则可以周期性地轮询报文到达的标志位,检测是否有新报文需要处理。整个过程中完全没有中断处理过程,因此应用程序的网络报文处理能力得以极大提升。

故此,想要 CPU 执行始终高效,就必然需要一个内核线程去主动 Poll(轮询)网卡,而这种行为与当前的内核协议栈是不相容的,即便当前内核协议栈可以使用 NAPI 中断+轮询的方式,但依旧没有根本上解决问题。除非再重新实现一套全新的内核协议栈,显然这并不现实,但幸运的是,我们可以在用户态实现这一点。

针对 Intel 网卡,DPDK 实现了基于轮询方式的 PMD(Poll Mode Drivers)网卡驱动。该驱动由用户态的 API 以及 PMD Driver 构成,内核态的 UIO Driver 屏蔽了网卡发出的中断信号,然后由用户态的 PMD Driver 采用主动轮询的方式。除了链路状态通知仍必须采用中断方式以外,均使用无中断方式直接操作网卡设备的接收和发送队列。

PMD Driver 从网卡上接收到数据包后,会直接通过 DMA 方式传输到预分配的内存中,同时更新无锁环形队列中的数据包指针,不断轮询的应用程序很快就能感知收到数据包,并在预分配的内存地址上直接处理数据包,这个过程非常简洁。

PMD 极大提升了网卡 I/O 性能。此外,PMD 还同时支持物理和虚拟两种网络接口,支持 Intel、Cisco、Broadcom、Mellanox、Chelsio 等整个行业生态系统的网卡设备,以及支持基于 KVM、VMware、 Xen 等虚拟化网络接口。PMD 实现了 Intel 1GbE、10GbE 和 40GbE 网卡下基于轮询收发包。

UIO+PMD,前者旁路了内核,后者主动轮询避免了硬中断,DPDK 从而可以在用户态进行收发包的处理。带来了零拷贝(Zero Copy)、无系统调用(System call)的优化。同时,还避免了软中断的异步处理,也减少了上下文切换带来的 Cache Miss。

值得注意的是,运行在 PMD 的 Core 会处于用户态 CPU 100% 的状态,如下图:

由于,网络空闲时 CPU 会长期处于空转状态,带来了电力能耗的问题。所以,DPDK 引入了 Interrupt DPDK(中断 DPDK)模式。Interrupt DPDK 的原理和 NAPI 很像,就是 PMD 在没数据包需要处理时自动进入睡眠,改为中断通知,接收到收包中断信号后,激活主动轮询。这就是所谓的链路状态中断通知。并且 Interrupt DPDK 还可以和其他进程共享一个 CPU Core,但 DPDK 进程仍具有更高的调度优先级。

PMD 与 UIP 的交互实现

对于 PMD 的实现来说,重点是处于用户态的 PMD 驱动程序如何通过 igb_uio 内核驱动模块与 UIO 进行交互,从而实现数据包处理的内核旁路。

  1. 调用 igbuio_setup_bars,设置 uio_info 的 uio_mem 和 uio_port。这一步骤的细节在前文中已有提到,igb_uio 内核模块在发现了 PCI 设备的 Memory BAR 和 IO BAR 之后会将这些 resources 的信息保存到 uioX 设备的 maps 中,这样处于用户态的 PMD 就可以访问这些原本只能被内核访问的 BAR 空间了。
  2. 设置 uio_info 的其他成员。
  3. 调用 uio_register_device,注册 uioX 设备。PMD 通过 uioX 设备与 igb_uio 内核驱动模块进行交互。

  1. 打开 uioX 设备,应用层已经可以使用 uioX 设备了。DPDK 的应用层代码,会打开 uioX 设备。在函数 pci_uio_alloc_resource 中。

打开对应的 uioX 设备时,对应的内核操作为 uio_open(),其又会调用 igb_uio 的 open(),流程图如下:

  1. 设置中断信息,igb_uio 默认的中断模式为 RTE_INTR_MODE_MSIX,在 igbuio_pci_enable_interrupts 的关键代码如下:
  2. 注册中断。当打开 uio 设备时,igb_uio 就会注册了一个中断。

    那么为什么作为轮询模式的 PMD 驱动需要注册中断呢?这是因为,即使应用层可以通过 UIO 来实现设备驱动,但是设备的某些事件还是需要内核进行响应,然后通知应用层的。当然,PMD 的中断处理已经非常简单了。


其中的关键步骤是调用 uio_event_notify。

这个函数很简单:

  1. 增加 uioX 设备的 “事件” 数;
  2. 唤醒在 idev->wait 等待队列中的 task;
  3. 使用信号异步通知 async_queue 队列中的进程;

注意,因为目前 DPDK 没有使用异步 IO 的方式,所有对于 DPDK PMD 来说,只有前两个语句有用。

  1. 调用 UIO 的 mmap(),将注册的 uioX 设备的 “内存空间” 映射到应用空间,让 PMD 得以真正的从用户态中去访问内存。其 mmap 函数为 uio_mmap(),关键代码如下:

至此,UIO 框架和 igb_uio 内核模块已经可以让 PMD 访问 PCI 设备的大部分资源了。

PMD 的应用层实现

当 DPDK Application 启动时,会首先进行 EAL 初始化,如下图:

在 pci_uio_alloc_resource 中,主要是打开 DPDK Application 要管理的 uioX 设备。

同时,DPDK App 还需要把 PCI 设备的 BAR 映射到应用层。在 pci_uio_map_resource() 中,除了调用上图中的 pci_uio_alloc_resource,还会调用 pci_uio_map_resource_by_index 做资源映射。

下面就是 PMD 在应用层的驱动实现了。以最简单的 e1000 驱动为例,其初始化函数 eth_igb_dev_init 如下。

上面我们提到了,当 uioX 设备有事件触发时,由 eth_igb_interrupt_handler() 负责处理,实现了用户态的中断处理。


eth_igb_interrupt_handler 的实现非常简单,只是处理设备的状态变化事件,如:Link Status。

接下来,就是最重要的了,PMD 如何读取网卡数据。DPDK App 会调用 rte_eth_rx_burst 读取数据报文。

在这个函数中,会调用驱动 dev->rx_pkt_burst 来做实际的操作。以 e1000 为例,即 eth_igb_recv_pkts。

这里的实现很简单。如果网卡接收 buffer descriptor 表示已经完成一个报文的接收,有 E1000_RXD_STAT_DD 标志,则 rte_mbuf_raw_alloc 一个 mbuf,进行处理。如果没有报文,直接跳出循环。

对应 RTC 模型的 DPDK App 来说,就是不断的调用 rte_eth_rx_burst 去 “询问” 网卡是否有新的报文。如果有,就取走所有的报文或达到参数 nb_pkts 的上限。然后进行报文处理,处理完毕,再次循环。

参考文章

https://cloud.tencent.com/developer/article/1411982

DPDK — PMD,DPDK 的核心优化相关推荐

  1. DPDK PMD( Poll Mode Driver)轮询模式驱动程序

    DPDK PMD( Poll Mode Driver)轮询模式驱动程序 目录 Mellanox PMDs 轮询模式驱动程序 要求和假设 设计原则 逻辑核心,内存和NIC队列关系 设备标识,所有权和配置 ...

  2. How-to: Build VPP FD.IO with Mellanox DPDK PMD on top CentOS 7.7 with inbox drivers.

    目录 References Prerequisites Installation, Compilation and Configuration This short document will gui ...

  3. dpdk pmd驱动分析

    缘起dpdk_devbind.py 运行dpdk程序之前我们一般都会使用dpdk_devbind.py程序对指定的驱动与设备进行绑定与解绑(如下命令).那么dpdk_devbind.py程序是如何实现 ...

  4. 【DPDK】DPDK 入门介绍

    博主未授权任何人或组织机构转载博主任何原创文章,感谢各位对原创的支持! 博主链接 文章目录 DPDK 入门介绍 网络IO的处境和趋势 Linux + x86网络IO瓶颈 DPDK的基本原理 DPDK旁 ...

  5. 【DPDK】DPDK技术介绍--研读

    DPDK是INTEL公司开发的一款高性能的网络驱动组件,旨在为数据面应用程序提供一个简单方便的,完整的,快速的数据包处理解决方案,主要技术有用户态.轮询取代中断.零拷贝.网卡RSS.访存DirectI ...

  6. dpdk中文-dpdk简单介绍

    bestboyxie话说DPDK~~其实dpdk中文文档太少了,好多大神都不愿意分享,所以我如果不写对不起谢大神名号啦~~ DPDK = Data Plane Development Kit  数据平 ...

  7. 【DPDK】dpdk样例源码解析之三:dpdk-l3fwd_001

    本篇文章主要介绍dpdk-l3fwd实例源码,通过分析代码逻辑,学习DPDK中几个API接口作用以及如何使用? 操作系统版本:CentOS 8.4 DPDK版本:dpdk-20.11.3 如何单独创建 ...

  8. MySQL 第七天(核心优化一)

    一.Mysql核心优化 1. 优化的方面 ① 存储层:数据表"存储引擎"选取.字段选取.逆范式(3范式) ② 设计层:索引.分区/分表 ③ 架构层:分布式部署(主从模式/共享) ④ ...

  9. 字节跳动在 Spark SQL 上的核心优化实践

    作者 | 郭俊 封图 | BanburyTang 字节跳动数据仓库架构团队负责数据仓库领域架构设计,支持字节跳动几乎所有产品线(包含但不限于抖音.今日头条.西瓜视频.火山视频)数据仓库方向的需求,如 ...

最新文章

  1. 如何用Linux的at命令安排一个任务
  2. 第55件事 产品疯传的7个基本原则
  3. Matlab 接受字符串并转为符号表达式,inline函数,匿名函数形式的方法汇总
  4. 最长递增子序列 最长连续递增序列
  5. php mysql建表_mysql建表测试
  6. Codevs 1049 棋盘染色
  7. 数据结构--------------静态表的希尔排序
  8. 同源策略——浏览器安全卫士
  9. 剑指offer48-最长不含重复字符的子字符串(双指针经典)
  10. 百亿美元合同告吹!微软“到嘴的鸭子”飞了
  11. 黑马程序员__用户禁用cookie后登录不成功的原因
  12. [转帖]Android Bitmap内存限制OOM,Out Of Memory
  13. iText5官方系列教程-iText in Action(一)
  14. 87-分布式前端微信操作
  15. 机械制图与计算机绘图习题集第二版答案,机械制图与计算机绘图习题集(第2版)-曾令宜.pdf...
  16. 遭遇灰鸽子BackDoor.Gpigeon.ymg新变种
  17. 首开先河 | 脑机接口让这位ALS患者可读可写
  18. For ‘mall-coupon‘ URL not provided. Will try picking an instance via load-balancing. org.springfram
  19. RPG游戏制作-03-人物行走及A*寻路算法
  20. nvme协议 sata接口_NVMe/SATA SSD有啥不一样?萌新怎么选

热门文章

  1. Swift3.0语言教程使用编码创建和初始化字符串
  2. Unity网络多玩家游戏开发教程(上册)
  3. go语言和java并发_彻底搞清楚Java并发 (一) 基础
  4. css3 卡片亮光_利用css3实现文字亮光特效的代码
  5. findcontours函数_opencv轮廓findContoursamp;drawContours
  6. 果蝇玩VR登Nature,发现注意力机制、工作记忆都有,昆虫大脑原来没比哺乳类差多少...
  7. 万物皆可JOJO:这个GAN直接让马斯克不做人啦 | Demo可玩
  8. 计算机专业学生却被强迫工厂实习?结果发生意外手指被截肢,学校回应:会治到满意为止...
  9. 新模拟算法揭秘加州地震史:更准确有效
  10. IBM又双叒叕要分拆了,IT基础设施部门将剥离,未来专注云计算和AI