首页 资讯频道 互联频道 智能频道 网络 数据频道 安全频道 服务器频道 存储频道

详解DPDK与云计算虚拟化

2020-03-25 14:55:08 来源 : ssdfans

从DPDK诞生的那一天起,就受到了hyperscale的关注。原因也很简单,因为他们有对于性能的强烈需求,而且有大量的用户态的程序员。从2010年开始出现,6wind可能算是DPDK比较早期的支持者,因为它在北京有一个研发中心[1],可能这也是DPDK在中国发展得很好的一个原因。相对比,另一个同样也是用户态的高性能网络的编程框架OFED就不如它了。

本节的主要内容还是基于RedHat的Blog:

Data Plane Development Kit

DPDK提供了一种快速包处理方法。“run to completion for package processing", 就是意味着所有资源要在调用数据路径的处理程序之前就绪,这些专用的资源在专用的CPU上执行。一句话,如果你想在stackoverflow上利用"CPU Usage 100%" 来寻求帮助的话,你会失望的。

如下图所示,DPDK的框架中有个PMD (Polling Model Driver)负责把数据从网络网卡的接口搬移到用户态,可以看到这样操作的好处两个:Bypass Kernel的I/O操作,从而消除了因为处理中断带来的花销。不使用kernel的网络协议栈,之前Linux的网络协议栈的效率在高带宽网络的时代比较诟病。

DPDK是由一系列的用户态的库组成,码农们使用用户态的应用程序调用,非常方便。这里面唯一的不便就是原来那些基于Socket编程的教程就不适用了。没关系,互联网云计算为了追求效率,压榨硬件,从头到脚都可以自己搞定。

OVS-DPDK

在之前的OVS的定义中,open vswitch转发网络包都是利用kernel的数据路径的。在ovs的kernel模块中由一个简单的流表来处理包转发,如果命中,就直接通过kernel的数据路径发送,但是如果没有命中的包,就需要进行用户态和kernel之间的切换到OVS-deamon处理,找到对应的流表后会把新的规则更新到kernel的module。

显然,使用DPDK的好处就是by kernel,放弃kernel 的数据通路,使用用户态的应用直接和物理网卡通讯。在下图中,DPDK的应用在Host的用户态中,同样DPDK也可以在Guest的用户态。

Vhost-user/Virtio-PMD

在这个架构中,可以在host和guest的用户态都使用DPDK,这样就分成后端和前端。

后端:vhost-user 在host的用户态使用ovs-dpdk的应用。对于每个Guest的VM,都有一个对应的ovs-dpdk对应。

前端:在Guest的VM上运行pmd 驱动以及用户态的DPDK应用。

这样,和之前的kernel态的vhost-net/virtio-net对比,这个架构把数据路径从kernel态完全搬移到了用户态。通过host 的dpdk应用通过DPDK的大页内存直接访问物理网卡,从而bypass了host的kernel。通过virtio-pmd也一样bypass了Guest上的VM的kernel。这样性能会增加2到4倍,唯一的代价就是至少占有一个物理CPU和一个vCPU的core。

对于Hyperscale来讲,之前的DPDK的导入完全不是问题,因此在Host上的DPDK的后端基本上都可以搞定,问题在于前端,大部分公有云的客户没有能力做前端的开发,他们更喜欢的方式是使用一个virtio-net的驱动,他们使用正常的socket接口来和他们原来一样进行开发。

对于DPDK的导入,还有一个问题就控制路径的实现。我们在deep dive中详细解释。

DPDK的细节

记得自己在刚刚接触PCIE Flash的时候,因为之前的HardDisk的性能和PCIE Flash的差别很大,因此在大部分的应用程序没有准备好之前,你要做各种各样的设置从而优化PCIE Flash的性能。同样,DPDK也需要:CPU的亲和:DPDK需要把每个不同线程绑定在特定的CPU上从而得到最佳的并行化。这个也就意味着CPU最好各司其职,不要有应用程序在CPU之间切换。大页:DPDK有自己独立的内存管理方法。通过使用2M或者更大的page,他们可以降低cache miss以及TLB的lookup。

无锁的ring buffer 这个是DPDK的高效的一个核心,通过调用ring library进行队列的处理,可以提供支持burst 进队和出队的操作。PMD 使用PMD 驱动就避免了中断。支持VFIO :很多人把VFIO看作是PCIE 设备passthrough的代名词,其实是错误的。PCIE设备的passthrough在hyperviosr出现不久就可以支持,而基于vt-d技术的VFIO本质上是提供了安全的内存访问保护的高性能接口,当然它的定义不局限于SRIOV。[2]

同时,DPDK也提供了vhost-user的用户态库实现vhost的协议。以及virtio-pmd。OVS-DPDK

这个已经是DPDK的一个标准模块了,在用户态实现了OVS的fast path,这样OVS的slow path和fast path都是在用户态,成功避免了用户/kernel切换,并利用DPDK的高性能。

Vhost-user with DPDK

