首页 > 科技 >

SRIOV:智能网卡就靠它了!

2020-04-01 06:13:07 暂无 阅读:1780 评论:0

在DPDK的那一篇中,其实有一个重要的笔误,但是除了一个朋友看到后指出外,基本上没有人说到这个。这个就是DPDK是Kernel-Bypass的,本写成了Kernel-By。

看样子,大家都有深知kernel-bypass对于高速网络的重要性。在云计算的VPC业务主流之前,大部分都预见了kernel的瓶颈。

一个MTU 1500的帧的Time budget [1]

10Gbit/s =1230.4ns (812, 774 PPS)

25Gbit/s = 492.3ns (2,031,859 PPS)

40Gbit/s = 307.6ns (3,251,096 PPS)

100Gbit/s= 123.0ns (8,127,740 PPS)

同样,对于最小的以太帧84Byte,

10Gbit/s = 67.2ns ( 14,880,952 PPS)

以一个主流的Intel的X86 的CPU,3.0G为例:67.2ns 差不多就是201个CPU Cycle。[2]

而linux kernel主要的机制的代价如下:

SRIOV:智能网卡就靠它了!

因此结论也很明确,目前linux 缺省的网络协议最高也只能handle

1-2MPPS的性能,大家需要考虑kernel-bypass。[3]

目前Linux已知的Kernel-ByPass 框架:DPDK (Intel/LF)RDMA/IBVerbs (Mellanox/OFA)eBPF/XDP (Vmware/FB/RedHat/Huawei)netmap (FreeBSD)PF_RING/DNA (ntop)Open (Xilinx)Maglev (Google)Snabb (Deutsche Telekom)FD.IO/VPP (Cisco)

这里就在回应上一篇ARM同学的话,原来做硬件的网卡厂家只需要照顾自己的Linux驱动,但是现在为了让自己Smart起来,就要支持不同的kernel-bypass的框架,这个的确是伤不起。关键还有一点就是,这样的硬件厂家本来也就不多了。

个人觉得Redhat关于DPDK项目的声明是非常好的例子[4],总结下来如下:Redhat的网络总监是从Broadcom过来的,之前参加了很多项目。 包括:upstream and downstream development of Linux kernel networking, DPDK, OVS OVN, NFV, MPTCP, ebpf XDP.Redhat和DPDK之间的关系只要是使用DPDK进行OVS的packet转发。对于DPDK,在新的硬件出现之后,不用等待kernel的驱动upstream,就可以使用新硬件。Telco 是Redhat主要关注的客户,他们希望使用X86和Redhat的开源软件。目前DPDK的贡献者太少了,只有Redhat,Mellanox和Intel。最后就是DPDK如何和SmartNIC结合,这个是Redhat和一些硬件厂家一起比较关心的。

对于软件人员来讲,需要通过各种不同的编程框架来实现Kernel-bypass,但是PCIE设备的一个SRIOV能力就可以非常简单的实现了对于host kernel的bypass。

SRIOV的问题也是很明显的:[5]Rigid: Composability issuesControl plane is pass through, puts pressure on Hardware resourcesParts of the PCIe config space are direct map from HardwareLimited scalability (16 bit)SR-IOV NIC forces switching features into the HWAll the Switching Features in the Hardware or nothing

因此,就有了Redhat系列的新思路:

SRIOV隔离VM的流量:

SRIOV:智能网卡就靠它了!

OVS的kernel和SRIOV 不使用PF,而是VF上提供多个网络接口给OVS kernel模块。每个VF都有一段kernel 内存空间。OVS DPDK和SRIOV 直接使用VF可以bypass kernel空间直接对接用户态的OVS DPDK模块。我们把host用户态的内存映射到每个网卡的VF。Guest的 SRIOV 如上图最右边,我们把Guest的内存空间映射到网卡的VF。在这种设备绑定中,网卡的ring 的layout在物理网卡和Guest之间共享。因为这部分的信息都是私有的,因此Guest上需要制定网卡厂家的驱动。

上面还有一种设备绑定,就是在Guest的用户态通过DPDK访问在Guest中的VF网卡设备。

SRIOV For Mapping NIC to Guest

对于在Guest空间的SRIOV设备,在实现通过memory的映射的机制进行网路报文的快速收发,有两条路径:使用Guest 的kernel驱动。使用网卡厂家的驱动,通过直接映射IO memeory,网卡的硬件设备可以直接访问guest kernel的内存。基本上支持SRIOV的厂家都有类似的实现,例如AWS的ENA,Intel的ixgbegbe,以及Mellanox的MLX4/5.在Guest上使用DPDK,利用厂家提供的VF的PMD驱动,通过DPDK的内存映射,网卡设备可以访问Guest的用户态内存。

SRIOV:智能网卡就靠它了!

