什么是 SR-IOV?SR-IOV 是 Single Root I/O Virtualization 的缩写。Intel 提出来 SR-IOV 这个东西。SR-IOV最初应用在网卡上。简单的说,就是一个物理网卡可以虚拟出来多个轻量化的 PCI-e 物理设备,从而可以分配给虚拟机使用。启用 SR-IOV 的这个功能,将大大减轻宿主机的 CPU 负荷,提高网络性能,降低网络时延等。
本文是根据我自己的设备,查阅了相关的资料整理记录分享整个过程。如果您浏览到这篇文章,可以给您做一个参考。
开启直通
首先是开启 PVE 的硬件直通功能,使用 nano 编辑器,打开 /etc/default/grub

然后在 GRUB_CMDLINE_LINUX_DEFAULT=”quiet” 后面中加入以下内容
intel_iommu=on iommu=pt pcie_acs_override=downstream,multifunction

完整的代码如下:
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt pcie_acs_override=downstream,multifunction"

然后按Ctrl+x 退出,按Y保存。

引导参数
- iommu=pt:启用 Intel VT-d 或 AMD-Vi 的 IOMMU。这是一种硬件功能,用于管理设备对系统内存的访问。在虚拟化环境中,启用 IOMMU 后,可以将物理设备直通到虚拟机中,以便虚拟机可以直接访问硬件设备。“iommu=pt”不是必须的,PT模式只在必要的时候开启设备的IOMMU转换,可以提高未直通设备PCIe的性能,建议添加。
- initcall_blacklist=sysfb_init:禁用 sysfb_init 内核初始化函数。这个函数通常用于在内核启动过程中初始化系统帧缓冲。在使用 GPU 直通的情况下,这个函数可能会干扰直通操作,因此需要禁用它。
- i915.enable_gvt=1:启用 Intel GVT-g 虚拟 GPU 技术。这个选项用于创建一个虚拟的 Intel GPU 设备,以便多个虚拟机可以共享物理 GPU 设备。启用 GVT-g 需要在支持虚拟 GPU 的 Intel CPU 和主板上运行,并且需要正确配置内核和虚拟机。想开启GVT-g的就添加这条,显卡直通的就不要添加了。
- initcall_blacklist=sysfb_init:屏蔽掉pve7.2以上的一个bug,方便启动时候就屏蔽核显等设备驱动;
- pcie_acs_override=downstream,multifunction:便于iommu每个设备单独分组,以免直通导致物理机卡死等问题
- multifunction:允许覆盖多功能 PCIe 设备的 ACS 规则,支持单独直通设备的某一个功能(如仅直通网卡的 VF 功能,不影响其他功能);
- pci=nommconf:意思是禁用pci配置空间的内存映射,所有的 PCI 设备都有一个描述该设备的区域(您可以看到lspci -vv),访问该区域的最初方法是通过 I/O 端口,而 PCIe 允许将此空间映射到内存以便更简单地访问。
更新引导
grub 修改完成后执行以下命令对引导进行更新。
update-grub

添加模块
编辑 /etc/modules 文件将以下模块加入。(核心作用是 让 Linux 系统开机时自动加载 VFIO 相关驱动,为 PCIe 设备硬件直通提供基础支持,是虚拟化(KVM/QEMU)、容器高性能网络等场景的关键配置。)
vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd

