SR-IOV

本页的目的是描述如何在 OpenStack (使用 OpenStack Networking) 中启用 SR-IOV 功能。此功能首次在 OpenStack Juno 版本中引入。本页旨在作为配置 OpenStack Networking 和 OpenStack Compute 以创建 SR-IOV 端口的指南。

基础知识

PCI-SIG 单根 I/O 虚拟化和共享 (SR-IOV) 功能自 Juno 版本以来在 OpenStack 中可用。SR-IOV 规范定义了一种虚拟化 PCIe 设备的标准化机制。该机制可以将单个 PCIe 以太网控制器虚拟化为多个 PCIe 设备。每个设备都可以直接分配给实例,绕过 hypervisor 和虚拟交换机层。因此,用户能够实现低延迟和接近线路速度的性能。

本文档中使用了以下术语

术语

定义

PF

物理功能。支持 SR-IOV 的物理以太网控制器。

VF

虚拟功能。从物理以太网控制器创建的虚拟 PCIe 设备。

SR-IOV 代理

SR-IOV 代理允许您设置端口的管理员状态、配置端口安全 (启用和禁用欺骗检查) 以及配置 QoS 速率限制和最小带宽。您必须在每个使用 SR-IOV 端口的计算节点上包含 SR-IOV 代理。

注意

在 Mitaka 之前,SR-IOV 代理是可选的,并且在 Liberty 之前未默认启用。

注意

在 Liberty 中添加了控制端口安全性和 QoS 速率限制设置的功能。

支持的以太网控制器

已知以下制造商的产品可以正常工作

  • Intel

  • Mellanox

  • QLogic

  • Broadcom

有关 Mellanox SR-IOV Ethernet ConnectX 卡的信息,请参阅 Mellanox: 如何在 ConnectX-4 或更新版本上配置 SR-IOV VFs

有关 QLogic SR-IOV Ethernet 卡的信息,请参阅 用户指南 OpenStack SR-IOV 配置部署

有关 Broadcom NetXtreme 系列以太网卡的信息,请参阅 Broadcom NetXtreme 产品页面

使用 SR-IOV 接口

为了启用 SR-IOV,需要执行以下步骤

  1. 创建虚拟功能 (计算)

  2. 配置 nova-compute 中 PCI 设备的允许列表 (计算)

  3. 配置 neutron-server (控制器)

  4. 配置 nova-scheduler (控制器)

  5. 启用 neutron sriov-agent (计算)

我们建议使用 VLAN 提供商网络进行隔离。这样,您可以在单个网络上组合没有 SR-IOV 端口的实例和具有 SR-IOV 端口的实例。

注意

在本指南中,eth3 用作 PF,physnet2 用作配置为 VLAN 范围的提供商网络。这些端口在不同的环境中可能会有所不同。

创建虚拟功能 (计算)

创建将用于 SR-IOV 的网络接口的 VFs。我们使用 eth3 作为 PF,它也用作 VLAN 提供商网络的接口,并且可以访问所有机器的私有网络。

注意

这些步骤详细介绍了如何在 Intel 系统上使用 Mellanox ConnectX-4 和更新/Intel SR-IOV 以太网卡创建 VFs。对于不同的硬件配置,步骤可能会有所不同。

  1. 确保在 BIOS 中启用了 SR-IOV 和 VT-d。

  2. 通过将 intel_iommu=on 添加到内核参数,在 Linux 中启用 IOMMU,例如使用 GRUB。

  3. 在每个计算节点上,通过 PCI SYS 接口创建 VFs

    # echo '8' > /sys/class/net/eth3/device/sriov_numvfs
    

    注意

    在某些 PCI 设备上,请注意,当更改 VF 的数量时,您会收到 Device or resource busy 错误。在这种情况下,您必须首先将 sriov_numvfs 设置为 0,然后将其设置为您的新值。

    注意

    网络接口可以同时用于 PCI 直通 (使用 PF) 和 SR-IOV (使用 VFs)。如果使用 PF,则存储在 sriov_numvfs 文件中的 VF 数量将丢失。如果 PF 重新连接到操作系统,分配给此接口的 VF 数量将为零。为了始终将 VF 数量分配给此接口,请修改接口配置文件,添加一个 ifup 脚本命令。

    在 Ubuntu 上,修改 /etc/network/interfaces 文件

    auto eth3
    iface eth3 inet dhcp
    pre-up echo '4' > /sys/class/net/eth3/device/sriov_numvfs
    

    在 RHEL 及其衍生版本上,修改 /sbin/ifup-local 文件

    #!/bin/sh
    if [[ "$1" == "eth3" ]]
    then
        echo '4' > /sys/class/net/eth3/device/sriov_numvfs
    fi
    

    警告

    或者,您可以将 max_vfs 传递给网络接口的内核模块来创建 VFs。但是,max_vfs 参数已被弃用,因此 PCI SYS 接口是首选方法。

    您可以确定 PF 可以支持的最大 VF 数量

    # cat /sys/class/net/eth3/device/sriov_totalvfs
    63
    
  4. 验证 VFs 是否已创建并且处于 up 状态。例如

    # lspci | grep Ethernet
    82:00.0 Ethernet controller: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ Network Connection (rev 01)
    82:00.1 Ethernet controller: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ Network Connection (rev 01)
    82:10.0 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
    82:10.2 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
    82:10.4 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
    82:10.6 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
    82:11.0 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
    82:11.2 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
    82:11.4 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
    82:11.6 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
    
    # ip link show eth3
    8: eth3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT qlen 1000
       link/ether a0:36:9f:8f:3f:b8 brd ff:ff:ff:ff:ff:ff
       vf 0 MAC 00:00:00:00:00:00, spoof checking on, link-state auto
       vf 1 MAC 00:00:00:00:00:00, spoof checking on, link-state auto
       vf 2 MAC 00:00:00:00:00:00, spoof checking on, link-state auto
       vf 3 MAC 00:00:00:00:00:00, spoof checking on, link-state auto
       vf 4 MAC 00:00:00:00:00:00, spoof checking on, link-state auto
       vf 5 MAC 00:00:00:00:00:00, spoof checking on, link-state auto
       vf 6 MAC 00:00:00:00:00:00, spoof checking on, link-state auto
       vf 7 MAC 00:00:00:00:00:00, spoof checking on, link-state auto
    

    如果接口处于关闭状态,请在启动客户机之前将其设置为 up,否则实例将无法启动

    # ip link set eth3 up
    
  5. 重启后持久化创建的 VFs

    # echo "echo '7' > /sys/class/net/eth3/device/sriov_numvfs" >> /etc/rc.local
    

    注意

    使 PCI SYS 设置持久化的建议方法是通过 sysfsutils 工具。但是,这在许多主流发行版上默认情况下不可用。

配置 nova-compute 的 PCI 设备允许列表 (计算)

  1. 配置 nova-compute 服务可以使用哪些 PCI 设备。编辑 nova.conf 文件

    [pci]
    passthrough_whitelist = { "devname": "eth3", "physical_network": "physnet2"}
    

    这告诉 Compute 服务,属于 eth3 的所有 VFs 都可以传递到实例,并且属于提供商网络 physnet2

    或者,[pci] passthrough_whitelist 参数也支持通过以下方式允许设备

    • PCI 地址:地址使用与 lspci 中相同的语法,并且可以使用星号 (*) 来匹配任何内容。

      [pci]
      passthrough_whitelist = { "address": "[[[[<domain>]:]<bus>]:][<slot>][.[<function>]]", "physical_network": "physnet2" }
      

      例如,要匹配任何域、总线 0a、插槽 00 和所有功能

      [pci]
      passthrough_whitelist = { "address": "*:0a:00.*", "physical_network": "physnet2" }
      
    • Linux 实用程序 lspci 显示的 PCI vendor_idproduct_id

      [pci]
      passthrough_whitelist = { "vendor_id": "<id>", "product_id": "<id>", "physical_network": "physnet2" }
      

    如果由 PCI 地址或 devname 定义的设备对应于 SR-IOV PF,则 PF 下的所有 VFs 都将匹配该条目。支持每个主机上多个 [pci] passthrough_whitelist 条目。

    为了使 SR-IOV 请求“信任模式”,[pci] passthrough_whitelist 参数还支持 trusted 标记。

    注意

    此功能仅从 Compute 服务的 18.0.0 (Rocky) 版本开始支持,该版本配置为使用 libvirt 驱动程序。

    重要提示

    启用信任端口存在安全隐患。受信任的 VFs 可以设置为 VF 混杂模式,这将使其能够接收发送到物理功能的未匹配和多播流量。

    例如,要允许用户请求具有设备 eth3 上信任功能的 SR-IOV 设备

    [pci]
    passthrough_whitelist = { "devname": "eth3", "physical_network": "physnet2", "trusted":"true" }
    

    端口必须使用与 trusted 标记匹配的绑定配置文件创建,请参阅 使用 SR-IOV 端口启动实例

  2. 重新启动 nova-compute 服务以使更改生效。

配置 neutron-server (控制器)

注意

本节不适用于使用 SR-IOV 在主机端使用 SmartNIC DPU 设备的远程管理端口,也不依赖于 sriovnicswitch 机制驱动程序。

  1. sriovnicswitch 添加为机制驱动程序。编辑每个控制器的 ml2_conf.ini 文件

    [ml2]
    mechanism_drivers = openvswitch,sriovnicswitch
    
  2. 确保为所选的网络类型配置 physnet。编辑每个控制器的 ml2_conf.ini 文件

    [ml2_type_vlan]
    network_vlan_ranges = physnet2
    
  3. plugin.ini 文件作为参数添加到 neutron-server 服务。编辑适当的初始化脚本以配置 neutron-server 服务以加载插件配置文件

    --config-file /etc/neutron/neutron.conf
    --config-file /etc/neutron/plugin.ini
    
  4. 重新启动 neutron-server 服务。

配置 nova-scheduler (控制器)

  1. 在每个运行 nova-scheduler 服务的控制器节点上,将 PciPassthroughFilter 添加到 [filter_scheduler] enabled_filters 以启用此过滤器。确保 [filter_scheduler] available_filters 设置为默认值 nova.scheduler.filters.all_filters

    [filter_scheduler]
    enabled_filters = ComputeFilter, ComputeCapabilitiesFilter, ImagePropertiesFilter, ServerGroupAntiAffinityFilter, ServerGroupAffinityFilter, PciPassthroughFilter
    available_filters = nova.scheduler.filters.all_filters
    
  2. 重新启动 nova-scheduler 服务。

启用 neutron-sriov-nic-agent (计算)

  1. 如果需要,请安装 SR-IOV 代理。

  2. 编辑每个计算节点上的 sriov_agent.ini 文件。例如

    [sriov_nic]
    physical_device_mappings = physnet2:eth3
    exclude_devices =
    

    注意

    physical_device_mappings 参数不限于物理网络和 NIC 之间的 1:1 映射。这使您可以将相同的物理网络映射到多个 NIC。例如,如果 physnet2 连接到 eth3eth4,则 physnet2:eth3,physnet2:eth4 是一个有效选项。

    注意

    SR-IOV 代理未实现任何类型的防火墙驱动程序。

    exclude_devices 参数为空,因此与 eth3 关联的所有 VFs 都可以由代理配置。要排除特定的 VFs,请将它们添加到 exclude_devices 参数,如下所示

    exclude_devices = eth1:0000:07:00.2;0000:07:00.3,eth2:0000:05:00.1;0000:05:00.2
    
  3. 确保 SR-IOV 代理成功运行

    # neutron-sriov-nic-agent \
      --config-file /etc/neutron/neutron.conf \
      --config-file /etc/neutron/plugins/ml2/sriov_agent.ini
    
  4. 启用 neutron SR-IOV 代理服务。

    如果从源代码安装,则必须手动为 init 系统配置 daemon 文件。

(可选) FDB L2 代理扩展

转发数据库 (FDB) 填充是 OVS 代理的 L2 代理扩展。其目的是更新现有实例的 FDB 表,使用普通端口。这使得 SR-IOV 实例和普通实例之间的通信成为可能。FDB 填充扩展的使用场景是

  • 直接端口和普通端口实例位于同一计算节点上。

  • 使用浮动 IP 地址和网络节点位于同一主机的直接端口实例。

有关描述该问题的更多信息,请参阅:虚拟交换技术和 Linux 桥接。

  1. 编辑每个计算节点上的 ovs_agent.ini 文件。例如

    [agent]
    extensions = fdb
    
  2. 添加 FDB 部分和 shared_physical_device_mappings 参数。此参数将每个物理端口映射到其物理网络名称。每个物理网络可以映射到多个端口

    [FDB]
    shared_physical_device_mappings = physnet1:p1p1, physnet1:p1p2
    

使用 SR-IOV 端口启动实例

完成配置后,您可以使用 SR-IOV 端口启动实例。

  1. 如果它不存在,请为所选 physnet 创建网络和子网。这是将连接 SR-IOV 端口的网络。例如

    $ openstack network create --provider-physical-network physnet2 \
        --provider-network-type vlan --provider-segment 1000 \
        sriov-net
    
    $ openstack subnet create --network sriov-net \
        --subnet-pool shared-default-subnetpool-v4 \
        sriov-subnet
    
  2. 获取要创建 SR-IOV 端口的网络 id

    $ net_id=$(openstack network show sriov-net -c id -f value)
    
  3. 创建 SR-IOV 端口。vnic-type=direct 在此处使用,但其他选项包括 normaldirect-physicalmacvtap

    $ openstack port create --network $net_id --vnic-type direct \
        sriov-port
    

    或者,要请求 SR-IOV 端口接受信任功能,应使用 trusted 标记增强绑定配置文件。

    $ openstack port create --network $net_id --vnic-type direct \
        --binding-profile trusted=true \
        sriov-port
    
  4. 获取创建的端口的 id

    $ port_id=$(openstack port show sriov-port -c id -f value)
    
  5. 创建实例。为 NIC 指定在步骤二中创建的 SR-IOV 端口

    $ openstack server create --flavor m1.large --image ubuntu_18.04 \
        --nic port-id=$port_id \
        test-sriov
    

    注意

    有两种方法可以将 VFs 附加到实例。您可以创建 SR-IOV 端口,或使用 Compute 服务中的 pci_alias。有关使用 pci_alias 的更多信息,请参阅 nova-api 配置

ConnectX-3/ConnectX-3 Pro 双端口以太网上的 SR-IOV

与 Mellanox 新一代 NIC 相比,ConnectX-3 系列网络适配器在系统中公开单个 PCI 设备 (PF),无论物理端口的数量如何。当设备是 双端口 并且启用了 SR-IOV 并进行了配置时,我们可能会在 Linux 网络子系统中观察到一些不一致之处。

注意

在下面的示例中,enp4s0 表示与物理端口 1 关联的 PF 网络设备,enp4s0d1 表示与物理端口 2 关联的 PF 网络设备。

示例: 具有 ConnectX-3 双端口设备的系统,总共配置了四个 VFs,两个 VFs 分配给端口一,两个 VFs 分配给端口二。

$ lspci | grep Mellanox
04:00.0 Network controller: Mellanox Technologies MT27520 Family [ConnectX-3 Pro]
04:00.1 Network controller: Mellanox Technologies MT27500/MT27520 Family [ConnectX-3/ConnectX-3 Pro Virtual Function]
04:00.2 Network controller: Mellanox Technologies MT27500/MT27520 Family [ConnectX-3/ConnectX-3 Pro Virtual Function]
04:00.3 Network controller: Mellanox Technologies MT27500/MT27520 Family [ConnectX-3/ConnectX-3 Pro Virtual Function]
04:00.4 Network controller: Mellanox Technologies MT27500/MT27520 Family [ConnectX-3/ConnectX-3 Pro Virtual Function]

系统中可用四个 VFs,但是,

$ ip link show
31: enp4s0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop master ovs-system state DOWN mode DEFAULT group default qlen 1000
    link/ether f4:52:14:01:d9:e1 brd ff:ff:ff:ff:ff:ff
    vf 0 MAC 00:00:00:00:00:00, vlan 4095, spoof checking off, link-state auto
    vf 1 MAC 00:00:00:00:00:00, vlan 4095, spoof checking off, link-state auto
    vf 2 MAC 00:00:00:00:00:00, vlan 4095, spoof checking off, link-state auto
    vf 3 MAC 00:00:00:00:00:00, vlan 4095, spoof checking off, link-state auto
32: enp4s0d1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether f4:52:14:01:d9:e2 brd ff:ff:ff:ff:ff:ff
    vf 0 MAC 00:00:00:00:00:00, vlan 4095, spoof checking off, link-state auto
    vf 1 MAC 00:00:00:00:00:00, vlan 4095, spoof checking off, link-state auto
    vf 2 MAC 00:00:00:00:00:00, vlan 4095, spoof checking off, link-state auto
    vf 3 MAC 00:00:00:00:00:00, vlan 4095, spoof checking off, link-state auto

ip 命令将每个 PF 关联的网络设备识别为每个具有四个 VFs

注意

Mellanox mlx4 驱动程序允许 ip 命令执行来自任一 PF 关联网络设备的所有 VFs 的配置。

为了使 neutron SR-IOV 代理能够正确识别属于正确 PF 网络设备的 VF(从而属于正确的网络端口),管理员需要在 sriov_agent.ini 中提供 exclude_devices 配置选项。

