Introduction

Network throughput is one of the first bottlenecks administrators hit when consolidating workloads onto Proxmox VE. The default virtio NIC model is fast and flexible, but every packet still passes through the host kernel's network stack and QEMU's userspace emulation layer before it reaches a virtual machine. For workloads that need consistent low latency and near-native throughput — software-defined storage nodes, packet-processing appliances, high-frequency trading test rigs, or dense NFV labs — that extra hop matters. Single Root I/O Virtualization (SR-IOV) removes it by letting a single physical network adapter present itself to the host as many lightweight, independent PCIe devices called Virtual Functions (VFs), each of which can be passed directly into a guest.

This article walks through configuring SR-IOV on Proxmox VE 9.x (Debian 13 "Trixie", kernel 6.14/6.17 series) from bare metal to a running virtual machine with a dedicated VF. It covers the BIOS and kernel prerequisites, the exact commands to create and verify VFs, how to make the configuration survive a reboot, how to attach a VF to a guest, and the mistakes that most commonly derail this setup in production.

Problem Overview

SR-IOV is a PCIe specification implemented directly in a device's hardware and firmware. A physical NIC port (the Physical Function, or PF) exposes a configurable number of Virtual Functions. Each VF is a cut-down PCIe function with its own MAC address, its own set of TX/RX queues, and its own Base Address Registers, but it shares the physical port's MAC/PHY layer and, in most cases, its firmware and driver logic with the PF. Because a VF appears to the operating system as an independent PCI device, it can be handed to a KVM guest with the standard PCI passthrough mechanism (VFIO), giving that guest direct hardware access without the host's virtual switch or QEMU network emulation sitting in the data path.

On Proxmox VE this matters most for three groups of workloads: latency-sensitive virtual appliances (firewalls, routers, load balancers), storage or Ceph-adjacent VMs that saturate a 10/25/40GbE link with virtio-net's CPU overhead, and telco/NFV labs that specifically need to test SR-IOV-aware guest drivers. The trade-off is that SR-IOV sacrifices some of virtualization's conveniences — live migration, the software firewall, and VLAN-aware bridging all get more complicated once a VF is passed straight through.

Symptoms

Administrators usually arrive at SR-IOV after observing one or more of the following:

  • High ksoftirqd or vhost-* CPU usage on the Proxmox host correlating with network-heavy VMs, even though the guest itself reports low CPU load.
  • Latency jitter in the guest's network stack that disappears when the same workload runs on bare metal.
  • Throughput on a 10GbE or faster link plateauing well below line rate under virtio-net, particularly with many small packets (high PPS workloads).
  • A need to expose hardware NIC offload features (checksum offload, RSS, SR-IOV-aware VLAN tagging) directly to a guest OS or a network function VM that expects to see a real NIC.
  • Existing GPU or PCI passthrough already working on the host, prompting the question of whether the same VFIO mechanism can be extended to networking hardware.

Root Cause

The underlying cause is architectural, not a misconfiguration: any purely software-emulated or even paravirtualized (virtio) NIC requires the hypervisor to intercept, queue, and forward every packet, consuming host CPU cycles and adding scheduling latency. virtio-net is efficient compared to full device emulation, but it cannot eliminate that hop. SR-IOV bypasses it by giving the guest direct, hardware-enforced access to a slice of the physical adapter. The VF's DMA and interrupts are remapped by the IOMMU (Intel VT-d or AMD-Vi) directly to the guest, so packets move between the NIC and guest memory without the host CPU touching the payload.

Enabling this requires three things to be true simultaneously: the physical NIC and its firmware must support SR-IOV, the platform (CPU, chipset, and often BIOS/UEFI settings) must support IOMMU with interrupt remapping, and the Proxmox VE kernel must have IOMMU and VFIO enabled at boot. If any one of these is missing, VF creation either fails silently, produces VFs that cannot be isolated into their own IOMMU group, or results in a passthrough attempt that Proxmox rejects at VM start.

Diagnosis

Before changing any configuration, confirm the hardware and current host state.

Check whether the CPU exposes virtualization and IOMMU extensions:

egrep -c '(vmx|svm)' /proc/cpuinfo

Confirm IOMMU is active once you've enabled it in the kernel command line (see Step-by-Step Solution below):

dmesg | grep -e DMAR -e IOMMU

You should see lines indicating IOMMU is enabled and, on Intel platforms, that DMAR (DMA Remapping) tables were parsed. On AMD platforms look for AMD-Vi entries instead.

