GCP 网络系统Andromeda --- 数据面

2020-07-01 00:00:00 数据 队列 内存 网卡 主机

这个系列总共有三篇,分别在:

肖宏辉:GCP 网络系统Andromeda --- 概述篇

肖宏辉:GCP 网络系统Andromeda --- 控制面

肖宏辉:GCP 网络系统Andromeda --- 数据面

下图展示了Andromeda的主机数据面,前面介绍过,主机数据面主要由两部分组成:Fast Path和Coprocessor Path。

主机数据面实际上就是一个运行在用户空间的进程,它同时具有虚拟网卡和虚拟交换机的功能,负责完成所有当前主机上虚拟机的包处理。在主机上与数据面相关的程序还有:

  • 每个虚机都对应了一个用户空间的Virtual Machine Manager(VMM)。VMM通过RPC向数据面发送相应的操作,例如mapping虚机内存,配置虚拟网卡中断和卸载,关联虚拟网卡队列。
  • 前面介绍过,vswitchd有VMC编程下发的所有转发信息,当一个packet不能在Fast Path中找到相应的转发信息,它会被送到主机上的vswitchd进程。之后vswitchd会更新Fast Path中的转发信息,同时将packet重新注入到Fast Path中。

Fast Path

Fast Path只有一个工作,就是高性能的转发packets。为此,对它有以下设计实践:

  • 为Fast Path分配一个专属的CPU,不停的对网卡进行轮询。同一个物理CPU上的另一个逻辑CPU则被用来处理一些低CPU消耗的控制面工作,例如RPC处理。这样可以将一个物理CPU的绝大部分资源出让给Fast Path使用。
  • 使用一些硬件卸载功能也被用来减少Fast Path对CPU的要求。当前,encryption,checksums都卸载到了网卡,同时利用Intel QuickData DMA引擎卸载了内存拷贝操作。
  • 软件设计上简单高效:避免软件锁和费时的同步操作,优化内存使用,使用大页内存,避免线程切换,批量操作,避免系统调用。例如Fast Path只使用系统调用来唤醒Coprocessor线程和虚拟终端;Fast Path使用了无锁的SPSC( Single Producer / Single Consumer)packet rings来与控制程序和Coprocessor线程通信。

Fast Path包含了独立的ingress engine和egress engine来处理两个方向的packets。每一个engine都是由一条pipeline组成,pipeline上的每个element只完成一个任务。同时element对一批packets同时做操作(ingress一批多128个,egress一批多32个)。批量操作比单个packet操作有2.4倍的性能提升。虚机和主机的网卡队列是pipeline的两个端点。为了避免线程切换和系统调用,Fast Path通过共享内存直接访问虚机和物理网卡的队列,绕过了VMM和主机操作系统。

因为Fast Path是当前主机上的所有虚拟机共用,为了避免不同的虚拟机之间相互影响,需要在Fast Path中做资源隔离。对于Egress比较好办,Fast Path只需要以Round-robin的方式轮询VM的发送队列即可。这样,就算一个VM要发送大量的包,也不会影响其他VM Egress。对于Ingress,因为进来的时候没法知道packet对应的虚拟机,会稍微复杂一些。Andromeda将Ingress分成了两个部分,部分轮询网卡,查找Fast Path的flow table,然后将packets放到per-VM的队列中。第二部分再分别从队列中取出packet,将packet拷贝到虚拟机中。图7中的后半部分,就是基于per-VM的队列进行处理。在第二部分中,有一个VM Priority Scheduler,它会选择近消耗了较少CPU的队列。这样当某个虚拟机的Ingress流量巨大时,不会对一些小流量的虚拟机造成影响。不过,当部分overload之后,例如Ingress流量超过了网卡的能力,还是会造成虚拟机之间网络流量的影响,这是Fast Path可以改进的一个点。

另一方面,Fast Path映射了所有虚机的内存,这在提供高性能的同时,带来了一些挑战:

  • 虚拟机的内存对应的是主机的tmpfs,并且是demand-allocated。如果Fast Path访问了虚机的一个还未分配的内存页,会导致内存页分配,而这个内存通常会记在触发分配的进程,也就是数据面进程上。因此Andromeda修改了主机Linux 内核,使得虚拟机的内存分配总是记在虚拟机上,而不是触发内存分配的进程上。
  • 数据面访问虚拟机的内存可能导致虚拟机的crash,VMM也可能裁剪虚机的内存对应的backing file。为了应对这些问题,数据面通过一个定制的memcpy函数完成对虚拟机内存的操作,当copy出错时,数据面程序会断开与相应的VM队列的连接。