在这个场景中:整个数据通路是厂家定义的,并且直接由VF功能来实现。对SRIOV,需要在Host的kernel (PF 驱动)以及Guest的用户态(VF-PMD)Host kernel的驱动和Guest的用户态的VF-PMD不能直接通信。因此PF/VF驱动需要通过其他的接口进行。厂家的VF-PMD主要用来配置NIC的VF,而host kernel的PF驱动则负责整个网卡的配置。

这个里面,的确可以实现线速的网络性能,但是因为接口都需要网卡厂家来提供,这样对于整个系统的升级相对比较麻烦。

Virtio Full HW Offloading

这个的确是摆脱厂家驱动的一个办法,把virtio的数据和控制通路都卸载到硬件中,物理网卡通过SRIOV提供VF给Guest。这个设备同样支持virtio ring的layout,在guest和NIC之间建立内存映射。

SRIOV:智能网卡就靠它了!

在Virtio Full Offloading中,在Host kernel甚至不需要驱动,物理网卡是一个支持SRIOV的virtio网卡,VF和PF都是基于virtio协议的实现。

在这个图中,SRIOV带来的控制路径和数据路径bypass可能会对管理带来挑战。同样, 我们可以在Guest的OS 中使用virtio的kernel驱动,而不是PMD。

vDPA --标准化数据通路

vDPA -虚拟的数据通路加速,它的主要目的是标准化网卡的SRIOV数据通路,让SRIOV的VF可以支持virtio ring的layout,并且在Guest的空间可以使用标准的virtio驱动,而不是厂家的驱动。通过这个抽象,可以在为未来支持类似于scalable IOV的技术。

和上图不同,在SRIOV的VF的控制路径上可以让厂家继续使用自己的驱动(支持vDPA addon),并通过一个标准的vDPA驱动在厂家驱动/virtio之间进行翻译。

在数据路径,基本上和上图的Virtio Full hardware offloading类似。

vDPA的主要好处:

SRIOV:智能网卡就靠它了!

开放的标准,和virtio一样线速性能,和SRIOV一样,没有中间的memory地址翻译。可以支持未来的Scaleble IOV统一了Guest的网卡驱动。可以在两个vDPA的网卡之间做冗余保护。支持live migration,因为了vDPA一个控制链路的中间层,因此可以在不同的网卡厂家之间进行live migration。在裸金属的场景下,virtio的驱动可以成为一个事实上的标准驱动,和NVMe驱动一样,通过vDPA的框架支持不同厂家的网卡。

对比:

SRIOV:智能网卡就靠它了!

这个里面可能要纠正一点就是,Virtio Full HW offloading对于live migration的支持,这里主要是指在不同的厂家之间进行live migration。

------------------------------------------------------------------------------

Deep Dive

HW Blocks for virtio Full HW offloading

在一般的情况下,厂家的网卡PF创建VF的时候都使用自己专用的ring layout,但是在virtio full HW offloading中使用virtio的 ring layout。

SRIOV:智能网卡就靠它了!

HW Blocks for virtio Full HW offloading

SRIOV:智能网卡就靠它了!

对于Full HW offloading的网卡,都要使用vfio-pci的kernel驱动进行virtio full hw offloading的设备访问,在Host和Guest中都一样。

下面的Full pciture,可以看出来数据通路和控制通路的区别。

SRIOV:智能网卡就靠它了!

来讨论一下网卡如何访问Guest的应用的queue。网卡和Guest 之间的内存映射应该先建立,然后才能DMA。为了建立DMA的mapping,guest的PMD的驱动使用ioctl命令去配置DMA和vfio。这个时候,iommu主要是映射 GIOVA到GPA之后,vIOMMU会把GPA翻译成HVAGuest这边就建立了GIOVA到HVA的映射同样,在host side,VFIO建立了GIOVA到HPA的映射网卡开始使用GIOVA,这样它就可以访问到guest application使用的HPA。一旦我们设置了guest应用的virtqueue,HW就可以直接去访问它们。

对于控制路径:virtio-net-pmd和guest kernel的VFIO通信。Guest的VFIO和vfio-pci交互Guest kernel的vfio-pci驱动和QEMU的vfio设备通过虚拟的PCIE bus交互。QEMU的vfio设备访问host kernel的VFIO (通过ioctl)Host kernel的VFIO和host kernel的vfio-pci交互。Host kernel vfio-pci和真正的物理网卡交互。

这个要求数据和控制路径都全部卸载到硬件。这个需要网卡厂家完全在网卡中实现virtio的全部协议,一般是通过一个标准的接口如PCIE。但是,一般来讲,每个厂家肯定有不同的实现机制。

对于live migration,仅仅实现了virtio的协议是不够的,比如dirty pages的tracking,这个需要网卡和QEMU的API之间进行协作。在Virtio的1.1的标准中,并没有这方面的定义。