步骤 1:从 mlx4 驱动程序配置文件中获取 VF 到端口的映射:/etc/modprobe.d/mlnx.conf/etc/modprobe.d/mlx4.conf

$ cat /etc/modprobe.d/mlnx.conf | grep "options mlx4_core"
options mlx4_core port_type_array=2,2 num_vfs=2,2,0 probe_vf=2,2,0 log_num_mgm_entry_size=-1

其中

num_vfs=n1,n2,n3 - 驱动程序将在物理端口 1 上启用 n1 个 VF,在物理端口 2 上启用 n2 个 VF,并在双端口 HCA 上启用 n3 个双端口 VF(仅当所有端口都是以太网端口时适用)。

probe_vfs=m1,m2,m3 - 驱动程序探测物理端口 1 上的 m1 个单端口 VF,物理端口 2 上的 m2 个单端口 VF(仅当存在此类端口时适用),m3 个双端口 VF。这些 VF 将附加到 hypervisor。(仅当所有端口都配置为以太网时适用)。

VF 的枚举顺序如下

  1. 端口 1 VF

  2. 端口 2 VF

  3. 双端口 VF

在我们的示例中

04:00.0 : PF 与两个端口关联。
04:00.1 : VF 与端口 1 关联
04:00.2 : VF 与端口 1 关联
04:00.3 : VF 与端口 2 关联
04:00.4 : VF 与端口 2 关联

步骤 2:使用正确的映射更新 sriov_agent.ini 中的 exclude_devices 配置选项

与 PF 关联的每个网络设备都应排除其他端口的 VF

[sriov_nic]
physical_device_mappings = physnet1:enp4s0,physnet2:enp4s0d1
exclude_devices = enp4s0:0000:04:00.3;0000:04:00.4,enp4s0d1:0000:04:00.1;0000:04:00.2

带有 InfiniBand 的 SR-IOV

带有 InfiniBand 的 SR-IOV 支持将虚拟 PCI 设备 (VF) 直接映射到客户机,从而实现更高的性能和高级功能,例如 RDMA(远程直接内存访问)。要使用此功能,您必须

  1. 使用启用 InfiniBand 的网络适配器。

  2. 运行 InfiniBand 子网管理器以启用 InfiniBand 结构。

    所有 InfiniBand 网络都必须运行子网管理器才能正常工作。即使在没有交换机且网卡背靠背连接的简单网络中也是如此。子网管理器对于网卡上的链路启动是必需的。可以有多个子网管理器。在这种情况下,其中一个将充当主子网管理器,任何其他子网管理器将充当在主子网管理器发生故障时接管的备份子网管理器。

  3. 在计算节点上安装 ebrctl 实用程序。

    检查 ebrctl 是否列在 /etc/nova/rootwrap.d/* 中的某个位置

    $ grep 'ebrctl' /etc/nova/rootwrap.d/*
    

    如果 ebrctl 未出现在任何 rootwrap 文件中,请将其添加到 /etc/nova/rootwrap.d/compute.filters 文件中的 [Filters] 部分。

    [Filters]
    ebrctl: CommandFilter, ebrctl, root
    

已知限制

  • 在使用服务质量 (QoS) 时,max_burst_kbps(超过 max_kbps 的突发流量)不受支持。此外,max_kbps 将四舍五入到 Mbps。

  • 在使用 SR-IOV 时,不支持安全组。

  • SR-IOV 未集成到 OpenStack Dashboard (horizon) 中。用户必须使用 CLI 或 API 来配置 SR-IOV 接口。

  • 在 Train 版本中,带有 neutron SR-IOV 端口的实例的 Libvirt Nova virt-driver 中已添加了实时迁移支持。间接模式 SR-IOV 接口(vnic-type: macvtap 或 virtio-forwarder)现在可以透明地迁移到客户机。直接模式 SR-IOV 接口(vnic-type: direct 或 direct-physical)在迁移前分离,迁移后重新连接,因此对客户机而言不是透明的。为了避免在使用直接模式 sriov 进行实时迁移时丢失网络连接,用户应在客户机中创建一个故障转移绑定,其中包含透明的实时迁移端口类型,例如 vnic-type normal 或间接模式 SR-IOV。

    注意

    SR-IOV 功能可能需要特定的 NIC 驱动程序版本,具体取决于供应商。例如,Intel NIC 需要 ixgbe 版本 4.4.6 或更高版本,以及 ixgbevf 版本 3.2.2 或更高版本。

  • 从 Victoria 版本开始,支持将 SR-IOV 端口附加到现有的服务器。