vhost原本是一套消息机制来从qemu实现来卸载virtio的数据路径。因此DPDK的vhost-user 库是一套用户态的vhost协议的实现,可以让qume把virtio的数据路径卸载给任意的DPDK应用程序,比如OVS-DPDK。

vhost-user库和vhost-net的主要不同就是通路。vhost-net是使用ioctl来实现的,而vhost-user库是通过socket接口收发特定的消息。

DPDK可以配置成Socket的模式,作为server端让qume作为client端进行连接。通过这种方式,可以解耦和DPDK和VM,DPDK端可以重启,而VM不需要。在Socket通讯上,所有的请求来自Qemu,vhost-user库可以让QEMU定义数据路径的卸载:功能的协商 :virtio以及vhost-user的功能协商都是通过支持功能的bitmap机制实现。内存空间的配置:Master定义内存map空间,handler可以通过mmap进行访问。Vring的配置:Qemu设置virtqueue的数量以及内存空间地址。vhost-user可以支持多队列,因此virtqueue可以有多个。Kick /Call的文件描述符:通常情况下和之前一样,使用irqfd和iovenetfd。

通过以上的方式,基于DPDK的应用可以通过和Guest共享内存可以进行包的处理,同时通过irqfd和ioeventfd和guest收发notification,而不用Qemu参与。

Virtio-Device-Model with Qemu它仿真了一个virtio设备,通过提供个Guest一个PCIE设备可以被probed而且可以提供配置空间信息。它把ioeventfd接口映射到仿真设备的memory-mapper I/O 空间,把irqfd映射到它的Global System Interrupt。这样guest就不用感知notification和irq都被vhost-user 库接管了。这个设备不用自己实现virtio的数据路径的功能,而是作为一个master使用vhost-user的协议去卸载virtio数据路径到vhost-user DPDK实现。它需要处理控制路径的请求,它需要把请求翻译成vhost-user 的request,作为master发送给slave。 下图是vhost-user 库和virtio-pci device的总体。

通过vfio设备驱动可以把vIOMMU和任何的用户态的网络应用进行整合。这个VFIO驱动会进行设备的隔离以及自动添加iova-GPA的映射。

DPDK的大页内存的使用机制使用静态的内存池作为包的缓存以及虚拟队列,因此设备的TLB的同步信息会大大减少,这个和之前讲的网络的TSO和LSO的效果类似。同样,大页内存可以优化TLB的查找,因为可以使用更少的元数据.

vIOMMU和vhost-user的整合

当一个仿真设备在qemu里面的试图通过DMA访问guest virtio的I/O空间的时候,它还是要访问viommu的TLB去查找page映射并进行一个安全的DMA操作。但是如果真正的DMA已经被卸载到使用DPDK的vhost-user 库的外部进程上。

当vhost-user直接访问这段共享内存时,它必须把IOVA翻译成自己的内存。它请求QEMU的vIOMM通过设备的TLB进行翻译。Vhost-user库(和vhost-net kernel驱动)使用PCIE 的地址翻译服务(ATS)请求[4]Qemu,这个通路基于unix socket,在iommu设置的时候已经配置。总体的步骤:QEMU 的vIOMMU翻译IOVA到GPGAQemu的内存管理翻译GPA到 HVAVhost-User翻译QEMO的HVA到它自己的HVA。通常添加QEMU的HVA到mmap的返回地址。

下图是Host DPDK和Guest DPDK的通讯

Full Picture

目前下图可能是最复杂的流程图了。有必要再复习一下控制和数据路径的setup过程:

控制路径:Host的OVS-DPDK启动的时候会创建一个Socket( server mode)用来和qemu进行virtio相关的通讯。qemu启动的时候会连接这个socket,如果vhost-user提供了VHOST_USER_PROTOCOL_F_SLAVE_REQ,qemu会创建第二个socket并提供给vhost-user,并建立连接,进行iotlb同步信息传输。当QEMU和vhost-user 库的协商结束,有2个socket连接在他们之间。一个是virtio的配置,另一个是iotlb消息交互。Guest启动,vfio的驱动绑定PCI设备,它建立了对iommu的访问。当一个DPDK应用在Guest上启动,它的初始化如下:初始化PCI-VFIO设备。vfio驱动映射PCI的配置空间到用户内存。分配virtqueue使用vfio,发出一个DMA请求,把virtqueue的内存空间通过IOMMU的驱动mapping到vIOMMU设备。进行virtio设备功能的协商。这在里,virtqueue使用的地址是IOVA。映射ioeventfd和irqfd。最后,DPDK应用分配内存作为网络的缓存。同时添加这段内存空间到vIOMMU。

数据路径:Guest上的DPDK应用通过virtio-pmd发送一个网络包。它写入缓存空间,并增加对于的ring描述符。Host空间的vhost-user PMD pollingvirtqueue,它会立刻检测到新描述符并开始处理。对于每个virtqueue的描述符,vhost-user会映射到buffer (IOVA到Vhost-User HVA)。只有在这段buffer的page没有在vhost-user的IOTLB中,才会请求QEMU进行page walk。正常情况下,DPDK都使用静态的大页内存,需要QEMU pagewalk的概率很低。Vhost-user PMD复制数据到mbufs中(DPDK的message buffer)把这个描述符添加到used 的ring上,这时已经在polling的guest的DPDK应用就知道请求已经被处理了。Host端的DPDK对于mbufs中的数据进行处理。

