4. DPDK轮询模式驱动PMD初始化
任务目标
编写一个基于DPDK的最小程序,完成EAL初始化、端口探测,并打印检测到的端口数量及每个端口的MAC地址。该程序用于验证DPDK PMD驱动是否成功绑定网卡并能够被应用层访问。
环境依赖
- DPDK版本:20.11或更高(建议使用LTS版本)
- 编译依赖:
meson、ninja、pkg-config - 运行权限:root用户或具有
CAP_SYS_ADMIN权限,且需要大页内存配置 - 网卡绑定:目标网卡需绑定到
igb_uio/vfio-pci驱动(示例使用vfio-pci)
完整实现代码
#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_ether.h>
#include <stdio.h>
#include <stdint.h>
#define MAX_PORTS 16
int main(int argc, char *argv[])
{
int ret;
uint16_t port_id;
uint16_t nb_ports;
struct rte_ether_addr addr;
/* 1. 初始化EAL环境 */
ret = rte_eal_init(argc, argv);
if (ret < 0) {
fprintf(stderr, "EAL初始化失败: %s\n", rte_strerror(rte_errno));
return -1;
}
/* 2. 探测可用端口数量 */
nb_ports = rte_eth_dev_count_avail();
printf("检测到 %u 个可用DPDK端口\n", nb_ports);
if (nb_ports == 0) {
printf("未检测到端口,请检查网卡绑定状态\n");
rte_eal_cleanup();
return 0;
}
/* 3. 遍历所有端口,打印MAC地址 */
for (port_id = 0; port_id < nb_ports && port_id < MAX_PORTS; port_id++) {
/* 获取端口MAC地址(无需先启动设备) */
ret = rte_eth_macaddr_get(port_id, &addr);
if (ret != 0) {
fprintf(stderr, "获取端口 %u MAC地址失败: %s\n",
port_id, rte_strerror(rte_errno));
continue;
}
printf("端口 %u MAC地址: %02X:%02X:%02X:%02X:%02X:%02X\n",
port_id,
addr.addr_bytes[0], addr.addr_bytes[1],
addr.addr_bytes[2], addr.addr_bytes[3],
addr.addr_bytes[4], addr.addr_bytes[5]);
}
/* 4. 清理EAL环境 */
rte_eal_cleanup();
return 0;
}
编译与运行
# 编译(假设使用pkg-config获取DPDK编译参数)
gcc -o pmd_probe pmd_probe.c $(pkg-config --cflags --libs libdpdk)
# 运行前准备:绑定网卡到vfio-pci驱动
modprobe vfio-pci
dpdk-devbind.py --bind=vfio-pci 0000:03:00.0 # 替换为实际PCI地址
# 配置大页内存(示例:2GB)
echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
mkdir -p /mnt/huge
mount -t hugetlbfs pagesize=2MB /mnt/huge
# 运行程序
./pmd_probe --file-prefix=pmd_probe --huge-dir=/mnt/huge
验证方法与判定标准
- 编译通过:上述gcc命令无报错,生成可执行文件
pmd_probe。 - 运行成功:程序输出包含“检测到 N 个可用DPDK端口”,其中N≥1。
- MAC地址正确:输出的MAC地址与网卡物理地址一致(可通过
ip link命令对比确认)。 - 退出码为0:程序正常执行完毕,无错误信息输出。
常见问题排查
- EAL初始化失败:检查是否以root运行、大页内存是否挂载、
--file-prefix是否与其他DPDK进程冲突。 - 端口数为0:使用
dpdk-devbind.py --status确认网卡已绑定到vfio-pci或igb_uio驱动。 - MAC获取失败:部分虚拟网卡(如virtio-net)在未启动设备前无法获取MAC,可尝试先调用
rte_eth_dev_configure和rte_eth_dev_start后再获取。