SR-IOV on XEN

개요

SR-IOV?

  • SR-IOV : Single Root-Input Output Virtualization
  • 물리 PCIe 장치를 여러 개의 PCIe 장치로 보이게 하는 PCI-SIG(http://www.pcisig.com/)에서 제정한 표준 스펙문서
  • SR-IOV는 Physical functions(PFs)와 Virtual Functions(VFs)로 나누어짐
  • PFs : Full-featured PCIe functions (configuration and data functions)
  • VFs : lightweight PCIe functions (only data functions)
  • PCIe 장치는 최대 256 VFs까지 가질수 있으나 각 VF는 실제 하드웨어 리소스가 필요하기 때문에 실제적인 최대값은 64VFs
  • 제한점
    • VF는 PF와 같은 장치로만 사용 가능
    • VF는 PF와 같은 네트워크 대역이어야 함
  • 조건
    • SR-IOV를 지원하는 mainboard(bios)와 CPU (intel VT-D or AMD iommu)
    • SR-IOV를 지원하는 NIC (e.g. Intel 82576)
    • SR-IOV를 지원하는 Hypervisor, Dom0, DomU

Xennet vs. SR-IOV

설정

지원확인

먼저 서버의 CMOS 에 들어가서 Intel VT-d 가 켜져 있는지 확인하라. VT-d 가 없으면 SR-IOV를 사용할 수 없다.

dom0# xm dmesg
(XEN) Intel VT-d Snoop Control enabled.
(XEN) Intel VT-d Dom0 DMA Passthrough not enabled.
(XEN) Intel VT-d Queued Invalidation enabled.
(XEN) Intel VT-d Interrupt Remapping enabled.
(XEN) Intel VT-d Shared EPT tables not enabled.
(XEN) I/O virtualisation enabled

NIC 역시 SR-IOV를 지원해야 한다. 아래 Intel 82576 NIC은 SR-IOV를 지원하는 NIC이다. linux module 이름은 igb 이다.

dom0# modinfo igb
filename:       /lib/modules/2.6.32.39-175.xendom0.el6.x86_64/kernel/drivers/net/igb/igb.ko
version:        1.3.16-k2
license:        GPL
description:    Intel(R) Gigabit Ethernet Network Driver
author:         Intel Corporation, <e1000-devel@lists.sourceforge.net>
srcversion:     67CCD4CBBFB5F99C69546C2
alias:          pci:v00008086d000010D6sv*sd*bc*sc*i*
alias:          pci:v00008086d000010A9sv*sd*bc*sc*i*
alias:          pci:v00008086d000010A7sv*sd*bc*sc*i*
alias:          pci:v00008086d000010E8sv*sd*bc*sc*i*
alias:          pci:v00008086d0000150Dsv*sd*bc*sc*i*
alias:          pci:v00008086d000010E7sv*sd*bc*sc*i*
alias:          pci:v00008086d000010E6sv*sd*bc*sc*i*
alias:          pci:v00008086d00001518sv*sd*bc*sc*i*
alias:          pci:v00008086d0000150Asv*sd*bc*sc*i*
alias:          pci:v00008086d000010C9sv*sd*bc*sc*i*
depends:        dca
vermagic:       2.6.32.39-175.xendom0.el6.x86_64 SMP mod_unload
parm:           max_vfs:Maximum number of virtual functions to allocate per physical function (uint)

마지막 parm: 라인을 주목하자. 이것이 바로 SR-IOV의 기능을 설명한다. max_vfs option을 주어 몇 개의 VF를 만들지 설정할 수 있다.

Dom0 설정

GRUB_CMDLINE_LINUX_DEFAULTpci_pt_e820_access=on, GRUB_CMDLINE_XEN_DEFAULTiommu=1 msi=1 추가하고 grub를 업데이트(update-grub)한다.

dom0# vi /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="quiet pci_pt_e820_access=on"
GRUB_CMDLINE_XEN_DEFAULT="dom0_mem=4G,max:4G iommu=1 msi=1"
dom0# update-grub
  • iommu=1 : enables SR-IOV
  • msi=1 : enables MSI-X interrupts
  • pci_pt_e820_access=on : enables direct assignment of a PCIe device to a Virtual Machine

그리고 아래와 같이 modprobe를 설정한다. igb driver를 loading할때 7개의 VF를 생성하고,

dom0# vi /etc/modprobe.d/igb.conf
options igb max_vfs=7
dom0# vi /etc/modprobe.d/igbvf-blacklist.conf
blacklist igbvf
dom0# update-initramfs -k `uname -r` -t -u
  • options igb max_vfs=7 : igb driver를 loading할 때 VF를 7개 생성
  • blacklist igbvf : igbvf는 domU에서 VF를 사용하기 위해서 loading하는 module이다. 따라서 dom0에서는 blacklist에 올려놓아 loading하지 않도록 한다.

이제 SR-IOV 설정이 끝났다. 리부팅한다.

dom0# lspci |grep Eth
01:00.0 Ethernet controller: Intel Corporation 82575EB Gigabit Network Connection (rev 02)
01:00.1 Ethernet controller: Intel Corporation 82575EB Gigabit Network Connection (rev 02)
03:00.0 Ethernet controller: Intel Corporation 82576 Gigabit Network Connection (rev 01)
03:00.1 Ethernet controller: Intel Corporation 82576 Gigabit Network Connection (rev 01)
03:10.0 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
03:10.1 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
03:10.2 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
03:10.3 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
03:10.4 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
03:10.5 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
03:10.6 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
03:10.7 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
03:11.0 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
03:11.1 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
03:11.2 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
03:11.3 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
03:11.4 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
03:11.5 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)

