目录


文章目录

  • 目录
  • 前文列表
  • 前言
  • Neutron 的网络实现模型
  • 基于虚拟网络设备的虚拟机流量走向
  • 基于虚拟网络设备的性能瓶颈
  • 在 Neutron 中引入 SR-IOV 技术
  • 基于 SR-IOV 技术的虚拟机流量走向
  • Neutron 配置启用 SR-IOV
  • SR-IOV 与 NUMA 亲和
  • SR-IOV 与 VLAN tag
  • SR-IOV 与安全组


前文列表

《SR-IOV 网卡虚拟化技术》

前言

文章是基于「计算机系统应用」月刊文章《SR-IOV 技术在 OpenStack 中的应用》的学习、扩展与整理,感谢作者分享。

官方网站:https://wiki.openstack.org/wiki/SR-IOV-Passthrough-For-Networking

Neutron 的网络实现模型

Neutron 的网络实现模型,即 Neutron 为了支撑上层抽象的网络资源模型(e.g. Network、Subnet、Port、Router etc.)所实现的底层网元(e.g. Linux Bridge、Open vSwitch、LAN Device etc.)依赖。

  • 计算节点网络实现模型启用 SR-IOV 解决 Neutron 网络 I/O 性能瓶颈_性能瓶颈

  • 网络节点网络实现模型启用 SR-IOV 解决 Neutron 网络 I/O 性能瓶颈_linux_02

  • Neutron 的整体网络实现模型启用 SR-IOV 解决 Neutron 网络 I/O 性能瓶颈_性能瓶颈_03
    启用 SR-IOV 解决 Neutron 网络 I/O 性能瓶颈_虚拟网络_04

基于虚拟网络设备的虚拟机流量走向

启用 SR-IOV 解决 Neutron 网络 I/O 性能瓶颈_虚拟网络_05

虚拟机 1 存在于计算节点 1 上,虚拟机 4 存在于计算节点 2 上,并且虚拟机 1 和虚拟机 4 属于同一个租户网络的同一个子网内,两者之间的数据通信将会经过连接到计算机点 1 与计算节点 2 的物理交换机上进行传输。当虚拟机 1 想发送一个报文给位于不同计算节点上的虚拟机 4 时, 首先会发送一个 ARP 广播报文来确定虚拟机 4 的 MAC 地址。该 ARP 广播报文会通过 Tap 设备以及 qbr 网桥,然后被计算节点 1 上的虚拟交换机 br-int 转发到所有与 br-int 相连的接口上。当广播报文经过计算节点 1 上 br-ethx 时,会被带上一个外部 Vlan id(内外 VLAN ID 转换,为了防止 VxLAN 类型网络与 VLan 类型网络混杂平面场景中出现 VLAN ID 冲突,所以无论是 VLAN 还是 VxLAN 的网络包杂经过 br-int 或 br-tun 网桥时会进行内外部 VLAN ID 转换,通过 Neutron 的算法逻辑来确保避免 VLAN ID 冲突的发生。)。需要注意的是,同一租户的相同网络里所有的虚拟机发出与接收的报文都会带有相同的外部 Vlan id,因此该 ARP 报文会被物理交换机转发到所有其他节点上。当 ARP 报文到达计算节点 2 上时,该数据报文的 Vlan id 会在虚拟交换机 br-int 上被转换成对应的内部 Vlan id,并被广播到所有与 br-int 所连的接口上,最后虚拟机 4 会应答该 ARP 广播。当 虚拟机 1 知道虚拟机 4 的 MAC 地址后,就可以直接与 虚拟机 4 进行数据通信了。

基于虚拟网络设备的性能瓶颈

上文可知,Neutron 会在计算节点上创建大量的虚拟网络设备(e.g. Tap、veth、qbr、br-int、br-ethx etc.),这些虚拟网络设备的建立和运行会给云平台上的计算节点带了很大的 CPU 开销,加上这些虚拟网络设备本身存在一定的缺陷和性能瓶颈,会极大地减少计算节点上的网络带宽(e.g. 使用一般的英特尔 82599ES 万兆网卡,那么该计算节点最大的网络 I/O 吞吐量可能只能达到 5~6 Gbps 左右)。因此寻找一种更加优秀的 I/O 虚拟化方案来替代目前 Neutron 实现虚拟化网络的方式,有可能解决 OpenStack 云平台网络 I/O 性能瓶颈问题。

