从IPU向主机提供的virtio-blk服务看vDPA和LM的实现
科技
科技
2023-07-12 12:00
上海
Intel目前可以分别提供基于FPGA 和基于ASIC的IPU(Infrastructure Processing Units)解决方案,相应的IPU可以对主机host提供NVMe和virtio-blk两类存储特性的PF(Physical Function)/VF(Virtual Function)。此处将结合IPU向主机导出的virtio-blk的PF/VF使用来进一步剖析vDPA和LM的实现。
众所周知,Vhost主要是为Qemu等虚拟化应用场景提供IO加速的一种实现:通过Qemu实现VM(Virtual Machine)中使用的virtio设备的模拟和控制面的管理,但IO路径上VM可以直接和Qemu之外的单独的Vhost Target交互。一般情况下Vhost Target侧(或者叫backend---后端) 主要是通过软件的方式来实现,即实际可能没有真正的virtio-blk的硬件设备存在。对软件实现的Vhost Target而言,各种类型的存储资源如Malloc bdev、AIO bdev、Ceph RBD bdev等等均可以用来作为其的实际后端存储。VM发出的IO由Vhost的软件进行处理然后再与后端实际的存储资源进行交互,例如图1所示基于SPDK实现的Vhost scsi Target (目前用户态的Vhost 框架是由DPDK定义的,SPDK中Vhost scsi和Vhost blk都是基于DPDK定义的用户态框架进一步的扩展实现) 实际就是通过共享了VM中分配的virtqueue内存的方式来实现IO的传递,并且由Vhost中创建的poller来不断轮询virtqueue vring中各个avail entry指向的IO,然后再对具体的后端bdev进行读写。
图1. 基于SPDK实现的Vhost scsi Target实现举例在Vhost定义的实现框架下经过扩展,就产生了vDPA的技术,也即vDPA实际是一种特殊的Vhost实现----就本文讨论的场景就是将一个对主机而言具有真正virtio-blk功能的硬件设备的PF/VF应用于Vhost的软件框架中(vDPA的用户态实现目前主要依托于DPDK中定义的Vhost的软件框架,其相应的驱动存在于DPDK代码中,要支持新的硬件需要添加实现相应的vDPA驱动逻辑,可参考DPDK源码中/dpdk/drivers/vdpa目录下的代码实现),在通过软件完成控制面的握手和virtqueue地址等信息设置后,实现VM在数据面直接和virtio-blk硬件设备通信,不需要vDPA软件来处理VM发出的具体的IO----“例如先将VM中分配的virtqueue的地址信息设置给实际的virtio-blk设备,后续只需要更新vring的avail_idx并通过寄存器通知硬件设备”。这样在vDPA的使用中完成控制面初始化后,便可以在IO操作后写寄存器通知设备读取IO并执行,而IO对应的完成消息则由Qemu产生中断通知VM,或者由VM软件对vring的used_idx项进行不断轮询。最终IO的实际存储由virtio-blk硬件设备来完成,例如对于IPU提供的virtio-blk特性则可能是通过网络传送到了远端的存储。基于DPDK中Vhost框架实现的用户态vDPA驱动的整体结构可以如图2所示。
图2. 基于DPDK中Vhost框架实现的用户态vDPA驱动的整体结构示意当前最新的DPDK master版本中自带的/dpdk/drivers/vdpa/ifc驱动(主要支持Intel的相关硬件产品) 已支持通过vDPA的方式使用Intel提供的基于FPGA的IPU(如BSC --- Big Spring Canyon)和基于ASIC的IPU(如MEV --- Mount Evans)卡。
使用IPU卡提供的virtio-blk PF/VF
Intel基于ASIC的IPU卡(如MEV)对主机可以提供8个virtio-blk类型的PF设备,且各个PF设备可以支持通过SR-IOV和SIOV方式扩展出VF进行使用,MEV对主机Host呈现的virtio-blk设备的信息可以如图3所示。
图3. Intel 基于ASIC的IPU卡对host呈现的virtio-blk的PF (每个PF支持扩展出VF) 这些virtio-blk的PF/VF即可以直接被主机上的virtio_blk驱动初始化成对应的block设备使用,也可以通过Passthrough的方式透传给VM让其中的virtio_blk驱动来初始化。对于虚拟化的使用场景,这些virtio-blk的PF/VF还可以通过Vhost和vDPA的方式来被使用。
将MEV提供的virtio-blk的PF/VF以Vhost的方式提供给VM使用的情况可如图4所示。基于SPDK的vhost示例程序可以参考如下命令创建基于virtio-blk PF/VF的bdev,然后再在此基础上创建相应的vhost ctrlr设备。
#create bdev based on the virtio PF/VF provided by MEV
./spdk/scripts/rpc.py bdev_virtio_attach_controller -t pci -a 0b:01.0 -d blk virtio0
#create vhost ctrlr based the bdev created previously
./spdk/scripts/rpc.py vhost_create_blk_controller --cpumask 0x1 --transport vhost_user_blk vhost0 virtio0
#command parameter for starting VM through Qemu and
connecting to the vhost ctrlr#"/var/tmp” is parameter defined by -S when starting the
vhost app-chardev socket,id=spdk_vhost_blk0,path=/var/tmp/vhost0-device
vhost-user-blk-pci,chardev=
spdk_vhost_blk0,num-queues=1,queue-size=512,page-per-vq=on图4. MEV对host呈现的PF/VF用于Vhost的后端以支撑VM的使用
将MEV提供的virtio-blk的PF/VF指定给vDPA的驱动提供给VM使用的情况可如图5所示。通过基于DPDK的vDPA示例程序使用MEV提供的virtio-blk PF/VF的相关命令可参考如下。/dpdk/build/examples/dpdk-vdpa --log-level=8 -l 2,4
--proc-type primary --no-shconf --socket-mem 2048 -a 0000:0b:01.0,vdpa=1
--file-prefix test -- --iface /tmp/vdpa_test#command parameter for starting VM through Qemu and
connecting to the vdpa ctrlr-chardev socket,id=spdk_vhost_blk0,path=/tmp/vdpa_test -device
vhost-user-blk-pci,chardev=spdk_vhost_blk0,num-queues=1,queue-size=512,page-per-vq=on图5. MEV对host呈现的PF/VF 以vDPA的方式支撑VM的使用
如图4中所示情况,虽然可以通过Vhost的方式使用从MEV提供的virtio-blk 的PF/VF初始化的bdev作为后端资源来支持VM的使用,但明显效率是不如以vDPA的方式进行使用高的。实际过程中一般也不会以这种Vhost的方式来使用真实的virtio-blk的硬件,此处仅仅只是为了更好地说明Vhost和VDPA的实现差异。从上述的使用方式对比中可以很清晰地看到,若对主机而言实际使用的设备是可以支持virtio-blk的硬件,则可以直接通过vDPA的方式来使用,这样会比Vhost更高效。
LM本身是虚拟化场景定义的一种用于在VM之间迁移Inflight IO以实现VM中的应用能够持续运行的功能。以基于Qemu的VM为例,只要具体的后端设备(如Vhost/vDPA) 按需实现了对应的命令(消息)的处理,就可以支持VM的数据热迁移。具体而言涉及的功能主要是“dirty page log” 和 “device status save/restore” ,其中前者是为了将的源VM中Inflight IO使用的内存页一起拷贝到目的VM中,后者主要是用于存储和恢复标识Inflight IO所涉及的virtqueue vring 的Index如last_used_idx。 对于virtio-blk的场景,启动LM时源VM中的应用IO会暂停,这样vring中的avail_idx就不会增长,此时保存last_used_idx, 并且这两个index之间的entry对应的request就会被定位为Inflight IO一起拷贝。拷贝完这些信息后才会销毁源VM。之后Qemu会根据拷贝的信息在目的VM中恢复应用的运行状态及Inflight IO的内容,并在目的VM对应的virtio-blk设备初始化时,通过消息向Vhost或vDPA设置新的vring地址等信息,其中会设置上次保存的last_used_idx作为新的last_avail_idx。Vhost或vDPA对应的controller就从这个index开始重新执行源VM中迁移前的Inflight IO, 从而目的VM中原先在源VM中运行的应用可以继续运行。这样LM的过程对于VM中的应用而言就感觉只是短暂卡顿了一下,对实际所发生的变化不会有强的感知。但 LM只会负责迁移Inflight IO,对于已经完成的IO则不在迁移的范围之列,需要由应用自行处理,比如源VM和目的VM对应的Vhost/vDPA的后端存储资源使用相同的bdev以实现共享等。 前已提及, Vhost场景下,VM和Vhost软件之间是使用共享内存的方式来实现virtqueue的共同访问,涉及LM的相应处理在Vhost软件实现即可。对于vDPA的场景,相应的命令(消息)被vDPA驱动接收后一般是会通过对virtio-blk硬件设备寄存器读写的操作来完成相应的处理。 此外,现在有些硬件(包括MEV),还在BAR空间中设置了专门的寄存器用于处理LM相关的工作,但这种情况主要是为了实现VF passthrough场景时的迁移情况,与此处Vhost/vDPA涉及的迁移不同,在此不进行展开。
MEV卡的virtio-blk PF/VF执行LM操作
对使用MEV卡提供的virtio-blk PF/VF的VM之间执行LM,和使用软件实现的Vhost或者其他virtio硬件设备时的情况是一致的,并无特别的操作。具体LM涉及的细节已经被vDPA驱动和MEV卡之间的交互所隐藏。其中涉及的主要步骤可以概述如下。A. 使用MEV提供给host的两个virtio-blk的PF或者VF,以vDPA的驱动初始化。 可以简单在MEV上配置这两个PF或者VF对应的后端共享的bdev,以模拟源VM和目的VM共享存储的情况。源VM对应的vDPA设备初始化的命令可参考如下。对于目的VM对应的vDPA,只需修改命令中--iface 定义的设备名字和实际使用PF/VF对应PCIe地址。./dpdk/build/examples/dpdk-vdpa --log-level=8 -l 2,4
--proc-type primary --no-shconf --socket-mem 2048 -a
0000:0b:01.0,vdpa=1,sw-live-migration=0--file-prefix sourceblk0 -- --iface
/tmp/vdpa_sourceblk0B. 通过Qemu基于基于这两个初始化的vDPA设备分别创建并启动源VM和目的VM。
源VM的Qemu启动命令参数示例。
-chardev
socket,id=spdk_vhost_blk_sourceblk, path=/tmp/vdpa_sourceblk0-device
vhost-user-blk-pci, chardev=spdk_vhost_blk_sourceblk,num-queues=1,queue-size=512,page-per-vq=on
-monitor telnet::3331,server,nowait -nographic -serial telnet::5551,server,nowait -net
user,hostfwd=tcp:: 10020-:22 -net nic -vnc :55-chardev
socket,id=spdk_vhost_blk_targetblk, path=/tmp/vdpa_targetblk0-device
vhost-user-blk-pci, chardev=spdk_vhost_blk_targetblk,num-queues=1,queue-size=512,page-per-vq=on
-monitor telnet::3332,server,nowait--incoming tcp::4000 -nographic -serial
telnet::5552,server, nowait-net user,hostfwd=tcp::10021-:22 -net nic -vnc :56C. 通过telnet登录源VM,输入命令触发迁移。例如以上述的举例的命令,就是在VM所在的host上执行telnet 127.0.0.1 3331 然后在界面中输入migrate
-d tcp:127.0.0.1:4000。
2. https://spdk.io/doc/vhost.html3. https://ci.spdk.io/download/2022-virtual-forum-prc/D2_6_Jun_Accelerating_The_Storage_Application_with_Intel_MEV_IPU.pdf4. https://www.redhat.com/en/blog/how-deep-does-vdpa-rabbit-hole-go