版本信息
dpdk 版本:dpdk-22.11-rc0
方法
usertools/dpdk-pmdinfo.py -d /usr/share/misc/pci.ids ./dpdk-testpmd
输出示例:
PMD NAME: net_ixgbe
PMD PARAMETERS: fiber_sdp3_no_tx_disable=<0|1>
PMD KMOD DEPENDENCIES: * igb_uio | uio_pci_generic | vfio-pci
PMD HW SUPPORT:
Intel Corporation (8086) : 82598 10GbE PCI-Express Ethernet Controller (10b6) (All Subdevices)
Intel Corporation (8086) : 82598EB Gigabit BX Network Connection (1508) (All Subdevices)
Intel Corporation (8086) : 82598EB 10-Gigabit AF Dual Port Network Connection (10c6) (All Subdevices)
Intel Corporation (8086) : 82598EB 10-Gigabit AF Network Connection (10c7) (All Subdevices)
Intel Corporation (8086) : 82598EB 10-Gigabit AT Network Connection (10c8) (All Subdevices)
Intel Corporation (8086) : 82598EB 10-Gigabit AT2 Server Adapter (150b) (All Subdevices)
Intel Corporation (8086) : 82598EB 10-Gigabit Dual Port Network Connection (10db) (All Subdevices)
Intel Corporation (8086) : 82598EB 10-Gigabit AT CX4 Network Connection (10dd) (All Subdevices)
Intel Corporation (8086) : 82598EB 10-Gigabit AT CX4 Network Connection (10ec) (All Subdevices)
Intel Corporation (8086) : 82598EB 10-Gigabit AF Dual Port Network Connection (10f1) (All Subdevices)
Intel Corporation (8086) : 82598EB 10-Gigabit AF Dual Port Network Connection (10e1) (All Subdevices)
Intel Corporation (8086) : 82598EB 10-Gigabit AF Network Connection (10f4) (All Subdevices)
Intel Corporation (8086) : 10 Gigabit BR KX4 Dual Port Network Connection (10f7) (All Subdevices)
Intel Corporation (8086) : Ethernet X520 10GbE Dual Port KX4 Mezz (1514) (All Subdevices)
Intel Corporation (8086) : 82599ES 10 Gigabit Network Connection (1517) (All Subdevices)
Intel Corporation (8086) : 82599 10 Gigabit Dual Port Backplane Connection (10f8) (All Subdevices)
Intel Corporation (8086) : 82599 10 Gigabit Dual Port Network Connection (10f9) (All Subdevices)
Intel Corporation (8086) : 82599ES 10-Gigabit SFI/SFP+ Network Connection (10fb) (All Subdevices)
Intel Corporation (8086) : 82599 10 Gigabit Dual Port Backplane Connection with FCoE (152a) (All Subdevices)
Intel Corporation (8086) : 82599 10 Gigabit Dual Port Network Connection with FCoE (1529) (All Subdevices)
Intel Corporation (8086) : Ethernet Express Module X520-P2 (1507) (All Subdevices)
Intel Corporation (8086) : Ethernet 10G 2P X520 Adapter (154d) (All Subdevices)
PMD NAME 为驱动的名称,PMD PARAMETERS 为驱动支持的参数,PMD KMOD DEPENDENCIES 表示驱动依赖的 passthrough 内核驱动,PMD HW SUPPORT 为此驱动支持的设备列表。
实现原理
在 dpdk pmd 驱动中,使用驱动的名称以及支持的设备列表信息,使用宏生成一个特定前缀与后缀的字符串数组,数组中保存驱动支持的设备列表结构的名称。
i40e 中使用如下代码进行注册:
RTE_PMD_REGISTER_PCI_TABLE(net_i40e, pci_id_i40e_map);
RTE_PMD_REGISTER_KMOD_DEP(net_i40e, "* igb_uio | uio_pci_generic | vfio-pci");
如上代码经过预处理,会生成如下数组定义:
static const char __net_i40e_pci_tbl_export[] __rte_used = "pci_id_i40e_map";
static const char __net_i40e_kmod_dep_export[] __rte_used = "* igb_uio | uio_pci_generic | vfio-pci";
pci_id_i40e_map 为 i40e 支持的 pci 设备列表,其定义部分摘录如下:
static const struct rte_pci_id pci_id_i40e_map[] = {
{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710) },
{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QEMU) },
{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_B) },
{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_C) },
{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_A) },
{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_B) },
drivers 目录中的 meson.build 脚本中有如下命令:
# generate pmdinfo sources by building a temporary
# lib and then running pmdinfogen on the contents of
# that lib. The final lib reuses the object files and
# adds in the new source file.
out_filename = lib_name + '.pmd.c'
tmp_lib = static_library('tmp_' + lib_name, sources,
include_directories: includes,
dependencies: static_deps,
c_args: cflags)
objs += tmp_lib.extract_all_objects(recursive: true)
sources = custom_target(out_filename,
command: [pmdinfo, tmp_lib.full_path(), '@OUTPUT@', pmdinfogen],
output: out_filename,
depends: [tmp_lib])
在编译生成驱动静态库之前,先编译临时的驱动静态库。然后调用自定义命令 pmdinfo 来生成 *pmd.c 文件并更新编译源码列表。pmdinfo 命令定义如下:
./buildtools/meson.build:25:pmdinfo = py3 + files('gen-pmdinfo-cfile.py') + [meson.current_build_dir()]
pmdinfo 命令调用 gen-pmdinfo-cfile.py 脚本,此脚本首先使用 ar -t 命令获取临时库中目标文件列表,然后调用 pmdinfogen.py 脚本来扫描所有的目标文件,遍历 elf 格式文件符号表匹配以 pci_tbl_export 以及 dep_export 后缀结尾的对象,根据对象的内容找到相应的表结构,然后在 drivers 编译目录中生成后缀为 .pmd.c 的源文件并更新驱动库的 sources 列表加入生成的 xxx.pmd.c 源文件。
i40e 驱动 pmd.c 源文件内容如下:
$ cat ./drivers/rte_net_i40e.pmd.c
static __attribute__((unused)) const char *generator = "../buildtools/pmdinfogen.py";
const char net_i40e_pmd_info[] __attribute__((used)) = "PMD_INFO_STRING= {\"name\": \"net_i40e\", \"params\": \"enable_floating_veb=1floating_veb_list=<string>queue-num-per-vf=1|2|4|8|16support-multi-driver=1\", \"kmod\": \"* igb_uio | uio_pci_generic | vfio-pci\", \"pci_ids\": [[32902, 5490, 65535, 65535], [32902, 5492, 65535, 65535], [32902, 5504, 65535, 65535], [32902, 5505, 65535, 65535], [32902, 5507, 65535, 65535], [32902, 5508, 65535, 65535], [32902, 5509, 65535, 65535], [32902, 5510, 65535, 65535], [32902, 5511, 65535, 65535], [32902, 5512, 65535, 65535], [32902, 5513, 65535, 65535], [32902, 5514, 65535, 65535], [32902, 5515, 65535, 65535], [32902, 14156, 65535, 65535], [32902, 14286, 65535, 65535], [32902, 14287, 65535, 65535], [32902, 14288, 65535, 65535], [32902, 14289, 65535, 65535], [32902, 14290, 65535, 65535], [32902, 14291, 65535, 65535], [32902, 3320, 65535, 65535], [32902, 3416, 65535, 65535], [32902, 5631, 65535, 65535], [32902, 4127, 65535, 65535], [32902, 4175, 65535, 65535], [32902, 4174, 65535, 65535]]}";
可以看到它定义了一个以 pmd_info 结尾的字符变量,此变量的值为 json 格式的驱动支持列表。
此后重新编译生成的静态库中就会带有 xxx.pmd.c.o 的目标文件,i40e 驱动库中文件列表示例如下:
$ ar -t ./drivers/librte_net_i40e.a
meson-generated_.._rte_net_i40e.pmd.c.o
......................................
net_i40e_rte_pmd_i40e.c.o
net_i40e_i40e_rxtx_vec_sse.c.o
net_i40e_i40e_rxtx_vec_avx2.c.o
可以看到 net_i40e_rte_pmd_i40e.c.o 就是其中 i40e 驱动库的 pmd.c.o 目标文件。此后链接 dpdk 驱动库生成的 dpdk 程序中将会包含 xxx_pmd_info 符号,示例如下:
$ nm ./dpdk-testpmd | grep i40e_pmd_info
00000000018abf00 R net_i40e_pmd_info
最后 dpdk-pmdinfo.py 解析 elf 文件,在 .rodata section 中查找以 PMD_INFO_STRING 开始的位置,使用 json 库解析信息,然后使用指定的 pci.ids 生成程序支持的设备信息并格式化输出就完成了所有过程。