Fast Path Flow Table

不论是Ingress Engine,还是Egress Engine,在pipeline中都有一个element是Flow Table。这个Flow Table对应了Open vSwitch的快速路径,只是Andromeda自己实现了这一部分。对于这一部分,提升性能意味着减少每个packet对应的操作。

Flow Table使用一个hash table,将一个网络流转换成一个整数(flow index)。其他的一些操作,例如action table,policy table,都是基于flow index寻址的一些数组。

为了避免高代价的同步操作,Flow Table并没有使用锁,为了更新Flow Table,控制程序会生成一个新的Flow Table,然后通过SPSC将engine指向这个新的Flow Table。每个engine维护自己的Flow Table统计,vswitchd会周期性的读这些统计,并进行汇总。

所以,当一个packet要经过Flow Table时,Flow Table首先会计算packet对应的flow index,之后根据flow index完成对应的actions和其他的一些操作,后更新统计数据。如果packet能直接发送给虚拟机,那么packet通过内存拷贝送到虚机内部。

如果packet对应的操作是送到Coprocessor Path,packet会被送到对应的Coprocessor线程。

Coprocessor Path

Coprocessor Path用来完成对CPU消耗较高,且对时延没有严格要求的功能。Coprocessor Path对于小化Fast Path的功能起了关键作用,同时将网络功能与Fast Path的性能做了解耦。在Coprocessor开发功能更加简单,因为Coprocessor不用遵循Fast Path的严格的要求。例如,Coprocessor stages可以使用锁;分配内存;执行系统调用等。Coprocessor Path在一个per-VM的Coprocessor线程上执行,CPU消耗算到了对应的VM上去,这样可以提供VM之间网络处理的公平和隔离,这对于CPU消耗较大的packet处理工作来说非常关键。一个Coprocessor线程,如果用来执行ACL 和shaping,通过netperf TCP stream可以测出,11.9Gb/s的吞吐;如果用来执行WAN加密,只能达到4.6Gb/s的吞吐。

Fast Path Flow Table的查找行为决定了是否将packet发送到Coprocessor Path。如果需要发送到Coprocessor Path,Fast Path会通过 SPSC packet ring将packet送给对应的Coprocessor 线程。Coprocessor线程对packet进行相应的加工,然后再通过一个packet ring将packet返回给Fast Path,后完成转发。

Andromeda数据面演进

  • Pre-Andromeda:所有转发在VMM中完成,只支持虚拟网卡的单队列,且没有任何的offload。
  • Andromeda 1.0: VMM做了优化,配合修改了的kernel OVS datapath,并且打开了虚拟网卡的多队列和egress offload。
  • Andromeda 1.5: 增加了ingress 虚拟网卡的offload,并且通过取消VMM中的部分查找,进一步优化了VMM的packet pipeline,这部分查找通过kernel OVS的flow table查找完成。主机内核调度和管理也做了优化,减少了时延。
  • Andromeda 2.0:将VMM和kernel OVS datapath合并成一个新的OS-bypass的busy-polling 用户空间数据平面。VMM继续处理VM的虚拟网卡的ring 和中断,但是所有的包处理在新的数据平面完成。VMM与该数据平面通过SPSC共享内存 ring交换packet。数据平面直接从VM的内存拷进拷出数据。
  • Andromeda 2.1:绕过VMM,数据平面直接读写VM虚拟网卡的ring。性能要求高的packet直接由Fast Path处理。通过将VMM从packet处理中移除,减少了每个network round trip中的4次线程唤起,显著的提升了时延和CPU效率。
  • Andromeda 2.2:使用了Intel QuickData DMA引擎来卸载大包的拷贝,提升了吞吐量。DMA出于安全的考虑使用IOMMU,并且直接从用户态dataplane访问,避免了绕OS。但是对于小包来说,异步拷贝的同时要保持包的顺序,相比Andromeda 2.1 稍微增加了时延。

下图是两个VM之间总计200个TCP stream的throughput测试结果,吞吐量总计有19倍的提升。

下图是相同场景下时延的测试,总计有7倍的提升。

下图是CPU效率的测试,单位是cycles per byte。测试包括了发送方和接收方的CPU使用情况,同时包括了虚机和主机的数据平面的CPU消耗。主机数据平面的CPU消耗包括了所有主机的网络报文处理,其中可能包括了VMM的处理,kernel的处理,新的OS-bypass数据面的处理(不同时期,处理进程不同)。总的来说,Andromeda减少了cycles per byte16倍。

相关文章