DPDK之PMD原理

本文介绍了基于用户态轮询机制的驱动PMD的基本原理。阐述了其依赖内核策略,如uio模块和igb_uio内核模块,说明了使用DPDK脚本bind网卡的操作,以及PMD与UIO的交互过程。还介绍了应用层的初始化、驱动实现,以及PMD读取网卡数据的流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PMD是Poll Mode Driver的缩写,即基于用户态的轮询机制的驱动。本文将介绍PMD的基本原理。

在不考虑vfio的情况下,PMD的结构图如下:

图1. PMD结构图

虽然PMD是在用户态实现设备驱动,但还是依赖于内核提供的策略。其中uio模块,是内核提供的用户态驱动框架,而igb_uio是DPDK kit中拥有与uio交互,bind指定网卡的内核模块。

当使用DPDK脚本dpdk-devbind来bind网卡时,会通过sysfs与内核交互,让内核使用指定驱动来匹配网卡。具体的行为向/sys/bus/pci/devices/(pci id)/driver_override写入指定驱动名称,或者向/sys/bus/pci/drivers/igb_uio(驱动名称)/new_id写入要绑定网卡的PCI ID。前者是配置设备,让其选择驱动。后者是是配置驱动,让其支持新的PCI设备。按照内核的文档https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-pci,这两个动作都会促使驱动bind新设备。但是在dpdk-devbind脚本中,还是通过向/sys/bus/pci/drivers/igb_uio(驱动名称)/bind写入pci id来保证bind。—— 也许是处于兼容性考虑吧。

当使用igb_uio bind指定设备后,内核会调用igb_uio注册的struct pci_driver的probe函数,即igbuio_pci_probe。在这个函数中,设置PCI的一些操作(如设置PCI BAR、DMA等),不是重点,那是驱动工程师的职责:) 对于PMD来说,重点是与UIO的交互。

1. 调用igbuio_setup_bars,设置uio_info的uio_mem和uio_port。

图2. igbuio_setup_bars

2. 设置uio_info的其他成员

图3. igb_uio设置uio_info

3. 调用uio_register_device,注册uio设备。

查看/dev目录,可以发现对应的uioX设备,如下图:

图4. uio设备

打开uio设备

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

图5. 打开uio设备

当open对应的uio设备时,对应的内核操作为uio_open,其又会调用igb_uio的open函数,流程图如下:

图6. open uio设备

igb_uio的默认中断模式为RTE_INTR_MODE_MSIX,在igbuio_pci_enable_interrupts的关键代码如下:

图7. 设置中断信息

图8. 注册中断

当打开uio设备时,igb_uio注册了一个中断。这时大家应该有个疑问,PMD不是用户态轮询设备吗?为什么还要申请中断,注册中断处理函数呢?这是因为,即使应用层可以通过uio来实现设备驱动,但是设备的某些事件还是需要内核进行响应,然后通知应用层。当然,现在的中断处理已经非常简单了。

图9. igb_uio中断处理函数

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

图10. uio_event_notify

这个函数很简单:1. 增加uio设备的“事件”数; 2. 唤醒在idev->wait等待队列中的task;3. 使用信号异步通知async_queue队列中的进程;目前DPDK没有使用异步IO的方式,所有对于DPDK的PMD来说,只有前两个语句有用。

uio模块除了实现了上面的“事件”通知,还支持了mmap方法,用于将注册的uio设备的“内存空间”映射到应用空间。其mmap的函数为uio_mmap,关键代码如下:

图11.uio_mmap

至此,uio已经可以让PMD的应用层访问设备的大部分资源了。接下来,要转过去看看PMD的应用层。

当DPDK的app启动时,会进行EAL初始化,如下图:

图12. 应用层uio初始化

在pci_uio_alloc_resource中,主要是打开dpdk要管理的uio设备

图13. 打开ui设备

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

图14. pci_uio_map_resource

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

图15. 注册e1000的中断处理函数

从图11和图12的代码中,可以看出当uio设备有事件时,由eth_igb_interrupt_handler负责处理,实现了用户态的中断处理。

图16. eth_igb_interrupt_handler

eth_igb_interrupt_handler非常简单,只是处理设备的状态变化事件,如link status。

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

图17.rte_eth_rx_burst

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

图18 eth_igb_recv_pkts

图19 eth_igb_recv_pkts

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

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

