用户态虚拟化IO通道实现概览及实践(上)

自虚拟化技术诞生起,提升虚拟化场景中IO设备性能和驱动的兼容性、可扩展性一直是备受关注和追求的目标。随着半虚拟化技术的出现,virtio设备及驱动也很快流行并逐步变成了虚拟化应用中的主要IO通道形态。例如,virtio现已支持实现的设备涵盖了网络设备(virtio-net)、块设备(virtio-blk)、串口设备在(virtio-console)等等。其后,通过DPDK/SPDK技术加持,virtio技术全用户态化的实现也如火如荼地落地并广泛应用。

不仅如此,沿着虚拟IO全用户态化的思路,vfio-user技术也应运而生,且被SPDK集成用于为虚拟机提供了高性能模拟的NVMe设备。

 接下来,本文将主要结合virtio和vfio-user的角度来对主要的虚拟化IO通道的用户态实现方式进行简单的介绍。

virtio的

用户态实现分析

对于virtio的用户态实现技术,此处将主要从virtio标准、virtio front-end和back-end的用户态实现情况分别进行说明。

virtio标准 

virtio机制让客户机(Guest)系统知道自己是运行在虚拟化环境中,通过与hypervisor配合协作,借助CPU提供的虚拟化技术(如Intel VT-d或AMD-v)达到更好的性能。同时,virtio机制也给众多的虚拟化平台和系统提供了统一的IO设备及驱动模型,提升了多平台&多系统扩展性、兼容性,降低了跨系统移植复用时的复杂度。

virtio的机制从2008年在论文中提出后,已经过了v0.95、v1.0 和v1.1 这3个标准。其主要构成可以大致分为前端(front-end)驱动、传输队列(virtqueue)和后端(back-end) 设备这几个部分。Front-end驱动运行在虚拟机(Guest)系统或者bare-metal应用进程中,back-end设备存在于主机(Host)系统的hypervisor进程(如Qemu)或者单独的进程(或模块)中,而virtqueue则主要通过内存共享映射在front-end驱动和back-end设备之间传递数据。virtqueue的主要实现结构是vring,在virtio的的各个标准版本中有split和packed两种实现方式。

                                                           图1. Virtio机制主要结构

(transport即指virtqueue,通过virng实现)

virtio的back-end主要实现

为了尽可能的提升性能,virtio back-end设备的实现方式一直在不断变化。以KVM-Qemu应用场景为例,back-end设备的实现就从最初完全在Qemu进程中逐步变为“控制面通过Qemu、IO面基于独立进程或模块(如vhost)”以及“控制面基于Qemu、IO面基于硬件(vDPA)”的形式。

完全基于Qemu的实现

在back-end设备完全基于Qemu的实现方式中,virtqueue back-end侧的处理在Qemu进程中完成,涉及的数据由Qemu进程解析后再和实际进行数据处理的设备驱动交互。虽然这种方式使用过程中Qemu进程可以不依赖于其他的进程或模块,但这的确也是性能最差的virtio back-end设备实现方式。

                                                  图2. 完全基于Qemu的virtio实现举例

(IO路径如见虚线)

Vhost实现

vhost实现就是将virtqueue的IO面(数据处理逻辑)从Qemu进程中拿出来由Host下的其他模块或者进程来实现,控制面(如virtqueue的参数协商等)仍需经过Qemu进程完成。得益于CPU的虚拟化技术,可以实现Host系统和Guest系统下内存地址的直接映射和快速转换,从而提升了IO访问的性能。

vhost的IO处理逻辑最初是在内核态实现,Qemu通过ioctl的机制和内核态vhost模块进行交互。随着后续的发展,逐步有了基于用户态进程的实现 --- Qemu直接在用户态通过unix socket与vhost进程进行交互 。

对基于用户态实现的vhost,其既可以通过Qemu等hypervisor向Guest系统呈现pci形态的virtio设备来与运行在Guest下的virtio front-end驱动交互;也能够单独以user通道(基于unix socket)的方式来向其他进程(例如,与Qemu无关的Container等 bare-metal模式应用)提供virtio back-end设备功能。对于第二种情况,其对应的virtio front-end 驱动也是基于virtio-user类型的实现。

                                                     图3. vhost back-end实现示例

vDPA实现

vDPA(virtual Data Path Acceleration)就是在vhost的思路上更进一步,将back-end侧对virtqueue的数据处理逻辑完全由硬件来实现。这样可以进一步降低Host侧CPU的消耗,从而提升性能。不仅如此,这种实现方式还带来了其他的价值。vDPA的实现和SR-IOV应用时的pci pass-through的方式有点类似(不过SR-IOV方式下控制面和数据面都卸载到硬件来执行)。但相较于pci pass-through模式在Guest系统下应用时不同设备需要各自不同驱动来支持以及无法实现VM在线迁移(live migration)的限制,vDPA使得在Guest系统下使用统一的front-end驱动来支持不同的设备以及实现在线迁移特性成为可能。

virtio用户态virtio front-end驱动\back-end设备实现

鉴于DPDK/SPDK用户态驱动在性能优化方面的独到特性,virtio front-end驱动和back-end设备的用户态版本,主要基于DPDK/SPDK框架来进行开发。接下来本文将从front-end驱动和back-end设备的角度来分别介绍virtio的用户态实现及其主要的代码结构和运行机制。

virtio front-end 驱动的用户态实现

virtio front-end 驱动主要工作于Guest系统中,对基于KVM-Qemu的VM系统,其主要的处理对象是Qemu虚拟出来的virtio类型的pci controller;对于bare-metal模式的其他系统,其可以通过用户态unix socket来与后端设备交互。目前主流的virtio front-end用户态驱动主要有:virtio-net、virtio-blk/virtio-scsi、virtio-user-net、virtio-user-blk/virtio-user-scsi这几种。

virtio-net的用户态驱动

virtio-net用户态驱动的实现代码在 “DPDK/drivers/net/virtio” 目录下,其主要处理对象是 “Virtio network device” 的pci controller。结合代码可以大致将相关流程梳理如下:

1. DPDK程序启动时,注册支持的设备id-table 和驱动函数;

1)设备id-table通过“pci_id_virtio_map”数据结构定义了支持的pci vendor和pci device的ID并使用RTE_PMD_REGISTER_PCI_TABLE(net_virtio, pci_id_virtio_map)进行注册;

2)驱动由“rte_virtio_net_pci_pmd”数据结构定义,并在 “rte_pci_register(&rte_virtio_net_pci_pmd) ”中进行注册。

2. 在DPDK初始化流程中完成设备探测匹配并加载驱动;

在DPDK初始化流程中主要藉由DPDK eal提供的用户态bus、device、driver的匹配模型进行设备探测、匹配和驱动加载。函数rte_eal_init会根据DPDK程序启动参数中指定的允许访问的设备信息进行设备探测和匹配(默认情况下DPDK/SPDK均不会主动加载通过vfio、uio驱动管理的设备,只会在参数显示指定后进行处理) 。当匹配到前述已注册的virtio-net的设备后,就会回调加载对应注册的驱动并调用eth_virtio_pci_probe进行设备初始化。

3. 初始化virtio network device pci controller;

初始化的入口函数是eth_virtio_pci_probe,除基本的pci相关的初始化外,其中主要可以分为两个层面的资源处理,其一是virtio设备本身层面的,如在vtpci_init函数中根据设备类型填充vtpci_ops类型的函数集,用于执行virtio设备的基本配置操作;其二,是rte_eth_dev设备层面的,在函数eth_virtio_dev_init

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值