2016年6月15日 星期三

[Ubuntu] KVM啟用SR-IOV功能

Virtual Function I/O - VFIO 

Single Root I/O Virtualization (SR-IOV)



  • 確認網卡支援SR-IOV
    //選擇要確認的網卡
    #lspci
    ...(省略)
    05:00.0 Ethernet controller: Intel Corporation Ethernet Controller 10-Gigabit X540-AT2 (rev 01)
    ...(省略)

    #lspci -s 05:00.0 -vvv | grep "Single Root I/O Virtualization"

  • 啟動IOMMU
    //編輯 grub (vim /etc/default/grub)

    //Intel CPU
    GRUB_CMDLINE_LINUX_DEFAULT="intel_iommu=on"

    //AMD CPU
    GRUB_CMDLINE_LINUX_DEFAULT="amd_iommu=on"
    #update-grub

    //啟動匯入
    //編輯 ixgbe.conf(/etc/modprobe.d/ixgbe.conf)
    #

  • 匯入Driver
    //匯入vxlan
    #modprobe vxlan

    //匯入pci-stub
    #modprobe pci_stub

    // 啟動Virtual Function
    // 方法一:
    // 匯入1G的ko檔,開啟Function。成功開啟後可從ip a看到新的網卡。
    #modprobe -r ixgbe // 移除ixgbe
    #modprobe ixgbe max_vfs=<int> //啟動Virtual Functions功能,<int>根據網卡而定。

    //匯入10G的ko檔,開啟Function。成功開啟後可從ip a看到新的網卡。
    #modprobe -r igb // 移除ixgbe
    #modprobe igb max_vfs=<int> //啟動Virtual Functions功能,<int>根據網卡而定。

    // 方法二:
    // 取得該張網卡可使用的最大VFS
    // 指令:
    #cat /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_totalvfs
    Ex:
    #cat /sys/bus/pci/devices/0000\:01\:00.0/sriov_totalvfs
    
    
    取得 01\:00.0 方式:
    #lspci
    
    顯示:
    ...(省略)
    
    01:00.0 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
    
    ...(省略)
    
    // 指定對某實體開啟VF
    // 指令:
    #echo 8 > /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs
    
    
    Ex:
    #echo 8 > /sys/bus/pci/devices/0000\:01\:00.0/sriov_numvfs




  • 初始化PCI相關設定
    //本機器共有兩張支援SR-IOV功能的網卡,假設使用第二張網卡做為本次實驗。
    #lspci | grep "Virtual Function"

    顯示:
    ...(省略)

    01:00.0 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
    01:00.1 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
    01:10.0 Ethernet controller: Intel Corporation I350 Ethernet Controller Virtual Function (rev 01)
    01:10.1 Ethernet controller: Intel Corporation I350 Ethernet Controller Virtual Function (rev 01)
    ...(省略)
    取得 01:10.1,再取的 vendor和device ID
    #lspci -s 01:10.1 -n

    顯示:
    01:10.3 0200: 8086:1520 (rev 01)

  • 匯入至 pci-stub
    echo "8086 1520" > /sys/bus/pci/drivers/pci-stub/new_id
    echo "0000:01:10.1" > /sys/bus/pci/drivers/igbvf/unbind
    echo "0000:01:10.1" > /sys/bus/pci/drivers/pci-stub/bind

    若要取消功能則執行

    echo "8086 1520" > /sys/bus/pci/drivers/pci-stub/remove_id

  • 啟動KVM
    #brctl addbr br0
    #tunctl -t tap0

    #qemu-system-x86_64 test.img --enable-kvm -netdev tap,id=hostnet0,ifname=vnet0,script=/etc/qemu-ifup -device pci-assign,host=01:10.1 -vnc :0,password -k en-us -monitor stdio

    Note :
    /etc/qemu-ifup的功能是綁定default gw的那張網卡,若不是要綁定那張網卡,需修改該script

  • 指定某個Virtual Function tagged vlan
    //假設 eth0是Physical function,並且 virtual function 1 tagged vlan 2
    //指令:
    #ip link set <pf> vf <vf_index> vlan <vlan id>  qos <pirority> mac  <macaddr>

    #ip link set eth0 down
    #ip link set eth0 vf 1 vlan 2
    #ip link set eth0 up

    //顯示vf狀態 #ip link show dev eth0

    顯示:
    link/ether a0:36:9f:41:8b:e3 brd ff:ff:ff:ff:ff:ff
      vf 0 MAC 9e:21:26:cb:dc:47, vlan 2, spoof checking on, link-state auto
      vf 1 MAC 5e:8c:75:69:c3:19, spoof checking on, link-state auto
      vf 2 MAC 00:00:00:00:00:00, spoof checking on, link-state auto ...(省略)

    //啟動KVM,假設virtual function 1 , host=01:10.3
    # qemu-system-x86_64 test.img --enable-kvm -netdev tap,id=hostnet0,script=/etc/qemu-ifup -device pci-assign,host=01:10.3 -vnc :0,1qazxcvb -k en-us -monitor stdio

Reference: 
[1] 英特爾的VT-x、VT-d、VT-c技術概述
[2] KVM 介绍(4):I/O 设备直接分配和 SR-IOV [KVM PCI/PCIe Pass-Through SR-IOV]
[3] SR-IOV Mode Utilization in a DPDK Environment
[4] PCI_EXPRESS_PASSTHROUGHb
[5] HowTo Set Virtual Network Attributes on a Virtual Function (SR-IOV)

1 則留言: