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

验证方法与判定标准

  1. 编译通过:上述gcc命令无报错,生成可执行文件pmd_probe。
  2. 运行成功:程序输出包含“检测到 N 个可用DPDK端口”,其中N≥1。
  3. MAC地址正确:输出的MAC地址与网卡物理地址一致(可通过ip link命令对比确认)。
  4. 退出码为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后再获取。