Ви вмикаєте SR-IOV, бо хочете чисту, передбачувану пропускну здатність і менше навантаження на CPU. Ви перезавантажуєте систему, записуєте число в
sriov_numvfs, і… нічого. Або ще гірше: VFs з’являються, але хост втрачає лінк, гості не отримують пакети, або IOMMU-групи
виглядають як клубок, і VFIO відмовляється працювати.
Перший запуск SR-IOV рідко блокується «через баг». Він блокується ланцюжком припущень: налаштування прошивки, параметри ядра,
вибір драйверів PF/VF, топологія PCIe і одна невинна «оптимізація», яка виявляється пасткою.
SR-IOV на одній сторінці (без казок)
SR-IOV (Single Root I/O Virtualization) дозволяє PCIe-пристрою виявляти кілька легковагових PCI-функцій. Фізична функція (PF) — це
інтерфейс «власника». Віртуальні функції (VFs) — це «шматочки», які ви передаєте гостям або контейнерам (зазвичай через VFIO passthrough) або керуєте на
хості для маршрутизації трафіку.
Обіцянка: обійти частину програмного перемикання, зменшити накладні витрати на пакет і отримати майже лінійну пропускну здатність з меншими затримками.
Вартість: ви тепер залежите від поведінки апаратури, політики прошивки, топології PCIe та суворих очікувань драйверів. Це не «складно», але це
інше. Менталітет налагодження ближчий до «усунення неполадок HBA для зберігання», ніж до «тонкого налаштування Linux bridge».
На Debian 13 SR-IOV здебільшого — це історія ядра+драйвера+прошивки. Debian не «робить» SR-IOV за вас; він дає хороші інструменти, щоб бачити, що відбувається.
Ваше завдання — зробити платформу чесною: увімкнути IOMMU, забезпечити адекватний ACS, стабільний PF-драйвер і відсутність магічних припущень.
Основна модель: три площини
- План керування: перемикачі sysfs, devlink, ethtool, конфігурація PF, перемикачі прошивки.
- План даних: реальний шлях пакетів/IO усередині NIC; відображення черг, фільтри VLAN/MAC, перевірки спуфінгу.
- План ізоляції: IOMMU/VT-d/AMD-Vi, IOMMU-групи, ACS, прив’язки VFIO, маршрутизація переривань.
Більшість звернень «SR-IOV не працює» — це проблеми площини ізоляції, замасковані під проблеми площини даних. Другі за частотою — це дефолти
площини керування, про які ви не знали.
Цікаві факти та трохи історії (щоб ви перестали звинувачувати не ту річ)
-
SR-IOV — це специфікація PCI-SIG з кінця 2000-х, створена через біль від CPU-насичених стеків віртуалізації, що тягли трафік 10GbE та
зберігання через програмну емулювану обробку. -
«Virtual Function» не вигадали в Linux. Це номер PCIe-функції зі стандартизованою структурою можливостей.
Linux лише відкриває її через sysfs і драйвери. - Перші розгортання SR-IOV були не лише про мережі. HBA та NVMe-подібні рішення просували схожі патерни «прямого призначення».
-
Впровадження IOMMU відставало від SR-IOV у багатьох дата-центрах. Люди вмикали VFs раніше, ніж увімкнули ізоляцію DMA,
і так навчаються різниці між «працює» і «безпечне». -
ACS (Access Control Services) — це функція PCIe, що контролює поведінку peer-to-peer. Без належного ACS ваші IOMMU-групи можуть бути надто великими,
щоб безпечно передавати окремі функції. -
Драйвери VF часто навмисно відкривають менше налаштувань, ніж PF-драйвери. Це зроблено навмисно: менше гострих країв для орендарів і
менше способів застрягнути пристрій. -
Деякі NIC реалізують поведінку, схожу на комутатор, всередині. VFs — це не лише черги; є внутрішнє маршрутизація, фільтрація
і іноді вбудована логіка. -
SR-IOV не завжди швидший. Для дрібних пакетів навантаження на хост може зменшитись; для деяких робочих навантажень операційна
складність перевищує вигоди і краще працює vhost-net/virtio з хорошим тюнінгом.
Як SR-IOV виходить з ладу у реальному житті
Збої SR-IOV групуються. Якщо ви зможете класифікувати те, що бачите, ви перестанете метатись і почнете вимірювати.
Клас помилок A: «VFs не з’являються»
Ви записуєте 8 в /sys/class/net/<pf>/device/sriov_numvfs і отримуєте
Invalid argument або значення залишається нуль. Поширені причини:
- SR-IOV вимкнено в BIOS/UEFI або в прошивці NIC (так, обидва можуть бути важливими).
- Завантажено неправильний PF-драйвер (вбудований vs постачальницький; або запасний драйвер без підтримки SR-IOV).
- Обмеження прошивки: ви запросили більше VFs, ніж підтримує пристрій/порт.
- Пристрій у стані, коли VFs не можна створити (наприклад, конфігуровано режим, що конфліктує зі створенням VF).
Клас помилок B: «VFs з’являються, але passthrough не працює»
VF-пристрої видно в lspci, але ваш гіпервізор не може їх призначити. Або vfio зв’язується, але QEMU видає помилки з IOMMU-групами.
Поширені причини:
- IOMMU не увімкнено на рівні ядра.
- ACS/IOMMU-групи занадто великі; VF ділить групу з PF або з іншими пристроями.
- vfio-pci не прив’язується, бо інший драйвер вже захопив VF.
- Secure Boot або політика блокування ядра перешкоджають завантаженню модулів або VFIO (залежно від середовища).
Клас помилок C: «Пакети губляться, ARP дивний, VLAN плутається»
Гість бачить лінк, може пінгувати шлюз один раз, а потім зв’язок пропадає. Або VLAN-теги зникають. Або ARP-відповіді не повертаються. Поширені причини:
- PF накладає політики anti-spoof/MAC/VLAN, а VF не налаштовано відповідно.
- Захист порту комутатора відхиляє кілька MAC-адрес; MAC-и VF не відповідають дозволеному списку.
- Функції оффлоаду взаємодіють з шляхом віртуального комутатора несподіваним чином (рідше, але буває).
Клас помилок D: «Продуктивність гірша за virtio»
Це те, що викликає підозри у керівництва. Поширені причини:
- Шторми переривань через погану афініті IRQ або надмірну кількість черг.
- Розподіл слотів PCIe або зниження швидкості лінку (x8 стає x4, Gen4 стає Gen3).
- NUMA-невідповідність: VF на одному сокеті, vCPU ВМ — на іншому.
- Дрібні пакети з навантаженням, де накладні витрати на VM (фаєрвол, conntrack, блокування в додатку) домінують.
Жарт 1: SR-IOV — це як дати вашій VM власну смугу на шосе — поки ви не зрозумієте, що з’їзд все ще керує комітет.
Швидкий плейбук діагностики (перші/другі/треті перевірки)
Це послідовність, якою я користуюсь, коли хтось каже «SR-IOV не працює» і я хочу корисну відповідь за 15 хвилин. Мета — виявити
перший зламаний шар, а не виправити все одночасно.
1) Підтвердити, що платформа може робити ізоляцію (IOMMU + групи)
- Перевірте, чи IOMMU увімкнено в параметрах завантаження ядра та в dmesg.
- Перевірте IOMMU-групи: чи можна ізолювати VF чисто?
- Якщо групи неправильні — зупиніться. Не переходьте до «тонкого налаштування» або змін гостя.
2) Підтвердити, що NIC та PF-драйвер дійсно підтримують SR-IOV
- Перевірте
sriov_totalvfs. - Перевірте драйвер PF і версії прошивки.
- Створіть спочатку невелику кількість VFs (2), а не відразу 32.
3) Підтвердити прив’язку VF і шлях підключення до гостя
- Переконайтеся, що VFs прив’язані до vfio-pci під час passthrough; інакше вони прив’яжуться до мережевого драйвера на хості і ви будете боротися з udev.
- Підтвердіть, що гість бачить пристрій і завантажує правильний драйвер VF.
4) Тільки потім: перевірка здоров’я площини даних
- Політика порту комутатора та правила транкування VLAN.
- Фільтри MAC/VLAN на PF для кожного VF.
- Лічильники продуктивності та розміщення черг/IRQ.
Практичні завдання: команди, виходи та рішення (12+)
Це можна запустити на Debian 13. Показані виходи є репрезентативними. Ваші рядки можуть відрізнятись, але логіка прийняття рішень зберігається.
Завдання 1: Визначити PF-інтерфейс і PCI-адресу
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>
Що це означає: enp129s0f0 виглядає як ваш PF (один з фізичних портів).
Рішення: оберіть PF, з якого створюватимете VFs; не намагайтесь одночасно працювати з обома портами.
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
Що це означає: У вас є адреса шини 0000:81:00.0 і PF-драйвер.
Рішення: запишіть адресу шини; більшість операцій SR-IOV і VFIO простіші, коли думати в термінах PCI ID.
Завдання 2: Підтвердити наявність SR-IOV і ліміт VF
cr0x@server:~$ cat /sys/class/net/enp129s0f0/device/sriov_totalvfs
64
Що це означає: Комбінація заліза/драйвера може вивести до 64 VFs на цьому PF.
Рішення: почніть з 2 або 4. Якщо ви одразу запросите 64 і щось піде не так, ви не знатимете, чи проблема в «SR-IOV» або «ви попросили занадто багато».
Завдання 3: Спробувати створити VFs (і обробити два поширені режими відмови)
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
Що це означає: VFs створено успішно.
Рішення: переходьте до переліку VFs у PCI і зіставлення їх з індексами VF.
Якщо це не вдалось, ви побачите щось на кшталт:
cr0x@server:~$ echo 4 | sudo tee /sys/class/net/enp129s0f0/device/sriov_numvfs
tee: /sys/class/net/enp129s0f0/device/sriov_numvfs: Invalid argument
4
Що це означає: Ядро відхилило створення VF. Зазвичай це політика драйвера/прошивки/платформи, а не опечатка.
Рішення: негайно перегляньте dmesg для реальної причини (наступне завдання).
Завдання 4: Прочитати dmesg для специфічної помилки пристрою, а не загального шуму
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
Що це означає: Драйвер каже, що не може виділити ресурси або прошивка блокує.
Рішення: перевірте налаштування прошивки, режим PF і впевніться, що ви не в обмеженій конфігурації NIC.
Завдання 5: Перевірити, чи IOMMU увімкнено (це блокує VFIO і безпечне призначення)
cr0x@server:~$ cat /proc/cmdline
BOOT_IMAGE=/vmlinuz-6.12.0-amd64 root=UUID=8c3d... ro quiet intel_iommu=on iommu=pt
Що це означає: Параметри ядра вимагають Intel IOMMU і режим passthrough для пристроїв хоста.
Рішення: якщо ви не бачите intel_iommu=on (або amd_iommu=on), додайте його і перезавантажтеся перед роботою з 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
Що це означає: IOMMU і перенаправлення переривань активні.
Рішення: переходьте до перевірки груп; якщо перенаправлення переривань відсутнє, очікуйте дивакуватостей MSI/MSI-X під навантаженням.
Завдання 6: Перевірити IOMMU-групи (запит «чи можу я ізолювати VF?»)
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
Що це означає: PF і VFs можуть бути в одній групі (залежить від списку пристроїв). Це може бути проблемою для passthrough: багато
налаштувань вимагають, щоб кожен VF був у власній групі.
Рішення: якщо VF ділить групу з PF або з чужими пристроями, можливо потрібно змінити налаштування BIOS ACS, інше розміщення в слоті,
або прийняти, що платформа не дозволяє «чисте» призначення VF.
Завдання 7: Перелік недавно створених PCI-функцій VF
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]
Що це означає: VFs існують на 81:00.1 по 81:00.4.
Рішення: вирішіть, чи хост використовуватиме ці VFs як netdev (рідко у чистих дизайнах), або прив’язувати їх до VFIO для гостей.
Завдання 8: Зіставити індекс VF з PCI-адресою (припиніть гадати, який VF ви віддали)
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
Що це означає: Індекси VF існують, але MAC-и не встановлені і trust вимкнено.
Рішення: встановіть MAC/VLAN/trust явно на PF перед тим, як віддавати VF гостю, інакше ви будете налагоджувати «мережеву нестабільність», яка насправді є примусовою політикою.
Завдання 9: Встановити політику MAC і VLAN для VF (або навмисно відключити контроль)
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
Що це означає: VF0 може використовувати лише вказаний MAC і VLAN 120; спуфінг заблоковано; trust вимкнено.
Рішення: у мульті-орендарних середовищах тримайте spoof checking увімкненим. Якщо гостю потрібна роль маршрутизатора, можливо, потрібен
trust on (і тоді краще мати відповідну модель безпеки вище по ланцюжку).
Завдання 10: Прив’язати VF до vfio-pci (для passthrough) і перевірити, що прив’язка збереглась
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
Що це означає: VF наразі прив’язана до мережевого драйвера на хості. Це нормально для використання на хості, але не для VFIO passthrough.
Рішення: відв’яжіть і прив’яжіть до vfio-pci, і забезпечте персистентність через конфіг modprobe або правила 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
Що це означає: VF тепер належить VFIO і готова до passthrough.
Рішення: якщо прив’язка не вдається з помилкою «Device or resource busy», значить хтось ще користується пристроєм (наприклад NetworkManager або systemd-networkd);
зупиніть ці сервіси або заблокуйте драйвер VF для таких функцій.
Завдання 11: Перевірити швидкість/ширину PCIe-лінку (ваш «SR-IOV повільний» сигнальний маркер)
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)
Що це означає: Карта підтримує x16, але працює на x8. Це може бути нормально або обмежувати під навантаженням.
Рішення: якщо ви очікували x16 і ви насичуєте канал, перевірте підключення слота, біфуркацію BIOS, riser-и та чи інший пристрій не забрав лінії.
Завдання 12: Перевірити NUMA-локальність (бо DMA між сокетами — невидимий податок)
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
Що це означає: Ваш NIC знаходиться на NUMA-вузлі 1.
Рішення: прив’яжіть vCPU ВМ (і бажано пам’ять) до вузла 1 при використанні VF з цього NIC. Інакше ви заміряєте латентність і випадково вимірюєте швидкодію міжз’єднання.
Завдання 13: Підтвердити розподіл переривань (прихована причина зростання CPU)
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
Що це означає: Всі переривання потрапляють на CPU0 (перша колонка), що типово, коли ми забули про афініті IRQ.
Рішення: розподіліть IRQ між CPU, локальними для NUMA-вузла NIC, або увімкніть irqbalance з адекватними налаштуваннями.
Завдання 14: Підтвердити, що PF не блокує VF політикою (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
Що це означає: Політика встановлена і видима.
Рішення: якщо гість відправляє теги на інший VLAN, їх буде відкинуто. Це не «баг Linux»; це ви застосували політику і забули про неї.
Завдання 15: Підтвердити, що гість бачить VF і завантажує правильний драйвер (всередині 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
Що це означає: VM бачить VF-пристрій і має драйвер.
Рішення: якщо VM бачить пристрій, але драйвер не зв’язується — у гостя немає підтримки драйвера або застаріле ядро/initramfs.
Завдання 16: Перевірити проблеми з можливістю скидання PCI (поширено для 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
Що це означає: VF може не підтримувати Function Level Reset (FLR). VFIO переключиться на інші шляхи скидання.
Рішення: якщо ВМ падають при перезавантаженні або гарячому ресеті, можливо потрібен інший VF, повний робочий процес скидання PF або операційні правила
(«мігрувати замість перезавантаження під навантаженням»).
Три міні-історії з корпоративного життя (усі досить правдиві, щоб боліти)
Міні-історія 1: Інцидент, спричинений хибним припущенням
Команда розгорнула SR-IOV для набору сервісів із чутливими затримками. Вони провели лабораторні випробування: чудові цифри, чисті графіки, самовдоволені усмішки.
У продакшені вони передали VFs у ВМ і все виглядало нормально. Лінк був, DHCP працював, health check-і зелені. Потім, через п’ять хвилин,
випадкові інстанси стали «напівмертвими»: могли відправляти трафік, але відповіді поверталися ненадійно.
Перше припущення було, що винен комутатор. Друге — що це проблема з ARP. Третє — що це регресія ядра. У кожного був свій привид.
Насправді нудна причина: на аплінку комутатора було встановлено ліміт MAC «одна MAC на порт». SR-IOV ввів кілька MAC за тим самим фізичним портом.
Комутатор не повністю закривав порт; він вибірково відкидав кадри після перевищення ліміту, через що виглядало, ніби хост «не надійний».
В різних стійках ситуація різнилась, бо не усі порти мали однакову політику безпеки.
Виправлення було двоє: змінити політику порту комутатора, щоб дозволити очікувану кількість MAC-адрес (або використовувати профіль trunk для віртуалізації),
і впровадити попередню перевірку, що рахувала заплановані VFs та порівнювала їх із політикою комутатора. Справжній урок не в «вимкнути безпеку».
Він у тому, щоб «не припускати, що мережа ставиться до порту сервера як до єдиної ідентичності».
Вони також засвоїли соціальний урок: коли ви змінюєте семантику інтерфейсу, ви несете відповідальність за радіус впливу. Команда мережі нічого не зламала;
команда обчислень просто змінила правила без попередження.
Міні-історія 2: Оптимізація, що обернулась проти
Інша організація вирішила, що SR-IOV вирішить навантаження CPU на хостах з великою кількістю дрібних потоків. Вони створили максимальну кількість VFs на NIC,
«бо може знадобитись пізніше», і заздалегідь прив’язали їх до VFIO. Вони також увімкнули всі оффлоади, які знайшли, «бо NIC створений для цього».
Результат: часи завантаження збільшились, окремі хости іноді не завантажувались чисто після обслуговування. Коли вони завантажувались, моніторинг
показував дивні спайки латентності кожні кілька хвилин. Легко було звинуватити «SR-IOV нестабільний», що стало політичним приводом.
Коренева причина виявилася поєднанням дефіциту ресурсів і переривань. Створення великої кількості VFs збільшило облік пристрою,
і хост отримав купу IRQ, які за замовчуванням лягли на невелику підмножину CPU. Оффлоади не були тотально поганими, але деякі взаємодіяли
погано з шаблоном трафіку і гостевими драйверами. Їхня «оптимізувати все» позиція створила систему крихку під завантаженням, непередбачувану при перезавантаженні і важку для діагностики.
План відкату був простий: створювати лише ту кількість VFs, яка потрібна для ролі хоста, правильно розподілити IRQ, і вмикати оффлоади лише після перевірки.
Продуктивність відновилась — і надійність покращилась більше, ніж p99 латентність.
Жарт 2: Якщо ви створюєте 64 VFs «про всяк випадок», ви винайшли новий вид технічного боргу: PCIe-борг, який доведеться платити при перезавантаженні.
Міні-історія 3: Скучна, але правильна практика, що врятувала ситуацію
Третя команда виконувала змішані робочі навантаження: деякі ВМ потребували SR-IOV для пропускної здатності, інші були задоволені virtio. Вони стандартизували
операційне правило: кожне призначення VF вимагало записаного відображення PF ім’я → VF індекс → PCI адреса → VM. Без винятків.
Люди скаржились. Здавалось бюрократією. Здавалось паперовою роботою для інженерів, які «знають, що роблять». Потім хост перезавантажився після оновлення ядра
і порядок enumeratsii udev змінився. PCI-адреси залишились стабільними, але визначення ВМ посилалися на неправильні VF-індекси в одному кластері, бо хтось «просто кликав» в UI і покладався на імена ярликів.
У команди не було аварії. Був невеликий переляк і кілька неправильно спрямованих підключень, виявлених у препродакшн перевірках, бо їхня таблиця відображень (а пізніше невеликий внутрішній сервіс інвентарю) зробили невідповідність очевидною.
Їхня нудна практика також полегшила аудит: можете пояснити «цей VF належить цьому орендарю», коли можете вказати детерміновані ID, а не відчуття.
Надійність часто — це канцелярська дисципліна в технічному одязі.
Парафраз ідеї, яка часто приписується W. Edwards Deming: «Ви не можете поліпшити те, що не вимірюєте.»
Поширені помилки: симптом → корінна причина → виправлення
1) «echo в sriov_numvfs повертає Invalid argument»
- Симптом:
Invalid argumentпри створенні VFs. - Корінна причина: SR-IOV вимкнено в прошивці/BIOS, неправильний PF-драйвер або ви запросили більше, ніж
sriov_totalvfs. - Виправлення: переконайтесь, що
sriov_totalvfs> 0; перевірте dmesg на підказки драйвера; увімкніть SR-IOV в BIOS/NIC; спочатку запросіть менше VFs.
2) «VFs є, але VFIO passthrough не працює через помилку IOMMU групи»
- Симптом: гіпервізор скаржиться, що пристрій не в ізольованій IOMMU-групі; QEMU відмовляється призначити.
- Корінна причина: ACS не надає ізоляцію або платформа групує PF+VF разом.
- Виправлення: перемістіть NIC в інший слот/root port, увімкніть BIOS-опції, пов’язані з ACS, якщо доступні, або прийміть, що ця платформа не підходить для per-VF passthrough.
3) «Гість має лінк, але не може надійно передавати трафік»
- Симптом: періодична втрата зв’язку, проблеми з ARP, односторонній трафік.
- Корінна причина: перевірка спуфінгу/trust/VLAN політика VF не відповідає поведінці гостя; ліміт MAC на порту комутатора.
- Виправлення: встановіть MAC/VLAN на PF, регулюйте spoof/trust усвідомлено, переконайтесь, що порт комутатора дозволяє кілька MAC.
4) «Продуктивність гірша після SR-IOV»
- Симптом: вищий CPU або менша пропускна здатність у порівнянні з virtio.
- Корінна причина: IRQ-і прив’язані до неправильних CPU, NUMA-невідповідність, зниження ширини/швидкості лінку, надмірна кількість черг/оффлоадів.
- Виправлення: перевірте ширину/швидкість лінку, розмістіть VM на тому ж NUMA-вузлі, налаштуйте афініті IRQ, зменшіть кількість VF/черг, перевірте оффлоади вимірюваннями.
5) «VF зникає після перезавантаження»
- Симптом: VFs зникають або скидаються до 0 після рестарту хоста.
- Корінна причина: створення VFs не персистентне; ви не повторно застосували
sriov_numvfsпри запуску, або сервіс скидає пристрій. - Виправлення: реалізуйте механізм при завантаженні (systemd unit), щоб встановити
sriov_numvfsпісля завантаження PF-драйвера; перевірте порядок завантаження.
6) «Не вдається розвантажити PF-драйвер / пристрій застряг»
- Симптом: не можете змінити кількість VF; відвантаження драйвера не вдається; пристрій зайнятий.
- Корінна причина: VFs все ще існують і використовуються; VFs прив’язані до драйверів; ВМ утримує VF відкритим через VFIO.
- Виправлення: встановіть
sriov_numvfsв 0, відключіть VFs від гостей, відв’яжіть VFs від драйверів, потім повторно налаштуйте.
Чеклісти / покроковий план
Чекліст перед роботою на хості (зробіть це перед зміною гостей)
- Підтвердьте драйвер PF і прошивку:
ethtool -i. - Підтвердьте можливість SR-IOV:
sriov_totalvfs> 0. - Увімкніть IOMMU в параметрах ядра; перезавантажтесь; перевірте dmesg.
- Перегляньте IOMMU-групи; якщо ізоляція неможлива — зупиніться і переробіть дизайн.
- Перевірте швидкість/ширину PCIe; усуньте проблеми зі слотами/біфуркацією на ранньому етапі.
- Створіть невелику кількість VFs (2–4) і переконайтесь, що dmesg чистий.
- Визначте політику: MAC/VLAN/trust/spoof для кожного VF.
- Вирішіть прив’язку: мережевий драйвер хоста vs vfio-pci, а не обидва одночасно.
План створення VF і політики (повторювані операції)
- Встановіть кількість VF в 0 (чистий стан).
- Створіть потрібну кількість VFs.
- Призначте MAC/VLAN/trust для кожного VF детерміновано (зареєструйте це в інвентарі).
- Прив’яжіть до vfio-pci, якщо передаєте в гостя.
- Підключіть до VM; підтвердьте драйвер гостя; виконайте простий ping + iperf тест.
Чекліст валідації гостя (доведіть, що він не бреше)
- Підтвердьте, що пристрій видно в гості:
lspci -nnk. - Підтвердьте, що ім’я інтерфейсу в гості з’явилось і лінк UP.
- Підтвердьте, що MTU відповідає мережі (не припускайте, що джамбо-рамки проходять по всій трасі).
- Підтвердьте, що поведінка VLAN відповідає політиці PF.
- Запустіть захоплення пакетів на uplink хоста, якщо підозрюєте відкидання політикою (істина площини даних краще за теорію).
План персистентності (бо перезавантаження — це функція)
Конфігурація SR-IOV часто скидається при перезавантаженні. Ставте створення VF і політику VF як звичайну системну конфігурацію: декларативно і
застосовуйте через systemd у правильному порядку.
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.
Що це означає: ви зробили створення VF і політику повторюваними.
Рішення: тримайте цей unit простим. Уникайте вбудовування логіки прив’язки VFIO сюди, поки не будете впевнені в порядку завантаження модулів і поведінці udev у вашому середовищі.
FAQ
1) Чи потрібно увімкнути SR-IOV у BIOS, або достатньо в NIC?
Можливо обидва. Деякі платформи ставлять SR-IOV за заслоном в BIOS/UEFI (особливо для «IO virtualization»), а деякі NIC мають перемикачі прошивки або профілі ресурсів,
що обмежують створення VF. Якщо sriov_totalvfs = 0, вважайте це за «щось вимкнено», поки не доведено протилежне.
2) У чому різниця між iommu=pt і не використанням його?
iommu=pt (pass-through) зазвичай означає, що власні пристрої хоста використовують відображення ідентичності для меншої накладної вартості,
при цьому зберігаючи трансляцію/ізоляцію для VFIO-пристроїв. Це поширено на хостах віртуалізації. Якщо ви налагоджуєте дивні DMA-помилки, можете спробувати без нього,
але вимірюйте і розумійте компроміси.
3) Чому мої IOMMU-групи великі?
Бо ваша топологія PCIe і налаштування ACS вирішують, що можна ізолювати. Деякі платформи для споживачів і деякі серверні рішення за певними комутаторами групують функції разом.
Якщо VF ділить групу з PF або чужими пристроями, ваш план «чистого» per-VF passthrough може бути неможливим на цьому обладнанні.
4) Чи можна використовувати SR-IOV VFs з Linux bridge або Open vSwitch замість passthrough?
Можна, але зазвичай це не причина, через яку люди впроваджують SR-IOV. Якщо ви тримаєте VFs на хості і мостите їх, ви часто знову вводите програмне
перемикання та складність політик. Вирішіть, чого ви хочете: «пряме призначення» або «кероване хостом перемикання». Змішування цілей породжує невизначеність.
5) Чому прив’язка VFIO іноді повертається після перезавантаження?
Тому що дефолтний драйвер може прив’язатися першим під час перебору. Виправте це персистентними правилами прив’язки: driver_override застосованим у потрібний час,
або конфігурацією modprobe, що гарантує, що vfio-pci претендує на конкретні vendor/device ID. Будьте обережні: захоплення за ID може також забрати пристрої,
які ви не мали наміру, якщо у вас кілька однакових NIC.
6) Чи варто ставити trust on для VFs?
Лише якщо ви точно знаєте чому. Trust дозволяє VF змінювати поведінку MAC/VLAN і може послабити фільтрацію. Це корисно для appliance-ів,
маршрутизаторів або вкладених мереж, але змінює модель загроз. Дефолтна позиція: trust off, spoofchk on і явне встановлення MAC/VLAN.
7) Чи «безкоштовні» jumbo-кадри з SR-IOV?
Ні. Вам все одно потрібна узгодженість MTU на всьому шляху: інтерфейс гостя, VF, PF, порт комутатора і upstream шлях. Несправні jumbo-кадри часто виглядають як випадкові втрати,
бо дрібні контрольні пакети проходять, а великі payload-и чомусь пропадають.
8) Чому продуктивність відрізняється на хостах з тим же NIC?
Топологія PCIe, розміщення NUMA, дефолти BIOS і профілі прошивки. Два ідентичні NIC у різних слотах можуть поводитись дуже по-різному.
Також розміщення IRQ і масштабування частоти CPU можуть спотворити результати. Розглядайте продуктивність як властивість платформи, а не лише NIC.
9) Чи є SR-IOV межою безпеки?
Це може бути частиною межі, але не вважайте її чарівною стіною. Ви покладаєтесь на ізоляцію IOMMU, правильну прошивку, коректну поведінку драйверів і дисципліну в операціях.
Якщо ваша модель загроз — сильна мульти-орендарність, потрібна дисциплінована конфігурація та аудит. Якщо модель — «тримати чесних людей чесними», це простіше.
10) Коли не слід використовувати SR-IOV?
Коли вам потрібна гнучка політика L2/L3 на хості, коли платформа не може ізолювати IOMMU-групи, коли ви не можете координувати політику порту комутатора,
або коли вам потрібно живе переміщення без переривань і ваші інструменти не справляються з SR-IOV. Virtio з хорошим тюнінгом — це не сором.
Часто це правильне рішення.
Наступні кроки, які можна зробити цього тижня
Якщо хочете, щоб SR-IOV поводився на Debian 13, перестаньте ставитися до нього як до одного перемикача. Ставтеся до нього як до малого проекту інтеграції платформи.
- Оберіть один хост і один порт NIC і перевірте IOMMU + ізоляцію спочатку. Якщо групи неправильні, переробіть дизайн зараз.
- Створіть 2 VFs, не 32. Прив’яжіть один до VFIO і підключіть до тестової ВМ. Перевірте драйвер гостя і базову зв’язність.
- Зробіть політику явною: встановіть VF MAC/VLAN/spoof/trust навмисно і документуйте відображення VF → орендар.
- Виміряйте продуктивність з урахуванням топології: підтвердьте ширину/швидкість лінку та розміщення NUMA до того, як звинувачувати драйвери.
- Автоматизуйте персистентність простим systemd oneshot unit, що відтворює VFs і політики після перезавантаження.
Коли SR-IOV стане стабільним, можете почати думати про цікавіші речі: кількість черг, оффлоади, DPDK і зменшення мікросекунд. Спочатку зробіть це нудним. Нудна мережа — та, що не розбудить вас серед ночі.