3. DPDK绑定网卡到VFIO驱动

任务目标

将物理网卡从内核驱动解绑并绑定到VFIO驱动,使DPDK用户态程序能够直接接管该网卡。完成后需验证网卡已归属于正确的IOMMU组,且VFIO设备文件可被用户态访问。

环境要求

  • Linux内核版本 ≥ 3.6(建议4.15+),支持VFIO
  • CPU和主板支持IOMMU(Intel VT-d或AMD-Vi)
  • DPDK已编译(本案例使用DPDK 21.11+,路径以$RTE_SDK指代)
  • 目标网卡不支持SR-IOV时,需确认其支持VFIO直通(多数Intel 82599/XL710、Mellanox CX系列均可)

关键实现

VFIO绑定涉及内核参数、驱动模块和DPDK工具链三部分。以下脚本按顺序完成全部配置,并输出验证所需的关键状态。

#!/bin/bash
# vfio_bind.sh - 将指定PCI网卡绑定到VFIO驱动
# 用法: sudo ./vfio_bind.sh 0000:01:00.0

set -e
PCI="$1"
if [ -z "$PCI" ]; then
    echo "用法: $0 <PCI地址,如 0000:01:00.0>"
    exit 1
fi

# 1. 检查IOMMU是否启用
if [ ! -d /sys/kernel/iommu_groups ]; then
    echo "错误: IOMMU未启用。请在内核命令行添加 intel_iommu=on iommu=pt 后重启。"
    exit 1
fi

# 2. 加载VFIO内核模块
modprobe vfio-pci || { echo "加载vfio-pci失败"; exit 1; }

# 3. 获取网卡当前驱动和IOMMU组
CUR_DRV=$(basename $(readlink /sys/bus/pci/devices/$PCI/driver) 2>/dev/null || echo "无")
IOMMU_GROUP=$(readlink /sys/bus/pci/devices/$PCI/iommu_group | awk -F'/' '{print $NF}')
echo "当前驱动: $CUR_DRV, IOMMU组: $IOMMU_GROUP"

# 4. 解绑旧驱动
if [ -n "$CUR_DRV" ] && [ "$CUR_DRV" != "vfio-pci" ]; then
    echo "$PCI" > /sys/bus/pci/drivers/$CUR_DRV/unbind
    echo "已从 $CUR_DRV 解绑"
fi

# 5. 获取并写入VFIO vendor/device ID
VENDOR=$(cat /sys/bus/pci/devices/$PCI/vendor | sed 's/^0x//')
DEVICE=$(cat /sys/bus/pci/devices/$PCI/device | sed 's/^0x//')
echo "$VENDOR $DEVICE" > /sys/bus/pci/drivers/vfio-pci/new_id
echo "已写入VFIO ID: $VENDOR $DEVICE"

# 6. 绑定到VFIO
echo "$PCI" > /sys/bus/pci/drivers/vfio-pci/bind
echo "绑定完成"

# 7. 验证结果
sleep 1
NEW_DRV=$(basename $(readlink /sys/bus/pci/devices/$PCI/driver))
echo "绑定后驱动: $NEW_DRV"
ls -l /dev/vfio/$IOMMU_GROUP
echo "VFIO设备节点: /dev/vfio/$IOMMU_GROUP"

运行步骤

  1. 确认网卡PCI地址:lspci | grep Ethernet(如01:00.0对应地址0000:01:00.0)
  2. 执行绑定脚本:sudo ./vfio_bind.sh 0000:01:00.0
  3. 若需DPDK自动绑定,可改用DPDK自带工具:$RTE_SDK/usertools/dpdk-devbind.py --bind=vfio-pci 0000:01:00.0

验证方法

执行以下命令确认绑定成功:

# 检查驱动归属
lspci -ks 0000:01:00.0
# 预期输出: Kernel driver in use: vfio-pci

# 检查IOMMU组设备节点
ls /dev/vfio/
# 预期输出: 包含对应IOMMU组号(如 16)和 vfio 控制节点

# 检查设备访问权限
ls -l /dev/vfio/16
# 预期输出: crw------- 1 root root ... /dev/vfio/16

通过条件:lspci显示驱动为vfio-pci,且/dev/vfio/<组号>存在。若运行DPDK程序时使用非root用户,需将设备节点权限改为当前用户(chmod 666 /dev/vfio/16)或配置udev规则。

常见问题

  • IOMMU组为空:确认BIOS中开启VT-d,且内核命令行包含intel_iommu=on iommu=pt。
  • 绑定失败提示Device or resource busy:先检查该网卡是否已被其他进程占用(如内核驱动eth0接口),执行ip link set eth0 down后再试。
  • 多网口网卡:同一PCI地址下的所有物理功能(PF)会共享IOMMU组,需全部解绑后才能绑定VFIO。
VFIO绑定流程与数据路径 内核驱动 (igb/ixgbe) 解绑 (unbind) vfio-pci 驱动 IOMMU Group /dev/vfio/16 (设备节点) IOMMU 地址翻译 物理网卡 MMIO/中断 直通映射 DPDK 用户态程序 (通过 /dev/vfio/N 访问)

上图展示了绑定完成后数据路径:网卡硬件中断和MMIO区域通过IOMMU组映射到用户态,DPDK程序通过/dev/vfio/N设备节点直接操作网卡,无需经过内核网络协议栈。