Red Hat Training

A Red Hat training course is available for Red Hat Enterprise Linux

16.2.2. 使用 SR-IOV

本节介绍了使用 PCI 透传将支持 SR-IOV 的虚拟功能(multiport 网卡)为虚拟机为虚拟机分配为网络设备。
通过添加带有 virsh editvirsh attach-device 命令的 <hostdev> 中的设备条目,可将 SR-IOV 虚拟功能(VF)分配给虚拟机。但是,这个问题可能会有问题,因为与常规网络设备不同,SR-IOV VF 网络设备没有永久唯一的 MAC 地址,每次主机重启时都会分配一个新的 MAC 地址。因此,即使客户端重启后分配了相同的 VF,当主机重启时,客户机确定其网络适配器具有新的 MAC 地址。因此,客户机在每次都连接了新硬件,通常需要对客户机的网络设置进行重新配置。
libvirt 包含 <interface type='hostdev'> 接口设备。通过使用此接口设备,libvirt 将首先执行指示的任何网络特定硬件/交换机初始化(如设置 MAC 地址、VLAN 标签或 802.1Qbh 虚拟端口参数),然后对客户机执行 PCI 设备分配。
使用 <interface type='hostdev'> 接口设备需要:
  • 支持 SR-IOV 的网卡,
  • 支持 Intel VT-d 或 AMD IOMMU 扩展的主机硬件
  • 要分配的 VF 的 PCI 地址。
重要
将 SR-IOV 设备分配给虚拟机需要主机硬件支持 Intel VT-d 或 AMD IOMMU 规格。
要在 Intel 或 AMD 系统中附加 SR-IOV 网络设备,请按照以下步骤执行:

