《深入浅出DPDK》——半虚拟化Virtio

半虚拟化Virtio

virtio是一种半虚拟化的设备抽象接口规范。与宿主机纯软件模拟I/O设备相比,Virtio可以获得更好的I/O性能。

缺点是必须要求客户机安装特定的Virtio驱动使其知道运行在虚拟化环境中。

Virtio使用场景

现代数据中心大量采用虚拟化技术,设备的虚拟化是其中重要的一环。

Virtio作为一种标准化的设备接口,主流的操作系统和应用都逐渐加入了对Virtio设备的直接支持,这给数据中心的运维带来了很多方便。

Virtio同I/O透传技术相比,目前在网络吞吐率、时延以及抖动上尚不具优势,相关的优化工作正在进行当中。

I/O透传的一个典型问题是从物理网卡接收到的数据包将直接送达客户机的接收队列,或者从客户机发送队列发出的包将直接到达其他客户机(比如同一个PF的VF)的接收队列或者直接从物理网卡发出,绕过了宿主机的参与。

但是在很多应用场景下,有需求要求网络包必须先经过宿主机的处理(防火墙、负载均衡等),再传递给客户机。

另外I/O透传技术不能从硬件上支持虚拟机的动态迁移以及缺乏足够灵活的流分类规则。

 

上图是Virtio设备的典型应用场景,宿主机使用虚拟交换机连通物理网卡和虚拟机。虚拟交换机内部有一个DPDK vhost,实现了Virtio的后端网络设备驱动程序逻辑。虚拟机里有DPDK的Virtio前端网络设备驱动。前端和后端通过Virtio的虚拟机队列交换数据。这样虚拟机里的网络数据可以发送到虚拟交换机中,然后经过转发逻辑,可以经由物理网卡进入外部网络。

Virtio规范和原理

Virtio规范主要有两个版本,0.95和1.0,其规定的实现接口有PCI、MMIO(内存映射)和Channel IO方式,而Channel IO方式是1.0规范中新加的。

PCI是现代计算机系统中普遍使用的一种总线接口,最新的规范是PCI-e。

在一些系统中(例如嵌入式系统中),可能没有PCI接口,Virtio可使用内存映射方式。

IBM S/390的虚拟机系统既不支持PCI接口也不支持内存映射方式,只能使用特有的Channel IO方式。

DPDK目前只支持Virtio PCI接口方式。

Virtio在PCI(传输层)的结构之上还定义了Virtqueue(虚拟队列)接口,他在概念上将前端驱动程序连接到后端驱动程序。

驱动程序可以使用一个或多个队列,具体的数量取决于需求。例如,Virtio网络驱动程序使用两个虚拟队列(一个用于接收,另一个用于发送),而Virtio块驱动程序则使用一个虚拟队列。

Virtio用PCI接口实现时,宿主机会使用后端驱动程序模拟一个PCI的设备,并将这个设备添加在虚拟机配置中。

设备的配置:

  • 设备的初始化

  1. 手工重启设备状态,或者是设备上电时的自动启动后,系统发现设备。

  2. 客户机操作系统设置设备的状态为Acknowledge,表示当前已经识别到设备。

  3. 客户机操作系统设置设备的状态为Driver,表明客户操作系统已经找到合适的驱动程序。

  4. 设备驱动的安装和配置:进行特性列表的协商,初始化虚拟队列,可选的MSI-X的安装,设备专属的配置等。

  5. 设置设备状态为Driver_OK,或者如果中途出现错误,则为Failed。

  • 设备的发现

通过Virtio Device ID来识别各个Virtio设备。

  • 传统模式Virtio的配置空间

传统模式使用PCI设备的BAR0来对PCI设备进行配置。如果传统设备配置了MSI-X中断,则在Bits后添加两个域。紧接着,这些通常的Virtio参数可能会有指定设备(例如网卡)专属的配置参数。

  • 现代模式Virtio的配置空间

和传统设备固定使用BAR0不同,现代设备通过标准的PCI配置空间中的能力列表,可以指定配置信息的存储位置(使用哪个BAR,从BAR空间开始的偏移地址等)。

1.0规范定义了四种配置信息:通用配置、提醒、中断服务状态、设备专属配置。

设备状态:

Device Status 域主要由 guest 来更新,表示当前 drive 的状态。状态包括:

0:写入 0 表示重启该设备

1:Acknowledge,表明 guest 已经发现了一个有效的 virtio 设备

2:Driver,表明 guest 已经可以驱动该设备,guest 已经成功注册了设备驱动

3:Driver_OK,表示 guest 已经正确安装了驱动,准备驱动设备

4:FAILED,在安装驱动过程中出错

128: 在安装驱动过程中出错

8: FEATURES_OK,表示驱动程序和设备特性协商成功

64:DEVICE_NEEDS_RESET,表示设备遇到错误,需要重启。

特性列表:

设备和驱动都有单独的特性列表,现代设备特性列表有64字位,传统设备只支持32字位。通过特性列表,设备和驱动都能提供自己致辞的特性集合。设备在初始化过程中,驱动程序读取设备的特性列表,然后挑选其中自己能够支持的作为驱动的特性列表。这就完成了驱动和设备之间的特性协商。

中断配置:

现代设备和传统设备都支持两种中断源(设备中断和队列中断)和两种中断放式(INTx和MSI-X)。每个设备中设备中断源只有一个,队列中断源则可以每个队列一个。但具体有多少个中断还取决于中断方式。

INTx方式下,一个设备只支持一个中断,所以设备中断源和队列中断源必须共享这一个中断。

MSI-X支持多个中断,每个单独中断也称为中断向量。

设备的专属性配置:

此配置空间包含了特定设备(例如网卡)专属的一些配置信息,可由驱动读写。

虚拟队列的配置

虚拟队列(Virtqueue)是连接客户机操作系统中Virtio设备前端驱动和宿主机后端驱动的实际数据链路。

虚拟队列主要由描述符列表(descriptor table)、可用环表(available ring)、已用环表(used ring)组成。

描述符列表指向的是实际要传输的数据。两个环表指向的是描述符列表,分别用来标记前端和后端驱动对描述符队列表中描述符的处理进度。

在传统网卡设备中,对描述符的处理进度,一般用两个指针就可以标记:前端指针指向网卡驱动在描述符列表的处理位置,后端指针指向 网卡设备处理的位置。

网卡设备中双指针方案有一个缺点:描述符只能顺序执行,前一个 描述符处理完之前,后一个描述符就只能等待。

Virtio设备中的虚拟队 列则不存在这个限制,队列的生产者(前端驱动)将生产出来的描述符放在可用环表中,而消费者(后端驱动)消费之后将消费过的描述符放 在已用环表中。前端驱动可以根据已用环表来回收描述符以供下次使用。这样即使中间有描述符被后端驱动所占用,也不会影响被占用描述 符之后其他描述符的回收和循环使用。

  • 初始化虚拟队列

  1. 选择虚拟队列的索引,写入队列选择寄存器(Queue Select)

  2. 读取队列容量寄存器(Queue Size),获得虚拟队列的大小,如 果是0的话,则表示这个队列不可用。(传统设备中,队列容量只能由设备指定,而现代设备中,如果驱动可以选择写入一个小一些的值到队列容量寄存器来减少内存的使用。)

  3. 分配队列要用到的内存,并把处理后的物理地址写入队列地址寄存器(Queue Address)。

  4. 如果MSI-X中断机制启用,选择一个向量用于虚拟队列请求的中断,把对应向量的MSI-X序号写入队列中断向量寄存器(Queue Vector),然后再次读取该域以确认返回正确值。

  • 描述符列表

描述符列表中每一个描述符代表的是客户虚拟机这侧的一个数据缓冲区,供客户机和宿主机之间传递数据。如果客户机和宿主机之间一次 要传递的数据超过一个描述符的容量,多个描述符还可以形成描述符链 以共同承载这个大的数据。

每个描述符有4个属性:

  1. Address:数据缓冲区的客户机物理地址。

  2. Len:数据缓冲区的长度。

  3. Next:描述符链中下一个描述符的地址。

  4. Flags:标志位,表示当前描述符的一些属性,包括Next是否有效 (如无效,则当前描述符是整个描述符链的结尾),和当前描述符对设 备来说是否可写等。

  • 可用环表

可用环表是一个指向描述符的环型表,是由驱动提供(写入),给设备使用(读取)的。设备取得可用环表中的描述符后,描述符所对应 的数据缓冲区既可能是可写的,也可能是可读的。可写的是驱动提供给 设备写入设备传送给驱动的数据的,而可读的则是用于发送驱动的数据 到设备之中。