Identify the physical NIC and confirm it advertises SR-IOV capability:

lspci -nn | grep -i ethernet
lspci -vvv -s 0000:01:00.0 | grep -A 3 "Single Root I/O Virtualization"

If the Single Root I/O Virtualization (SR-IOV) capability block is present, the card supports it at the hardware level. Note the Total VFs value reported — this is the ceiling the firmware allows, and it varies by card and firmware version (commonly 4 to 64 on server-grade Intel X710/E810 or Broadcom NetXtreme adapters).

Finally, check IOMMU groups to confirm the NIC's PF (and, once created, its VFs) sit in their own isolated group, since Proxmox will refuse to pass through a device that shares a group with unrelated hardware unless every device in that group is assigned together:

find /sys/kernel/iommu_groups/ -maxdepth 2 -name '*:*' | sort -V

Step-by-Step Solution

1. Enable SR-IOV support in BIOS/UEFI

On many server boards, SR-IOV must be explicitly enabled in firmware before the OS-level configuration has any effect — look for settings named SR-IOV Support, PCIe ARI, or similar under the PCI/chipset configuration menu, alongside VT-d (Intel) or SVM Mode / IOMMU (AMD). Some platforms also require SR-IOV to be enabled per PCIe root port; consult the board's manual if the capability doesn't appear after enabling it globally.

2. Enable IOMMU on the kernel command line

Proxmox VE 9 boots either via GRUB or via systemd-boot/proxmox-boot-tool, depending on whether the root filesystem is on ZFS or a plain partition. Check which one applies:

proxmox-boot-tool status

If it reports boot entries managed by proxmox-boot-tool, edit /etc/kernel/cmdline and add the IOMMU parameters to the existing line:

root=ZFS=rpool/ROOT/pve-1 boot=zfs intel_iommu=on iommu=pt

Then refresh the boot entries:

proxmox-boot-tool refresh

If instead the host boots via classic GRUB, edit /etc/default/grub and set:

GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt"

Then regenerate the GRUB configuration:

update-grub

On AMD platforms, replace intel_iommu=on with amd_iommu=on. The iommu=pt (passthrough) flag is recommended because it leaves devices not being passed through running at native DMA performance, only routing translation for devices actually assigned to VFIO.

3. Load the VFIO kernel modules

Add the following modules to /etc/modules so they load at every boot:

vfio
vfio_iommu_type1
vfio_pci

Rebuild the initramfs so the modules are available early enough in the boot process:

update-initramfs -u -k all

Reboot the host, then re-run the dmesg check from the Diagnosis section to confirm IOMMU is active.

4. Create Virtual Functions on the physical NIC

With IOMMU confirmed active, create VFs against the PF's PCI address. Using ixgbe (Intel 82599/X520) as an example, first check the driver-imposed maximum, then create VFs dynamically through sysfs — this works on any modern SR-IOV-capable driver (ixgbe, i40e, ice, mlx5_core, bnxt_en, and others) without a reboot:

cat /sys/bus/pci/devices/0000:01:00.0/sriov_totalvfs
echo 4 > /sys/bus/pci/devices/0000:01:00.0/sriov_numvfs

Confirm the VFs appeared:

lspci -nn | grep -i "Virtual Function"

Each VF now has its own PCI bus address (for example 01:10.0, 01:10.1, and so on) and its own IOMMU group. Verify isolation with the same find /sys/kernel/iommu_groups/ command used earlier — each VF should appear alone in its group.

5. Persist the VF count across reboots

sriov_numvfs is a runtime setting and resets to zero on reboot. The most reliable way to persist it on a Proxmox host is a pre-up hook on the physical interface's stanza in /etc/network/interfaces, since that file is already read early during network bring-up on every boot. See the Configuration Examples section for the exact stanza.

6. Attach a Virtual Function to a VM

