目录

Virtio规范简介

相关数据结构

Vring机制简介

相关文章


 

实现IO虚拟化主要有三种方式:全虚拟化、半虚拟化和透传。全虚拟化Guest OS不会感知到自己是虚拟机,也无需修改Guest OS,但是它的效率比较低。半虚拟化Guest OS知道自己是虚拟机,通过Frontend/Backend驱动模拟实现IO虚拟化。透传就是直接分配物理设备给VM用。Virtio是一种半虚拟化的设备抽象接口规范,在Qemu和KVM中得到了广泛使用,本文将简单介绍Virtio的基本原理。

代码版本

  • Qemu
    • qemu-2.10.1
  • Kernel
    • kernel-3.10.0

Virtio SPEC

  Virtio在Guest中实现了前端驱动在Host中实现了后端驱动,前后端之间通过Virtqueue(虚拟队列)交换数据,Host中会使用后端驱动程序模拟一个PCI设备,因此也称前端驱动为Driver,后端驱动为Device。Guest在Host OS上表示为一个Qemu的进程,Guest OS的pa实际上也属于Host OS的地址空间,因此Virtio采用的Virtqueue的方式来避免了Guest和Host间数据的复制。下面先介绍一下Virtio,更为详细的描述请阅读前言中提供的Virtio SPEC文档,那里是最准确而详细的描述,在此仅简单介绍一下后文需要用到的概念。

 

Virtio规范简介


Basic Facilities of a Virtio Device

  每个Virtio设备包括以下部分

  • Device status field  设备状态字段
  • Feature bits  特征位
  • Device Configuration space  设备配置空间
  • One or more virtqueues  一个或多个virtqueues

virtqueues

  在virtio设备上进行批量数据传输的机制被称为virtqueue,每个设备可以拥有零个或多个virtqueue,每个virtqueue由三部分组成:

  • Descriptor Table
  • Available Ring
  • Used Ring

  每部分在客户机内存中是物理连续的,并且有不同的对齐要求,virtqueue的每个部分的内存对齐和大小要求如下表,其中Queue Size对应virtqueue中的最大buffer数,始终为2的n次幂,以特定于总线的方式指定:

Virtqueue PartAlignmentSize
Descriptor Table1616*(Queue Size)
Available Ring26 + 2*(Queue Size)
Used Ring46 + 8*(Queue Size)

  Descriptor Table指的是Driver用于Device的缓冲区,由Queue Size个Descriptor组成。Descriptor中存有GPA的字段addr,长度字段len,可以链接next Descriptor的next指针等(形成描述符链)。如果协商了VIRTIO_F_INDIRECT_DESC feature则可以使用Indirect Descriptors来增加ring的容量。
  Available Ring中的每个条目是一个是描述符链的头部,它仅由Driver写入并由Device读取,Device获取Descriptor后,Descriptor对应的缓冲区可能是可读的也可能是可写的,可读的用于Driver发送数据,可写的用于接收数据。
  Used Ring的介绍直接贴SPEC文档中的描述上来比翻译过来更容易理解。The used ring is where the device returns buffers once it is done with them: it is only written to by the device,and read by the driver.简单来说Used Ring的作用就是Device使用完Descriptor之后,将Descriptor放入这里,通知Driver回收。

 

相关数据结构


一些数据结构只列举了部分关键信息

如图所示,virtnet_info作为virtio网络设备的私有数据将virtio_devicenet_device链接在一起。对于virtio网络设备来说,它至少有两个virtqueue(如果协商了VIRTIO_NET_F_MQ则可以创建多个队列,详见VirtIO SPEC中5.1.2 ),一个用于TX(send_queue),另一个用于RX(receive_queue),TX和RX队列中都包含了virtqueuescatterlist[]virtio_device、virtnet_info、receive_queue、send_queue、virtqueue给定任一结构体均可得到其它结构体信息。

可以把virtqueue理解为一个接口类,而vring_virtqueue作为这个接口的一个实现,vring_virtqueue通过成员vq可以与上述其它struct建立联系。virtio的环形缓冲区机制是由vring来承载的,vring由三部分组成:Descriptor表(vring_desc),Available ring(vring_avail)和Used ring(vring_used)。

Vring机制简介


在virtio设备上进行批量数据传输的机制被称为virtqueue。每个设备可以拥有零个或多个virtqueue,当Driver想要向设备发送数据时,它会填充Descriptor Table中的一项(或将几项链接在一起),并将描述符索引写入Available Ring中,然后它通知Device,当Device完成后,它将描述符索引写入Used Ring中并发送中断。(详见SPEC 2.4)

下图Virtio网络设备发包过程为例讲解上述机制,Driver将sk_buffer填充进scatterlist table中(只是设置地址没有数据搬移),然后通过计算得到GPA并将GPA写入Descriptor Table中,同时将Desc chain的head记录到Available Ring中,然后通过PIO的方式通知Device,Device发包并更新Used Ring

后续会有一篇文章专门分析发包过程

 

相关文章


Linux虚拟化KVM-Qemu分析(八)之virtio初探

Linux虚拟化KVM-Qemu分析(九)之virtio设备

virtio 网络的演化

使用DPDK打开Open vSwitch(OvS) *概述

Open vSwitch(OVS)文档

《深入浅出DPDK》读书笔记(十五):DPDK应用篇(Open vSwitch(OVS)中的DPDK性能加速)

virtio 网络的演化:原始virtio > vhost-net(内核态) > vhost-user(DPDK) > vDPA

 

站外参考文章


SR-IOV:网卡直通技术

关于英特尔® 以太网服务器适配器中 SR-IOV 的常见问题解答

Vhost-user详解

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