在 Neutron 中引入 SR-IOV 技术

SR-IOV 技术允许将单个物理网络设备同时共享给多台虚拟机,将虚拟机的虚拟端口与支持 SR-IOV 功能的物理网卡上所虚拟出来的虚拟功能 VF 相关联,这样不仅可以实现对物理网卡的共享,同时不再需要 Neutron 组件额外地去创建 Tap 设备、qbr 网桥以及 OVS 虚拟交换机,使虚拟机的流量绕过 Neutron 所创建的虚拟网络设备,直接到达物理网卡上,极大地减少了计算机点上的 CPU 开销。而且虚拟机数据处理逻辑跳过了计算节点的虚拟网络设备,由物理网卡决定数据如何处理,从而进一步释放了计算节点的 CPU 资源。这 种方式使得虚拟机达到近线速的性能,并且不需要为每台虚拟机单独去分配独立的物理网卡端口。在 Neutron 中引入 SR-IOV 技术,经测试得出的结论是:在数据包需要经过了多个物理服务器节点,在网卡上有真正的发包与收包过程的情况下,网络的 I/O 吞吐量可以达到的极限值约 9.4Gbit/sec,与该网卡的理论速率 10Gbit/sec 已经非常接近了。​可见,SR-IOV 解决了 Neutron 在计算节点上的网络 I/O 性能瓶颈问题。但是对网络节点的网络 I/O 性能瓶颈却及就没有太大的影响。想要解决这个问题,还需要继续引入 DVR 技术或者是 DPDK 等技术才能实现,这里暂不展开​。

基于 SR-IOV 技术的虚拟机流量走向

启用 SR-IOV 解决 Neutron 网络 I/O 性能瓶颈_性能瓶颈_06

虚拟机 1 处于计算节点 1 上,虚拟机 4 处于计算节点 2 上,两台虚拟机属于同一租户下同一网段内。两台计算节点上均有一张带有 SR-IOV 功能的物理网卡,其中虚拟网卡功能 VF1 是分配给虚拟机 1 的,虚拟网卡功能 VF4 是分配给虚拟机 4 的。 虚拟机所发出的报文会直接发送到与虚拟机相关联的 VF 上,然后由物理网卡来决定如何对数据报文进行处理。在图 3 中可以看到,从虚拟机 1 发出的报文直接发送到 VF1 上,然后此报文经过物理网卡的处理后流入到物理交换机上,通过物理交换机到达计算节点 2 上,最终到达虚拟机 4。

NOTE​:与传统 Neutron 组件中 Linux 网桥和 OVS 虚拟交换机方式相比,在计算节点内部没有了网桥 qbr 和虚拟交换机 br-int与 br-ethx 等虚拟设备,虚拟机的数据报文直接通过 VF 传到了物理网卡上。

Neutron 配置启用 SR-IOV

官方文档:https://docs.openstack.org/newton/networking-guide/config-sriov.html

Step 1​. Ensure SR-IOV and VT-d are enabled in BIOS.

Step 2.​ Enable IOMMU in Linux by adding intel_iommu=on to the kernel parameters, for example, using GRUB.

...
linux16 /boot/vmlinuz-3.10.0-862.11.6.rt56.819.el7.x86_64 root=LABEL=img-rootfs ro console=tty0 console=ttyS0,115200n8 crashkernel=auto rhgb quiet intel_iommu=on iommu=pt isolcpus=2-3,8-9 nohz=on nohz_full=2-3,8-9 rcu_nocbs=2-3,8-9 intel_pstate=disable nosoftlockup default_hugepagesz=1G hugepagesz=1G hugepages=16 LANG=en_US.UTF-8
...

Step 3​. On each compute node, create the VFs via the PCI SYS interface(e.g. enp129s0f0, enp129s0f1).

[root@overcloud-compute-0 ~]# cat /etc/sysconfig/network-scripts/ifcfg-enp129s0f0
DEVICE="enp129s0f0"
BOOTPROTO="dhcp"
ONBOOT="yes"
TYPE="Ethernet"
[root@overcloud-compute-0 ~]# cat /etc/sysconfig/network-scripts/ifcfg-enp129s0f1
DEVICE="enp129s0f1"
BOOTPROTO="dhcp"
ONBOOT="yes"
TYPE="Ethernet"