Virtual function이 14개 생성된 것을 볼 수 있다. 82576 NIC이 두 개이고, max_vfs=7으로 했으므로 2*7 = 14개 생성된 것이다. 이것은 dmesg에서 보다 더 잘 볼 수 있다.

dom0# dmesg |grep -i vfs
igb 0000:03:00.0: 7 vfs allocated
igb 0000:03:00.1: 7 vfs allocated

이제 domU가 PCIe 장치를 바로 사용할 수 있도록 설정하자.

dom0# vi /etc/modprobe.d/pciback.conf
alias pciback xen-pciback
options pciback hide=(03:10.0)(03:10.1)(03:10.2)(03:10.3)(03:10.4)(03:10.5)(03:10.6)(03:10.7)(03:11.0)(03:11.1)(03:11.2)(03:11.3)(03:11.4)(03:11.5)

위 내용은 pciback module을 올릴 때 VFs에 해당하는 장치를 숨긴다. 실제 module이름은 xen-pciback이고 alias로 pciback을 설정하였다. 그리고 hide option을 통해 VFs 장치를 나열하였다.

pciback module을 올려보자.

dom0# modprobe pciback
dom0# dmesg
....
[  134.962573] pciback 0000:03:10.0: seizing device
[  134.962583] pciback 0000:03:10.2: seizing device
[  134.962592] pciback 0000:03:10.4: seizing device
[  134.962597] pciback 0000:03:10.6: seizing device
[  134.962602] pciback 0000:03:11.0: seizing device
[  134.962607] pciback 0000:03:11.2: seizing device
[  134.962612] pciback 0000:03:11.4: seizing device
[  134.962617] pciback 0000:03:10.1: seizing device
[  134.962621] pciback 0000:03:10.3: seizing device
[  134.962627] pciback 0000:03:10.5: seizing device
[  134.962632] pciback 0000:03:10.7: seizing device
[  134.962636] pciback 0000:03:11.1: seizing device
[  134.962641] pciback 0000:03:11.3: seizing device
[  134.962646] pciback 0000:03:11.5: seizing device
[  134.962707] pciback 0000:03:11.5: enabling device (0000 -> 0002)
[  134.962750] pciback 0000:03:11.3: enabling device (0000 -> 0002)
[  134.962787] pciback 0000:03:11.1: enabling device (0000 -> 0002)
[  134.962823] pciback 0000:03:10.7: enabling device (0000 -> 0002)
[  134.962865] pciback 0000:03:10.5: enabling device (0000 -> 0002)
[  134.962908] pciback 0000:03:10.3: enabling device (0000 -> 0002)
[  134.962944] pciback 0000:03:10.1: enabling device (0000 -> 0002)
[  134.962978] pciback 0000:03:11.4: enabling device (0000 -> 0002)
[  134.963011] pciback 0000:03:11.2: enabling device (0000 -> 0002)
[  134.963045] pciback 0000:03:11.0: enabling device (0000 -> 0002)
[  134.963080] pciback 0000:03:10.6: enabling device (0000 -> 0002)
[  134.963116] pciback 0000:03:10.4: enabling device (0000 -> 0002)
[  134.963150] pciback 0000:03:10.2: enabling device (0000 -> 0002)
[  134.963183] pciback 0000:03:10.0: enabling device (0000 -> 0002)
[  134.963240] xen-pciback: backend is vpci