总结:

DPDK对于OVS的加速对于网络虚拟化的吸引力很大,OVS对于CPU的消耗会随着网络节点的数量增加而指数级增加。

Virtio-net提供了一个高效的安全的Guest和Host的交互通路,这个对于在两边使用DPDK很重要。

Vhost-user library实现了网络处理的DPDK卸载。

在Guest上,需要使用virtio-pmd来创建一个快速的datapath。

总体来讲,通过virtio的virqueue,在host和guest都有DPDK应用使用polling在检测ring的描述符。这样的确实现了数据路径的高性能,但是就是有点苦了CPU。毕竟,云计算是卖CPU的,这个就是AWS在收购了annapurna labs之后并没有使用下图的架构。

virtio的内存空间是Guest分配的。上图的virtio设备的驱动和virtio设备是按照正常的virtio协议交互,设备提供了基于PCI的BAR的配置接口。virtio-device-model 使用vhost-user 协议配置vhost-user DPDK模块,并设置irqfd和ioeventfd的文件描述符。virtio的内存空间是通过mmap的syscall 映射给 host上的vhost-user 库DPDK应用可以直接通过共享内存读写网络包,并使用irqfd和ioeventfd和Guest进行交互。

Guest的用户态实现

我们之间讲的都是如何从host的kernel卸载数据路径到用户态的DPDK。但是如果Guest的应用也想使用DPDK呢?如果在Guest上实现一个用户态的网络协议,需要:VFIO接口,VFIO之前已经讲过,这个是一个用户态的驱动开发框架,它可以实现用户态应用直接访问设备。(bypass kernel)Virtio-pmd driver 实现virtio协议的Poll Mode DriverIOMMU Driver:这个iommu驱动管理虚拟的IOMMU,vIOMMU是一个管理DMA设备的I/O地址映射的仿真设备。

VFIO

再次强调一下VFIO,DPDK支持的UIO在虚拟化环境中是usafe的,主要原因是Guest和Host内存访问权限问题。[3]

vIOMMU and DPDK整合通过vfio设备驱动可以把vIOMMU和任何的用户态的网络应用进行整合。这个VFIO驱动会进行设备的隔离以及自动添加iova-GPA的映射。

DPDK的大页内存的使用机制使用静态的内存池作为包的缓存以及虚拟队列,因此设备的TLB的同步信息会大大减少,这个和之前讲的网络的TSO和LSO的效果类似。同样,大页内存可以优化TLB的查找,因为可以使用更少的元数据.

vIOMMU和vhost-user的整合

当一个仿真设备在qemu里面的试图通过DMA访问guest virtio的I/O空间的时候,它还是要访问viommu的TLB去查找page映射并进行一个安全的DMA操作。但是如果真正的DMA已经被卸载到使用DPDK的vhost-user 库的外部进程上。

当vhost-user直接访问这段共享内存时,它必须把IOVA翻译成自己的内存。它请求QEMU的vIOMM通过设备的TLB进行翻译。Vhost-user库(和vhost-net kernel驱动)使用PCIE 的地址翻译服务(ATS)请求[4]Qemu,这个通路基于unix socket,在iommu设置的时候已经配置。总体的步骤:QEMU 的vIOMMU翻译IOVA到GPGAQemu的内存管理翻译GPA到 HVAVhost-User翻译QEMO的HVA到它自己的HVA。通常添加QEMU的HVA到mmap的返回地址。

下图是Host DPDK和Guest DPDK的通讯

Full Picture

目前下图可能是最复杂的流程图了。有必要再复习一下控制和数据路径的setup过程:

OVS-DPDK

在之前的OVS的定义中,open vswitch转发网络包都是利用kernel的数据路径的。在ovs的kernel模块中由一个简单的流表来处理包转发,如果命中,就直接通过kernel的数据路径发送,但是如果没有命中的包,就需要进行用户态和kernel之间的切换到OVS-deamon处理,找到对应的流表后会把新的规则更新到kernel的module。

显然,使用DPDK的好处就是by kernel,放弃kernel 的数据通路,使用用户态的应用直接和物理网卡通讯。在下图中,DPDK的应用在Host的用户态中,同样DPDK也可以在Guest的用户态。

Vhost-user/Virtio-PMD

在这个架构中,可以在host和guest的用户态都使用DPDK,这样就分成后端和前端。

后端:vhost-user 在host的用户态使用ovs-dpdk的应用。对于每个Guest的VM,都有一个对应的ovs-dpdk对应。

前端:在Guest的VM上运行pmd 驱动以及用户态的DPDK应用。

这样,和之前的kernel态的vhost-net/virtio-net对比,这个架构把数据路径从kernel态完全搬移到了用户态。

相关文章

最近更新