这里多说一下,对于一个PCIE设备进行live migration, 一般的需要处理的内容如下:在Guest中通过ioMMUtracking 脏页内存。统一的VF和半虚拟化的驱动。处理Guest和Host之间的IO共享内存。Doorbell以及对应的PCIE寄存器和中断的映射。

因此,如果你可以实现对这些内容的处理和监控,从Guest OS来看,你是不是个Virtio设备并不重要。

vDPA

和前面的Full HW offloading对比,vDPA就是可以使用一个厂家自定义的控制路径,但是在Guest面前又是一个标准的virtio设备。因此就需要一个在网卡私有控制和virtio之间的翻译。

这里就引入了一个新机制,mdev, mediator device可以实现设备的仿真(软件虚拟化)和设备的中介(软件和硬件虚拟化)。它可以在一个物理设备上暴露出多个虚拟设备。mdev最早是用在GPU的虚拟化的场景。Intel增加它对IOMMU的支持。[6]

SRIOV:智能网卡就靠它了!

本质上,vDPA在数据路径还是全部使用HW,但是在控制路径上使用mdev的机制进行设备仿真。

在使用SRIOV中,一个网上的可以配置多个VF,但是每个VF都有自己特定的内存空间(在Guest中),但是VF无法访问host上的mdev的空间,因此目前在使用SRIOV时,控制路径上和mdev相关的操作要经过PF,或者只能是单向的mdev到VF。未来的Scalable IOV会解决这个问题。

至于VFIO的驱动框架,就是用户态对于PCIE设备的支持访问,这个框架可以支持各种设备,比如GPU. 这就意味着Guest上的用户态应用可以支持访问物理设备。

MDEV包含了以下部分:

1.mediated core driver API

2.mediated device API

3. mdev-bus

4. management interface

SRIOV:智能网卡就靠它了!

Virtio-Mdev 框架

virtio-mdev框架的主要目的是提供给不同的vDPA网卡厂家一个标准的API来实现他们自己的控制路径。mdev提供的框架可以支持vDPA实现数据和控制路径的分离。数据路径硬化,控制路径在软件实现。

这个驱动可以是用户态基于VFIO,也可以是内核态基于virtio的。在目前这个系列,主要关注基于vfio的用户态驱动,但是在未来也会讨论基于virtio的内核态驱动,比如支持AF_VIRTIO。

这个驱动的实现也比较简单,本质上就是一些列的virtio-mdev的API。主要包含:

.set/get 设备的配置空间

.set/get virtqueue的元数据:vring地址,大小和基地址

.kick一个特定的virtqueue

.为一个特定的virtqueue..回调中断

.协商功能

.set/get 脏页日志

.启动/重置设备

vhost-mdev 是一个kernel的模块,主要功能是:转发用户空间的virtio 命令到virtio mdev的API重用VFIO的框架来准备DMA映射和解映射的用户空间请求。

vhost-mdev的主要功能:

.把自己..成一个新类型的mdev驱动

.对外提供和vhost-net兼容的ioctl接口,用户空间的VFIO驱动可以传递virtio的命令

. 翻译好的virtio命令以virtio mdev API的形式通过mdev bus传递给virtio-mdev设备。

.当一个新的mdev设备创建时,kernel总是厂商去加载驱动

.在加载过程中,vhost-mdev会把virtio mdev设备连接在VFIO的群组,因此DMA请求就可以通过VFIO的文件描述符。

vhost-mdev是连接用户空间驱动(这里是VFIO)和virtio-mdev设备的关键。它为用户空间驱动提供两个文件描述符:vhost-mdev FD:从用户空间接受vhost的控制命令VFIO container FD:用户空间驱动用来设置DMA

Virtio-mdev 驱动可以把自己..成一个新的mdev设备,暴露一个基于mdev的传输接口给vitio驱动。它作为kernel的virtio驱动和virtio mdev设备的桥梁。因为virtio支持的其他类型传输方式,因此它可以无缝地和virtio-net驱动对接。

virtio-mdev设备本质就是一个mdev设备,它可以使用virtio-mdev驱动,也可以使用vhost-mdev驱动,vDPA主要关注vhost-mdev流程。

如果从mdev-bus的角度看virtio-mdev,它就是一个设备,因为它实现了mdev设备的API。

如果从PCIE BUs的角度看virtio-mdev,它就是一个驱动,因为它主要作用就是发生命令到真正的硬件去。

SRIOV:智能网卡就靠它了!

注意,在本图中,virtio-mdev驱动和virtio-mdev驱动在这里主要表示virtio mdev设备统一的mdev 的API,但是他们并不是vDPA kernel流程的一部分。

vDPA kernel based 实现

我们需要引入一个新的模块vhost-vfio来理解vDPA的kernel实现流程。

