5.1.4 使用virtio_net
1. 配置和使用virtio_net
在选择KVM中的网络设备时,一般来说优先选择半虚拟化的网络设备而不是纯软件模拟的设备,使用virtio_net半虚拟化驱动,可以提高网络吞吐量(thoughput)和降低网络延迟(latency),从而让客户机中网络达到几乎和原生网卡差不多的性能。
virtio_net的使用,需要两部分的支持,在宿主机中的QEMU工具的支持和客户机中virtio_net驱动的支持。较新的qemu-kvm都对virtio网卡设备的支持,且较新的流行Linux发行版中都已经将virtio_net作为模块编译到系统之中了,所以使用起来还是比较方便的。
可以通过如下几个步骤来使用virtio_net。
1. 检查QEMU是否支持virtio类型的网卡
[root@jay-linux kvm_demo]# qemu-system-x86_64 -net nic,model=?
qemu: Supported NIC models: ne2k_pci,i82551,i82557b,i82559er,rtl8139,e1000,pcnet,virtio
从输出信息中支持网卡类型可知,当前qemu-kvm支持virtio网卡模型。
2. 启动客户机时,指定分配virtio网卡设备。
[root@jay-linux kvm_demo]# qemu-system-x86_64 rhel6u3.img -smp 2 -m 1024 -net nic,model=virtio,macaddr=00:16:3e:22:22:22 -net tap
VNC server running on ::1:5900'
3. 在客户机中查看virtio网卡的使用情况。
[root@kvm-guest ~]# grep VIRTIO_ /boot/config-2.6.32-279.el6.x86_64
CONFIG_VIRTIO_BLK=m
CONFIG_VIRTIO_NET=m
CONFIG_VIRTIO_CONSOLE=m
CONFIG_VIRTIO_RING=m
CONFIG_VIRTIO_PCI=m
CONFIG_VIRTIO_BALLOON=m
[root@kvm-guest ~]# lspci
00:00.0 Host bridge: Intel Corporation 440FX - 82441FX PMC [Natoma] (rev 02)
00:01.0 ISA bridge: Intel Corporation 82371SB PIIX3 ISA [Natoma/Triton II]
00:01.1 IDE interface: Intel Corporation 82371SB PIIX3 IDE [Natoma/Triton II]
00:01.3 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 03)
00:02.0 VGA compatible controller: Cirrus Logic GD 5446
00:03.0 Ethernet controller: Red Hat, Inc Virtio network device
[root@kvm-guest ~]# lspci -vv -s 00:03.0
00:03.0 Ethernet controller: Red Hat, Inc Virtio network device
Subsystem: Red Hat, Inc Device 0001
Physical Slot: 3
Control: I/O+ Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Interrupt: pin A routed to IRQ 11
Region 0: I/O ports at c000 [size=32]
Region 1: Memory at febf1000 (32-bit, non-prefetchable) [size=4K]
Expansion ROM at febe0000 [disabled] [size=64K]
Capabilities: [40] MSI-X: Enable+ Count=3 Masked-
Vector table: BAR=1 offset=00000000
PBA: BAR=1 offset=00000800
Kernel driver in use: virtio-pci
Kernel modules: virtio_pci
[root@kvm-guest ~]# lsmod | grep virtio
virtio_net 16760 0
virtio_pci 7113 0
virtio_ring 7729 2 virtio_net,virtio_pci
virtio 4890 2 virtio_net,virtio_pci
[root@kvm-guest ~]# ethtool -i eth1
driver: virtio_net
version:
firmware-version:
bus-info: virtio0
[root@kvm-guest ~]# ifconfig eth1
eth1 Link encap:Ethernet HWaddr 00:16:3E:22:22:22
inet addr:192.168.156.200 Bcast:192.168.255.255 Mask:255.255.0.0
inet6 addr: fe80::216:3eff:fe22:2222/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:500 errors:0 dropped:0 overruns:0 frame:0
TX packets:103 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:65854 (64.3 KiB) TX bytes:19057 (18.6 KiB)
[root@kvm-guest ~]# ping 192.168.199.98 -c 1
PING 192.168.199.98 (192.168.199.98) 56(84) bytes of data.
64 bytes from 192.168.199.98: icmp_seq=1 ttl=64 time=0.313 ms
--- 192.168.199.98 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.313/0.313/0.313/0.000 ms
根据上面输出信息可知,网络接口eth1使用了virtio_net驱动,且当前网络连接正常工作。如果启动Windows客户机使用virtio类型的网卡,则在Windows客户机的“设备管理器”中看到一个名为“Red Hat VirtIO Ethernet Adapter”的设备即是客户机中的网卡。
2. 宿主机中TSO和GSO的设置
据Redhat的文档[3]介绍,如果你在使用半虚拟化网络驱动(即virtio_net)时依然得到较低的性能,可以检查宿主机系统中对GSO和TSO[4]特性的设置。关闭GSO和TSO可以使半虚拟化网络驱动的性能得到更加优化。
如下的命令可以检查宿主机中GSO和TSO的设置,其中eth0是建立bridge供客户机使用的网络接口。
[root@jay-linux ~]# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.001320fb4fa8 yes eth0
tap0
[root@jay-linux ~]# ethtool -k eth0
Offload parameters for eth0:
rx-checksumming: on
tx-checksumming: on
scatter-gather: on
tcp-segmentation-offload: on #这个就是TSO的状态
udp-fragmentation-offload: off
generic-segmentation-offload: on #这是GSO的状态
generic-receive-offload: on
large-receive-offload: off
通过如下命令可以关闭其GSO和TSO功能。
[root@jay-linux ~]# ethtool -K eth0 gso off
[root@jay-linux ~]# ethtool -K eth0 tso off
[root@jay-linux ~]# ethtool -k eth0
Offload parameters for eth0:
rx-checksumming: on
tx-checksumming: on
scatter-gather: on
tcp-segmentation-offload: off
udp-fragmentation-offload: off
generic-segmentation-offload: off
generic-receive-offload: on
large-receive-offload: off
3. 用vhost_net后端驱动
前面提到virtio在宿主机中的后端处理程序(backend)一般是由用户空间的QEMU提供的,然而如果对于网络IO请求的后端处理能够在在内核空间来完成,则效率会更高,会提高网络吞吐量和减少网络延迟。在比较新的内核中有一个叫做“vhost-net”的驱动模块,它是作为一个内核级别的后端处理程序,将virtio-net的后端处理任务放到内核空间中执行,从而提高效率。
在第4章介绍“使用网桥模式”的网络配置时,有几个选项和virtio相关的,这里也介绍一下。
-net tap,[,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h][,vhostforce=on|off]
vnet_hdr =on|off
设置是否打开TAP设备的“IFF_VNET_HDR”标识。“vnet_hdr=off”表示关闭这个标识;“vnet_hdr=on”则强制开启这个标识,如果没有这个标识的支持,则会触发错误。IFF_VNET_HDR是tun/tap的一个标识,打开它则允许发送或接受大数据包时仅仅做部分的校验和检查。打开这个标识,可以提高virtio_net驱动的吞吐量。
vhost=on|off
设置是否开启vhost-net这个内核空间的后端处理驱动,它只对使用MIS-X[5]中断方式的virtio客户机有效。
vhostforce=on|off
设置是否强制使用vhost作为非MSI-X中断方式的Virtio客户机的后端处理程序。
vhostfs=h
设置为去连接一个已经打开的vhost网络设备。
用如下的命令行启动一个客户机,就在客户机中使用virtio-net作为前端驱动程序,而后端处理程序则使用vhost-net(当然需要当前宿主机内核支持vhost-net模块)。
[root@jay-linux kvm_demo]# qemu-system-x86_64 rhel6u3.img -smp 2 -m 1024 -net nic,model=virtio,macaddr=00:16:3e:22:22:22 -net tap,vnet_hdr=on,vhost=on
VNC server running on ::1:5900'
启动后,检查客户机网络,应该是可以正常连接的。
而在宿主机中,可以查看vhost-net的使用情况,如下。
[root@jay-linux kvm_demo]# grep VHOST /boot/config-3.5.0
CONFIG_VHOST_NET=m
[root@jay-linux kvm_demo]# lsmod | grep vhost
vhost_net 17161 1
tun 13220 3 vhost_net
[root@jay-linux kvm_demo]# rmmod vhost-net
ERROR: Module vhost_net is in use
可见,宿主机中内核将vhost-net编译为module,此时vhost-net模块处于使用中状态(试图删除它时即报告了一个“在使用中”的错误)。
一般来说,使用vhost-net作为后端处理驱动可以提高网络的性能。不过,对于一些网络负载类型使用vhost-net作为后端,却可能使其性能不升反降。特别是从宿主机到其中的客户机之间的UDP流量,如果客户机处理接受数据的速度比宿主机发送的速度要慢,这时就容易出现性能下降。在这种情况下,使用vhost-net将会是UDP socket的接受缓冲区更快地溢出,从而导致更多的数据包丢失。故这种情况下,不使用vhost-net,让传输速度稍微慢一点,反而会提高整体的性能。
使用qemu-kvm命令行,加上“vhost=off”(或没有vhost选项)就会不使用vhost-net,而在使用libvirt时,需要对客户机的配置的XML文件中的网络配置部分进行如下的配置,指定后端驱动的名称为“qemu”(而不是“vhost”)。
<interface type="network">
...
<model type="virtio"/>
<driver name="qemu"/>
...
</interface>
smiler 你好,请问一个问题。back-end driver 是由qemu提供,如果自己想开发一个qemu 没有提供驱动的网卡的的驱动的话,该怎么办呢?比如模仿qemu-kvm 中的e1000 或者 rtl8139 的驱动写一个加入到qemu-kvm 源码中,按照你之前提供的编译方式编译码?
Hi, 你可以参考hw/rtl8139.c 或者 e1000.c 的实现吧。还需要修改pci.c文件和编译配置项(x86_64-softmmu/config-devices.mak),也需要./pc-bios/pxe-rtl8139.rom 这样的网卡ROM文件。按照我提供的方式编译即可(注意把自己的新网卡设备编译进去)。我没这样实际做过,可能不完全准确。
你好请教一个问题,ethtool -i eth1 在相同配置的kvm上分别执行,输出不一样
driver: virtio_net
version:
firmware-version:
bus-info: virtio0
supports-statistics: no
supports-test: no
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: no
driver: virtio_net
version: 1.0.0
firmware-version:
bus-info: 0000:00:03.0
supports-statistics: no
supports-test: no
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: no
都是virtio_net,一个现实出pci接口 一个显示virtio0
1. 再次确认启动kvm虚拟机的配置是否一样
2. 看下两个虚拟化操作系统的版本是否一样
3. lspci | grep virtio 看看