本文介绍 virtio-net
和 vhost-net
网路实现原理。其中,vhost-net
是运行在宿主机内核空间的后端,virtio-net
是运行在虚拟机内核空间的前端。
virtio-net 架构图
virtio-net
一套网络半虚拟化驱动 + 设备的方案。
说明:
控制通道(control path)
用来管理 前端(Front-end)
和 后端(Back-end)
数据通道和参数配置,如图中蓝实线所示数据通道(data path)
传输数据,如图中 Host User Space
中红实线所示vring
虚拟机中与物理机共享的内存通知通道(notifications)
传递 vmexit/vCPU irq 等,如图中红虚线所示virtio data path interface
Qemu 和宿主机内核 tap
通信
网络通信流程
- 虚拟机中
virtio-net driver
通过虚拟 PCIE 总线
连接到 QEMU
模拟的 virtio-net device
;驱动初始化后,两者建立 控制通道(control path)
,协商通信能力,虚拟机分配 vring
并与 QEMU
共享 网络发包
:虚拟机更新 vring
,通过 KVM
通知 QEMU
,QEMU
在将报文发送到宿主机内核的 TAP
设备网络收包
:QEMU
收到报文,填充 vring
,通过 KVM
向虚拟机触发虚拟中断
,虚拟机完成收包
问题
- 上下文切换多,报文和通知需要在
虚拟机
、KVM
、QEMU
和 宿主机内核
四者之间多次切换 - 依赖
QEMU
传递数据,效率比较低
vhost-net/virtio-net 架构
vhost
是 virtio
的一种后端实现方案(一般实现在用户态的QEMU中,但 vhost
实现在宿主机内核中 vhost-net.ko
),vhost
通过将 virtio
的数据通道卸载到 内核态(如vhost-net)
或 用户态
来实现性能的提升
说明:
virtio-net driver
作为前端,运行在虚拟机内核态vhost-net
作为后端,运行在宿主机内核态virtio 控制平面(control plane)
将 vring
协商好后,数据
脱离 QEMU
,被 卸载
到vhost-net
,仅负责控制层面的事情vhost
会启动内核线程
,负责处理虚拟机的数据。其中,虚拟机的vring
直接映射到宿主机内核态,比较高效- 与
virtio-net
相比,vhost-net
处理数据在内核态,在发送到 tap
的时候少了一次数据的拷贝
vhost
与 kvm
的事件通信通过 eventfd
机制来实现,主要包括两个方向的 event:
- 一个是
guest
到 vhost
方向的 kick event
,通过 ioeventfd
实现 - 另一个是
vhost
到 guest
方向的 call event
,通过 irqfd
实现
配置
QEMU 2.10.0
和 libvirt 3.7.0
后,可以配置 tx_queue_size
和 rx_queue_size