过程 16.8. 在 Intel 或 AMD 系统中附加 SR-IOV 网络设备

  1. 在 BIOS 和内核中启用 Intel VT-d 或者 AMD IOMMU 规格

    在 Intel 系统中,在 BIOS 中启用 Intel VT-d(如果尚未启用)。请参阅 过程 16.1, “为 PCI 设备分配准备 Intel 系统” 在 BIOS 和内核中启用 Intel VT-d 中的程序帮助。
    如果 Intel VT-d 已经启用并正常工作,请跳过这一步。
    在 AMD 系统中,在 BIOS 中启用 AMD IOMMU 规格(如果尚未启用)。请参阅 过程 16.2, “为 PCI 设备分配准备 AMD 系统” 有关在 BIOS 中启用 IOMMU 的过程帮助。
  2. 验证支持

    验证是否检测到具有 SR-IOV 功能的 PCI 设备。这个示例列出了支持 SR-IOV 的 Intel 82576 网络接口卡。使用 lspci 命令验证该设备是否已检测到。
    # lspci
    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)
    请注意,输出已被修改来删除所有其它设备。
  3. 激活虚拟功能

    运行以下命令:
    # echo ${num_vfs} > /sys/class/net/enp14s0f0/device/sriov_numvfs
  4. 使虚拟功能持久

    要使虚拟功能在重新引导时持久保留,请使用您选择的编辑器创建类似如下的 udev 规则,其中指定 VF 的预期数量(本例中为 2),最多使用网络接口卡支持的限制。在以下示例中,将 enp14s0f0 替换为 PF 网络设备名称,并调整 ENV{ID_NET_DRIVER} 值以匹配正在使用的驱动程序:
    # vim /etc/udev/rules.d/enp14s0f0.rules
    ACTION=="add", SUBSYSTEM=="net", ENV{ID_NET_DRIVER}=="ixgbe",
    ATTR{device/sriov_numvfs}="2"
    
    这将确保在引导时启用该功能。
  5. 检查新的虚拟功能

    使用 lspci 命令,列出附加到 Intel 82576 网络设备的新增虚拟功能。(此外,使用 grep 搜索 虚拟功能,以搜索支持虚拟功能的设备。)
    # lspci | grep 82576
    0b:00.0 Ethernet controller: Intel Corporation 82576 Gigabit Network Connection (rev 01)
    0b:00.1 Ethernet controller: Intel Corporation 82576 Gigabit Network Connection (rev 01)
    0b:10.0 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
    0b:10.1 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
    0b:10.2 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
    0b:10.3 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
    0b:10.4 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
    0b:10.5 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
    0b:10.6 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
    0b:10.7 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
    0b:11.0 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
    0b:11.1 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
    0b:11.2 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
    0b:11.3 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
    0b:11.4 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
    0b:11.5 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
    PCI 设备标识符通过 lspci 命令的 -n 参数找到。物理功能与 0b:00.00b:00.1 对应。所有虚拟功能在描述中包含 虚拟功能
  6. 使用 virsh 验证设备是否存在

    libvirt 服务必须在向虚拟机中添加设备前识别该设备。libvirt 使用与 lspci 输出类似的标记。lspci 输出的所有标点字符 :. 均更改为下划线(_)。
    使用 virsh nodedev-list 命令和 grep 命令从可用主机设备列表中过滤 Intel 82576 网络设备。0b 是本例中 Intel 82576 网络设备的过滤器。这可能会因您的系统而异,并可能导致额外的设备。
    # virsh nodedev-list | grep 0b
    pci_0000_0b_00_0
    pci_0000_0b_00_1
    pci_0000_0b_10_0
    pci_0000_0b_10_1
    pci_0000_0b_10_2
    pci_0000_0b_10_3
    pci_0000_0b_10_4
    pci_0000_0b_10_5
    pci_0000_0b_10_6
    pci_0000_0b_11_7
    pci_0000_0b_11_1
    pci_0000_0b_11_2
    pci_0000_0b_11_3
    pci_0000_0b_11_4
    pci_0000_0b_11_5
    虚拟功能和物理功能的 PCI 地址应该位于列表中。
  7. 使用 virsh 获取设备详情

    pci_0000_0b_00_0 是物理功能之一,pci_0000_0b_10_0 是物理功能第一个对应的虚拟功能。使用 virsh nodedev-dumpxml 命令获取这两个设备的详情。
    # virsh nodedev-dumpxml pci_0000_03_00_0
    <device>
      <name>pci_0000_03_00_0</name>
      <path>/sys/devices/pci0000:00/0000:00:01.0/0000:03:00.0</path>
      <parent>pci_0000_00_01_0</parent>
      <driver>
        <name>igb</name>
      </driver>
      <capability type='pci'>
        <domain>0</domain>
        <bus>3</bus>
        <slot>0</slot>
        <function>0</function>
        <product id='0x10c9'>82576 Gigabit Network Connection</product>
        <vendor id='0x8086'>Intel Corporation</vendor>
        <capability type='virt_functions'>
          <address domain='0x0000' bus='0x03' slot='0x10' function='0x0'/>
          <address domain='0x0000' bus='0x03' slot='0x10' function='0x2'/>
          <address domain='0x0000' bus='0x03' slot='0x10' function='0x4'/>
          <address domain='0x0000' bus='0x03' slot='0x10' function='0x6'/>
          <address domain='0x0000' bus='0x03' slot='0x11' function='0x0'/>
          <address domain='0x0000' bus='0x03' slot='0x11' function='0x2'/>
          <address domain='0x0000' bus='0x03' slot='0x11' function='0x4'/>
        </capability>
        <iommuGroup number='14'>
          <address domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
          <address domain='0x0000' bus='0x03' slot='0x00' function='0x1'/>
        </iommuGroup>
      </capability>
    </device>
    # virsh nodedev-dumpxml pci_0000_03_11_5
    <device>
      <name>pci_0000_03_11_5</name>
      <path>/sys/devices/pci0000:00/0000:00:01.0/0000:03:11.5</path>
      <parent>pci_0000_00_01_0</parent>
      <driver>
        <name>igbvf</name>
      </driver>
      <capability type='pci'>
        <domain>0</domain>
        <bus>3</bus>
        <slot>17</slot>
        <function>5</function>
        <product id='0x10ca'>82576 Virtual Function</product>
        <vendor id='0x8086'>Intel Corporation</vendor>
        <capability type='phys_function'>
          <address domain='0x0000' bus='0x03' slot='0x00' function='0x1'/>
        </capability>
        <iommuGroup number='35'>
          <address domain='0x0000' bus='0x03' slot='0x11' function='0x5'/>
        </iommuGroup>
      </capability>
    </device>
    本例将虚拟功能 pci_0000_03_10_2 添加到第 8 步的虚拟机。请注意虚拟功能的 bus插槽 和功能参数:这些是添加该设备所必需的。
    将这些参数复制到临时 XML 文件中,例如 /tmp/new-interface.xml
       <interface type='hostdev' managed='yes'>
         <source>
           <address type='pci' domain='0x0000' bus='0x03' slot='0x10' function='0x2'/>
         </source>
       </interface>
    注意
    当虚拟机启动时,它应该会看到物理适配器提供的类型的网络设备,并配置了 MAC 地址。此 MAC 地址将在主机间保持不变,并且 guest 重新启动。
    以下 <interface> 示例显示可选 <mac address><virtualport><vlan> 元素的语法。在实践中,使用 <vlan><virtualport> 元素,不能同时使用这两个元素,如示例所示:
    ...
     <devices>
       ...
       <interface type='hostdev' managed='yes'>
         <source>
           <address type='pci' domain='0' bus='11' slot='16' function='0'/>
         </source>
         <mac address='52:54:00:6d:90:02'>
         <vlan>
            <tag id='42'/>
         </vlan>
         <virtualport type='802.1Qbh'>
           <parameters profileid='finance'/>
         </virtualport>
       </interface>
       ...
     </devices>
    如果您没有指定 MAC 地址,则会自动生成一个地址。<virtualport> 元素仅在连接到 802.11Qbh 硬件交换机时使用。<vlan> 元素将透明地将客户机的设备放在标记 42 的 VLAN 上。
  8. 将虚拟功能添加到虚拟机

    通过以下命令,将虚拟功能添加到虚拟机,以及上一步中创建的临时文件。这会立即附加新设备,并保存它以便在以后的客户机重启。
    virsh attach-device MyGuest /tmp/new-interface.xml --live --config
    
    使用 virsh attach-device 指定 --live 选项,将新设备附加到运行的客户机中。使用 --config 选项可确保新设备在以后的客户机重启后可用。
    注意
    只有在客户机运行时接受 --live 选项。如果在非运行的客户机中使用 --live 选项,则 virsh 将返回错误。
虚拟机检测到一个新的网卡。这个新卡是 SR-IOV 设备的虚拟功能。