SRIOV:智能网卡就靠它了!

vhost-vfio,从QEMU的观点来看,vhost-vfio就是一个新类型的QEMU网路后端用来支持virtio-net的设备。从kernel的观点来看,vhost-vfio就是vhost-mdev设备的用户态驱动。它的主要作用是:设置vhost-mdev设备:打开vhost-mdev的设备文件,用来传递vhost的命令到设备去,得到vhost-mdev设备的container,用来传递DMAsetup的命令到VFIO container。从virtio-net设备接收数据路径卸载的命令( set/get virtqueue 状态,set 脏页日志,功能协商等等),并把他们翻译vhost-mdev的ioctl。接受vIOMMU map和umap的命令并同VFIO DMA的ioctl执行。 下面这个图在原文中是错误的,我基于自己的理解在使用最小的代价作做个修改。Redhat的blog比较坑爹,不能反馈,有认识的大侠可以去反馈一下。

这里有一个关键信息需要强调,对于vDPA的实现,我们这里使用的基于SRIOV的网卡VF,但是这里并没有强制要求SRIOV,网卡厂家可以使用其他的方式在一个物理网卡上运行多个vDPA的实例。在这里SRIOV的VF实现是基于Virtio的,只要提供基于标准的vritio layout,这里并不局限于设备的类型。比如,在Beta-Metal设计中,vDPA的设备可以是多个PF。

比如在Scalable IOV中,网卡并不是分解成VF,而是QP级别的粒度。

SRIOV:智能网卡就靠它了!

从下到上在回顾一下vDPA的框图:在硬件层是vDPA设备,它可以使用私有的控制路径初始化virtqueue,在virtio Full hardware offloading时,这个设备是virtio-net 设备。virtio-mdev设备实现了vDPA设备的具体功能,就是我们如何卸载数据路径。virtio-mdev设备接受virtio-mdev基于API的传输命令,并完成mediated 设备的翻译,仿真或者中介的功能。virtio-mdev 传输API通过mdevbus提供了一个统一的API给用户态(qemu中)或者kernel的驱动。它本质上是一个driver的抽象设备。对于host用户空间, vhost-mdev把自己..成一个新的mdev设备,来bridge 用户空间的vhost驱动和virtio-mdev设备。它通过ioctl接受vhost-net兼容的命令,并把他们翻译成virtio-mdev的传输API。它同时属于VFIO group可以设置DMA。vhost-vfio是一个host 用户态的驱动,它和qemu中的virtio 设备一起对上面的VM提供一个虚拟化的virtio设备(例如virtio-pci). 从vIOMMU发出的DMA mapping 请求被转发到VFIO的contatier 句柄。而virtio设备的启动和配置都是通过vhost-mdev 来完成。在Guest中,VFIO 会暴露设备和DMA API给用户态的驱动,这个例子是virtio-net的PMD。

vDPA DPDK 的实现

DPDK从18.05开始支持vDPA。它是基于vhost-user的协议提供了一个后端实现。DPDK的实现主要目的是实现一个可以DEMO的,为了最终实现一个更见标准的,在kernel里面的,基于mdev框架的实现。

这里有两个新的组件:

vDPA驱动,用户态驱动来控制vDPA设备硬件。

vDPA框架,提供vhost-user socket和vDPA驱动的连接。

DPDK vDPA框架提供一系列的设备回调函数,由网卡厂家实现,这些函数被vhost-user调用来创建数据路径。

SRIOV:智能网卡就靠它了!

在vDPA设备支持热迁移的脏页他tacking的场景下,它的diver可以也会实现migration_done这样的回调函数。否则,vDPA框架可以在热迁移的时候把路径切换到软件上来执行。

Combining vDPA and virtio full HW offloading

在之前讲Virtio全硬件卸载的场景,硬件设备实现了数据和控制路径,因此设备可以使用kernel的virtio-net驱动,或者DPDK的virtio PMD。

在一个场景里,全硬件卸载可以使用vDPA设备,数据路径还是全硬件卸载,而控制路径可以使用vDPA API。

相对于全卸载的virtio PMD模式,这样的好处是:灵活: 它可以切换到其他的使用vDPA的硬件设备,或者回到全软件的路径。热迁移:可以实现对于热迁移的支持,把virtio ring的处理切换到软件路径并利用qemu tracking 内存脏页。标准化

这个POST主要讲了virtio 全硬件卸载和vDPA,这一节的确是最复杂的,包含了大量的用户态和核心态的实现。这个也说了,大家正在尝试使用vDPA的框架来替换掉现有的SRIOV的VM加速技术。在未来的Scale IOV中,vDPA也有足够的灵活性支持,不管是在VM还是在Container的情况下。

总之,在这个之后,在讲Container的网路加速之前,我们有必要搞一个SmartNIC 字典了。

相关文章