[root@overcloud-compute-0 nova]# echo 16 > /sys/class/net/enp129s0f0/device/sriov_numvfs
[root@overcloud-compute-0 nova]# echo 16 > /sys/class/net/enp129s0f1/device/sriov_numvfs

Step 4​. Verify that the VFs have been created and are in up state.

[root@overcloud-compute-0 ~]# lspci | grep Ethernet
03:00.0 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
03:00.1 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
81:00.0 Ethernet controller: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ Network Connection (rev 01)
81:00.1 Ethernet controller: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ Network Connection (rev 01)
81:10.0 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:10.1 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:10.2 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:10.3 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:10.4 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:10.5 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:10.6 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:10.7 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:11.0 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:11.1 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:11.2 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:11.3 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:11.4 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:11.5 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:11.6 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:11.7 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:12.0 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:12.1 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:12.2 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:12.3 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:12.4 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:12.5 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:12.6 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:12.7 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:13.0 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:13.1 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:13.2 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:13.3 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:13.4 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:13.5 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:13.6 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)
81:13.7 Ethernet controller: Intel Corporation 82599 Ethernet Controller Virtual Function (rev 01)

[root@overcloud-compute-0 ~]# ip link show enp129s0f0
4: enp129s0f0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 90:e2:ba:34:fb:32 brd ff:ff:ff:ff:ff:ff
vf 0 MAC be:40:5c:21:98:31, spoof checking on, link-state auto, trust off, query_rss off
vf 1 MAC b2:e9:21:c7:4a:e0, spoof checking on, link-state auto, trust off, query_rss off
vf 2 MAC ae:75:99:e3:dc:1d, spoof checking on, link-state auto, trust off, query_rss off
vf 3 MAC 66:73:75:d7:15:a8, spoof checking on, link-state auto, trust off, query_rss off
vf 4 MAC b6:04:f7:ed:ad:36, spoof checking on, link-state auto, trust off, query_rss off
vf 5 MAC a2:ad:62:61:2a:bd, spoof checking on, link-state auto, trust off, query_rss off
vf 6 MAC 1a:be:5b:ab:b9:fd, spoof checking on, link-state auto, trust off, query_rss off
vf 7 MAC 3a:63:44:d9:8f:44, spoof checking on, link-state auto, trust off, query_rss off
vf 8 MAC 7e:fe:c7:f6:9d:5d, spoof checking on, link-state auto, trust off, query_rss off
vf 9 MAC 4a:e9:57:84:50:29, spoof checking on, link-state auto, trust off, query_rss off
vf 10 MAC 0a:a7:e7:ff:ee:c8, spoof checking on, link-state auto, trust off, query_rss off
vf 11 MAC 02:58:45:61:15:a7, spoof checking on, link-state auto, trust off, query_rss off
vf 12 MAC 2a:75:77:ff:c1:6d, spoof checking on, link-state auto, trust off, query_rss off
vf 13 MAC be:99:4d:22:5a:87, spoof checking on, link-state auto, trust off, query_rss off
vf 14 MAC 52:44:5f:d7:fb:e3, spoof checking on, link-state auto, trust off, query_rss off
vf 15 MAC b2:16:c3:a2:5f:c7, spoof checking on, link-state auto, trust off, query_rss off
[root@overcloud-compute-0 ~]# ip link show enp129s0f1
5: enp129s0f1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 90:e2:ba:34:fb:33 brd ff:ff:ff:ff:ff:ff
vf 0 MAC 86:64:1f:09:bb:d5, spoof checking on, link-state auto, trust off, query_rss off
vf 1 MAC a2:0f:71:30:31:31, spoof checking on, link-state auto, trust off, query_rss off
vf 2 MAC 0e:b1:06:54:3f:75, spoof checking on, link-state auto, trust off, query_rss off
vf 3 MAC ca:35:be:e2:ea:70, spoof checking on, link-state auto, trust off, query_rss off
vf 4 MAC 26:35:04:86:42:50, spoof checking on, link-state auto, trust off, query_rss off
vf 5 MAC e2:fe:00:1a:74:f7, spoof checking on, link-state auto, trust off, query_rss off
vf 6 MAC 6a:ef:8b:61:a6:c0, spoof checking on, link-state auto, trust off, query_rss off
vf 7 MAC fa:61:e2:f9:a1:2d, spoof checking on, link-state auto, trust off, query_rss off
vf 8 MAC 16:8c:47:34:61:03, spoof checking on, link-state auto, trust off, query_rss off
vf 9 MAC f6:85:2d:85:8e:a3, spoof checking on, link-state auto, trust off, query_rss off
vf 10 MAC 0e:4b:d8:0a:9a:7f, spoof checking on, link-state auto, trust off, query_rss off
vf 11 MAC f2:27:a6:ee:da:be, spoof checking on, link-state auto, trust off, query_rss off
vf 12 MAC 82:37:55:7f:cd:19, spoof checking on, link-state auto, trust off, query_rss off
vf 13 MAC 2e:30:e1:3b:c1:a1, spoof checking on, link-state auto, trust off, query_rss off
vf 14 MAC 4e:56:c7:3f:e5:77, spoof checking on, link-state auto, trust off, query_rss off
vf 15 MAC 56:21:25:bd:ac:18, spoof checking on, link-state auto, trust off, query_rss off