以上就是PMD的大体流程。

<think>嗯,用户想了解OVS-DPDK的工作原理。我需要先回顾一下之前提供的参考资料,然后整理出一个清晰的解释。首先,OVS-DPDK是Open vSwitch结合DPDK的优化版本,对吧?根据引用[2],DPDK加速的OVS和原始OVS的主要区别在于数据路径的处理。原始OVS需要通过内核模块openvswitch.ko处理数据包,而OVS-DPDK通过DPDKPMD驱动直接将报文送到用户态的ovs-vswitchd进程,避免了内核态的开销。 接下来,用户态快速路径dpif-netdev取代了原来的内核datapath,这一点在引用[4]中提到过。这意味着数据包处理完全在用户空间进行,利用DPDK的高性能特性。然后,关于流表查询,引用[1]提到使用Classifier进行流表匹配,这应该涉及到高效的哈希算法或查找结构,比如元组空间搜索算法,以快速匹配流表项。 另外,OVS-DPDK的架构可能包括主线程负责管理,而数据面线程负责实际的包处理。这些线程绑定到特定的CPU核心,减少上下文切换,提升性能。还有内存管理方面,DPDK使用大页内存和内存池技术,减少内存分配的开销,确保零拷贝传输,这点可能需要在回答中详细说明。 用户可能还关心OVS-DPDK的优化点,比如流缓存、批处理、多队列等,这些在性能优化中很重要。同时,应用场景如NFV、云计算中的虚拟网络也是需要提到的部分,结合引用[3]中的安装和概述资料。 需要确保回答结构清晰,分点解释,比如架构变化、数据流向、流表处理、性能优化等。同时,生成的相关问题要围绕用户可能进一步想了解的内容,比如性能优化方法、与内核OVS的区别、适用场景等。检查是否有遗漏的关键点,比如零拷贝、CPU亲和性等,确保覆盖所有重要方面。</think>### OVS-DPDK工作原理详解 OVS-DPDK是Open vSwitch(OVS)结合Data Plane Development Kit(DPDK)技术实现的高性能用户态虚拟交换机,其核心目标是通过绕过内核协议栈来提升数据包处理效率。以下是其关键工作原理: --- #### 1. **架构变化** - **用户态数据路径**:OVS-DPDK使用`dpif-netdev`模块替代传统OVS的内核态`datapath`和用户态`dpif-netlink`,使数据包处理完全在用户空间完成,避免了内核态与用户态之间的上下文切换开销[^4]。 - **DPDK PMD驱动**:网络接口通过DPDKPoll Mode DriverPMD)直接管理,报文从物理网卡或虚拟网卡(如vhost-user)通过DPDK PMD直接进入用户态,无需内核参与[^2]。 --- #### 2. **数据流向** 1. **收包阶段**: 报文通过物理网卡或虚拟网卡(如vhost-user)进入,由DPDK PMD驱动直接传递给用户态的`ovs-vswitchd`进程。 2. **流表匹配**: 使用`Classifier`模块进行流表查询,通过元组(如五元组)匹配流表项。若命中流表,则按流表动作(如转发、修改字段)处理;若未命中,则上送控制面生成新流表项[^1]。 3. **转发处理**: 处理后的报文通过DPDK PMD发送到目标端口(如另一个虚拟机或物理网卡)。 --- #### 3. **流表处理优化** - **高效匹配算法**:采用哈希表或元组空间搜索算法(TSS)加速流表查询。 - **流缓存机制**:频繁访问的流表项缓存在快速路径中,减少控制面交互。 - **批量处理**:DPDK支持报文批量处理(如一次处理32个包),降低单包处理开销。 --- #### 4. **性能优化技术** - **零拷贝技术**:DPDK通过内存池(`mempool`)和大页内存(HugePages)实现报文内存零拷贝。 - **CPU亲和性**:将PMD线程绑定到专属CPU核心,减少缓存失效和线程切换。 - **多队列优化**:为每个CPU核心分配独立队列,避免资源竞争。 --- #### 5. **应用场景** - **NFV(网络功能虚拟化)**:为虚拟机或容器提供高性能虚拟网络。 - **云计算网络**:在OpenStack等平台中实现低延迟的虚拟交换机。 - **边缘计算**:适用于需要高吞吐量的边缘网关场景[^3]。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值