openeuler加载dpdk驱动模块
虽然是openeuler arm架构加载dpdk网卡驱动,但是linux加载驱动模块的流程和方法是一样的,遇到的问题也是相似的,所以借这个机会把相关的内容介绍一下
确认模块名称
驱动模块开发完成后是一个ko库,拷贝到系统指定目录,然后运行命令加载模块名。有时候想知道源码编译的模块名称是什么,可以在源码的Makefile
文件中查找:
#
# module name and path
#
MODULE = igb_uio
MODULE_PATH = drivers/net/igb_uio
_BUILD = $(MODULE).ko
如果使用uio,需要加载uio_pci_generic
(系统默认)
如果使用vfio,需要加载vfio
(系统默认)和vfio-pci
(系统默认)
如果使用igb_uio,需要加载uio
(系统默认)和igb_uio
(编译得到)。但是新版本的dpdk不再使用igb_uio
(虽然还可以打开配置进行编译),
命令介绍
操作驱动相关命令
insmod
insmod只会加载指定路径下的某个模块,不会解决依赖,比如insmod /home/dev/igb_uio.ko
modprobe
modprobe会帮忙解决依赖,也就是如果加载a模块需要b模块,那么会先加载b模块,再加载a模块,比如modprobe igb_uio
。
modprobe不需要指定具体路径,但是你必须要把你的模块放到系统指定目录/lib/modules/#uname -r#/
,这个路径不是固定的,会根据不同的系统而不一样,uname -r
就是后面的目录名称。
depmod
depmod会扫描模块,把结果写入/lib/modules/#uname -r#/modules.dep
文件中,如果安装一个新模块,需要先运行depmod扫描,再运行modprobe加载,不然会报错FATAL: Module igb_uio.ko not found in directory /lib/modules/xxx
lsmod
列出系统中安装的模块,内容有三列,第一列是模块名,第二列是模块大小,第三列是模块被谁调用
Module Size Used by
ib_uverbs 327680 1 rdma_ucm
ib_iser 262144 0
rdma_cm 262144 6 rpcrdma,ib_srpt,ib_srp,ib_iser,ib_isert,rdma_ucm
modinfo
查看模块的信息,可以指定具体路径,也可以不指定
$ modinfo igb_uio
filename: /lib/modules/4.19.90-2003.4.0.0036.oe1.aarch64/extra/dpdk/igb_uio.ko
author: Intel Corporation
license: GPL
description: UIO driver for Intel IGB PCI cards
srcversion: 26C63DAE2104091D5DE47C6
depends: uio
name: igb_uio
vermagic: 4.19.90-2110.8.0.0119.oe1.aarch64 SMP mod_unload modversions aarch64
parm: intr_mode:igb_uio interrupt mode (default=msix):
msix Use MSIX interrupt
msi Use MSI interrupt
legacy Use Legacy interrupt
(charp)
rmmod
删除模块,如果模块不需要了,或者想替换新的模块,需要用rmmod删除,命令如下rmmod igb_uio
module_init module_exit
这两个函数注册两个接口,用作加载和卸载模块的时候调用
module_init(mymodule_init);
module_exit(mymodule_exit);
操作设备与驱动命令
绑定驱动
dpdk-devbind -b igb_uio 0000:c6:00.0
dpdk-devbind是dpdk编译安装的工具,上面就是把igb_uio驱动绑定到指定的网卡bus info中
可以查看这个脚本,实际上就是把网卡的bus总线id写入到/sys/bus/pci/drivers/igb_uio/bind
文件中,如果想把哪个设备绑定到一个驱动上,就把这个设备的bus id写入到对应驱动目录/sys/bus/pci/drivers/xxx/bind
中,xxx就是这个驱动的名字。这个文件只有只写的权限,所以可以用echo 0000:c6:00.0 > /sys/bus/pci/drivers/igb_uio/bind
实现,也可以通过fopen
以只写的方式写入
除此之外,还有一些特殊处理,比如先卸载原先驱动或者绑定的驱动本身属于dpdk等。
查看网卡状态
dpdk-devbind -s
Network devices using DPDK-compatible driver
============================================
0000:c6:00.0 'Hi1822 Family (4*25GE) 1822' drv=igb_uio unused=hinic
Network devices using kernel driver
===================================
0000:7d:00.0 'HNS GE/10GE/25GE RDMA Network Controller a222' if=enp125s0f0 drv=hns3 unused=hns_roce_hw_v2,igb_uio *Active*
0000:7d:00.1 'HNS GE/10GE/25GE Network Controller a221' if=enp125s0f1 drv=hns3 unused=hclge,igb_uio
0000:7d:00.2 'HNS GE/10GE/25GE RDMA Network Controller a222' if=enp125s0f2 drv=hns3 unused=hns_roce_hw_v2,igb_uio
0000:7d:00.3 'HNS GE/10GE/25GE Network Controller a221' if=enp125s0f3 drv=hns3 unused=hclge,igb_uio
0000:c3:00.0 'Hi1822 Family (4*25GE) 1822' if=enp195s0 drv=hinic unused=igb_uio
0000:c4:00.0 'Hi1822 Family (4*25GE) 1822' if=enp196s0 drv=hinic unused=igb_uio
0000:c5:00.0 'Hi1822 Family (4*25GE) 1822' if=enp197s0 drv=hinic unused=igb_uio
0000:dd:00.0 'HNS GE/10GE/25GE RDMA Network Controller a222' if=enp221s0f0 drv=hns3 unused=hns_roce_hw_v2,igb_uio
可以看到0000:c6:00.0
这个网卡已经是dpdk的驱动了。
绑定dpdk驱动后,网卡会被dpdk接管,使用ifconfig
就无法查看到网卡信息和名称。
同样可以查看这个脚本,实际上还是用了lspci
ip
等相关命令整合的信息
解绑网卡驱动
dpdk-devbind -u 0000:c6:00.0
查看脚本可以知道解绑和绑定驱动类似,把bus id写入到对应驱动的/sys/bus/pci/drivers/xxx/unbind
中。
遇到问题
modprobe: ERROR: could not insert 'igb_uio': Invalid argument
当前系统的内核和编译模块内核不匹配,通过uname -r
和modinfo 模块名
查看系统内核与模块的vermagic值是否相同。
$ uname -r
4.19.90-2003.4.0.0036.oe1.aarch64
$ modinfo igb_uio
filename: /lib/modules/4.19.90-2003.4.0.0036.oe1.aarch64/extra/dpdk/igb_uio.ko
author: Intel Corporation
license: GPL
description: UIO driver for Intel IGB PCI cards
srcversion: 26C63DAE2104091D5DE47C6
depends: uio
name: igb_uio
vermagic: 4.19.90-2110.8.0.0119.oe1.aarch64 SMP mod_unload modversions aarch64
parm: intr_mode:igb_uio interrupt mode (default=msix):
msix Use MSIX interrupt
msi Use MSI interrupt
legacy Use Legacy interrupt
(charp)
parm: wc_activate:Activate support for write combining (WC) (default=0)
0 - disable
other - enable
(int)
这时候可以查看一下自己系统上安装的kernel-devel
与系统内核版本uname -r
是否匹配,如果不匹配,先卸载kernel-devel
,再安装指定版本yum install "kernel-devel-uname-r == $(uname -r)"
insmod: ERROR: could not insert module igb_uio.ko: Unknown symbol in module
这是因为有依赖模块,查看依赖模块名称
modinfo igb_uio.ko|grep depends
depends: uio
安装依赖模块modprobe uio
再次安装insmod igb_uio.ko
EAL: Error - exiting with code: 1 Cause: No Ethernet ports - bye
可以通过dmesg
查看出错日志,可能原因是驱动与内核版本不匹配,或者加载驱动失败。
目前遇到的问题就是dpdk的驱动没有加载,或者加载出错,反正就是dpdk驱动加载有问题,导致程序无法获得网口信息。
加载原生驱动
有时候需要还原驱动,可以在最开始调用ethtool -i 网卡名
查看
如果加载了dpdk驱动,而忘记或者没有查看原生驱动名称,可以通过lspci
查看详细信息获得
lspci -vs 03:00.0
03:00.0 Ethernet controller: Huawei Technologies Co., Ltd. Hi1822 Family (4*25GE) (rev 45)
Subsystem: Huawei Technologies Co., Ltd. Device d136
Flags: fast devsel, NUMA node 0
Memory at 80003d00000 (64-bit, prefetchable) [size=128K]
Memory at 800044a0000 (64-bit, prefetchable) [size=32K]
[virtual] Memory at 80000000000 (64-bit, prefetchable) [size=1M]
Expansion ROM at e9000000 [disabled] [size=1M]
Capabilities: [40] Express Endpoint, MSI 00
Capabilities: [80] MSI: Enable- Count=1/32 Maskable+ 64bit+
Capabilities: [a0] MSI-X: Enable- Count=32 Masked-
Capabilities: [b0] Power Management version 3
Capabilities: [c0] Vital Product Data
Capabilities: [100] Advanced Error Reporting
Capabilities: [150] Alternative Routing-ID Interpretation (ARI)
Capabilities: [200] Single Root I/O Virtualization (SR-IOV)
Capabilities: [310] Secondary PCI Express <?>
Capabilities: [4e0] Device Serial Number cc-05-77-ff-ff-ae-71-37
Capabilities: [4f0] Transaction Processing Hints
Capabilities: [600] Vendor Specific Information: ID=0000 Rev=0 Len=028 <?>
Capabilities: [630] Access Control Services
Kernel driver in use: igb_uio
Kernel modules: hinic
最后两行,Kernel driver in use是当前使用的驱动,Kernel moddules对应着原生驱动
iommu
./dpdk-helloworld
EAL: Detected 96 lcore(s)
EAL: Detected 4 NUMA nodes
EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
EAL: Selected IOVA mode 'PA'
EAL: Probing VFIO support...
EAL: PCI device 0000:03:00.0 on NUMA socket 0
EAL: probe driver: 19e5:1822 net_hinic
net_hinic: API CMD poll status timeout
net_hinic: chain type: 0x7
net_hinic: chain hw cpld error: 0x1
net_hinic: chain hw check error: 0x0
net_hinic: chain hw current fsm: 0x0
net_hinic: chain hw current ci: 0x0
net_hinic: Chain hw current pi: 0x1
net_hinic: Send msg to mgmt failed
net_hinic: Failed to get board info, err: -110, status: 0x0, out size: 0x0
net_hinic: Check card workmode failed, dev_name: 0000:03:00.0
net_hinic: Create nic device failed, dev_name: 0000:03:00.0
net_hinic: Initialize 0000:03:00.0 in primary failed
EAL: Requested device 0000:03:00.0 cannot be used
如果运行dpdk的时候报上面的错误,那是因为开启了IOMMU
,相关信息可以参考华为官网资料鲲鹏BoostKit虚拟化使能套件 OVS流表归一化 特性指南 07。
配置方法,在/etc/grub2-efi.cfg
中,在开机启动项一行最后增加iommu.passthrough=1
,绕过IOMMU。IOMMU是用于另外一种驱动方式vfio,需要软硬件支持。
linux /vmlinuz-4.19.90-2003.4.0.0036.oe1.aarch64 root=/dev/mapper/openeuler-root ro rd.lvm.lv=openeuler/r oot rd.lvm.lv=openeuler/swap video=VGA-1:640x480-32@60me smmu.bypassdev=0x1000:0x17 smmu.bypassdev=0x1000:0x15 cra shkernel=1024M,high video=efifb:off video=VGA-1:640x480-32@60me default_hugepagesz=2M hugepagesz=2M hugepages=128 i ommu.passthrough=1
iommu.passthrough
iommu.passthrough=
[ARM64, X86] Configure DMA to bypass the IOMMU by default.
Format: { "0" | "1" }
0 - Use IOMMU translation for DMA.
1 - Bypass the IOMMU for DMA.
unset - Use value of CONFIG_IOMMU_DEFAULT_PASSTHROUGH.
如果用vfio,需要开启iommu,配置为在上面开机启动项最后增加iommu=pt
intel_iommu=on
查看是否开启iommu
cat /proc/cmdline
查看cmdline相关信息是否有iommu=pt
和intel_iommu=on
https://github.com/torvalds/linux/blob/master/Documentation/admin-guide/kernel-parameters.txt
使用vfio驱动
确保cpu支持VT-x
或VT-d
,并且BIOS也打开了相关配置。
配置grub
linux /vmlinuz-4.19.90-2003.4.0.0036.oe1.x86_64 root=/dev/mapper/openeuler-root ro resume=/dev/ma pper/openeuler-swap rd.lvm.lv=openeuler/root rd.lvm.lv=openeuler/swap rhgb quiet quiet crashkernel=512M iommu=pt intel_iommu=on
增加iommu=pt intel_iommu=on
,打开iommu,重启系统
加载驱动
modprobe vfio
modprobe vfio-pci
绑定网卡
bin/dpdk-devbind.py -b vfio-pci 0000:84:00.0
查看网卡信息
bin/dpdk-devbind.py -s
Network devices using DPDK-compatible driver
============================================
0000:84:00.0 '82599ES 10-Gigabit SFI/SFP+ Network Connection 10fb' drv=vfio-pci unused=ixgbe
Network devices using kernel driver
===================================
0000:05:00.0 'I350 Gigabit Network Connection 1521' if=enp5s0f0 drv=igb unused=vfio-pci *Active*
0000:05:00.1 'I350 Gigabit Network Connection 1521' if=enp5s0f1 drv=igb unused=vfio-pci
0000:84:00.1 '82599ES 10-Gigabit SFI/SFP+ Network Connection 10fb' if=enp132s0f1 drv=ixgbe unused=vfio-pci