目錄
文章目錄
前言
該文章是基於「計算機系統應用」月刊文章《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