PCI SR-IOV 直通至 nova 实例

https://blueprints.launchpad.net/nova/+spec/pci-passthrough-sriov

启用 nova 实例使用 SR-IOV neutron 端口启动。

问题描述

目前,可以通过 libvirt 的 managed hostdev 设备定义在 domain XML 中实现通用 PCI 设备直通启动虚拟机。使用指南可在 [GPPWIKI] 找到。但是,无法通过 SR-IOV 网卡请求访问虚拟网络。需要 Nova 增强才能支持 Neutron 的 SR-IOV 网络。

传统上,neutron 端口是一个虚拟端口,它连接到计算节点上的 linux bridge 或 openvswitch bridge。随着基于 SR-IOV 的网卡(称为 vNIC)的引入,虚拟桥接器不再是必需的。每个 SR-IOV 端口都与逻辑上驻留在 vNIC 上的虚拟功能 (VF) 相关联。SR-IOV 网络有两种变体。SR-IOV 端口可以由硬件虚拟以太网桥接 (HW VEB) 提供;或者它们可以扩展到上游物理交换机 (IEEE 802.1br)。在后一种情况下,端口的配置在交换机中强制执行。将 SR-IOV 端口连接到其相应的 VF 也有两种变体。SR-IOV 端口可以直接连接到其 VF。或者,它可以连接到驻留在主机上的 macvtap 设备,然后该设备连接到相应的 VF。使用 macvtap 设备可以实现 SR-IOV 的实时迁移。

在 Icehouse 版本中,neutron 方面的一些蓝图得到了批准,并且相关的补丁提交,从而实现了 nova 和 neutron 之间 SR-IOV 网络的交互。有关详细信息,请参阅 [VIFDETA][BINDPRF]

另一个蓝图 [VNICTYP] 在 neutron 端口 API 中添加了支持,允许用户在创建 neutron 端口时指定 vnic-type。当前支持的 vnic-types 是

  • normal: 连接到计算节点上的 linux bridge 或 openvswitch bridge 的传统虚拟端口。

  • direct: 直接连接到虚拟机的 SR-IOV 端口

  • macvtap: 通过 macvtap 设备连接到虚拟机的 SR-IOV 端口。

本规范试图建立在上述 neutron 更改之上,并解决 nova 中的以下功能,以便 openstack 中的 SR-IOV 网络能够端到端地完全正常工作

  1. 生成启用 SR-IOV 网络的 libvirt domain XML 和 network XML。

  2. 基于 SR-IOV 端口的网络连接进行调度。

本规范的目标用例,因此对于 Juno 而言,是使用一个或多个可能使用不同 vnic-types 的 vNIC 启动虚拟机。特别是,用户将执行以下操作以使用 SR-IOV vnic 启动虚拟机

  • 创建一个或多个 neutron 端口。例如

neutron port-create <net-id> --binding:vnic-type direct
  • 使用一个或多个 neutron 端口启动虚拟机。例如

nova boot --flavor m1.large --image <image>
          --nic port-id=<port1> --nic port-id=<port2>

请注意,在 nova boot API 中,用户可以指定 port-id 或 net-id。如果是后者,则假定用户正在请求普通的虚拟端口(不是 SR-IOV 端口)。

本规范将利用现有的 PCI 直通实现,并进行一些增强以实现上述用例。因此,如 [GPPWIKI] 所记录的现有 PCI 直通支持按原样适用于通用 PCI 直通。

提议的变更

为了基于其网络连接调度具有 SR-IOV 端口的实例,必须在做出调度决策时使用 neutron 端口关联的物理网络。必须为每个 neutron 端口选择一个 VF。因此,必须让系统知道 VF 关联的物理网络,并且所选 VF 关联的物理网络必须与 neutron 端口中的物理网络匹配。为了实现上述目标,本规范建议将一个额外的标签称为 physical_network 关联到每个网络 VF。此外,nova 当前不知道 neutron 端口关联的物理网络。因此,nova 需要向 neutron 发出额外的调用,以便从 neutron 检索此信息。在下文中,将详细描述 nova 中的更改,以实现这一点。

请注意,本规范仅支持 libvirt 驱动程序。

PCI 白名单

本规范对现有的 PCI 白名单引入了一些增强功能

  • 允许使用 ‘*’ 和 ‘.’ 聚合声明 PCI 设备

  • 允许将标签与 PCI 设备关联。

请注意,它与以前的 PCI 白名单定义兼容。因此,与 PCI 白名单相关的现有功能按原样工作。

