天天看點

基于KVM的SRIOV直通配置及性能測試目錄1. SRIOV介紹2. 環境說明3. 開啟SRIOV4. 生成VF5. VF直通6. 開啟irqbalance7. VM遷移8. 帶寬限速9. 安全10. 其他使用限制11. 性能測試12. windows虛拟機使用VF13. 運維指令14. 宿主屏蔽VF驅動附. 包轉發率測試方法附. 參考文檔

基于KVM的SRIOV直通配置及性能測試目錄1. SRIOV介紹2. 環境說明3. 開啟SRIOV4. 生成VF5. VF直通6. 開啟irqbalance7. VM遷移8. 帶寬限速9. 安全10. 其他使用限制11. 性能測試12. windows虛拟機使用VF13. 運維指令14. 宿主屏蔽VF驅動附. 包轉發率測試方法附. 參考文檔

SRIOV介紹、VF直通配置,以及包轉發率性能測試

小慢哥的原創文章,歡迎轉載

目錄

▪ 1. SRIOV介紹

▪ 2. 環境說明

▪ 3. 開啟SRIOV

▪ 4. 生成VF

▪ 5. VF直通

▪ 6. 開啟irqbalance

▪ 7. VM遷移

▪ 8. 帶寬限速

▪ 9. 安全

▪ 10. 其他使用限制

▪ 11. 性能測試

▪ 12. windows虛拟機使用VF

▪ 13. 運維指令

▪ 14. 宿主屏蔽VF驅動

▪ 附. 包轉發率測試方法

▪ 附. 參考文檔

1. SRIOV介紹

基于KVM的SRIOV直通配置及性能測試目錄1. SRIOV介紹2. 環境說明3. 開啟SRIOV4. 生成VF5. VF直通6. 開啟irqbalance7. VM遷移8. 帶寬限速9. 安全10. 其他使用限制11. 性能測試12. windows虛拟機使用VF13. 運維指令14. 宿主屏蔽VF驅動附. 包轉發率測試方法附. 參考文檔

▷ 傳統方式的瓶頸:qemu的網卡,傳統方式是使用tap網卡,橋接到宿主的bridge上,但性能很差,尤其是包轉發率很低,難以滿足對性能要求比較高的場景。性能差的主要原因是路徑太長,經過的核心裝置太多,根本原因在于linux/unix核心本身就不是為高性能而設計的,linux/unix更适合做控制平面,而不是轉發平面。

▷ 解決思路:減少中間路徑,最簡單有效的方法就是bypass核心。SRIOV的作用就是bypass宿主核心。

▷ PF和VF:每個實體網卡(比如p1p1)就是一個PF,在開啟SRIOV後,每個PF可以生成固定數量的VF,每個VF都可以在宿主上作為一張網卡直接使用,或者直通到QEMU虛拟機裡作為虛拟機裡的網卡使用,這就實作了bypass宿主核心。

先給出性能測試的結論,SRIOV VF直通相比傳統tap+bridge方案,性能提升:

▷ 發包轉發率提高: 677%

▷ 收包轉發率提高: 171%

2. 環境說明

機型:Dell PowerEdge R620

網卡:Intel X520(82599ES)

宿主OS:CentOS 7

VM OS:CentOS 7

3. 開啟SRIOV

1️⃣ 在BIOS裡開啟SRIOV,如圖所示

基于KVM的SRIOV直通配置及性能測試目錄1. SRIOV介紹2. 環境說明3. 開啟SRIOV4. 生成VF5. VF直通6. 開啟irqbalance7. VM遷移8. 帶寬限速9. 安全10. 其他使用限制11. 性能測試12. windows虛拟機使用VF13. 運維指令14. 宿主屏蔽VF驅動附. 包轉發率測試方法附. 參考文檔

注:即使BIOS裡開啟全局SRIOV,網卡也依然可以當作普通網卡使用

2️⃣ 需要在BIOS裡開啟VT-d

3️⃣ grub配置iommu