NOTE: If the interfaces are down, set them to up before launching a guest, otherwise the instance will fail to spawn.

ip link set <interface> up

e.g.

enp129s0f1: <NO-CARRIER,BROADCAST,MULTICAST,UP>

Step 5​. Persist created VFs on reboot

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

Step 6​. Enable neutron sriov-agent (Compute)

# 修改配置,Label 为 sriov1
# /etc/neutron/plugins/ml2/sriov_agent.ini
[sriov_nic]
...
physical_device_mappings = sriov1:enp129s0f0,sriov1:enp129s0f1
exclude_devices =

[securitygroup]
firewall_driver = neutron.agent.firewall.NoopFirewallDriver

# 可选,排除 VF
# exclude_devices = enp129s0f0:0000:07:00.2; 0000:07:00.3, enp129s0f1:0000:05:00.1; 0000:05:00.2

# 启动 sriovagent service
systemctl enable neutron-sriov-nic-agent.service
systemctl start neutron-sriov-nic-agent.service
# OR
neutron-sriov-nic-agent \
--config-file /etc/neutron/neutron.conf \
--config-file /etc/neutron/plugins/ml2/sriov_agent.ini

Step 7​. Enable neutron open-vswitch-agent (Compute)

NOTE 1​:这里启用 OvS Agent 的原因是为了让 SR-IOV VLAN 类型 Network 的 DHCP 生效。我们在 Step 6 中为 SR-IOV Physical Network 配置了 ​​sriov1:enp129s0f0,sriov1:enp129s0f1​​,那么也应该在控制节点的中与 SR-IOV Physical Network 通信的 OvS Physical Network 配置上相同的 Mapping,这样才能够让计算节点中的 SR-IOV Network 虚拟机与控制节点上的 DHCP tag 进行通信。否则 SR-IOV Network 的 DHCP tag 的 VLAN ID 为 4095(特殊的 tag ID,表示 tag 设备无效)。因为 DHCP tag 是挂在控制节点上的 OvS Bridge br-int 的,所以需要让 OvS Agent 知道 SR-IOV Physical Network 的 Mapping,继而 OvS Agent 才会在 br-provider 上打上为 SR-IOV Network 的 VLAN tag 进行内外 VIO 转换的流表。相对的,对于 SR-IOV Flat Network 而言,就不需要这么麻烦了,因为 Flat Network 是直通运营商物理网络的,只要运营商物理网络存在 DHCP Server 即可。

NOTE 2​:以上配置切忌只对控制节点上的 OvS 执行。经过实践发现,如果 OvS Agent 和 SR-IOV Agent 在同一控制节点上使用了同一张物理网卡作为 Physical network,那么 SR-IOV 虚拟机在发包的时候会因为 PF(同时也是 OvS 的 br-provider) 被打上了流表,直接就将报文丢出去了,不会在本地 VFs 上使用 SR-IOV 网卡内置的 L2 switching(SR-IOV 网卡的桥接功能),这就可能导致 SR-IOV 虚拟机无法与本地的 DHCP Server 通信。也就是说,被 OvS bridge 接管了的物理网卡,是会丢失部分 L2/L3 转发功能的。因为 OvS 认为:网卡只做报文收发,转发全交给我。

