Vous activez SR-IOV parce que vous voulez un débit propre et prévisible et une charge CPU réduite. Vous redémarrez, vous echoez un nombre dans
sriov_numvfs, et… rien. Ou pire : des VFs apparaissent, mais l’hôte perd le lien, les invités ne reçoivent pas de paquets, ou les groupes IOMMU
ressemblent à un bol de spaghettis et VFIO refuse de coopérer.
Le premier déploiement SR-IOV est rarement bloqué par « un bug ». Il est bloqué par une chaîne d’hypothèses : paramètres du firmware, options du noyau,
choix de pilotes PF/VF, topologie PCIe, et une « optimisation » innocente qui s’avère être un piège.
SR-IOV en une page (sans contes de fées)
SR-IOV (Single Root I/O Virtualization) permet à un périphérique PCIe d’exposer plusieurs fonctions PCI légères. La fonction physique (PF) est l’interface
« propriétaire ». Les fonctions virtuelles (VFs) sont les « tranches » que vous donnez aux invités ou aux conteneurs (généralement via un passthrough VFIO) ou que vous gérez
sur l’hôte pour le steering du trafic.
La promesse : contourner une partie du switching logiciel, réduire le coût par paquet et obtenir des performances proches du débit ligne avec moins de jitter. Le coût :
vous dépendez désormais du comportement matériel, de la politique firmware, de la topologie PCIe et des attentes strictes des pilotes. Ce n’est pas « difficile », mais c’est
différent. L’état d’esprit pour déboguer ressemble plus à « dépannage HBA de stockage » qu’à « ajustement d’un bridge Linux ».
Sur Debian 13, SR-IOV est principalement une histoire de noyau+pilote+firmware. Debian ne « fait » pas SR-IOV à votre place ; il vous fournit de bons outils pour voir ce qui
se passe. Votre travail est de rendre la plateforme honnête : IOMMU activé, ACS raisonnable, pilote PF stable, et aucune hypothèse magique.
Modèle mental central : trois plans
- Plan de contrôle : boutons sysfs, devlink, ethtool, configuration PF, bascules firmware.
- Plan de données : trajet réel des paquets/IO à l’intérieur de la NIC ; mapping des queues, filtres VLAN/MAC, vérifications anti-spoof.
- Plan d’isolation : IOMMU/VT-d/AMD-Vi, groupes IOMMU, ACS, bindings VFIO, routage des interruptions.
La plupart des tickets « SR-IOV cassé » sont des problèmes du plan d’isolation déguisés en problèmes du plan de données. Le deuxième type le plus courant est constitué
par des valeurs par défaut du plan de contrôle que vous ne connaissiez pas.
Faits intéressants et un peu d’histoire (pour cesser d’accuser le mauvais élément)
-
SR-IOV est une spécification PCI-SIG de la fin des années 2000, née de la douleur des piles de virtualisation gourmandes en CPU faisant transiter du 10GbE et
du trafic stockage via une émulation logicielle. -
« Virtual Function » n’est pas une invention Linux. C’est un numéro de fonction PCIe avec une structure de capacité standardisée.
Linux se contente de l’exposer via sysfs et les pilotes. -
Les premiers déploiements SR-IOV concernaient autant le stockage que le réseau. Les HBA et des conceptions proches de NVMe ont poussé pour des modèles similaires
d’« affectation directe ». -
L’adoption de l’IOMMU a parfois été en retard sur SR-IOV dans de nombreux datacenters. Des gens ont activé des VFs avant d’activer l’isolation DMA,
ce qui vous apprend la différence entre « ça marche » et « c’est sûr ». -
ACS (Access Control Services) est une fonctionnalité PCIe qui contrôle le comportement peer-to-peer. Sans ACS correct, vos groupes IOMMU peuvent être trop larges pour
permettre un passthrough sûr de fonctions individuelles. -
Les pilotes VF exposent souvent volontairement moins de réglages que les pilotes PF. C’est voulu : moins de bords tranchants pour les locataires, et
moins de façons de bloquer le périphérique. -
Certaines NIC implémentent un comportement « de type switch » en interne. Les VFs ne sont pas juste des queues ; il y a du steering interne, du filtrage,
et parfois un peu de logique embarquée. -
SR-IOV n’est pas toujours plus rapide. Pour les petits paquets, la charge CPU hôte peut diminuer ; pour certaines charges, la complexité opérationnelle dépasse
les gains et il vaut mieux utiliser vhost-net/virtio bien réglé.
Comment SR-IOV échoue en conditions réelles
Les échecs SR-IOV se regroupent. Si vous pouvez catégoriser ce que vous observez, vous pouvez cesser d’agir au hasard et commencer à mesurer.
Classe d’échec A : « les VFs n’apparaissent pas »
Vous echoez 8 dans /sys/class/net/<pf>/device/sriov_numvfs et ça renvoie
Invalid argument ou reste silencieusement à zéro. Causes courantes :
- SR-IOV désactivé dans le BIOS/UEFI ou dans le firmware de la NIC (oui, les deux peuvent compter).
- Mauvais pilote PF chargé (inbox vs fournisseur ; ou un pilote de secours sans support SR-IOV).
- Limite firmware : vous avez demandé plus de VFs que le périphérique/port ne supporte.
- Le périphérique est dans un état où les VFs ne peuvent pas être créées (ex. configuré pour un mode en conflit avec la création de VFs).
Classe d’échec B : « les VFs apparaissent, mais le passthrough échoue »
Les périphériques VF apparaissent dans lspci, mais votre hyperviseur ne peut pas les assigner. Ou VFIO se lie, mais QEMU échoue avec des problèmes de groupe IOMMU.
Causes courantes :
- IOMMU non activé au niveau du noyau.
- ACS/groupes IOMMU trop larges ; la VF partage un groupe avec la PF ou d’autres périphériques non liés.
- vfio-pci ne se lie pas, parce qu’un autre pilote a déjà pris la VF.
- Secure Boot ou la politique de verrouillage du noyau bloque VFIO ou le chargement de modules dans certaines configurations.
Classe d’échec C : « pertes de trafic, ARP bizarre, confusion VLAN »
L’invité voit le lien up, peut pinger sa passerelle une fois, puis plus rien. Ou les tags VLAN disparaissent. Ou les réponses ARP ne reviennent pas. Causes courantes :
- La PF applique des politiques anti-spoof/MAC/VLAN et la VF n’est pas configurée en conséquence.
- La sécurité du port du switch rejette plusieurs MACs ; les MACs de vos VFs ne figurent pas dans la liste autorisée.
- Des fonctionnalités d’offload interagissent avec le chemin du switch virtuel de manière surprenante (moins fréquent, mais réel).
Classe d’échec D : « les performances sont pires que virtio »
C’est celui qui rend la direction méfiante. Causes courantes :
- Tempêtes d’interruptions dues à une mauvaise affinité IRQ ou à trop de queues.
- Bifurcation du slot PCIe ou rétrogradation de la vitesse du lien (x8 devient x4, Gen4 devient Gen3).
- Mauvaise correspondance NUMA : la VF est sur un socket, les vCPU de la VM sur un autre.
- Charge à petits paquets où la surcharge par VM ailleurs (firewall, conntrack, verrous applicatifs) domine.
Blague 1 : SR-IOV, c’est comme donner à votre VM sa propre voie sur l’autoroute — jusqu’à ce que vous réalisiez que la bretelle d’accès est encore gérée par un comité.
Playbook de diagnostic rapide (premiers/deuxièmes/troisièmes contrôles)
C’est la séquence que j’utilise quand on me dit « SR-IOV est cassé » et que je veux une réponse utile en moins de 15 minutes. L’objectif est d’identifier
la première couche brisée, pas de tout réparer en une fois.
1) Confirmer que la plateforme peut faire l’isolation (IOMMU + groupes)
- Vérifier IOMMU activé dans la ligne de commande du noyau et dans dmesg.
- Vérifier les groupes IOMMU : pouvez-vous isoler proprement une VF ?
- Si les groupes sont incorrects, arrêtez. Ne continuez pas vers la « mise au point » ou les changements invités.
2) Confirmer que la NIC et le pilote PF supportent réellement SR-IOV
- Vérifier
sriov_totalvfs. - Vérifier le pilote PF et les versions du firmware.
- Créer d’abord un petit nombre de VFs (2), pas 32.
3) Confirmer le binding des VFs et le chemin d’attachement vers l’invité
- S’assurer que les VFs sont liées à vfio-pci lors d’un passthrough ; sinon elles seront liées à un pilote réseau sur l’hôte et vous vous battrez avec udev.
- Confirmer que l’invité voit le périphérique et charge le pilote VF correct.
4) Ce n’est qu’ensuite : sanity check du plan de données
- Sécurité du port switch et règles de trunk VLAN.
- Filtres MAC/VLAN sur la PF pour chaque VF.
- Compteurs de performance et placement des queues/IRQ.
Tâches pratiques : commandes, sorties et décisions (12+)
Ces commandes sont exécutables sur Debian 13. Les sorties montrées sont représentatives. Vos chaînes exactes varieront, mais la logique décisionnelle reste la même.
Task 1: Identify the PF interface and PCI address
cr0x@server:~$ ip -br link
lo UNKNOWN 00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP>
enp129s0f0 UP 3c:fd:fe:12:34:56 <BROADCAST,MULTICAST,UP,LOWER_UP>
enp129s0f1 DOWN 3c:fd:fe:12:34:57 <BROADCAST,MULTICAST>
Ce que ça signifie : enp129s0f0 ressemble à votre PF (un des ports physiques).
Décision : choisissez la PF à partir de laquelle vous créerez des VFs ; n’essayez pas de faire les deux ports en même temps.
cr0x@server:~$ ethtool -i enp129s0f0
driver: mlx5_core
version: 6.1.0
firmware-version: 22.39.2048 (MT_0000000012)
expansion-rom-version:
bus-info: 0000:81:00.0
supports-statistics: yes
supports-test: yes
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: yes
Ce que ça signifie : Vous avez l’adresse bus 0000:81:00.0 et le pilote PF.
Décision : enregistrez l’adresse PCI ; la plupart des opérations SR-IOV et VFIO sont plus faciles quand on pense en IDs PCI.
Task 2: Confirm SR-IOV capability exists and see the VF limit
cr0x@server:~$ cat /sys/class/net/enp129s0f0/device/sriov_totalvfs
64
Ce que ça signifie : La combinaison matériel/pilote peut exposer jusqu’à 64 VFs sur cette PF.
Décision : commencez avec 2 ou 4. Si vous sautez directement à 64 et que ça échoue, vous ne saurez pas si le problème est « SR-IOV cassé » ou « vous avez demandé trop ».
Task 3: Try creating VFs (and handle the two common failure modes)
cr0x@server:~$ cat /sys/class/net/enp129s0f0/device/sriov_numvfs
0
cr0x@server:~$ echo 4 | sudo tee /sys/class/net/enp129s0f0/device/sriov_numvfs
4
cr0x@server:~$ cat /sys/class/net/enp129s0f0/device/sriov_numvfs
4
Ce que ça signifie : Les VFs ont été créées avec succès.
Décision : passez à l’énumération des VFs dans le PCI et mappez-les aux indices VF.
Si ça échoue, vous verrez quelque chose comme :
cr0x@server:~$ echo 4 | sudo tee /sys/class/net/enp129s0f0/device/sriov_numvfs
tee: /sys/class/net/enp129s0f0/device/sriov_numvfs: Invalid argument
4
Ce que ça signifie : Le noyau a rejeté la création des VFs. C’est généralement une politique du pilote/firmware/plateforme, pas une faute de frappe.
Décision : inspecter immédiatement dmesg pour la vraie raison (tâche suivante).
Task 4: Read dmesg for the device-specific error, not generic noise
cr0x@server:~$ sudo dmesg -T | tail -n 30
[Mon Dec 30 09:11:12 2025] mlx5_core 0000:81:00.0: SR-IOV: failed to enable VFs, error: -22
[Mon Dec 30 09:11:12 2025] mlx5_core 0000:81:00.0: hint: SR-IOV disabled in firmware or not enough resources
Ce que ça signifie : Le pilote vous dit qu’il ne peut pas allouer des ressources ou que le firmware bloque.
Décision : vérifiez les paramètres firmware, le mode PF, et assurez-vous de ne pas être dans une configuration NIC restreinte.
Task 5: Verify IOMMU is enabled (this blocks VFIO and safe assignment)
cr0x@server:~$ cat /proc/cmdline
BOOT_IMAGE=/vmlinuz-6.12.0-amd64 root=UUID=8c3d... ro quiet intel_iommu=on iommu=pt
Ce que ça signifie : Les paramètres du noyau demandent Intel IOMMU et le mode pass-through pour les périphériques hôtes.
Décision : si vous ne voyez pas intel_iommu=on (ou amd_iommu=on), ajoutez-le et redémarrez avant de faire du travail VFIO.
cr0x@server:~$ sudo dmesg -T | egrep -i 'DMAR|IOMMU|AMD-Vi' | head -n 20
[Mon Dec 30 09:02:01 2025] DMAR: IOMMU enabled
[Mon Dec 30 09:02:01 2025] DMAR: Host address width 46
[Mon Dec 30 09:02:01 2025] DMAR: DRHD base: 0x000000fed90000 flags: 0x0
[Mon Dec 30 09:02:01 2025] DMAR: Interrupt remapping enabled
Ce que ça signifie : IOMMU et le remapping d’interruptions sont actifs.
Décision : passez au contrôle des groupes ; si le remapping d’interruptions manque, attendez-vous à des comportements MSI/MSI-X étranges sous charge.
Task 6: Inspect IOMMU groups (the “can I isolate a VF?” question)
cr0x@server:~$ for g in /sys/kernel/iommu_groups/*; do \
echo "Group $(basename "$g")"; \
ls -l "$g/devices"; \
done | sed -n '1,60p'
Group 12
total 0
lrwxrwxrwx 1 root root 0 Dec 30 09:03 0000:81:00.0 -> ../../../../devices/pci0000:80/0000:80:01.0/0000:81:00.0
lrwxrwxrwx 1 root root 0 Dec 30 09:03 0000:81:00.1 -> ../../../../devices/pci0000:80/0000:80:01.0/0000:81:00.1
lrwxrwxrwx 1 root root 0 Dec 30 09:03 0000:81:00.2 -> ../../../../devices/pci0000:80/0000:80:01.0/0000:81:00.2
Ce que ça signifie : La PF et les VFs peuvent être dans le même groupe (selon votre listing de périphériques). Ça peut poser problème pour
le passthrough : de nombreuses configurations veulent chaque VF dans son propre groupe.
Décision : si la VF partage un groupe avec la PF ou des périphériques non liés, il vous faudra peut-être des options BIOS ACS, un emplacement de slot différent,
ou accepter que votre plateforme ne permette pas un « nettoyage » de l’affectation par VF.
Task 7: Enumerate the newly created VF PCI functions
cr0x@server:~$ lspci -nn | egrep -i 'Ethernet|Virtual Function|SR-IOV'
81:00.0 Ethernet controller [0200]: Mellanox Technologies MT28908 Family [ConnectX-6] [15b3:101b]
81:00.1 Ethernet controller [0200]: Mellanox Technologies MT28908 Family [ConnectX-6 Virtual Function] [15b3:101c]
81:00.2 Ethernet controller [0200]: Mellanox Technologies MT28908 Family [ConnectX-6 Virtual Function] [15b3:101c]
81:00.3 Ethernet controller [0200]: Mellanox Technologies MT28908 Family [ConnectX-6 Virtual Function] [15b3:101c]
81:00.4 Ethernet controller [0200]: Mellanox Technologies MT28908 Family [ConnectX-6 Virtual Function] [15b3:101c]
Ce que ça signifie : Les VFs existent à 81:00.1 jusqu’à 81:00.4.
Décision : décidez si l’hôte utilisera ces VFs comme netdevs (rare dans des architectures propres) ou si vous les lierez à VFIO pour les invités.
Task 8: Map VF index to PCI address (stop guessing which VF you handed out)
cr0x@server:~$ ip link show enp129s0f0
5: enp129s0f0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 3c:fd:fe:12:34:56 brd ff:ff:ff:ff:ff:ff
vf 0 link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff, spoof checking on, link-state auto, trust off
vf 1 link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff, spoof checking on, link-state auto, trust off
vf 2 link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff, spoof checking on, link-state auto, trust off
vf 3 link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff, spoof checking on, link-state auto, trust off
Ce que ça signifie : Les indices VF existent, mais les MACs ne sont pas définis et trust est off.
Décision : définissez MAC/VLAN/trust volontairement sur la PF avant d’assigner la VF à un invité, sinon vous déboguerez une « instabilité réseau »
qui est en fait une application de politique.
Task 9: Set VF MAC and VLAN policy (or deliberately disable enforcement)
cr0x@server:~$ sudo ip link set enp129s0f0 vf 0 mac 52:54:00:aa:bb:01
cr0x@server:~$ sudo ip link set enp129s0f0 vf 0 vlan 120 qos 0
cr0x@server:~$ sudo ip link set enp129s0f0 vf 0 spoofchk on
cr0x@server:~$ sudo ip link set enp129s0f0 vf 0 trust off
Ce que ça signifie : VF0 ne peut utiliser que le MAC spécifié et le VLAN 120 ; le spoofing est bloqué ; trust est désactivé.
Décision : dans des environnements multi-tenant, gardez le spoof checking activé. Si l’invité doit faire du routage, vous devrez peut-être
trust on (et dans ce cas vous devrez disposer d’un modèle de sécurité en amont cohérent).
Task 10: Bind a VF to vfio-pci (for passthrough) and verify it stuck
cr0x@server:~$ lspci -nnk -s 81:00.1
81:00.1 Ethernet controller [0200]: Mellanox Technologies MT28908 Family [ConnectX-6 Virtual Function] [15b3:101c]
Subsystem: Mellanox Technologies Device [15b3:0058]
Kernel driver in use: mlx5_core
Kernel modules: mlx5_core
Ce que ça signifie : La VF est actuellement liée à un pilote réseau hôte. C’est correct pour une utilisation côté hôte, mais pas pour un passthrough VFIO.
Décision : unbind et bind à vfio-pci, et assurez-vous que cela persiste via une configuration modprobe ou des règles udev.
cr0x@server:~$ sudo modprobe vfio-pci
cr0x@server:~$ echo 0000:81:00.1 | sudo tee /sys/bus/pci/devices/0000:81:00.1/driver/unbind
0000:81:00.1
cr0x@server:~$ echo vfio-pci | sudo tee /sys/bus/pci/devices/0000:81:00.1/driver_override
vfio-pci
cr0x@server:~$ echo 0000:81:00.1 | sudo tee /sys/bus/pci/drivers/vfio-pci/bind
0000:81:00.1
cr0x@server:~$ lspci -nnk -s 81:00.1
81:00.1 Ethernet controller [0200]: Mellanox Technologies MT28908 Family [ConnectX-6 Virtual Function] [15b3:101c]
Subsystem: Mellanox Technologies Device [15b3:0058]
Kernel driver in use: vfio-pci
Kernel modules: mlx5_core
Ce que ça signifie : La VF est maintenant détenue par VFIO et prête pour le passthrough.
Décision : si le bind échoue avec « Device or resource busy », vous avez encore des utilisateurs (comme NetworkManager ou systemd-networkd)
qui la prennent ; arrêtez-les, ou blacklistez le pilote VF pour ces fonctions.
Task 11: Check PCIe link speed/width (your “SR-IOV is slow” smoking gun)
cr0x@server:~$ sudo lspci -vv -s 81:00.0 | egrep -i 'LnkCap|LnkSta'
LnkCap: Port #0, Speed 16GT/s, Width x16, ASPM L1, Exit Latency L1 <64us
LnkSta: Speed 16GT/s (ok), Width x8 (downgraded)
Ce que ça signifie : La carte supporte x16 mais fonctionne en x8. Ça peut être acceptable, ou ça peut vous limiter sous charge.
Décision : si vous attendiez x16 et que vous saturiez, vérifiez le câblage du slot, la bifurcation BIOS, les risers, et si un autre périphérique a volé des lanes.
Task 12: Check NUMA locality (because cross-socket DMA is a silent tax)
cr0x@server:~$ cat /sys/bus/pci/devices/0000:81:00.0/numa_node
1
cr0x@server:~$ lscpu | egrep 'NUMA node1 CPU\(s\)|NUMA node0 CPU\(s\)'
NUMA node0 CPU(s): 0-31
NUMA node1 CPU(s): 32-63
Ce que ça signifie : Votre NIC se trouve sur le nœud NUMA 1.
Décision : épinglez les vCPUs de la VM (et idéalement la mémoire) sur le nœud 1 lorsque vous utilisez des VFs de cette NIC. Sinon, vous mesurerez
la latence et évaluerez accidentellement votre interconnect.
Task 13: Confirm interrupt distribution (the hidden reason CPU spikes)
cr0x@server:~$ grep -E 'mlx5|vfio|enp129s0f0' /proc/interrupts | head -n 12
156: 120345 0 0 0 IR-PCI-MSI 524288-edge mlx5_comp0@pci:0000:81:00.0
157: 98765 0 0 0 IR-PCI-MSI 524289-edge mlx5_comp1@pci:0000:81:00.0
158: 110002 0 0 0 IR-PCI-MSI 524290-edge mlx5_comp2@pci:0000:81:00.0
Ce que ça signifie : Toutes les interruptions arrivent sur le CPU0 (première colonne), ce qui est un classique « on a oublié l’affinité IRQ ».
Décision : répartissez les IRQs sur les CPU locaux au nœud NUMA de la NIC, ou activez irqbalance avec des contraintes raisonnables.
Task 14: Confirm PF isn’t blocking the VF with policy (spoof check, trust, link-state)
cr0x@server:~$ ip link show enp129s0f0 | sed -n '1,12p'
5: enp129s0f0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 3c:fd:fe:12:34:56 brd ff:ff:ff:ff:ff:ff
vf 0 link/ether 52:54:00:aa:bb:01 brd ff:ff:ff:ff:ff:ff, vlan 120, spoof checking on, link-state auto, trust off
Ce que ça signifie : La politique est définie et visible.
Décision : si l’invité envoie des trames taguées sur un autre VLAN, elles seront rejetées. Ce n’est pas un « bug Linux » ; c’est vous qui appliquez une règle que vous aviez oubliée.
Task 15: Confirm the guest sees the VF and loads the right driver (inside the VM)
cr0x@server:~$ lspci -nnk | egrep -A3 -i 'Ethernet|Virtual Function' | head -n 10
00:04.0 Ethernet controller [0200]: Mellanox Technologies MT28908 Family [ConnectX-6 Virtual Function] [15b3:101c]
Subsystem: Mellanox Technologies Device [15b3:0058]
Kernel driver in use: mlx5_core
Kernel modules: mlx5_core
Ce que ça signifie : La VM voit le périphérique VF et a un pilote.
Décision : si la VM voit le périphérique mais aucun pilote ne se lie, il vous manque le support pilote invité ou vous utilisez un noyau/initramfs trop ancien.
Task 16: Check for PCI reset capability issues (common with VFs)
cr0x@server:~$ sudo dmesg -T | egrep -i 'reset|FLR|vfio' | tail -n 20
[Mon Dec 30 09:20:44 2025] vfio-pci 0000:81:00.1: enabling device (0000 -> 0002)
[Mon Dec 30 09:20:44 2025] vfio-pci 0000:81:00.1: not capable of FLR, using PM reset
Ce que ça signifie : La VF peut ne pas supporter le Function Level Reset (FLR). VFIO utilisera d’autres chemins de reset en secours.
Décision : si les VMs échouent au reboot ou au reset à chaud, vous pourriez avoir besoin d’une VF différente, d’un workflow de reset complet de la PF,
ou de règles opérationnelles (« migrer plutôt que redémarrer sous charge »).
Trois mini-récits du monde de l’entreprise (tous assez vrais pour faire mal)
Mini-récit 1 : L’incident causé par une mauvaise hypothèse
Une équipe a déployé SR-IOV pour des services sensibles à la latence. Ils avaient fait les tests en labo : beaux chiffres, graphiques propres, sourires satisfaits. En production,
ils ont passé des VFs à des VMs et tout semblait normal. Lien up, DHCP OK, checks de santé verts. Puis, cinq minutes plus tard, des instances aléatoires sont devenues « à moitié mortes » :
elles pouvaient envoyer du trafic, mais les réponses ne revenaient pas de manière fiable.
La première hypothèse a été que c’était le switch. La seconde, que c’était un problème de cache ARP. La troisième, que c’était une régression du noyau. Chacun avait son fantôme préféré.
Le vrai problème était ennuyeux : le port du switch en amont avait une limitation du nombre de MACs par port définie sur « un MAC par port ». SR-IOV a introduit
plusieurs MACs derrière le même port physique. Le switch n’a pas complètement fermé le port ; il a discrètement supprimé des trames une fois la limite dépassée, ce qui
donnait l’impression d’un hôte instable. Diffentes baies se comportaient différemment car tous les ports n’avaient pas le même profil de sécurité.
La correction a été double : ajuster la sécurité du port switch pour permettre le nombre attendu de MACs (ou utiliser un profil trunk conçu pour la virtualisation),
et mettre en place une vérification préliminaire qui comptait les VFs prévues et comparait au policy du switch. La vraie leçon n’était pas « désactivez la sécurité ».
C’était « arrêtez de supposer que le réseau traite un port serveur comme une identité unique ».
Ils ont aussi appris une leçon sociale : quand vous changez la sémantique d’une interface, vous prenez la responsabilité du rayon d’impact. L’équipe réseau n’a rien cassé ;
l’équipe compute a changé les règles sans les en informer.
Mini-récit 2 : L’optimisation qui s’est retournée contre eux
Une autre organisation a décidé que SR-IOV résoudrait la consommation CPU des hôtes gérant beaucoup de petits flux. Ils ont créé le nombre maximal de VFs par NIC,
« au cas où », et les ont pré-liées à VFIO. Ils ont aussi activé tous les offloads possibles, parce que « la NIC est faite pour ça ».
Le résultat : les temps de boot se sont allongés, et des hôtes ont parfois échoué à démarrer correctement après maintenance. Quand ils démarraient, le monitoring montrait
des pics de latence tous les quelques minutes. L’histoire facile était « SR-IOV est instable », ce qui est devenu un argument politique.
La cause racine s’est révélée être une combinaison de pression sur les ressources et d’interruptions. La création d’un grand nombre de VFs a augmenté la gestion interne du périphérique,
et l’hôte s’est retrouvé avec un bazar d’IRQs par défaut placées sur un petit ensemble de CPUs. Les offloads n’étaient pas universellement mauvais, mais certains interagissaient mal avec
leur pattern de trafic et les pilotes invités. Leur posture « tout optimiser » a créé un système fragile au reboot, imprévisible sous charge, et difficile à déboguer.
Le plan de rollback a été simple : créer seulement le nombre de VFs nécessaire par rôle d’hôte, répartir correctement les IRQs, et n’activer que les offloads testés dans leur environnement.
Leurs performances se sont rétablies — et leur fiabilité s’est améliorée plus que leur p99.
Blague 2 : Si vous créez 64 VFs « juste au cas où », vous avez inventé une nouvelle forme de dette technique : la dette PCIe, payable au reboot.
Mini-récit 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise
Une troisième équipe gérait des charges mixtes : certaines VMs avaient besoin de SR-IOV pour le débit, d’autres allaient très bien avec virtio. Ils ont standardisé une règle opérationnelle :
chaque assignation de VF exigeait une cartographie enregistrée de nom PF → index VF → adresse PCI → VM. Pas d’exceptions.
Les gens se sont plaints. Ça semblait bureaucratique. Ça semblait être du papier pour des ingénieurs qui « savent ce qu’ils font ». Puis un hôte a redémarré après une mise à jour du noyau
et l’ordre d’énumération udev a changé. Les adresses PCI sont restées stables, mais les définitions de VM faisaient référence aux mauvais indices VF dans un cluster parce que quelqu’un
cliquait « juste comme ça » dans l’UI et se fiait à des noms d’étiquettes.
L’équipe n’a pas eu d’incident. Ils ont eu une petite frayeur et quelques attachs mal routés détectés en préproduction, parce que leur table de mapping (puis un petit service d’inventaire interne)
rendait la discordance évidente.
Leur pratique ennuyeuse a aussi facilité les audits : vous pouvez expliquer « cette VF appartient à ce locataire » quand vous pouvez pointer des IDs déterministes, pas des impressions.
La fiabilité est souvent une discipline administrative portant un chapeau d’ingénierie.
Une idée paraphrasée souvent attribuée à W. Edwards Deming convient aux opérations : « Vous ne pouvez pas améliorer ce que vous ne mesurez pas. » (idée paraphrasée)
Erreurs courantes : symptôme → cause racine → correctif
1) « echo vers sriov_numvfs retourne Invalid argument »
- Symptôme :
Invalid argumentlors de la création des VFs. - Cause racine : firmware/BIOS SR-IOV désactivé, mauvais pilote PF, ou vous avez demandé plus que
sriov_totalvfs. - Correctif : confirmez que
sriov_totalvfs> 0 ; inspectez dmesg pour l’indice du pilote ; activez SR-IOV dans le BIOS/NIC ; demandez d’abord moins de VFs.
2) « Les VFs existent mais le passthrough VFIO échoue avec erreur de groupe IOMMU »
- Symptôme : l’hyperviseur se plaint que le périphérique n’est pas dans un groupe IOMMU isolé ; QEMU refuse l’assignation.
- Cause racine : ACS n’assure pas l’isolation, ou la plateforme groupe PF+VF ensemble.
- Correctif : déplacer la NIC vers un slot/root port différent, activer les options BIOS liées à ACS si disponibles, ou accepter que cette plateforme ne permette pas un passthrough par-VF sûr.
3) « L’invité a le lien mais ne peut pas passer de trafic de façon fiable »
- Symptôme : connectivité intermittente, problèmes de résolution ARP, trafic unidirectionnel.
- Cause racine : spoof checking/trust/politique VLAN de la PF incompatible avec le comportement de l’invité ; limite MAC du port en amont.
- Correctif : définir MAC/VLAN sur la PF, ajuster spoof/trust intentionnellement, et s’assurer que le port du switch autorise plusieurs MACs.
4) « Les performances sont pires après SR-IOV »
- Symptôme : utilisation CPU plus élevée ou débit inférieur par rapport à virtio.
- Cause racine : IRQs épinglés sur de mauvais CPUs, mismatch NUMA, rétrogradation de la largeur du lien, trop de queues/offloads.
- Correctif : vérifier la largeur/vitesse du lien, placer la VM sur le même nœud NUMA, ajuster l’affinité IRQ, réduire le nombre de VFs/queues, valider les offloads par mesure.
5) « La VF disparaît après reboot »
- Symptôme : les VFs disparaissent ou retournent à 0 après un redémarrage de l’hôte.
- Cause racine : la création SR-IOV des VFs n’est pas persistante ; vous n’avez pas réappliqué
sriov_numvfsau démarrage, ou un service réinitialise le périphérique. - Correctif : implémenter un mécanisme au démarrage (unit systemd) pour définir
sriov_numvfsaprès le chargement du pilote PF ; vérifier l’ordre.
6) « Impossible de décharger le pilote PF / périphérique bloqué »
- Symptôme : vous ne pouvez pas changer le nombre de VFs ; le déchargement du pilote échoue ; le périphérique est occupé.
- Cause racine : des VFs existent encore et sont en cours d’utilisation ; VFs liées à des pilotes ; une VM tient une VF ouverte via VFIO.
- Correctif : définir
sriov_numvfsà 0, détacher les VFs des invités, délier les VFs des pilotes, puis reconfigurer.
Listes de vérification / plan pas à pas
Checklist pré-vol de l’hôte (faire ceci avant de toucher aux invités)
- Confirmer pilote PF et firmware :
ethtool -i. - Confirmer capacité SR-IOV :
sriov_totalvfs> 0. - Activer IOMMU dans la ligne de commande du noyau ; redémarrer ; vérifier dans dmesg.
- Inspecter les groupes IOMMU ; si l’isolation est impossible, arrêter et redessiner l’architecture.
- Vérifier la vitesse/largeur PCIe ; corriger les problèmes de slot/bifurcation tôt.
- Créer un petit nombre de VFs (2–4) et s’assurer que dmesg est propre.
- Décider de la politique : MAC/VLAN/trust/spoof par VF.
- Décider du binding : pilote réseau hôte vs vfio-pci, pas les deux.
Plan de création et de politique des VFs (opérations répétables)
- Mettre le nombre de VFs à 0 (état propre).
- Créer le nombre souhaité de VFs.
- Assigner MAC/VLAN/trust par VF de façon déterministe (inventoriez-le).
- Lier à vfio-pci si vous faites du passthrough.
- Attacher à la VM ; confirmer le pilote invité ; faire un ping simple + test iperf.
Checklist de validation invité (prouver que ce n’est pas mensonger)
- Confirmer le périphérique visible dans l’invité via
lspci -nnk. - Confirmer que le nom de l’interface invité apparaît et que le lien est up.
- Confirmer que le MTU correspond au réseau (ne pas supposer que les jumbo frames sont bout en bout).
- Confirmer que le comportement VLAN correspond à la politique PF.
- Faire une capture de paquets sur l’uplink hôte si vous suspectez des drops par politique (la vérité du plan de données bat la théorie).
Plan de persistance (parce que redémarrer est une fonctionnalité)
La configuration SR-IOV se réinitialise souvent au redémarrage. Traitez la création de VFs et la politique VF comme toute autre configuration système : déclarative et
appliquée par systemd dans le bon ordre.
cr0x@server:~$ cat /etc/systemd/system/sriov-enp129s0f0.service
[Unit]
Description=Configure SR-IOV VFs on enp129s0f0
After=network-pre.target
After=sys-subsystem-net-devices-enp129s0f0.device
Wants=network-pre.target
[Service]
Type=oneshot
ExecStart=/bin/sh -c 'echo 0 > /sys/class/net/enp129s0f0/device/sriov_numvfs; echo 4 > /sys/class/net/enp129s0f0/device/sriov_numvfs'
ExecStart=/sbin/ip link set enp129s0f0 vf 0 mac 52:54:00:aa:bb:01 vlan 120 spoofchk on trust off
ExecStart=/sbin/ip link set enp129s0f0 vf 1 mac 52:54:00:aa:bb:02 vlan 120 spoofchk on trust off
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
cr0x@server:~$ sudo systemctl daemon-reload
cr0x@server:~$ sudo systemctl enable --now sriov-enp129s0f0.service
Created symlink /etc/systemd/system/multi-user.target.wants/sriov-enp129s0f0.service → /etc/systemd/system/sriov-enp129s0f0.service.
Ce que ça signifie : vous avez rendu la création des VFs et la politique reproductible.
Décision : gardez cette unité simple. Évitez d’y embarquer la logique de binding VFIO à moins d’être sûr de l’ordre de chargement des modules et du comportement udev
dans votre environnement.
FAQ
1) Dois-je activer SR-IOV dans le BIOS, ou seulement dans la NIC ?
Potentiellement les deux. Certaines plateformes verrouillent SR-IOV derrière des options BIOS/UEFI (surtout pour la « virtualisation IO »), et certaines NICs ont des bascules firmware
ou des profils de ressources qui restreignent la création de VFs. Si sriov_totalvfs est 0, considérez cela comme « quelque chose est désactivé » tant que le contraire n’est pas prouvé.
2) Quelle est la différence entre iommu=pt et ne pas l’utiliser ?
iommu=pt (pass-through) signifie typiquement que les périphériques du host utilisent des mappings d’identité pour réduire la surcharge, tout en activant la traduction/isolation
pour les périphériques VFIO. C’est courant sur les hôtes de virtualisation. Si vous déboguez des fautes DMA étranges, vous pouvez essayer sans, mais mesurez et comprenez le compromis.
3) Pourquoi mes groupes IOMMU sont-ils énormes ?
Parce que votre topologie PCIe et les réglages ACS décident de ce qui peut être isolé. Certaines plateformes grand public et certains designs serveur derrière certains switches regroupent des fonctions.
Si la VF partage un groupe avec la PF ou des périphériques non liés, votre plan de passthrough propre par-VF peut être impossible sur ce matériel.
4) Puis-je utiliser des VFs SR-IOV avec des bridges Linux ou Open vSwitch au lieu du passthrough ?
Vous le pouvez, mais ce n’est généralement pas la raison pour laquelle on déploie SR-IOV. Si vous gardez les VFs sur l’hôte et les bridgez, vous réintroduisez souvent le switching logiciel et la complexité
des politiques. Décidez ce que vous voulez : « affectation directe » ou « switching géré par l’hôte ». Mélanger les objectifs est la façon de créer un réseau mystère.
5) Pourquoi le binding VFIO revient parfois après reboot ?
Parce que le pilote par défaut peut se lier en premier pendant l’énumération. Corrigez cela avec des règles de liaison persistantes : appliquer driver_override au bon moment,
ou une configuration modprobe qui garantit que vfio-pci réclame des vendor/device IDs spécifiques. Attention : réclamer par ID peut aussi capturer des périphériques non souhaités si vous avez plusieurs NICs identiques.
6) Dois-je mettre trust on pour les VFs ?
Seulement si vous savez exactement pourquoi. Trust permet à la VF de changer le comportement MAC/VLAN et peut assouplir le filtrage. C’est utile pour des appliances, routeurs, ou du networking imbriqué,
mais cela change votre modèle de menace. Position par défaut : trust off, spoofchk on, et définir explicitement MAC/VLAN.
7) Les jumbo frames sont-elles « gratuites » avec SR-IOV ?
Non. Il vous faut toujours une cohérence MTU de bout en bout : interface invité, VF, PF, port du switch et chemin en amont. Les jumbo frames qui échouent ressemblent souvent à des pertes aléatoires,
car le petit trafic de contrôle fonctionne tandis que les gros payloads disparaissent.
8) Pourquoi les performances varient-elles entre hôtes avec la même NIC ?
Topologie PCIe, placement NUMA, paramètres BIOS et profils firmware. Deux NIC identiques dans des slots différents peuvent se comporter très différemment.
De plus, le placement des IRQs et l’échelle de fréquence CPU de l’hôte peuvent biaiser les résultats. Considérez la performance comme une propriété de la plateforme, pas uniquement de la NIC.
9) SR-IOV est-ce une frontière de sécurité ?
Ça peut faire partie d’une frontière, mais ne la traitez pas comme un mur magique. Vous comptez sur l’isolation IOMMU, un firmware correct, un pilote correct, et des contrôles opérationnels sensés.
Si votre modèle de menace est une forte multi-tenancy, vous avez besoin d’une configuration disciplinée et d’audits. Si votre modèle de menace est « garder les gens honnêtes honnêtes », c’est plus simple.
10) Quand ne devrais-je pas utiliser SR-IOV ?
Quand vous avez besoin d’une politique L2/L3 flexible sur l’hôte, quand votre plateforme ne peut pas isoler les groupes IOMMU, quand vous ne pouvez pas coordonner les politiques des ports de switch,
ou quand vous avez besoin de migration à chaud sans interruption et que vos outils ne gèrent pas proprement SR-IOV. Virtio bien réglé n’est pas une honte. C’est souvent la bonne réponse.
Étapes suivantes que vous pouvez faire cette semaine
Si vous voulez que SR-IOV se comporte sur Debian 13, cessez de le traiter comme un simple interrupteur à bascule. Traitez-le comme un petit projet d’intégration plateforme.
- Choisissez un hôte et un port NIC et validez d’abord IOMMU + isolation. Si les groupes sont mauvais, redessinez maintenant.
- Créez 2 VFs, pas 32. Liez-en une à VFIO et attachez-la à une VM de test. Vérifiez le pilote invité et la connectivité de base.
- Rendez la politique explicite : définissez MAC/VLAN/spoof/trust pour les VFs et documentez la cartographie VF → locataire.
- Mesurez les performances en connaissance de la topologie : confirmez la largeur/vitesse du lien et le placement NUMA avant d’accuser les pilotes.
- Automatisez la persistance avec une simple unité systemd oneshot qui recrée les VFs et les politiques après un reboot.
Une fois SR-IOV stable, vous pouvez vous intéresser aux choses amusantes : nombres de queues, offloads, DPDK, et gagner des microsecondes. D’abord, rendez-le ennuyeux. Un réseau ennuyeux
est celui qui ne vous réveille pas.