iommu=pt intel_iommu=on           

4. 生成VF

# 啟動網卡
ip link set p1p1 up

# 檢視pf的pci編号
lshw -c network -businfo

# 檢視網卡支援的vf數量
cat /sys/bus/pci/devices/0000:41:00.0/sriov_totalvfs

# 生成vf,建議加入開機啟動
echo 63 > /sys/bus/pci/devices/0000:41:00.0/sriov_numvfs           

注意:若沒有屏蔽宿主的VF驅動,則在生成vf後還必須等待一會時間才能在宿主上看到所有命名完成的網卡(否則會看到一堆ethX網卡),vf數量越多需要等待時間越長,63個vf,差不多需要10秒

5. VF直通

如果qemu是通過libvirt管理的,有3種配置方法:

▷ 方法1(interface):在devices段落裡加入

<interface type='hostdev' managed='yes'>
  <mac address='52:54:00:ad:ef:8d'/>
  <source>
    <address type='pci' domain='0x0000' bus='0x41' slot='0x10' function='0x0'/>
  </source>
  <vlan>
    <tag id='4010'/>
  </vlan>
</interface>           

上面中address的位址,可以根據“lshw -c network -businfo”來配置,比如

pci@0000:41:10.0 p1p1_0           

▷ 方法2(hostdev):在devices段落裡加入

<hostdev mode='subsystem' type='pci' managed='yes'>
  <source>
    <address domain='0x0000' bus='0x41' slot='0x10' function='0x0'/>
  </source>
</hostdev>           

上面中address的位址,也是根據“lshw -c network -businfo”來配置

▷ 方法3(net-pool)

為每個PF網卡定義一個net-pool,即分别編輯一個xml檔案。這裡僅展示一個PF,編輯sriov-int.xml

<network>
  <name>sriov-int</name>
  <forward mode='hostdev' managed='yes'>
    <pf dev='p1p1'/>
  </forward>
</network>           

加入到libvirt net-pool、激活、并設定開機啟動

virsh net-define sriov-int.xml
virsh net-start sriov-int
virsh net-autostart sriov-int           

雖然配置了net-autostart,但并不管用,因為實體機啟動時候,經常會在啟動生成vf(假設在rc.local裡生成vf)之前就啟動libvirt,而這個net-pool(sriov-int)本應該在vf生成後才能啟動,是以建議在rc.local裡增加如下内容來確定啟動

ip link set p1p2 up
echo 63 > /sys/bus/pci/devices/0000:41:00.0/sriov_numvfs
virsh net-start sriov-int           

然後,在vm的xml裡增加

<interface type='network'>
  <mac address='52:54:00:ad:ef:8d'/>
  <source network='sriov-int'/>
  <vlan>
    <tag id='4010'/>
  </vlan>
</interface>           

3種方法如何選擇

▷ 方法1:功能多,可以配置mac和vlan

▷ 方法2:mac和vlan需要自己在宿主上敲ip指令設定

▷ 方法3:有2個問題

▪ 存在一個bug,當本宿主所有vm使用某個PF的VF總數超過VF上限後,不會報錯,也能啟動,但是可能會有異常,并且vm如果被destroy關機,那麼對應的VF就會出問題,比如使用ip link set p1p1 vf 0 mac 00:00:00:00:00:00來做重置時候,會提示“RTNETLINK answers: Cannot allocate memory”,而且難以修複,即使修複,也不知道有沒有看不見的異常存在。

▪ 沒有辦法知道某個vm使用的是哪個vf,是以如果要對vf設定限速或者開關spoofchk時候,隻能先在宿主上通過“ip link show dev p1p1 | grep MAC位址”方式來獲得vf号,然後才能設定限速等操作

綜上所述:使用方法3最便捷,但是存在bug,是以需要做好邏輯來防止vm使用vf總數超過上限的情況。

6. 開啟irqbalance