启用 SR-IOV 解决 Neutron 网络 I/O 性能瓶颈_性能瓶颈_07

Step 8​. Configure neutron-server (Controller)

# 修改配置
# /etc/neutron/plugins/ml2/ml2_conf.ini
[ml2]
...
mechanism_drivers = openvswitch,sriovnicswitch

[ml2_type_flat]
flat_networks = datacentre,sriov1

[ml2_type_vlan]
network_vlan_ranges =datacentre:1:29,sriov1:1:29

# 可选配置
# 也可能配置在 /etc/neutron/plugins/ml2/ml2_conf_sriov.ini
[ml2_sriov]
# 这个选项可以限制 SR-IOV 网卡的厂商,一般的我们注释掉他
# 否则当你实际的 SRIOV NIC 不包含在这个列表中时,即便创建 SR-IOV Port 成功了,但启动 SR-IOV 虚拟机也不会成功。
supported_pci_vendor_devs=8086:10ed
agent_required = True

# 重启 neutron-server service
systemctl restart neutron-server.service

需要注意的是,SR-IOV 虚拟机的跨节点通信的前提是 SR-IOV 物理网络首先是连通的,SR-IOV 物理网络只管物理交换机,没有虚拟交换机的事情,支持 Flat、VLAN 两种网络类型。如果 SR-IOV 物理网络本身是不通的话,不会影响 SR-IOV 虚拟机的创建,但虚拟机却没有办法访问网络节点的 DHCP Server。

NOTE 2​:​​8086:10ed​​ 通过指令 ​​lspci -nn | grep Ethe​​ 查看。

NOTE 3​:编辑 ​​[ml2_type_flat]​​ 和 ​​[ml2_type_vlan]​​ 追加 ​​sriov1​​ Lable 是因为 SR-IOV Network 需要为 Flat 或者 VLAN 类型,这两个类型的网络需要能够通过 ​​sriov1​​ Lable 找到对应的 physical network device mappings,如下文。

Step 9​. Configure nova-scheduler (Controller)

# 修改配置
# /etc/nova/nova.conf
[DEFAULT]
...
scheduler_default_filters=...,PciPassthroughFilter
scheduler_available_filters = nova.scheduler.filters.all_filters

# 重启 nova-compute service
systemctl restart openstack-nova-scheduler

Step 10​. Whitelist PCI devices nova-compute (Compute)

# 修改配置
# /etc/nova/nova.conf
[DEFAULT]
...
pci_passthrough_whitelist=[{"devname": "enp129s0f0", "physical_network": "sriov1"},{"devname": "enp129s0f1", "physical_network": "sriov1"}]
# OR
pci_passthrough_whitelist={"devname": "enp129s0f0", "physical_network": "sriov1"}
pci_passthrough_whitelist={"devname": "enp129s0f1", "physical_network": "sriov1"}

# 重启 nova-compute service
systemctl restart openstack-nova-compute

NOTE​. pci_passthrough_whitelist 的格式如下:

["device_id": "<id>",] ["product_id": "<id>",]
["address": "[[[[<domain>]:]<bus>]:][<slot>][.[<function>]]" |
"devname": "Ethernet Interface Name",]
"physical_network":"Network label string"
  • id:id 的值可以是通配符(*),或一个有效的 device/product id。可以使用​​lspci​​ 列出有效的设备名。
  • address:address 的格式与使用带有 -s 选项的​​lspci​​ 命令输出中的格式相同。
  • devname:devname 是一个有效的 PCI 设备名称。可以使用​​ifconfig -a​​ 列出全部有效的名称。这个项需要和与一个 vNIC 相关联的 PF 或 VF 值相对应。如果设备由代表一个 SR-IOV PF 的地址或 devname 来定义,则 PF 下的所有 VF 必须和这个项匹配。另外,可以把 0 个或多个 tag 关联到一个项。
  • physical_network:在使用 SR-IOV 网络时,“physical_network” 被用来指定设备附加到的物理网络。

Step 11​. Launching instances with SR-IOV ports.

  • create SR-IOV Network
    启用 SR-IOV 解决 Neutron 网络 I/O 性能瓶颈_虚拟网络_08
  • Create SR-IOV subnet
    启用 SR-IOV 解决 Neutron 网络 I/O 性能瓶颈_linux_09
  • Create SR-IOV Port