Once a VF exists as its own PCI device, assign it to a guest exactly like any other PCI passthrough device, either via the GUI (VM → Hardware → Add → PCI Device, selecting the VF's address as a Raw Device) or from the CLI:

qm set 100 -hostpci0 0000:01:10.0,pcie=1

Start the VM and confirm the guest OS sees the adapter as a native NIC, then install the vendor driver appropriate for the VF inside the guest (Intel's iavf/i40evf, Mellanox's mlx5_core, etc.) if it isn't already bundled with the guest kernel.

Commands

PurposeCommand
Check CPU virtualization extensionsegrep -c '(vmx|svm)' /proc/cpuinfo
Confirm IOMMU is activedmesg | grep -e DMAR -e IOMMU
List PCI devices with vendor/device IDslspci -nn
Check SR-IOV capability on a NIClspci -vvv -s <addr> | grep -A 3 "Single Root I/O Virtualization"
Show driver-reported max VFscat /sys/bus/pci/devices/<addr>/sriov_totalvfs
Create VFs at runtimeecho N > /sys/bus/pci/devices/<addr>/sriov_numvfs
Remove VFsecho 0 > /sys/bus/pci/devices/<addr>/sriov_numvfs
List created VFslspci -nn | grep -i "Virtual Function"
Check IOMMU group membershipfind /sys/kernel/iommu_groups/ -maxdepth 2 -name '*:*' | sort -V
Refresh boot entries (ZFS/systemd-boot hosts)proxmox-boot-tool refresh
Regenerate GRUB config (non-ZFS boot)update-grub
Rebuild initramfs after module changesupdate-initramfs -u -k all
Assign a VF to a VMqm set <vmid> -hostpci0 <pci-addr>,pcie=1
Show a VM's PCI passthrough configqm config <vmid> | grep hostpci

Configuration Examples

Kernel command line for an Intel host booting via proxmox-boot-tool (/etc/kernel/cmdline):

root=ZFS=rpool/ROOT/pve-1 boot=zfs intel_iommu=on iommu=pt

Equivalent GRUB configuration for an AMD host (/etc/default/grub):

GRUB_CMDLINE_LINUX_DEFAULT="quiet amd_iommu=on iommu=pt"

VFIO module loading (/etc/modules):

vfio
vfio_iommu_type1
vfio_pci

Persisting VF creation through a pre-up hook in /etc/network/interfaces, applied to the physical interface associated with 0000:01:00.0 (adjust the interface name and PCI address for your hardware):

auto enp1s0f0
iface enp1s0f0 inet manual
    pre-up echo 4 > /sys/bus/pci/devices/0000:01:00.0/sriov_numvfs

VM configuration snippet (/etc/pve/qemu-server/100.conf) showing a VF passed through alongside the default virtio management NIC:

net0: virtio=BC:24:11:AA:BB:CC,bridge=vmbr0
hostpci0: 0000:01:10.0,pcie=1

Driver-level VF limit set via modprobe options for cards where sysfs control is not exposed (adjust the driver name and parameter to match your NIC's driver documentation):

options ixgbe max_vfs=4

After creating a file like the one above under /etc/modprobe.d/, rebuild the initramfs with update-initramfs -u -k all and reboot for it to take effect.

Common Mistakes

  • Forgetting that sriov_numvfs is not persistent. Administrators create VFs manually with echo, confirm everything works, then find the VFs gone after the next reboot because nothing wrote the setting back at boot time.
  • Enabling IOMMU in the kernel but not in BIOS/UEFI, or vice versa. Both layers must agree; a kernel-side intel_iommu=on with VT-d disabled in firmware produces no IOMMU groups at all, and dmesg will show no DMAR entries.
  • Assuming every NIC that has an SR-IOV-capable chipset actually has it enabled in its firmware. Some OEM cards ship with SR-IOV locked off until a vendor-specific NVM/firmware update or configuration utility enables it.
  • Passing through the PF instead of a VF. This removes the NIC from the host entirely (including for other VFs' link status in some drivers) rather than sharing it across multiple guests, which defeats the purpose of SR-IOV.
  • Expecting live migration to work unchanged. A VM with a hostpci-assigned VF cannot be live-migrated in the same way as a VM using only virtio devices; the passthrough device has to be manually detached before migration and reattached afterward, or the workload needs to tolerate a brief network interruption.
  • Ignoring IOMMU group isolation. If a VF shares an IOMMU group with an unrelated device (common on some consumer or older server chipsets lacking ACS support), Proxmox will refuse to assign it, or assigning it will inadvertently expose sibling devices to the guest.
  • Overcommitting VFs beyond what the workload's aggregate link needs. All VFs on a port share the same physical bandwidth; creating the maximum VF count and assigning heavy-throughput VMs to several of them can produce contention that looks like a driver bug but is simply bandwidth oversubscription.
  • Not updating NIC firmware before troubleshooting. Several early SR-IOV bugs (dropped VLAN tags, VF reset hangs) were fixed in vendor firmware/driver updates rather than in the kernel or Proxmox itself.

Best Practices

  • Keep at least one NIC or bonded pair dedicated to host management and the Proxmox cluster network (corosync) separate from the SR-IOV-enabled adapter, so a VF misconfiguration can never take down cluster communication.
  • Standardize the VF count per port across identical hosts in a cluster so that VM configurations referencing hostpciN addresses remain portable when planning manual VM relocation.
  • Document the PCI address to physical port mapping for each host, since VF addresses can shift if the VF count changes; a quick lspci -nn | grep -i ethernet combined with the switch port label prevents guesswork during maintenance.
  • Where the workload can tolerate it, prefer iommu=pt over full remapping for devices that are not being passed through, to avoid unnecessary DMA translation overhead on the rest of the host's I/O.
  • Test IOMMU group isolation on new hardware models before relying on SR-IOV in production; consumer-grade motherboards and some early server platforms lack ACS support and place unrelated devices in the same group.
  • Monitor VF-level statistics from the host (where the driver exposes them, e.g. ip -s link show enp1s0f0 or vendor tooling) in addition to guest-side monitoring, since VF errors sometimes only surface in host driver counters.
  • Pin down NIC firmware and driver versions as part of your host build documentation; SR-IOV behavior is far more firmware-dependent than most other Proxmox features.
  • Plan for the migration limitation explicitly: for workloads that need both SR-IOV performance and high availability, consider whether a VirtIO fallback interface with manual failover, or accepting a short outage during planned migration, fits your SLA better than forcing live migration.

FAQ

Does every NIC support SR-IOV?

No. SR-IOV must be implemented in the adapter's silicon and firmware. Most server-class Intel (X520, X540, X710, E810), Mellanox/NVIDIA ConnectX, and Broadcom NetXtreme adapters support it; many consumer and entry-level NICs do not. Confirm with the lspci -vvv capability check before planning around it.

Can I use SR-IOV and a Linux bridge on the same physical NIC?

Not on the same port for the portion of bandwidth allocated to VFs handed to guests — once a VF is passed through, that slice of the adapter bypasses the host's bridge entirely. You can still use the PF itself, or unused VFs left on the host, for bridged traffic if the driver and card support mixing both modes.

Do SR-IOV VFs support VLAN tagging?

Many drivers allow you to set a VLAN on a VF from the host side (driver- and vendor-specific tooling, separate from Proxmox VE itself), which the hardware then enforces transparently to the guest. Consult your NIC vendor's driver documentation for the exact mechanism, since this is implemented outside of Proxmox VE's own configuration surface.

Why does my VM fail to start after I assign a VF?

The most common causes are an IOMMU group that includes other devices not also assigned to the VM, a VF that no longer exists because sriov_numvfs reset after a reboot, or a stale PCI address in the VM configuration after the VF count was changed. Re-run the diagnosis commands to confirm the VF is present and isolated before retrying.

Is SR-IOV worth it for a homelab?

It depends on the NIC. If you already own SR-IOV-capable hardware (common on used enterprise 10GbE cards), it's a good way to learn the IOMMU/VFIO stack and can meaningfully reduce CPU overhead for a router/firewall VM. For most homelab throughput needs below a few gigabit, virtio-net is simpler to operate and sufficient.

Can I combine SR-IOV with Proxmox VE's software-defined networking (SDN) features?

A VF passed directly into a guest bypasses the host's virtual networking stack, so SDN zones, VNets, and the Proxmox firewall do not apply to that VF's traffic. Keep SR-IOV workloads on their own physical segment and apply any required filtering either in the guest or on the upstream physical switch.

Conclusion

SR-IOV on Proxmox VE turns a single physical NIC into multiple hardware-isolated virtual adapters, cutting the host CPU and latency overhead that comes with software-emulated networking. Getting there reliably means treating it as a stack of dependent layers — BIOS/UEFI support, kernel IOMMU parameters, the VFIO modules, and finally driver-level VF creation — and verifying each layer before moving to the next rather than assuming success. The commands and configuration shown here (kernel cmdline changes, /etc/modules, sysfs VF creation, and the /etc/network/interfaces persistence hook) reflect the standard, driver-agnostic workflow that applies across Intel, AMD, Mellanox, and Broadcom SR-IOV-capable adapters on current Proxmox VE 9.x hosts. Once the VFs are stable and correctly isolated in their own IOMMU groups, attaching them to guests is identical to any other PCI passthrough device, giving latency-sensitive and high-throughput VMs near-native network performance without giving up the rest of the host's virtualized workloads.