x520是2隊列,x710是4隊列,需要在vm裡啟動中斷平衡服務(irqbalance),否則隻會有一個cpu來處理資料包。

另外,這與宿主上vf的query_rss無關。

7. VM遷移

直通網卡屬于PCI裝置,而libvirt和qemu卻不支援帶有非USB的PCI裝置的vm做遷移,包括冷遷移和熱遷移。是以熱遷移無法實作。

冷遷移,有2種方案:

▷ detach掉vf網卡,然後使用libvirt做遷移,遷移過去後,再在新宿主上attach vf網卡

▷ undefine vm,然後在新宿主上重新渲染并define vm

注意:不能在vm關機時候用libvirt的遷移功能,有時候會導緻虛拟機消失掉,包括原宿主和新宿主

8. 帶寬限速

隻能限制出站帶寬,無法限制入站帶寬

ip link set p1p1 vf 0 max_tx_rate 100           

表示出站帶寬限速100Mbps,不同網卡有差别:

▷ x520網卡最小限速11Mbps,最大限速10000Mbps,設為0表示不限速。若小于11或大于10000則會報錯

▷ x710網卡最小限速50Mbps,最大限速10000Mbps,設為0表示不限速。若小于50則自動設為50,若大于10000則會報錯

注意:vm關機後vf的帶寬限速不會複位

9. 安全

僅支援源mac過濾和網卡mac防篡改,不支援其他安全防護(防arp欺騙就無法實作)

源mac過濾

ip link set p1p1 vf 0 spoofchk on           

表示vm裡發出的包,如果源mac不是指定mac,那麼資料包不允許通過。注意:vm關機後vf的spoofchk不會複位

網卡mac防篡改

▷ 在宿主上修改mac,vm裡的mac不會跟着改;在vm裡修改mac,在宿主上可以看到變化

▷ 如果在vm關機狀态下改了mac位址,那麼當vm開機後會改為vm的mac,當vm又關機後,又回改為原先改的mac

▷ 隻有在宿主上看到的目前vf的mac為全0,才能在vm裡修改mac位址,即使vf的spoofchk為off。但有一種例外,若使用上面方法2來配置xml,雖然宿主上看到的vf的mac不為0,但vm裡可以修改

▷ 當在宿主上設定了mac後,虛拟機裡的mac就無法篡改了

▪ 方法1(interface)來配置xml,估計vm啟動時候就自動幫忙在宿主上設定了mac,是以就直接實作了防篡改功能

▪ 方法2(hostdev)來配置xml,需要在宿主上手動再設定一次mac位址才能實作防篡改

在宿主上手動修改mac方法(vm關機和開機情況下都可以改):

ip link set p1p1 vf 0 mac aa:bb:cc:dd:ee:ff           

建議:

▷ 在vm啟動前對vf做一次重置

▷ 在vm undefine後對vf做一次重置

10. 其他使用限制

▷ 直通到vm裡的vf網卡裡無法橋接到vm裡的linux bridge,這也導緻ebtables無法使用,iptables可以使用

▷ 直通到vm裡的vf網卡可以加入ovs橋接

▷ 一個vm最多隻能支援32個vf,超過數量會報錯

11. 性能測試

測試方法:

▷ 多台vm同時發包,一台vm收包,分别觀察發包性能和收包性能

▷ 發包vm在同一台宿主上,收包vm在另一台宿主上

▷ 測試工具:modprobe pktgen

▷ 測試包大小: udp包,size為64 bytes

配置:

▷ vm配置均為4核8G

▷ 實體網卡均為x520(vf隊列預設為2)

▷ 宿主和vm均開啟irqbalance、均關閉numad

▷ 不配置cpu綁定、不配置numa綁定

▷ 開啟大頁

測試結果:

基于KVM的SRIOV直通配置及性能測試目錄1. SRIOV介紹2. 環境說明3. 開啟SRIOV4. 生成VF5. VF直通6. 開啟irqbalance7. VM遷移8. 帶寬限速9. 安全10. 其他使用限制11. 性能測試12. windows虛拟機使用VF13. 運維指令14. 宿主屏蔽VF驅動附. 包轉發率測試方法附. 參考文檔