有3个属性:

  1. ring:存储描述符指针(id)的数组。

  2. index:驱动写入下一个可用描述符的位置。

  3. Flags:标志位,表示可用环表的一些属性,包括是否需要设备在使 用了可用环表中的表项后发送中断给驱动。

  • 已用环列表

已用环表也是一个指向描述符的环型表,和可用环表相反,它是由设备提供(写入),给驱动使用(读取)的。设备使用完由可用环表中 取得的描述符后,再将此描述符插入到已用环表,并通知驱动收回。

已用环表的表项有3个属性:

  1. ring:存储已用元素的数组,每个已用元素包括描述符指针(id) 和数据长度(len)

  2. index:设备写入下一个已用元素的位置。

  3. Flags:标志位,表示已用环表的一些属性,包括是否需要驱动在回收了已用环表中的表项后发送提醒给设备。

设备的使用

设备使用主要包括两部分过程:驱动通过描述符列表和可用环表提供数据缓冲区给设备用,和设备使用描述符后再通过已用环表还给驱 动。例如,Virtio网络设备有两个虚拟队列:发送队列和接收队列。驱动添加要发送的包到发送队列(对设备而言是只读的),然后在设备发送完之后,驱动再释放这些包。接收包的时候,设备将包写入接收队列中,驱动则在已用环表中接收处理这些包。

1.驱动向设备提供数据缓冲区:客户机操作系统通过驱动提供数据缓冲区给设备使用,具体包括以下步骤:

1)把数据缓冲区的地址、长度等信息赋值到空闲的描述符中。

2)把该描述符指针添加到该虚拟队列的可用环表的头部。

3)更新该可用环表中的头部指针。

4)写入该虚拟队列编号到Queue Notify寄存器以通知设备。

2.设备使用和归还数据缓冲区:设备使用数据缓冲区后(基于不同种类的设备可能是读取或者写入,或是部分读取或者部分写入),将用过的缓冲区描述符填充已用环表,并通过中断通知驱动。具体的过程如下:

1)把使用过的数据缓冲区描述符的头指针添加到该虚拟队列的已用环表的头部。

2)更新该已用环表中的头部指针。

3)根据是否开启MSI-X中断,用不同的中断方式通知驱动。

Virtio网络设备驱动设计

Virtio网络设备是Virtio规范中到现在为止定义的最复杂的一种设备。Linux内核和DPDK都有相应的驱动,Linux内核版本功能比较全面,DPDK则更注重性能。

virtio网络设备Linux内核驱动设计

Virtio网络设备Linux内核驱动主要包括三个层次:底层PCI-e设备层,中间Virtio虚拟队列层,上层网络设备层。

底层PCI-e设备层:底层PCI-e设备层负责检测PCI-e设备,并初始化设备对应的驱动程序。

中间Virtio虚拟队列层:中间Virtio虚拟队列层实现了Virtio协议中的虚拟队列。

上层网络设备:上层网络设备层实现了两个抽象类:Virtio设备 (virtio_net_driver::virtio_driver)和网络设备(dev::net_device)。

基于DPDK用户空间的Virtio网络设备驱动设计及性能优化

其主要实现是在目录drivers/net/virtio/下,也是包括三个层次:底层PCI-e设备层,中间Virtio虚拟队列层,上层网络设备层。

底层PCI-e设备层的实现更多的是在DPDK公共构件中实现,virtio_pci.c和virtio_pci.h主要是包括一些读取PCI-e中的配置等工具函数。

中间Virtio虚拟队列层实 现在virtqueue.c,virtqueue.h和virtio_ring.h中,vring及vring_desc等结构定义和Linux内核驱动也都基本相同。

上层的网络设备层实现的是rte_eth_dev的各种接口,主要在 virtio_ethdev.c和virtio_rxtx.c文件中。virtio_rxtx负责数据报的接受和发送,而virtio_ethdev则负责设备的设置。

DPDK用户空间驱动充分利用了DPDK在构架上的优势 (SIMD指令,大页机制,轮询机制,避免用户和内存之间的切换等)和只需要针对网卡优化的特性,虽然实现的是和内核驱动一样的Virtio协议,但整体性能上有较大的提升。

  • 关于单帧mbuf的网络包收发优化

如果一个数据包能够放入一个mbuf的结构体中,叫做单帧mbuf。

