目录
前文列表
《DPDK — 安装部署》
《DPDK — 数据平面开发技术》
《DPDK — 架构解析》
IGB_UIO
虽然 PMD 是在用户态实现的网卡驱动程序,但实际上还是会依赖于内核提供的策略。其中 UIO 内核模块,是内核提供的用户态驱动框架,而 IGB_UIO(igb_uio.ko)是 DPDK 用于与 UIO 交互的内核模块,通过 igb_uio 来 bind 指定的 PCI 网卡设备到 DPDK 使用。IGB_UIO 借助 UIO 技术来截获中断,并重设中断回调行为,从而绕过内核协议栈后续的处理流程。并且 IGB_UIO 会在内核初始化的过程中将网卡硬件寄存器映射到用户态。
IGB_UIO 内核模块主要功能之一就是用于注册一个 PCI 设备。可以使用 DPDK 提供个一个 Python 脚本 dpdk-devbind 来完成,当执行 dpdk-devbind 来 bind 网卡时,会通过 sysfs 与内核交互,让内核使用指定的驱动程序来匹配网卡。具体的行为是向文件 /sys/bus/pci/devices/{pci id}/driver_override 写入指定驱动的名称,或者向 /sys/bus/pci/drivers/igb_uio(驱动名称)/new_id 写入要 bind 的网卡设备的 PCI ID。前者是配置设备,让其选择驱动;后者是是配置驱动,让其支持新的 PCI 设备。按照内核的文档 https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-pci 中提到,这两个动作都会促使驱动程序 bind 新的网卡设备。
dpdk-devbind 具体的步骤如下:
- 获取脚本执行参数指定的网卡(e.g. eth1)设备的 PCI 信息。实际是执行指令
lspci–Dvmmn
查看,主要关注 Slot、Vendor 以及 Device 信息。
Slot: 0000:06:00.1
Class: 0200
Vendor: 8086
Device: 1521
SVendor: 15d9
SDevice: 1521
Rev: 01
- unbind 网卡设备之前的 igb 模块,将 Step 1 中获取到的 eth1 对应的 Slot 信息
0000:06:00.1
值写入 igb 驱动的 unbind 文件。e.g.echo 0000:06:00.1 > /sys/bus/pci/drivers/igb/unbind
。 - bind 网卡设备到新的 igb_uio 模块,将 eth1 的 Vendor 和 Device ID 信息写入 igb_uio 驱动的 new_id 文件。e.g.
echo 0x8086 0x1521 > /sys/bus/pci/drivers/igb_uio/new_id
。
IGB_UIO 内核模块的另一个主要功能就是让用于态的 PMD 网卡驱动程序得以与 UIO 进行交互:
- 调用 igbuio_setup_bars,设置 uio_info 的 uio_mem 和 uio_port。
- 设置 uio_info 的其他成员。
- 调用 uio_register_device,注册 UIO 设备。
- 打开 UIO 设备并注册中断。
- 调用 uio_event_notify,将注册的 UIO 设备的 “内存空间” 映射到用户态的应用空间。其 mmap 的函数为 uio_mmap。至此,UIO 就可以让 PMD 驱动程序在用户态应用层访问设备的大部分资源了。
- 应用层 UIO 初始化。同时,DPDK 还需要把 PCI 设备的 BAR 映射到应用层。在 pci_uio_map_resource 函数中会调用 pci_uio_map_resource_by_index 做资源映射。
- 在 PMD 驱动程序中,DPDK 应用程序,会调用 rte_eth_rx_burst 读取数据报文。如果网卡接收 Buffer 的描述符表示已经完成一个报文的接收(e.g. 有 E1000_RXD_STAT_DD 标志),则 rte_mbuf_raw_alloc 一个 mbuf 进行处理。
- 对应 RTC 模型的 DPDK 应用程序来说,就是不断的调用 rte_eth_rx_burst 去询问网卡是否有新的报文。如果有,就取走所有的报文或达到参数 nb_pkts 的上限。然后进行报文处理,处理完毕,再次循环。
来源:oschina
链接:https://my.oschina.net/u/4260285/blog/4271479