模块参数
- VFIO:(Virtual Function I/O)是 Linux 内核提供的一套 用户态 I/O 虚拟化框架,核心能力是:将物理 PCIe 设备(或 SR-IOV 虚拟功能 VF)从内核驱动 “解绑”,直接暴露给用户态程序(如虚拟机、容器),实现 “硬件级直通”—— 用户态程序可绕过内核协议栈,直接操作硬件设备,大幅降低延迟、提升 I/O 性能(对比传统虚拟化的 “软件模拟 I/O”)。
- vfio_iommu_type1:IOMMU 核心驱动(基础中的基础),核心功能:实现 Type-1 IOMMU(输入输出内存管理单元)的虚拟化支持,是 VFIO 框架的 “地基”。关键作用:地址转换:将虚拟机 / 用户态程序的 “虚拟地址” 转换为硬件可识别的 “物理地址”,确保设备能正确访问内存;隔离与安全:为不同虚拟机 / 设备划分独立的内存地址空间,避免相互干扰(比如虚拟机 A 无法访问虚拟机 B 的内存);中断重映射:将硬件设备的中断请求(IRQ)重定向到对应的虚拟机,确保虚拟机能正常响应设备事件(如网卡接收数据、磁盘完成读写)。注意:该模块依赖主板 BIOS/UEFI 启用 IOMMU 功能(Intel 叫 VT-d,AMD 叫 AMD-Vi),否则加载失败。
- vfio_pci:PCIe 设备直通驱动(设备与 VFIO 桥梁),核心功能:专门用于管理 PCIe 设备的 VFIO 驱动,负责将 PCIe 设备(物理网卡 PF、虚拟网卡 VF、显卡等)从默认内核驱动(如网卡的 e1000e、ixgbe 驱动)“解绑”,并挂载到 VFIO 框架下。关键作用:设备解绑 / 绑定:比如将 SR-IOV 虚拟网卡 VF 从内核网络驱动中解绑,避免内核占用设备;资源暴露:将 PCIe 设备的配置空间、I/O 端口、中断资源等暴露给 VFIO 框架,让用户态程序(如 KVM)能直接操作;兼容性适配:处理 PCIe 设备的热插拔、复位等操作,确保直通后设备稳定运行。关联场景:之前你配置的 SR-IOV VF(虚拟网卡),要想分配给虚拟机 / 容器,必须通过 vfio_pci 驱动绑定。
- vfio_virqfd:中断优化驱动(提升直通性能),核心功能:提供 “虚拟中断文件描述符(virqfd)” 机制,优化设备直通后的中断处理效率。关键作用:减少中断延迟:传统中断处理需要内核转发,而 vfio_virqfd 允许用户态程序(如 KVM)通过文件描述符直接接收设备中断,跳过内核中间层,降低延迟;提升并发性能:支持批量处理中断请求,适合高并发场景(如 SR-IOV VF 承载高流量网络传输、显卡渲染高帧率画面);稳定性保障:避免中断风暴(大量无效中断占用资源),优化中断触发逻辑。
重建内核
完成后执行以下命令,主要作用是重建系统中所有内核对应的初始化内存文件系统(initramfs),确保内核与硬件驱动、启动配置的兼容性,避免启动故障。
update-initramfs -u -k all

重启设备
#重启 PVE
reboot

网卡信息
开启网卡的 SR-IOV,查看网卡是否支持 SR-IOV,执行以下命令,获取网卡的 PCIe 总线地址(02:00.0 对应格式:总线号:设备号.功能号)
lspci | grep -i eth

根据对应 PCIe 总线地址输入以下命令,输出内容有 SR-IOV 相关则表示该网卡支持开启 SR-IOV 功能。
lspci -s 02:00.0 -v

另外一种方法,使用 ip a 命令查询网卡信息,然后将以下命令中的 eno1 替换进行查看。
cat /sys/class/net/eno1/device/sriov_totalvfs
命令执行后查看输出结果,我的输出结果是63,代表可以开启63个虚拟网卡。

创建文件
确认可以开启 SR-IOV 后,直接新建一个网卡 SR-IOV 的服务文件,文件名字自己定义,我的是 sriov-eno1.service 名字包含了网卡名称,方便自己记忆。
配置文件中的 /usr/bin/echo 10 数字10为要虚拟的网卡数量;/sys/devices/pci0000:00/0000:00:1b.4/0000:02:00.0 为网卡的 PCIe 总线地址,可以通过以下方式获得。还需要注意将 eno1 修改为你自己的网卡地址。#set VF MAC 和 #set VF up中条目数和你虚拟的网卡数量一致。#set VF MAC 条目中的 MAC 地址可以自定义。
#列出网卡接口
ip addr show
#读取符号链接的目标路径
readlink -f /sys/class/net/eno1