測試結論:

使用SR-IOV+VF直通方式可以明顯提升包轉發率,1對1的測試結果看到kernel态發包可以達到3.5Mpps,收包可以達到1.9Mpps

▷ 發包比vxlan提高: 1196%,比vlan提高: 677%。此結果參考1對1(1個發包vm,1個收包vm)

▷ 收包比vxlan提高: 363%,比vlan提高: 171%。此結果參考3對1(3個發包vm,1個收包vm)

說明:

▷ kernel态單核資料包(64B)處理能力為2Mpps

▷ 2Mpps是因為kernel态瓶頸是2Mpps,如果通過dpdk走使用者态,則可以大于2M,原因:收包端要将資料包中斷平衡到不同的cpu上,方法:可以通過多隊列方式,把每個隊列配置設定到單獨cpu上(irqbalance會自動均衡),然後source ip不一樣,就會對應到不同隊列,也就是不同的中斷上。即1個VF,2個隊列,VM有至少2核,那麼當符合負載均衡條件(mac、ip不同),則理論上最大可以達到4Mpps

更多測試結果:

以下測試使用的packet大小為64B

▷ kernel态,3層轉發性能:發包器使用不同的source ip

▪ BCM57800:2Mpps

▪ Intel X520:10Mpps

▪ Intel X710:12Mpps

▷ kernel态,2層轉發性能:發包器使用不同的source mac

▪ Intel X520:7.3Mpps

▪ Intel X710:7.8Mpps

▷ kernel态下vxlan封裝能力

▪ vxlan内層使用不同的source ip發包

▪ 收包在:1.1-1.2Mpps

▷ dpdk使用者态,2層轉發性能:發包器使用不同的source ip

▪ BCM57800:不支援

▪ Intel X520:14.8Mpps

▪ Intel X710:14.8Mpps

▷ SR-IOV模式

▪ X520總量11.2Mpps,每vm為11.2Mpps/vm總數(即VF數)

總結:

▷ kernel态下的中斷平衡的依據因素:2層依據source mac,3層依據source ip

▷ kernel态下使用傳統中斷模式的單核轉發能力極限2Mpps

注意:

▷ kernel态下,利用多隊列RSS中斷平衡提升吞吐率,會導緻cpu非常高

▷ 使用者态下即使source mac或source ip固定,吞吐率基本接近限速14.8Mpps

▷ vxlan不能利用多核來提升吞吐,主要原因為外層source ip不夠多

12. windows虛拟機使用VF

到網卡官網下載下傳對應驅動并安裝,經測試,win2012預設就有82599(x520)驅動,但版本舊

13. 運維指令

# 檢視網卡支援的vf數量
cat /sys/bus/pci/devices/0000:41:00.0/sriov_totalvfs

# 宿主屏蔽VF驅動後檢視vf和pf的對應
https://github.com/intel/SDN-NFV-Hands-on-Samples/blob/master/SR-IOV_Network_Virtual_Functions_in_KVM/listvfs_by_pf.sh
載下來後執行./listvfs_by_pf.sh即可

# 宿主屏蔽VF後檢視哪些VF正在被使用
yum install dpdk-tools
dpdk-devbind --status

# 檢視網卡對應哪個socket
lstopo-no-graphics

# lspci檢視網卡資訊
lspci -Dvmm|grep -B 1 -A 4 Ethernet

# 宿主上檢視具體VF流量(僅支援x520,x710查不到)
ethtool -S p1p1 | grep VF           

14. 宿主屏蔽VF驅動

echo "blacklist ixgbevf" >> /etc/modprobe.d/blacklist.conf           

表示當實體機啟動時候,預設不加載ixgbevf驅動,但是如果手動modprobe ixgbevf,則也會加載驅動。

如果目前已經加載了ixgbevf,想解除安裝,則需要如下步驟