使用 ‘[’ 表示 0 或 1 次出现,‘{’ 表示 0 或多次出现,‘|’ 表示互斥选择,白名单条目定义为

["device_id": "<id>",] ["product_id": "<id>",]
["address": "[[[[<domain>]:]<bus>]:][<slot>][.[<function>]]" |
 "devname": "PCI Device Name",]
{"tag":"<tag_value>",}

<id> 可以是 ‘*’ 或有效的 device/product id,如 linux 工具 lspci 显示的那样。address 使用与 lspci 中相同的语法。有关其描述,请参阅 lspci 的手册中的 ‘-s’ 选项。devname 可以是有效的 PCI 设备名称。本规范中支持的唯一设备名称是 linux 工具 ifconfig -a 显示的,并且对应于 vNIC 上的 PF 或 VF。条目可以关联 0 个或多个标签。

如果由 addressdevname 定义的设备对应于 SR-IOV PF,则 PF 下的所有 VF 都将匹配该条目。

对于 SR-IOV 网络,使用预定义的标签“physical_network”来定义设备连接到的物理网络。白名单条目定义为

["device_id": "<id>",] ["product_id": "<id>",]
["address": "[[[[<domain>]:]<bus>]:][<slot>][.[<function>]]" |
 "devname": "Ethernet Interface Name",]
"physical_network":"name string of the physical network"

支持每个主机上的多个白名单条目,就像现在一样。字段 device_idproduct_idaddressdevname 将与通过查询 libvirt 返回的 PCI 设备进行匹配。

白名单条目在 nova.conf 中以以下格式定义

pci_passthrough_whitelist = {<entry>}

{<entry>} 是一个 json 字典,其定义如上所述。pci_passthrough_whitelist 是一个复数配置,因此可以在 nova.conf 中多次出现。

一些示例是

pci_passthrough_whitelist = {"devname":"eth0",
                             "physical_network":"physnet"}

pci_passthrough_whitelist = {"address":"*:0a:00.*",
                             "physical_network":"physnet1"}

pci_passthrough_whitelist = {"address":":0a:00.",
                             "physical_network":"physnet1"}

pci_passthrough_whitelist = {"vendor_id":"1137","product_id":"0071"}

pci_passthrough_whitelist = {"vendor_id":"1137","product_id":"0071",
                             "address": "0000:0a:00.1",
                             "physical_network":"physnet1"}

PCI 统计信息

在计算节点上,PCI 设备按在 nova.conf 中定义的顺序与 PCI 白名单条目进行匹配。找到匹配项后,该设备将被放置在相应的 PCI 统计信息条目中。

如果设备匹配 PCI 白名单条目,并且 PCI 白名单条目已标记,则标签以及 product_idvendor_id 将用作统计信息键;否则,将使用现有的预定义键。

对于 SR-IOV 网络,PCI 白名单条目将标记有物理网络名称。因此,物理网络名称用作 SR-IOV 网络设备的统计信息键。从概念上讲,对于 SR-IOV 网络,PCI 统计信息条目跟踪连接到计算节点上物理网络的 SR-IOV 端口数量。对于调度目的,可以将其视为一个元组

<host_name> <physical_network_name> <count>

当从物理网络请求端口时,可以从统计信息条目中找到托管物理网络的计算节点。nova 调度器中现有的 PCI 直通过滤器无需更改即可支持 SR-IOV 网络。

不会更改如何使用 nova 资源跟踪器将条目更新并持久保存到 compute_nodes 数据库表中。当前,compute_nodes 数据库表中的一个名为 pci_stats 的列用于将 PCI 统计信息存储为 JSON 文档。PCI 统计信息 JSON 文档基本上是统计信息条目的列表,格式为 <key1> <key2> ….<keyn> : <count>。这不会为 SR-IOV 网络而更改。特别是对于 SR-IOV 网络,PCI 统计信息记录以标签 physical_network_name 以及 product_idvendor_id 作为键。

<physical_network_name>, <product_id>, <vendor_id> : <count>.

请求的网络 (NIC)

当前,每个请求的网络都是一个元组

<neutron-net-id> <v4-fixed-ip> <neutron-port-id>

neutron-net-id 或 neutron-port-id 必须具有有效值,并且 v4-fixed-ip 可以为 None。对于 nova boot 命令中指定的每个 –nic 选项,都会创建一个 requested_network 元组。所有 requested_network 元组都传递到计算节点,并且节点上运行的计算服务使用该信息来请求 neutron 服务。本规范建议在此元组中添加一个额外的字段:pci-request-id

对应于每个 requested_network 元组,都有一个具有有效 vnic-type 的 neutron 端口。如果 vnic-type 是 direct 或 macvtap,则必须将有效的 pci_request_id 填充到元组中(有关详细信息,请参见下文)。pci-request-id 稍后用于在实例启动过程中从 PCI 管理器检索分配给 requested_network 元组(因此是 NIC)的 PCI 设备。

PCI 请求

当前,pci_requests 作为键和关联的 JSON doc 字符串存储在实例的系统元数据中。此外,所有分配给 PCI 直通的 PCI 设备在生成 libvirt xml 方面都受到相同的对待。但是,对于 SR-IOV 网络,需要特殊的 libvirt xml。此外,我们需要一种方法来在实例启动过程的后期将分配的设备与请求的网络(NIC)相关联。在本规范中,我们建议使用 pci_request_id 用于此目的。

每个 PCI 请求都与在将 PCI 请求创建/保存到实例的系统元数据时生成的 pci_request_id 相关联。pci_request_id 用于在计算节点上检索分配的 PCI 设备。特别是对于 SR-IOV 网络,PCI 请求表示为

"physical_network" : <name>
"count" : 1
"pci_request_id" : <request-uuid>

对于 ‘nova boot’ 中指定的每个 –nic,nova-api 创建一个请求的网络元组。对于 SR-IOV NIC,它创建一个 PCI 请求,结果生成一个 pci_request_id 并将其保存在 PCI 请求规范中。相同的 pci_request_id 也保存在 requested_network 中(请参阅最后一部分)。

nova neutronv2 和 VIF

请注意,Nova 网络不会被增强以支持 SR-IOV。但是,负责与 neutron 交互的 Nova 模块需要进行增强。

请参阅 [BINDPRF][VIFDETA][VNICTYP],这些功能已经添加了支持 neutron 中 SR-IOV 端口的功能。因此,nova neutronv2 将被增强以与它们一起工作以支持 SR-IOV 端口。特别是

  • 当 nova 处理 –nic 选项时,物理网络名称将从 neutron 检索。这需要使用具有管理员访问权限的 neutron 提供程序扩展来完成。因此,将进行额外的 neutron 调用以检索物理网络名称。

  • 当 nova 更新 neutron 端口时,binding:profile 需要用包含 pci_vendor_info、pci_slot 和 physical_network 的 pci 信息填充。

  • 在 nova 成功更新 neutron 端口后,它从 neutron 检索端口信息,这些信息用于填充 VIF 对象。将添加新的属性到 VIF 类中以支持 binding:profile、binding:vif_details 和 binding:vnic_type。

nova VIF 驱动程序

每个 neutron 端口都与 vif-type 相关联。以下 VIF 类型与 SR-IOV 支持相关

  • VIF_TYPE_802_QBH: 对应于 IEEE 802.1BR(以前是 IEEE 802.1Qbh)

  • VIF_TYPE_HW_VEB: 用于支持虚拟嵌入式桥接的 vNIC 适配器

  • VIF_TYPE_802_QBG: 对应于 IEEE 802.1QBG。但是,现有的 vif 类型可能不再有用,因为支持 SR-IOV 的已知 neutron 插件不支持 libvirt 参数 1QBG(managerid、typeidversion 和 instanceid)。

nova 通用 libvirt VIF 驱动程序将得到增强以支持前两种 VIF 类型。这包括填充 VIF 配置对象和生成接口 XML。

备选方案

N/A

数据模型影响

当前,为每个 PCI 直通设备创建一个 nova 对象 PciDevice。数据库表 pci_devices 用于持久保存 PciDevice nova 对象。将在 PciDevice nova 对象中添加一个新字段 request_id。相应地,将在数据库表 pci_devices 中添加一个新列 request_id。将包含相应的数据库迁移脚本。

REST API 影响

安全影响

通知影响

其他最终用户影响

性能影响

需要从 neutron 检索端口连接到的物理网络,这需要额外的 neutron 调用。特别是,nova 将调用 neutron show_port 来检查端口的 vnic_type。如果 vnic_typedirectmacvtap,它将调用 neutron show_network 来检索关联的物理网络。因此,当在 nova boot 中的 –nic 选项中指定 port-id 时,对 neutron 的调用次数将略有增加。

其他部署者影响

没有已知的部署器影响,除了为 SR-IOV 网络设备配置 PCI 白名单。

开发人员影响

实现

负责人

主要负责人

baoli

其他贡献者

待定

工作项

  • PCI 白名单

  • PCI 请求

  • PCI 统计信息

  • DB 更改和所需的迁移脚本,PCI 设备对象更改

  • neutronv2

  • VIF

  • libvirt 通用 VIF 驱动程序和实例配置

  • nova compute api 检索物理网络,requested_networks 的更改

依赖项

测试

需要创建单元和 tempest 测试,以确保 SR-IOV 网络的正常运行。对于 tempest 测试,鉴于 SR-IOV 依赖于硬件的性质,可能需要供应商支持和使用适当的 neutron ML2 机制驱动程序。需要增强 Cisco Neutron CI 和 Mellanox 外部测试以支持 SR-IOV tempest 测试。

文档影响

  • 记录新的白名单配置更改

  • 关于如何在 openstack 中使用 SR-IOV 网络的指南/wiki

参考资料