详解基于KVM的SRIOV直通配置及性能测试

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介绍

▷ 传统方式的瓶颈: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

在BIOS里开启SRIOV,如图所示

注:即使BIOS里开启全局SRIOV,网卡也依然可以当作普通网卡使用

需要在BIOS里开启VT-d

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>

上面<source>中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>

上面<source>中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绑定
▷ 开启大页

测试结果:

测试结论:

使用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

▪ BCM57800:2Mpps
▪ 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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 详解基于KVM的SRIOV直通配置及性能测试

    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介绍 ▷ 传统方式的瓶颈:qemu的网卡,传统方式是使用tap网卡,桥接到宿主的bridge上,

  • 详解基于Vue+Koa的pm2配置

    目前使用的技术栈是:前端Vue.后端Koa.数据库Mongodb. 然而每当起服务的时候,都要 npm start . node ./server/app.js ,还要同时保持这两个窗口一直是开着的,很是麻烦. 而且因为我使用的是koa,也没有使用狼叔写的koa脚手架.是自己基于廖雪峰老师的 Koa框架 改的一个小型mvc.导致没有热更新. 为了简化这种没必要的操作及增加热更新,开始想怎么进行优化.于是选择了 pm2 配置pm2 先安装pm2: npm i pm2 . npm i pm2 -g

  • 详解基于vue-cli优化的webpack配置

    最近的项目度过了开始忙碌的基建期,也慢慢轻松下来,准备记录一下自己最近webpack优化的措施,希望有温故知新的效果. 项目采用的是vue全家桶,构建配置都是基于vue-cli去改进的.关于原始webpack配置大家可以看下这篇文章vue-cli#2.0 webpack配置分析,文章基本对于文件每行代码都做了详细的解释,有助于更好的理解webpack. 仔细总结了一下,自己的优化基本还是网上流传的那几点 通过 externals 配置来提取常用库,引用cdn 合理配置CommonsChunkPl

  • 详解基于Spring Cloud几行配置完成单点登录开发

    单点登录概念 单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.登录逻辑如上图 基于Spring 全家桶的实现 技术选型: Spring Boot Spring Cloud Spring Security oAuth2 客户端: maven依赖 <dependency> <groupId>org.springframework.boot</g

  • 详解基于django实现的webssh简单例子

    本文介绍了详解基于django实现的webssh简单例子,分享给大家,具体如下: 说明 新建一个 django 程序,本文为 chain. 以下仅为简单例子,实际应用 可根据自己平台情况 进行修改. 打开首页后,需要输入1,后台去登录主机,然后返回登录结果. 正常项目 可以post 主机和登录账户,进行权限判断,然后去后台读取账户密码,进行登录. djang后台 需要安装以下模块 安装后会有一个版本号报错,不影响 channels==2.0.2 channels-redis==2.1.0 amq

  • zabbix 4.04 安装文档教程详解(基于CentOS 7.6)

    1    安装前准备: 1.1   安装JDK 卸载openjdk # rpm -qa | grep java # yum remove java-1.8.0-openjdk # yum remove java-1.8.0-openjdk-headless 安装JDK包 # rpm -ivh jdk-8u191-linux-x64.rpm 1.2   安装依赖包 # yum install -y net-snmp net-snmp-devel OpenIPMI-devel libssh2-dev

  • 详解基于Mybatis-plus多租户实现方案

    一.引言 小编先解释一下什么叫多租户,什么场景下使用多租户. 多租户是一种软件架构技术,在多用户的环境下,共有同一套系统,并且要注意数据之间的隔离性. 举个实际例子:小编曾经开发过一套支付宝程序,这套程序应用在不同的小程序上,当使用者访问不同,并且进入相对应的小程序页面,小程序则会把用户相关数据传输到小编这里.在传输的时候需要带上小程序标识(租户ID),以便小编将数据进行隔离. 当不同的租户使用同一套程序,这里就需要考虑一个数据隔离的情况. 数据隔离有三种方案: 1.独立数据库:简单来说就是一个

  • 详解关于SpringBoot的外部化配置使用记录

    更新: 工作中突然想起来,关于Yaml的使用,并不属于Spring的范畴,是org.yaml.snakeyaml处理的.所以yaml的使用应该参考官方,不过貌似打不开... Spring利用snakeyaml将配置解析成PropertySource,然后写入到Environment,就能使用了 记录下使用SpringBoot配置时遇到的一些麻烦,虽然这种麻烦是因为知识匮乏导致的. 记录下避免一段时间后自己又给忘记了,以防万一. 如果放到博客里能帮助到遇到同样问题的同志,自是极好! SpringB

  • 详解基于IDEA2020.1的JAVA代码提示插件开发例子

    之前因为项目组有自己的代码规范,为了约束平时的开发规范,于是基于2019.1.3版本开发了一个代码提示的插件.但是在把IDEA切换到2020.1版本的时候,却发现疯狂报错,但是网上关于IDEA插件开发的相关文章还是不够多,只能自己解决.于是根据官方的SDK文档,使用Gradle重新构建了一下项目,把代码拉了过来.下文会根据2020.1版本简单开发一个代码异常的提示插件,把容易踩坑的地方提示一下. 1.首先先根据IDEA插件开发官方文档,用Gradle新建一个project 选中file -> n

  • Java 添加、删除、格式化Word中的图片步骤详解( 基于Spire.Cloud.SDK for Java )

    本文介绍使用Spire.Cloud.SDK for Java提供的ImagesApi接口来操作Word中的图片.具体可通过addImage()方法添加图片.deleteImage()方法删除图片.updateImageFormat()格式化Word中的图片以及getImageFormat()获取Word中的图片格式等.操作方法和代码示例可参考下文中的步骤. 步骤1:导入jar文件 创建Maven项目程序,通过maven仓库下载导入.以IDEA为例,新建Maven项目,在pom.xml文件中配置m

随机推荐