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"
运行步骤
- 确认网卡PCI地址:
lspci | grep Ethernet(如01:00.0对应地址0000:01:00.0) - 执行绑定脚本:
sudo ./vfio_bind.sh 0000:01:00.0 - 若需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。
上图展示了绑定完成后数据路径:网卡硬件中断和MMIO区域通过IOMMU组映射到用户态,DPDK程序通过/dev/vfio/N设备节点直接操作网卡,无需经过内核网络协议栈。