启用 SR-IOV 解决 Neutron 网络 I/O 性能瓶颈
2019-02-20 17:58 云物互联 阅读(3680) 评论(0) 编辑 收藏 举报目录
文章目录
前言
该文章是基于「计算机系统应用」月刊文章《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.)依赖。
-
计算节点网络实现模型
-
网络节点网络实现模型
-
Neutron 的整体网络实现模型
基于虚拟网络设备的虚拟机流量走向
虚拟机 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 网络实现模型的性能瓶颈
上文可知,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 性能瓶颈问题。
SR-IOV 技术简介
SR-IOV(Single-Root I/O Virtualization,单根 I/O 虚拟化)技术是一种基于物理硬件的虚拟化解决方案,可以提高物理 I/O 设备(e.g. 网络适配器)的性能与可扩展性。SR-IOV 技术允许在虚拟机之间高效共享 PCIe(Peripheral Component Interconnect Express,快速外设组件互连)设备,由于 SR-IOV 技术是基于硬件实现的,可以使虚拟机获得与宿主机媲美的 I/O 性能。
SR-IOV 规范(由 PCI-SIG 在 http://www.pcisig.com 上进行定义和维护)定义了一 种虚拟化 PCIe 设备的标准机制,启用了 SR-IOV 并且具有适当的硬件和 OS 支持的 PCIe 设备(e.g. 以太网端口)可以显示为多个单独的物理设备(虚拟成多个 PCIe 设备,每个都具有自己的 PCIe 配置空间)。SR-IOV 定义了两种功能类型:
-
物理功能(Physical Function,PF):PF 包含 SR-IOV 的功能结构,用于支持和管理 SR-IOV 的 PCI 功能。PF 是全功能的 PCIe,可以像其他任何 PCIe 设备一样进行发现、管理和处理。PF 拥有完全配置和控制 PCIe 设备资源的能力。
-
虚拟功能(Virtual Function,VF):VF 是一种轻量级 PCIe 功能,VF 可以与 PF 以及与同一 PF 相关联的其他 VF 共享一个或多个物理资源。VF 仅允许拥有用于其自身行为的配置资源。
NIC SR-IOV:
光纤 SR-IOV:
每个 SR-IOV 设备都可有一个 PF,每个 PF 最多可有 64,000 个与其关联的 VF。缺省情况下,SR-IOV 功能处于禁用状态,PF 充当传统 PCIe 设备。PF 可以通过寄存器创建 VF,一旦在 PF 中启用了 SR-IOV,就可以通过 PF 的总线、设备和功能编号(路由 ID)访问各个 VF 的 PCI 配置空间。每个 VF 都具有一个 PCI 内存空间,用于映射其寄存器集。VF 设备驱动程序对寄存器集进行操作以启用其功能,并且显示为实际存在的 PCI 设备。创建 VF 后,用户可以直接将每个 VF 直接分配给虚拟机,绕过虚拟机监控层(VMM),从而实现低延时和近线速。
SR-IOV 的优点:
- 性能:从虚拟机环境直接访问硬件。
- 成本降低:
- 节能
- 减少了适配器数量
- 简化了布线
- 减少了交换机端口
注:
- PCI(Peripheral Component Interconnect):符合 PCI 总线标准的设备就被称为 PCI 设备,PCI 总线架构中可以包含多个 PCI 设备。
- PCIe(Peripheral Component Interconnect Express):PCI Express,简称 PCI-E,是电脑总线 PCI 的一种,它沿用了现有的 PCI 编程概念及通讯标准,但建基于更快的串行通信系统。是 Intel 提出的新一代的总线接口,PCI Express 采用了目前业内流行的点对点串行连接,比起 PCI 以及更早期的计算机总线的共享并行架构每个 PCIe 设备都有自己的专用连接,不需要向整个总线请求带宽,而且可以把数据传输率提高到一个很高的频率,达到 PCI 所不能提供的高带宽。
如图,PCI 插槽都是等长的,防呆口位置靠上,大部分都是纯白色。PCIe 插槽大大小小,最小的 x1,最大的 x16,防呆口靠下。
在 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 技术的虚拟机流量走向
虚拟机 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
Step 5. Persist created VFs on reboot
echo "echo '7' > /sys/class/net/eth3/device/sriov_numvfs" >> /etc/rc.local
Step 6. 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
# 可选配置
[ml2_sriov]
supported_pci_vonder_devs=8086:10ed
agent_required = True
# 重启 neutron-server service
systemctl restart neutron-server.service
NOTE 1:8086:10ed
通过指令 lspci -nn | grep Ethe
查看。
NOTE 2:编辑 [ml2_type_flat]
和 [ml2_type_vlan]
追加 sriov1
Lable 是因为 SR-IOV Network 需要为 Flat 或者 VLAN 类型,这两个类型的网络需要能够通过 sriov1
Lable 找到对应的 physical network device mappings,如下文。
Step 7. 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 8. 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 9. 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 10. Launching instances with SR-IOV ports.
- create SR-IOV Network
- Create SR-IOV subnet
- 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 的网卡信息:
查看 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 与 VLAN tag
如上图,SR-IOV Port 的 VLAN tag 不是在 OvS Bridge 上处理的,而是直接在 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 文件如下:
<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 Network 不会经过 OvS Bridge 也就不存在内外 VID 转换的过程和必要,SR-IOV Network 的 Local VLAN ID 就是租户 VLAN ID。
至于 DHCP 给 SR-IOV 虚拟机分配 IP 的方式和普通情况下是一样的,只要 vf 能打上 VLAN tag,那么该 SR-IOV Network 在网络节点上的 qdhcp-XXX network namesapce 就能够与 SR-IOV 虚拟机通信。
KVM 与 SR-IOV
手动挂载 VF 到 Guest
- 查看 PCI 设备清单:
[root@overcloud-compute-0 ~]# virsh nodedev-list | grep pci
pci_0000_00_00_0
pci_0000_00_01_0
pci_0000_00_01_1
pci_0000_00_02_0
pci_0000_00_03_0
pci_0000_00_03_2
pci_0000_00_05_0
pci_0000_00_05_2
pci_0000_00_05_4
pci_0000_00_11_0
pci_0000_00_16_0
...
- 查看选择的 PCI 设备详情:
[root@overcloud-compute-0 ~]# virsh nodedev-dumpxml pci_0000_81_10_2
<device>
<name>pci_0000_81_10_2</name>
<path>/sys/devices/pci0000:80/0000:80:03.0/0000:81:10.2</path>
<parent>pci_0000_80_03_0</parent>
<driver>
<name>ixgbevf</name>
</driver>
<capability type='pci'>
<domain>0</domain>
<bus>129</bus>
<slot>16</slot>
<function>2</function>
<product id='0x10ed'>82599 Ethernet Controller Virtual Function</product>
<vendor id='0x8086'>Intel Corporation</vendor>
<capability type='phys_function'>
<address domain='0x0000' bus='0x81' slot='0x00' function='0x0'/>
</capability>
<iommuGroup number='46'>
<address domain='0x0000' bus='0x81' slot='0x10' function='0x2'/>
</iommuGroup>
<numa node='1'/>
<pci-express>
<link validity='cap' port='0' width='0'/>
<link validity='sta' width='0'/>
</pci-express>
</capability>
</device>
NOTE:主要关注 <address domain='0x0000' bus='0x81' slot='0x10' function='0x2'/>
设备信息,e.g.
domain='0x0000'
bus='0x81'
slot='0x10'
function='0x2'
-
Shut down the guest.
-
根据上述设备信息编写 new-dev XML 文件
$ cat /tmp/new-device.xml
<interface type='hostdev' managed='yes'>
<source>
<address type='pci' domain='0x0000' bus='0x81' slot='0x10' function='0x2' />
</source>
</interface>
- 将 New Device Attach 到 GuestOS
$ virsh attach-device VM1 /tmp/new-device.xml --live --config
Device attached successfully
- 查看 VM1 的 XML 更新
$ virsh dumpxml vm1
...
<devices>
...
<interface type='hostdev' managed='yes'>
<mac address='52:54:00:f0:d3:b8'/>
<driver name='kvm'/>
<source>
<address type='pci' domain='0x0000' bus='0x81' slot='0x10' function='0x2' />
</source>
<alias name='hostdev0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
</interface>
...
</devices>
NOTE:或者可以直接 Edit 虚拟机的 XML 文件
virsh edit MyGuest
# 添加下述标签端:
<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address bus='0x81' slot='0x10' function='0x2'/>
</source>
</hostdev>
- 进入 GuestOS 查看网卡信息
root@vm1:~# ip addr show eth4
4: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 2c:53:4a:02:20:3d brd ff:ff:ff:ff:ff:ff
inet 192.168.99.169/24 brd 192.168.99.255 scope global eth1
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe3b:6128/64 scope link
valid_lft forever preferred_lft forever
- 启动虚拟机
virsh start MyGuest
- Dettach 虚拟机的 PCI 设备
$ virsh nodedev-dettach pci_0000_06_10_0
Device pci_0000_06_10_0 detached
参考文档
https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux_openstack_platform/7/html/networking_guide/sec-sr-iov
https://docs.openstack.org/newton/networking-guide/config-sriov.html
http://blog.51cto.com/hj192837/1061407
https://docs.openstack.org/newton/networking-guide/config-sriov.html