이제 domU가 SR-IOV를 사용할 준비가 되었다. 다음 명령으로 어느 pci장치를 이용할 수 있는 지 알 수 있다.

dom0# xm pci-list-assignable-devices |sort -n  (xl pci-assignable-list)
xl pci-list-assignable-devices
0000:03:10.0
0000:03:10.1
0000:03:10.2
0000:03:10.3
0000:03:10.4
0000:03:10.5
0000:03:10.6
0000:03:10.7
0000:03:11.0
0000:03:11.1
0000:03:11.2
0000:03:11.3
0000:03:11.4
0000:03:11.5

DomU 설정

domU config파일에 pci=[‘03:10.0’] 을 추가하자.

#vif=["mac=00:16:3e:13:d1:31,bridge=xenbr0"]
pci=["03:10.0"]

vif 부분을 주석처리하였다. 즉, xen netback을 사용하지 않고 pci through 장치를 사용하겠다는 것이다.

VM을 구동하여 정상적으로 잡혀 있는지 확인한다.

domU#  lspci
00:00.0 Host bridge: Intel Corporation 440FX - 82441FX PMC [Natoma] (rev 02)
00:01.0 ISA bridge: Intel Corporation 82371SB PIIX3 ISA [Natoma/Triton II]
00:01.1 IDE interface: Intel Corporation 82371SB PIIX3 IDE [Natoma/Triton II]
00:01.2 USB Controller: Intel Corporation 82371SB PIIX3 USB [Natoma/Triton II] (rev 01)
00:01.3 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 01)
00:02.0 VGA compatible controller: Technical Corp. Device 1111
00:03.0 Unassigned class [ff80]: XenSource, Inc. Xen Platform Device (rev 01)
00:05.0 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)

맨 마지막 라인을 보면 pci passthrough가 된 것을 볼 수 있다. intel 82576 NIC의 VF가 보인다.

이제 DomU의 network를 설정하면 된다.

troubleshooting

DomU Kernel Version

Linux Kernel 2.6.37부터 PCI frontend driver가 SR-IOV를 지원한다.

Dom0에서 VF에 Mac 부여

VF에 Mac주소를 할당하지 않고 VM을 부팅하면 VM이 mac 주소가 없다고 하여 NIC자체를 거부한다. 따라서 dom0에 아래와 같이 할당할 VF에 대한 Mac을 설정해주고 domu를 부팅해야 한다.

dom0# ip link set eth0 vf 0 mac 00:1e:67:65:93:01

이전과 이렇게 다른 이유는 xen version 차이(4.1.4 vs. 4.4-unstable) 때문일 것이다.

특정 서버의 경우 iommu 옵션 변경 필요

일부 수퍼마이크로 서버의 경우 Xen grub option에 iommu=1 로 주고 부팅하면 다음과 같은 에러가 발생한다.

(XEN) DMAR_IQA_REG = 7f79d000
(XEN) DMAR_IQH_REG = 0
(XEN) DMAR_IQT_REG = 20
(XEN)
(XEN) ****************************************
(XEN) Panic on CPU 0:
(XEN) queue invalidate wait descriptor was not executed
(XEN) ****************************************
(XEN)
(XEN) Reboot in five seconds...

이 경우 queue invalidate를 하지 않도록 수정해야 한다. iommu=no-qinval을 주고 부팅하면 된다.