[root@overcloud-controller-0 ~]# net_id=`neutron net-show sriov-net | grep "\ id\ " | awk '{ print $4 }'`
[root@overcloud-controller-0 ~]# port_id=`neutron port-create $net_id --name sriov_port --binding:vnic_type direct | grep "\ id\ " | awk '{ print $4 }'`
  • Launch SR-IOV Instance
[root@overcloud-controller-0 ~]# nova boot --flavor 2U2G --image centos7-1809-99cloud --nic port-id=$port_id test-sriov
+--------------------------------------+-------------------------------------------------------------+
| Property | Value |
+--------------------------------------+-------------------------------------------------------------+
| OS-DCF:diskConfig | MANUAL |
| OS-EXT-AZ:availability_zone | |
| OS-EXT-SRV-ATTR:host | - |
| OS-EXT-SRV-ATTR:hostname | test-sriov |
| OS-EXT-SRV-ATTR:hypervisor_hostname | - |
| OS-EXT-SRV-ATTR:instance_name | |
| OS-EXT-SRV-ATTR:kernel_id | |
| OS-EXT-SRV-ATTR:launch_index | 0 |
| OS-EXT-SRV-ATTR:ramdisk_id | |
| OS-EXT-SRV-ATTR:reservation_id | r-77xg8wl5 |
| OS-EXT-SRV-ATTR:root_device_name | - |
| OS-EXT-SRV-ATTR:user_data | - |
| OS-EXT-STS:power_state | 0 |
| OS-EXT-STS:task_state | scheduling |
| OS-EXT-STS:vm_state | building |
| OS-SRV-USG:launched_at | - |
| OS-SRV-USG:terminated_at | - |
| accessIPv4 | |
| accessIPv6 | |
| adminPass | LP3xn44XuSVf |
| config_drive | |
| created | 2019-02-20T12:30:43Z |
| description | - |
| flavor | 2U2G (2644205c-b98c-407d-af57-33c90895b18e) |
| hostId | |
| host_status | |
| id | 0288fcd6-d75a-45c0-9cc0-4f31ca56ca45 |
| image | centos7-1809-99cloud (fa9755a4-b51a-4c32-aa91-49678298c515) |
| key_name | - |
| locked | False |
| metadata | {} |
| name | test-sriov |
| os-extended-volumes:volumes_attached | [] |
| progress | 0 |
| security_groups | default |
| status | BUILD |
| tags | [] |
| tenant_id | f745745cebce4a609f074b0121ae3a53 |
| updated | 2019-02-20T12:30:43Z |
| user_id | 11b816e454384d038472c7c89d2544f4 |
+--------------------------------------+-------------------------------------------------------------+

查看 SR-IOV Instance 的 XML:

<devices>
...
<interface type='hostdev' managed='yes'>
<mac address='fa:16:3e:ff:8b:bc'/>
<driver name='vfio'/>
<source>
<address type='pci' domain='0x0000' bus='0x81' slot='0x13' function='0x7'/>
</source>
<vlan>
<tag id='20'/>
</vlan>
<alias name='hostdev0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</interface>
...

查看 SR-IOV Instance 的网卡信息:

启用 SR-IOV 解决 Neutron 网络 I/O 性能瓶颈_linux_10

NOTE​:由于缺少了 Step7,所以 VF binding 的 vNIC 不能从 DHCP tag 获取 IP 地址。

查看 VF 的使用信息:

[root@overcloud-compute-0 ~]# ip link show enp129s0f1
5: enp129s0f1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 90:e2:ba:34:fb:33 brd ff:ff:ff:ff:ff:ff
...
vf 15 MAC fa:16:3e:ff:8b:bc, vlan 20, spoof checking on, link-state auto, trust off, query_rss off

NOTE​:VF 的 MAC 就是 SR-IOV instance ens4 的 MAC。

SR-IOV 与 NUMA 亲和

众所周知,SR-IOV 网卡也是具有 NUMA 亲和特性的,可以通过下述方式进行查看和修改。

[root@overcloud-compute-0 ~]# cat /sys/class/net/enp129s0f0/device/numa_node
1

# SR-IOV 网卡 enp129s0f0 所属于 NUMA Node 1