在QEMU/KVM的Virtio实现中,vring描述符的个数一般设置成 256个。对于接收过程,可以利用mbuf前面的HEADROOM作为virtio net header的空间,所以每个包只需要一个描述符。对于发送过程,除了需 要一个描述符指向mbuf的数据区域,还需要使用一个额外的描述符指向 额外分配的virtio net header的区域,所以每个包需要两个描述符。

  • Indirect特性在网络包发送中的支持

Indirect特性指的是Virtio前端和后端通过协商后,都支持 VIRTIO_F_RING_INDIRECT_DESC标示,表示驱动支持间接描述符表。

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: DPDK(Data Plane Development Kit)是一种高性能数据面开发工具包。深入浅出DPDK是一份详细介绍DPDK的PDF文档,适合初学者了解DPDK的基本概念和使用方法。 该文档从DPDK的介绍开始,介绍了DPDK的发展历史、使用场景和目标。接着详细介绍了DPDK的架构,包括主要组件和数据流向。其中详细介绍了包管理的基本原理和流程、缓存池的管理方式、内存对齐和地址映射等内容。 文档还介绍了如何使用DPDK,包括DPDK的编译和安装、如何使用DPDK进行虚拟网络功能(VNF)处理,以及如何使用DPDK进行数据包嗅探和过滤等。 此外,该文档还介绍了DPDK的性能优化技巧,包括如何优化包接收和处理、如何使用多核心优化性能和如何配置DPDK与硬件交互。 总体而言,深入浅出DPDK是一份非常有价值的文档,它不仅为初学者提供了详细的DPDK介绍和使用指南,还涵盖了DPDK的高级主题和性能优化技巧,为使用DPDK进行高性能数据面开发的人员提供了重要的参考资料。 ### 回答2: DPDK(Data Plane Development Kit)是一个高性能数据平面开发工具包,它使用用户态技术实现了零拷贝的数据处理和高速的数据包转发。作为一款开源工具,DPDK已经被广泛应用于虚拟化、云计算及网络功能虚拟化等领域。 《深入浅出dpdk》是一份由DPDK社区编写的指南,它的目的是帮助开发人员更好地了解DPDK,并使用DPDK构建高性能网络应用程序。该指南提供了详细的DPDK架构、API接口、应用案例和性能调优等方面的介绍,同时也介绍了其他相关技术,例如硬件加速、 NUMA架构、 数据库加速、分布式系统等。 《深入浅出dpdk》PDF版本可以从DPDK社区网站上自由下载,它包含了大量易懂的图表和代码实例,让开发人员更容易理解DPDK的概念和原理。对于想要在高性能数据平面开发方面取得突破的开发人员来说,这份指南是不可或缺的学习资料。 需要注意的是,《深入浅出dpdk》不仅是一份教材,更是一份指导开发人员如何使用DPDK进行数据平面开发的实际指南。开发人员在阅读本指南的同时,也需要具备一定的网络编程基础和C语言编程能力。同时,开发过程中还需要注意DPDK版本的兼容性和网络设备的支持情况。 ### 回答3: DPDK(Data Plane Development Kit)是一种高性能数据面开发工具包,它可以帮助开发人员快速地实现高性能网络应用程序。本篇文章解析的Deep Dive into DPDK的PDF文件是一份帮助初学者深入了解DPDK的指南,其中详细地介绍了DPDK的各种重要概念、特性和使用方法。 首先,这份PDF文件详细介绍了DPDK的架构和工作原理。DPDK采用轮询机制减少了对内核的依赖,从而显著提高了网络数据处理的性能。此外,本文还介绍了DPDK中各种组件的作用和功能,例如EAL(Environment Abstraction Layer)、Mempool、Ring等。这些组件都是DPDK中重要的工具,它们可以帮助开发人员更好地构建高性能应用程序。 其次,本文还介绍了如何使用DPDK来构建网络应用程序。首先,开发人员需要安装DPDK,并正确配置相应环境变量。其次,本文还介绍了如何使用DPDK的API来实现数据包的发送和接收。这些API提供了高效的数据传输方式和内存管理方式,开发人员可以根据自己的需求进行自定义。 此外,本文还介绍了DPDK的一些高级功能,例如NUMA支持、内存优化等。这些功能可以帮助开发人员更好地控制和管理系统资源,从而确保系统的高性能和稳定性。 总之,本文是一份非常实用的DPDK指南,其中介绍了DPDK的各种重要概念、特性和使用方法。初学者可以通过阅读这份文件,快速掌握DPDK的核心知识,为构建高性能应用程序打下牢固的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值