nano /etc/systemd/system/sriov-eno1.service
在文件中填入以下内容。
[Unit]
Description=Script to enable SR-IOV on boot
[Service]
Type=simple
#start SR-IOV
ExecStartPre=/usr/bin/bash -c '/usr/bin/echo 10 > /sys/devices/pci0000:00/0000:00:1b.4/0000:02:00.0/sriov_numvfs'
#set VF MAC
ExecStartPre=/usr/bin/bash -c '/usr/bin/ip link set dev eno1 vf 0 mac 00:20:00:00:00:00'
ExecStartPre=/usr/bin/bash -c '/usr/bin/ip link set dev eno1 vf 1 mac 00:20:00:00:00:01'
ExecStartPre=/usr/bin/bash -c '/usr/bin/ip link set dev eno1 vf 2 mac 00:20:00:00:00:02'
ExecStartPre=/usr/bin/bash -c '/usr/bin/ip link set dev eno1 vf 3 mac 00:20:00:00:00:03'
ExecStartPre=/usr/bin/bash -c '/usr/bin/ip link set dev eno1 vf 4 mac 00:20:00:00:00:04'
ExecStartPre=/usr/bin/bash -c '/usr/bin/ip link set dev eno1 vf 5 mac 00:20:00:00:00:05'
ExecStartPre=/usr/bin/bash -c '/usr/bin/ip link set dev eno1 vf 6 mac 00:20:00:00:00:06'
ExecStartPre=/usr/bin/bash -c '/usr/bin/ip link set dev eno1 vf 7 mac 00:20:00:00:00:07'
ExecStartPre=/usr/bin/bash -c '/usr/bin/ip link set dev eno1 vf 8 mac 00:20:00:00:00:08'
ExecStartPre=/usr/bin/bash -c '/usr/bin/ip link set dev eno1 vf 9 mac 00:20:00:00:00:09'
#set PF up
ExecStartPre=/usr/bin/bash -c '/usr/bin/ip link set eno1 up'
#set VF up
ExecStartPre=/usr/bin/bash -c '/usr/bin/ip link set eno1v0 up'
ExecStartPre=/usr/bin/bash -c '/usr/bin/ip link set eno1v1 up'
ExecStartPre=/usr/bin/bash -c '/usr/bin/ip link set eno1v2 up'
ExecStartPre=/usr/bin/bash -c '/usr/bin/ip link set eno1v3 up'
ExecStartPre=/usr/bin/bash -c '/usr/bin/ip link set eno1v4 up'
ExecStartPre=/usr/bin/bash -c '/usr/bin/ip link set eno1v5 up'
ExecStartPre=/usr/bin/bash -c '/usr/bin/ip link set eno1v6 up'
ExecStartPre=/usr/bin/bash -c '/usr/bin/ip link set eno1v7 up'
ExecStartPre=/usr/bin/bash -c '/usr/bin/ip link set eno1v8 up'
ExecStart=/usr/bin/bash -c '/usr/bin/ip link set eno1v9 up'
Restart=on-failure
[Install]
WantedBy=multi-user.target

开机启动
#添加 sriov-eno1.service 开机启动
systemctl enable sriov-eno1.service
#删除 sriov-eno1.service 开机启动,
systemctl disable sriov-eno1.service
#刷新 systemd 配置缓存
systemctl daemon-reload
验证结果
以上设置完毕后,在 PVE 中编辑虚拟机,给虚拟机添加 PCI 设备时就可以看到已经开启 SR-IOV 的网卡

网络互通
以上设置了网卡的 SR-IOV 功能,但是还有个头疼的问题网络互通,以上设置完成后,虚拟网卡(SR-IOV)和 PVE 的网桥(vmbr)不能互通。当 SR-IOV 物理网卡与虚拟网桥(vmbr)绑定后,物理网卡的 FDB(二层转发数据库)可能缺少虚拟机(KVM)、容器(LXC)的 MAC 地址,导致二层流量无法转发表现为能获取 IP 但无法通信。以下的脚本就是解决此问题,自动提取所有 VM / 容器的 MAC 地址 + 对应虚拟网桥的 MAC 地址,批量注册到绑定的 SR-IOV 物理网卡 FDB,确保二层转发正常。
#1、创建脚本文件,添加内容,需要注意的看下面;
nano /usr/local/bin/vf-vmbr-add.sh
#2、赋予执行权限,进入vf-vmbr-add.sh所在目录;
chmod +x vf-vmbr-add.sh
#3、执行脚本,进入vf-vmbr-add.sh所在目录,新增虚拟机时需要再次执行一次;
./vf-vmbr-add.sh
#4、查看 SR-IOV 网卡的 FDB 记录,存在说明成功。将 eno1 修改为自己的网卡名称;
bridge fdb show dev eno1 | grep permanent
#HomeLAB 是我自己的PVE主机名称,修改为你自己的主机名称;
CTCONFDIR=/etc/pve/nodes/HomeLAB/lxc
VMCONFDIR=/etc/pve/nodes/HomeLAB/qemu-server
# 这里填写 SR-IOV 网卡名称,将eno1、eno2修改为你自己的网卡名称;
IFBRIDGES=(“eno1” “eno2”)
# vmbr0 是需要和 SR-IOV 网卡互通的虚拟交换机名称,根据自己的情况修改 ;
LBRIDGES=(“vmbr0” “vmbr1” “vmbr2” “vmbr3”)
将以下内容添加到 vf-vmbr-add.sh 文件中。
#!/usr/bin/bash
#
# vf_add_maddr.sh Version 1.3 Multi-NIC, Multi-Bridge Edition without logging
# 脚本基于kriss35,由Rama、Zimri更新。
# Usage: execute directly without arguments or as a systemd service.
CTCONFDIR=/etc/pve/nodes/HomeLAB/lxc
VMCONFDIR=/etc/pve/nodes/HomeLAB/qemu-server
# Define arrays for IFBRIDGE (SR-IOV enabled NICs) and LBRIDGE (virtual bridges)
IFBRIDGES=("eno1" "eno2") # 这里填写 SR-IOV 网卡名称
LBRIDGES=("vmbr0" "vmbr1" "vmbr2" "vmbr3") # 这里填写需要和 SR-IOV 网卡互通的虚拟交换机
# 逻辑开始
if [ ! -d "$CTCONFDIR" ] || [ ! -d "$VMCONFDIR" ]; then
echo "ERROR: 配置目录未装载!"
exit 1
fi
MAC_LIST_VMS=$(cat ${VMCONFDIR}/*.conf | grep bridge | grep -Eo '([[:xdigit:]]{1,2}[:-]){5}[[:xdigit:]]{1,2}' | tr '[:upper:]' '[:lower:]')
MAC_LIST_VMS+=" $(cat ${CTCONFDIR}/*.conf | grep hwaddr | grep -Eo '([[:xdigit:]]{1,2}[:-]){5}[[:xdigit:]]{1,2}' | tr '[:upper:]' '[:lower:]')"
for (( i=0; i<${#IFBRIDGES[@]}; i++ )); do
IFBRIDGE=${IFBRIDGES[$i]}
LBRIDGE=${LBRIDGES[$i]}
TMP_FILE="/tmp/vf_add_maddr_${IFBRIDGE}_${LBRIDGE}.tmp"
MAC_ADD2LIST="$(cat /sys/class/net/$LBRIDGE/address)"
MAC_LIST="$MAC_LIST_VMS $MAC_ADD2LIST"
/usr/sbin/bridge fdb show | grep "${IFBRIDGE} self permanent" > "$TMP_FILE"
for mactoregister in $MAC_LIST; do
if (grep -Fq "$mactoregister" "$TMP_FILE"); then
:
else
/usr/sbin/bridge fdb add "$mactoregister" dev "${IFBRIDGE}"
fi
done
done
exit 0


如果您想获取这篇文章的最新信息,可以收藏此文章,当文章更新时我们会通过邮件通知您!点击下面的 即可收藏 ↓