echo 0 > /sys/bus/pci/devices/0000:41:00.0/sriov_numvfs
rmmod ixgbevf
echo 63 > /sys/bus/pci/devices/0000:41:00.0/sriov_numvfs           

附. 包轉發率測試方法

modprobe pktgen:發包通過pktgen來發,收包通過sar -n DEV來看,發的是udp包

#!/bin/bash

NIC="eth1"
DST_IP="192.168.1.2"
DST_MAC="52:54:00:43:99:65"

modprobe pktgen

pg() {
    echo inject > $PGDEV
    cat $PGDEV
}

pgset() {
    local result
    echo $1 > $PGDEV

    result=`cat $PGDEV | fgrep "Result: OK:"`
    if [ "$result" = "" ]; then
         cat $PGDEV | fgrep Result:
    fi
}
# Config Start Here -----------------------------------------------------------

# thread config
# Each CPU has own thread. Two CPU exammple. We add ens7, eth2 respectivly.

PGDEV=/proc/net/pktgen/kpktgend_0
echo "Removing all devices"
pgset "rem_device_all"
echo "Adding ${NIC}"
pgset "add_device ${NIC}"

# device config
# delay 0 means maximum speed.

CLONE_SKB="clone_skb 1000000"
# NIC adds 4 bytes CRC
PKT_SIZE="pkt_size 64"

# COUNT 0 means forever
COUNT="count 0"
DELAY="delay 0"

PGDEV=/proc/net/pktgen/${NIC}
echo "Configuring $PGDEV"
pgset "$COUNT"
pgset "$CLONE_SKB"
pgset "$PKT_SIZE"
pgset "$DELAY"
pgset "dst ${DST_IP}"
pgset "dst_mac ${DST_MAC}"

# Time to run
PGDEV=/proc/net/pktgen/pgctrl

echo "Running... ctrl^C to stop"
pgset "start"
echo "Done"

# Result can be vieved in /proc/net/pktgen/eth[3,4]           

▷ 将腳本開頭的eth1改為發包對應的網卡

▷ 将腳本開頭的192.168.1.2改為目标ip

▷ 将腳本開頭的52:54:00:43:99:65改為目标mac

pktgen-dpdk

# 固定ip固定mac
set 0 dst ip 192.168.10.240
set 0 src ip 192.168.10.245/24
set 0 dst mac c8:1f:66:d7:58:ba
set 0 src mac a0:36:9f:ec:4a:28


# 可變source ip可變source mac
stop 0
range 0 src ip 192.168.0.1 192.168.0.1 192.168.200.200 0.0.0.1
range 0 dst ip 10.1.1.241 10.1.1.241 10.1.1.241 0.0.0.0
range 0 dst mac c8:1f:66:d7:58:ba c8:1f:66:d7:58:ba c8:1f:66:d7:58:ba 00:00:00:00:00:00
range 0 src mac a0:36:9f:ec:4a:28 a0:36:9f:ec:4a:28 a0:36:9f:ec:ff:ff 00:00:00:00:01:01
range 0 src port 100 100 65530 1
range 0 dst port 100 100 65530 1
range 0 size 64 64 64 0
enable 0 range
enable 0 latency
start 0


# 按50%的速率發包
set 0 rate 50           

附. 參考文檔

# openstack關于sriov的限制
https://docs.openstack.org/mitaka/networking-guide/config-sriov.html

# 遷移
https://wenku.baidu.com/view/d949db67998fcc22bcd10dfd.html
https://www.chenyudong.com/archives/live-migrate-with-pci-pass-through-fail-with-libvirt-and-qemu.html

# sriov配置
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/virtualization_host_configuration_and_guest_installation_guide/sect-virtualization_host_configuration_and_guest_installation_guide-sr_iov-how_sr_iov_libvirt_works

# 線速
http://netoptimizer.blogspot.tw/2014/05/the-calculations-10gbits-wirespeed.html           

繼續閱讀