DPDK网卡需匹配PMD驱动、正确绑定VFIO/IGB_UIO、显式加载PMD模块、配置RX队列并绑定lcore,否则rte_eth_dev_count_avail()返回0或收包失败。

确认网卡是否支持对应PMD驱动
DPDK不是通用驱动框架,每个网卡型号只被特定PMD支持。硬配错驱动会导致rte_eal_init()失败或rte_eth_dev_count_avail()返回0。必须先查官方NIC支持列表(如https://doc.dpdk.org/guides/nics/overview.html),再核对实际PCI设备ID。
常见错误现象:运行lspci -nn | grep Ethernet看到8086:10fb(Intel X710),却误用igb_uio绑定——它只支持e1000系千兆卡,X710必须用vfio-pci + net_i40e PMD。
- 执行
lspci -s 0000:01:00.0 -vv | grep "Driver\|Class"确认当前内核驱动(如ixgbe) - 查DPDK文档确认该设备ID是否在
net_i40e、net_ice等PMD的supported_nics列表中 - 不支持的网卡强行加载PMD,
rte_eth_dev_configure()会返回-ENODEV
绑定网卡到UIO或VFIO用户态驱动
DPDK不能直接操作硬件,必须让内核把网卡控制权移交用户空间。这步失败,后续所有PMD调用都会因设备不可见而报错。
关键区别:igb_uio是旧方案(仅支持MSI-X中断,需禁用IOMMU),vfio-pci是新标准(强制IOMMU开启,安全性更高,DPDK 20.11+默认推荐)。两者绑定命令不同,且内核启动参数必须匹配。
立即学习“C++免费学习笔记(深入)”;
- 若用
vfio-pci:确保内核启动时加了intel_iommu=on iommu=pt(Intel)或amd_iommu=on(AMD) - 绑定前卸载原驱动:
sudo modprobe -r ixgbe(否则dpdk-devbind.py会失败) - 正确绑定命令:
sudo dpdk-devbind.py --bind=vfio-pci 0000:01:00.0,而非--bind=igb_uio - 验证:
sudo dpdk-devbind.py --status中该设备应显示Active且Driver列为vfio-pci
初始化EAL并启用对应PMD模块
EAL(Environment Abstraction Layer)初始化时必须显式加载PMD动态库,否则rte_eth_dev_count_avail()始终为0。DPDK 22.11+默认不内置所有PMD,需手动指定。
常见错误是只传-c 0x3 -n 4,漏掉--vdev或--load-module参数,导致PMD未注册,rte_eth_dev_get_port_by_name()找不到端口。
- 静态链接PMD:编译时加
-d librte_net_i40e.so(CMake)或CONFIG_RTE_LIBRTE_NET_I40E=y(.config) - 运行时加载:启动参数加
--vdev="net_i40e0,mac=00:11:22:33:44:55"(虚拟设备)或确保librte_net_i40e.so在LD_LIBRARY_PATH中 - 检查PMD是否注册:
rte_eal_init()后调用rte_pmd_i40e_init()(仅调试用),或看日志是否有PMD: i40e_driver_init
配置端口时指定轮询队列与亲和核
PMD轮询本质是CPU核心主动读取RX/TX描述符环,不依赖中断。但若没把队列绑定到固定lcore,收包线程可能被调度到其他核,缓存失效、延迟飙升。
典型坑:调用rte_eth_rx_burst(port_id, queue_id, ...)前,没用rte_eth_dev_configure()启用RX队列,或没用rte_eth_dev_adjust_nb_rx_tx_desc()调大描述符数量,导致burst返回0包。
- 必须调用
rte_eth_dev_configure(port_id, nb_rx_q, nb_tx_q, &port_conf)启用队列,nb_rx_q至少为1 - 每个RX队列只能被一个lcore轮询,多核轮询同一队列会触发PMD断言(
rx_queue is already in use) - 收包循环必须绑定到指定核:
while (!force_quit) { nb_rx = rte_eth_rx_burst(0, 0, pkts, MAX_PKT_BURST); },且该线程已用rte_eal_remote_launch()或pthread_setaffinity_np()绑核 - 性能敏感场景:用
RTE_ETH_RX_OFFLOAD_CHECKSUM等offload标志,让网卡做校验和卸载,避免CPU重复计算
最易忽略的是RSS与Flow Director配置——默认情况下单队列只走一个核,即使有8个物理核,rte_eth_rx_burst()也永远只从queue 0收包。要真正发挥多核轮询能力,必须显式配置RSS key和hash function,或用Flow Director分流,否则“轮询”只是单点轮询,吞吐卡死在单核瓶颈上。



