所以 Nova 为了进一步提升虚拟机的网络 I/O 性能,在 Launch instance for SR-IOV Port 时,也会充分考虑 SR-IOV 网卡的 NUMA 亲和特性。如果同时还为虚拟机设置了 NUMA 亲和、CPU 绑核等属性,那么该虚拟机就会运行在与 SR-IOV 网卡相同的 NUMA Node 中。e.g.

openstack port create --network sriov-net --vnic-type direct Port1
openstack flavor create --vcpus 4 --ram 4096 --disk 10 --property hw:cpu_policy=dedicated --property hw:numa_nodes=1 Flavor1
openstack server create --image CentOS_image --flavor Flavor1 --nic port-id={port1_uuid} VM1

查看 VM1 的 vCPU 绑定情况:

virsh vcpupin VM1_uuid

可以看见 VM1 的 4 个 vCPU 都会运行在与 SR-IOV 网卡相同的 NUMA Node 1 上,如果 NUMA Node 1 上的 Processor 分配完了,那么就无法再启动与 VM1 具有相同属性(SR-IOV Port、NUMA Affinity、CPU Binding)的虚拟机了。

注意​:因为 SR-IOV 与 NUMA 节点的亲和性要求,所以当创建具有 SR-IOV 端口的虚拟机,并且该虚拟机具有 NUMA 亲和及 CPU 绑定特性时,就会强制使用与 SR-IOV 网卡相同的 NUMA 节点资源,这样就很容易造成 NUMA 节点资源紧张。触发如下异常:

nsufficient compute resources: Requested instance NUMA topology together with requested PCI devices cannot fit the given host NUMA topology; Claim pci failed..

直到 Queens 版本,引入了 PCI NUMA Policies 功能,可以灵活的配置 PCI 设备的 NUMA 亲和性策略,包括 NUMA 软亲和。详见官方文档:https://specs.openstack.org/openstack/nova-specs/specs/queens/implemented/share-pci-between-numa-nodes.html

SR-IOV 与 VLAN tag

启用 SR-IOV 解决 Neutron 网络 I/O 性能瓶颈_性能瓶颈_11

正如上文 Step7 所说,这里再次强调:​为了让 SR-IOV VLAN 类型 Network 的 DHCP 生效。我们在 Step 6 中为 SR-IOV Physical Network 配置了 Physical mapping ​​sriov1:enp129s0f0,sriov1:enp129s0f1​​ 以及在 Step 8 中配置了 VLAN mapping ​​sriov1:1:29​​,那么也应该在控制节点的中为与 SR-IOV Physical Network 通信的 OvS Physical Network(如上图,控制节点的 br-ethx)配置上相同的两个 Mappings,这样才能够让计算节点中的 VF(准确说是使用了 VF 的虚拟机)与控制节点上的 DHCP 进行通信。否则 SR-IOV Network 的 DHCP tag 的 VLAN ID 为 4095(特殊的 tag ID,表示 tag 设备无效)。因为 DHCP tag 是挂在控制节点上的 OvS Bridge br-int 的,所以需要让 OvS Agent 知道 SR-IOV Network 的两个 Mappings,继而 OvS Agent 才会在 br-provider(如上图,控制节点的 br-ethx)上打上为 SR-IOV Network 的 VLAN tag 进行内外 VID 转换的流表,将 Tenant VLAN ID 转换为 Local VLAN ID,即 DHCP tag 在 br-int 上的 ID。相对的,对于 SR-IOV Flat Network 而言,就不需要这么麻烦了,因为 Flat Network 是直通运营商物理网络的, 理论上只要运营商物理网络存在 DHCP Server 即可​。

如上图,SR-IOV Port 的 VLAN tag 是直接在 VF 上打的 Tag。e.g.

[root@overcloud-compute-0 yangkai]# ip l |grep 5e:9c
vf 14 MAC fa:16:3e:90:5e:9c, vlan 19, spoof checking on, link-state auto, trust on, query_rss off

KVM 虚拟机的 XML 文件中也记录了 VF 设备的 VLAN ID,如下:

<interface type='hostdev' managed='yes'>                                                         
<mac address=' fa:aa:aa:aa:aa:aa '/>
<driver name='kvm'/>
<source>
<address type='pci' domain='0x0000' bus='0x02' slot='0x00' function='0x7'/>
</source>
<vlan>
<tag id='190'/>
</vlan>
<alias name='hostdev0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</interface>

SR-IOV 与安全组

SR-IOV Port 不支持安全组​。