将晦涩难懂的技术讲的通俗易懂
分类: 虚拟化
2018-07-29 18:49:31
SRVM:
Hypervisor Support for Live Migration with Passthrough SR-IOV Network Devices
SRVM是Vmware设计的一个用于SR-IOV场景对vm进行热迁移的模块,通过修改hypervisor来实现。
SR-IOV(Single-Root I/O Virtualization)方式是一种直接将设备透传给vm的方式,由于设备直接passthrough,所以可以达到较高的网络性能,同时可以支持RDMA等特性。但是缺点就无法很好的支持vm热迁移。下面是SR-IOV方式和传统半虚拟化方式的对比:
当前支持SR-IOV热迁移主要有两种方案。一种方案是迁移硬件状态,这种方案尽可能多的尝试迁移(save-restore)硬件状态,对于那些无法save的硬件状态,则使用一层模拟层来模拟,由于这种方案需要修改guest驱动,所以很难被采用。另一种方案是通过bond方式将一个半虚拟化设备和一个SR-IOV设备做bond,一般转发场景使用SR-IOV设备,热迁移时候切换为半虚拟化设备。这种bond驱动需要特殊的guest OS支持,例如微软的Hyper-V仅对windows的guest支持。这种方式有两个问题,一个是vm规格比较大时,迁移时间会比较长,另一个是如果guest中的应用采用dpdk,由于dpdk的pmd驱动仅能接管某一种类型的设备(SR-IOV的直通设备或半虚拟化设备),所以无法支持这种bond设备。Ps:论文是2016年的,当前最新的dpdk已经尝试对这种bond场景的支持。
VM热迁移通常由以下几步构成:
(1) Mark memory pages: 在热迁移的开始阶段,将vm的所有内存都标记为脏页,等待迁移;
(2) Pre-copy:Pre-copy阶段会迭代的扫描vm内存,将那些已经标记为脏页的内存页进行拷贝迁移,这里会存在一个页迁移后又被修改进而标记为脏页的情况,所以hypervisor需要跟踪这些修改,当然这可以借助硬件完成,如Intel EPT。Pre-copy阶段会持续直到只有很少数量的脏页为止,所以对应大规格vm,这个阶段时间会比较长;
(3) Checkpoint:Pre-copy结束后hypervisor会暂停vm,保存vm的设备状态和cpu状态;
(4) Switch-over:将Pre-copy剩余的一部分脏页以及Checkpoint部分保存的状态传输到目的host;
(5) Resume VM:将Checkpoint的状态在目的host恢复(restore),vm重新运行。
和半虚拟化场景不同,SR-IOV场景hypervisor是无法完全控制VF的行为的。Hypervisor关联的仅仅是控制面,如PCI的配置,中断的传递路径(中断映射),内存的映射(MMIO),而转发面是由guest驱动管理的,如设置Tx/Rx rings,分配数据buffer。在数据传输过程中,VF会直接访问guest内存而不需要借助hypervisor。
这会导致两个问题,一个是在pre-copy阶段hypervisor无法跟踪那些通过DMA修改的内存页,因为DMA过程的地址转换是通过硬件IOMMU完成的而不是hypervisor,这就会导致迁移过程中丢失新修改的内存。另一个就是checkpoint阶段设备状态的保存和Resume VM阶段设备状态的恢复。虚拟设备的状态可以很容易的被存储和恢复,因为都是软件状态,但是对于直通的VF设备来说由于其状态并不是完全由hypervisor管理,或者其中一些状态对hypervisor是只读的,所以很难像虚拟设备一样对设备状态进行存储和恢复。
SRVM要解决三个问题:
1. 在热迁移过程中收到的数据包可能会丢失,这是因为SR-IOV方式是通过DMA将数据包送入guest,DMA是直接通过借助硬件IOMMU,将数据从VF设备拷贝到guest内存,这个过程对hypervisor是透明的,hypervisor无法感知那些guest内存被修改,所以热迁移时也就无法及时同步这些修改;
2. 在迁移过程中,目的host会创建一个新的VF设备,但是guest内部的VF驱动保存的还是之前源host VF的状态信息,所以hypervisor必须需要让guest能够访问新的VF设备并在guest VF驱动和新的VF之间同步状态;
3. SR-IOV设备可能用于用户态驱动,如dpdk,所以这种迁移方式不能仅限于传统内核驱动。
SRVM的整体结构如下图所示:
主要由两个模块构成:dirty memory tracking module和SR-IOV VF checkpoint module,前者利用hypervisor的PF驱动获取VF状态,已经获取接收数据包的地址。将这些地址发送给热迁移模块进行迁移,确保热迁移过程的所有接收数据的内存都被迁移,在Pre-copy阶段结束后停止工作。后者保存VF控制面的一些状态信息(如MMIO信息和MSI-X中断向量表),然后再目的host创建一个新的VF并将之前保存的控制面状态设置到新的VF中。这个模块确保guest驱动访问VF设备时能够访问到新的VF设备。下面是这两个模块的详细实现介绍。
Dirty Memory Tracking
前面说过SR-IOV场景中hypervisor很难跟踪脏页,因为数据面之间DMA不经过hypervisor。但是VF的硬件状态是存放在PF设备中的,所以我们可以通过PF驱动获取VF的状态信息。
由于只有接受方向能够产生脏页,所以我们先看一下SR-IOV设备的数据收包流程,如下图所示:
Guest驱动在初始化时会分配一个ring,这个ring包含若干entry,每个entry记录着接收数据将要存放的地址。VF设备收到数据后,根据ring中entry中地址进行DMA数据传输。所以为了跟踪脏页,我们需要获取到ring的地址,从而解析ring中的entry。
Ring的相关信息,如起始地址和长度被存放在VF设备的寄存器中,Dirty Memory Tracking 模块可以通过PF驱动获取到这些信息,这些信息通畅仅在pre-copy阶段前获取一次即可,因为除非VF设备被重新配置,否则这些信息是不会变的。如果VF设备确实发生了重新设置,就需要重新获取这些信息了。
获取到ring的地址后,则需要获取最近更新的entry信息,其中包含了接收数据包的目的地址,由于我们只需要知道数据的地址即可,不需要真的访问数据。所以我们只需要访问guest的很少一部分内存(约2k左右)。数据包接收一般有两种模型:中断模式和polling模式。
通常内核驱动即采用的中断模式,中断信息通过hypervisor传递给guest,所以我们可以利用这些中断消息来唤醒Dirty Memory Tracking模块来获取ring中的信息,没有中断的时候模块就处于sleep状态。但是在polling模式中由于不再使用中断,所以Dirty Memory Tracking模块也会采用polling模式来获取ring的信息。
由于guest驱动和Dirty Memory Tracking模块都会对ring进行访问,所以就需要避免冲突。其中一个方式是加锁,但由于guest驱动不感知Tracking模块的存在,所以如果加锁就需要修改guest驱动。事实上由于Tracking模块对ring的操作是只读,且操作非常快,所以完全没必要使用锁。
对应ring的信息获取又根据ring descriptor的两种格式:advanced 格式和legacy格式,有不同的处理方式,这里不再展开。
SR-IOV VF checkpoint
热迁移后,原理的VF设备就不再了,取而代之的是目的host上的新VF设备。但是guest并不知道这个变化,仍然会使用guest驱动中保存的之前的配置去访问VF设备,如果hypervisor不做特殊处理的话就会发生错误。SR-IOV VF checkpoint必须解决以下问题:
(1) VF控制面的配置必须按照源host上的配置,以便guest使用原有的驱动配置仍可以访问;
(2) 在guest驱动和VF设备间同步数据面的配置;
控制面配置处理
SR-IOV设备需要通过hypervisor配置后才能被guest使用。设备的控制面配置主要包括:PCI(e)配置(如:MMIO配置),以及中断传递路径。
PCI配置存放在一系列标准的寄存器中,这些都是按照PCI规范来的,无论什么设备都相同,如MMIO配置。
对应host,MMIO是由BIOS或OS来配置的,MMIO的映射地址被存放在PCI BAR(base address
registers)中。在当前VMware ESXi的实现中,针对SR-IOV场景使用了一个虚拟的MMIO,通过利用这个虚拟的MMIO来存储控制面的配置。如下图
Guest只能看到虚拟MMIO,hypervisor关联虚拟MMIO和VF的物理MMIO之间的映射关系。当迁移后,为了避免guest驱动使用原有的配置之间访问新的虚拟MMIO,hypervisor需要在迁移前从VF PCI BAR中获取并存储VF控制面配置,并在迁移后恢复到新的虚拟MMIO。虚拟MMIO提供了很大的灵活性,如新的VF设备的VF ID可以和老的VF设备不同,
中断传递路径同样需要配置,这是通过存储和恢复中断向量表来完成的,中断路径配置完成后,guest驱动就能够访问新的VF设备了。
原文链接: