网络虚拟化协议GENEVE

去年看到过一篇文章[1],说是通过OpenVSwitch的测试,GENEVE的性能要略优于VXLAN。我相信大多数人的反应可能跟我的第一反应一样,这不又是一种Overlay协议吗?为什么性能会更好?难道有什么黑科技?我们这次来分析一下GENEVE有什么不一样。

网络虚拟化

要说清楚来龙去脉,需要从网络虚拟化开始说起。网络虚拟化(Networking Virtualization)是在一个underlay网络上划分出多个overlay网路。原本只支持一套网络的设备,通过网络虚拟化,现在可以用来支持多套网络。网络虚拟化本身不是一个新的技术,从其诞生之日起,各种各样的协议就被提出,远的有VLAN(IEEE 802.1Q)、MPLS(RFC3031),近的有VXLAN(RF7348)、NVGRE(RFC7637),STT。那究竟是网络虚拟化的什么特性,导致了这么多相关的协议被提出?

如果我们把网络中的所有节点看成一个分布式系统,那么underlay网络为这个分布式系统的各个节点提供了网络连接。而各种各样的网络虚拟化协议,则为这个分布式系统的各个节点提供了通信所使用的协议。比如说,在一个云环境里面,所有的服务器共同组成了一个部署虚机的分布式系统。underlay网络连接这个分布式系统的各个节点(各个服务器),而网络虚拟化协议用来封装各个节点之间传递的数据(虚机之间的网络数据)。

网络虚拟化协议GENEVE

虚机间的网络数据基本都是以太帧,但是不同的应用场景,系统规模,对于协议的要求也不一样。所以才会有这么多网络虚拟化协议。目前的各种网络虚拟化的协议,本质上来说都是一样的。那就是,以一定的格式封装原始网络数据,再辅以一定的元数据(metadata),来实现附加的功能。元数据对于网络虚拟化来说不是一个陌生的概念,网络标识符(Virtual Network Identifier,VNI)就是一种元数据。通过VNI可以识别并隔离多个租户(tenant)网络。

现在比较流行的网路虚拟化协议是VXLAN,有24bit的VNI,可以对应1600万个不同的tenant网络。VXLAN的提出常常说是为了解决VLAN(12bit VNI)所提供的租户网络数不够的问题。现在来看1600万这个数字是足够大了,但是能保证以后一直够用吗?因为在VLAN被提出的时候,4000多个租户网络已经很够用了。只是随着云计算和数据中心规模的发展,渐渐变的不够用。那么激进点看,随着技术的发展,24bit的VNI会不会也有不够用的一天?

退一步说,就算24bit的VNI是够用的,现在一些新的应用需要网络虚拟化协议里面携带其他的元数据。例如加入port ID来作为安全规则的识别符。假设port ID是16bit,那24bit的VNI只剩下8bit用来标识租户网络,这明显是不够用的。

所以,尽管现有的网络虚拟化协议能满足当前的需求,但是随着技术的发展和使用场景的变化,并不能保证它们能够一直满足需求。解决办法有两种,一种是到时候再定义新的协议,另一种是定义一种灵活,可扩展的网络虚拟化协议。GENEVE采用的是后者。

GENEVE

GENEVE这个单词对应的是瑞士城市日内瓦,但是这个网络协议本身与日内瓦应该没什么关系。这个单词是Generic Network Virtualization Encapsulation的简称,对应中文是通用网络虚拟化封装,由IETF草案定义[2]。

GENEVE的作者称,他们考虑了所有可能的应用场景,发现一个固定长度的元数据(例如前面提到的VNI)不能适应所有可能的场景。同时,他们也参考了买二手游戏平台地图其他一些常青的协议,例如BGP,LLDP,IS-IS。这些协议已经存在几十年了,并且现在还很流行。背后的原因在于,这些协议并不是一成不变,而是随着技术的发展,支持了新功能的扩展。例如BGP,最基本的路由选择算法一直没有改变,但是却从只支持IPv4到支持IPv6,VPNv4,VPNv6等其他地址族。

所以,他们提出了一种网络虚拟化协议,这个协议的元数据本身是可扩展的。这样,就算需求变化了,这个协议也能扩展以满足需求。这个协议就是GENEVE。

在实现上,GENEVE与VXLAN类似,仍然是Ethernet over UDP,也就是用UDP封装Ethernet。VXLAN header是固定长度的(8个字节,其中包含24bit VNI),与VXLAN不同的是,GENEVE header中增加了TLV(Type-Length-Value),由8个字节的固定长度和0~252个字节变长的TLV组成。GENEVE header中的TLV代表了可扩展的元数据。我们来看一下GENEVE header:

网络虚拟化协议GENEVE

  • Version(2bit):没什么好说的,目前是0
  • Opt Len(6bit):以4字节为单位,表明Variable Length Options的长度。因为只有6bit,所以Variable Length Options最多是252(63*4)字节。
  • O(1bit):表明这是一个OAM包,包含了控制信息,而非数据。Endpoint可以根据这个bit来优先处理这个包。
  • C(1bit):表明在Variable Length Options里面,存在一个或者多个Critical的option。当C被置位时,Variable Length Options必须被解析,如果当前Endpoint不支持GENEVE解析,那么应该丢弃数据包。如果C没有被置位,那么Endpoint可以根据Opt Len直接丢弃所有的Variable Length Options。
  • Rsvd.(6bit):保留字段。
  • Protocol Type(16bit):被封装的协议类型,例如Ethernet就是0x6558。这个字段的存在,使得GENEVE封装其他的二层协议成为可能。
  • VNI(24bit):老朋友了。
  • Reserved(8bit):保留字段。
  • Variable Length Options:由TLV构成,包含了可扩展的元数据。

性能考虑

从协议格式可以看出,GENEVE与其他网络虚拟化协议的主要区别在于一个长度可变的header。这使得GENEVE变得灵活,可扩展。但是可扩展和高性能从来都是矛盾的。因为可扩展意味着更多的元数据来支持更多的功能,而高性能却要求更少的数据传输和处理。对此GENEVE定义了O和C位(参见上面协议格式分析),使得Endpoint能够更灵活的处理数据,以减少额外的元数据对性能带来的影响。

控制层考虑

尽管某些网络虚拟化协议里面包含了对控制层的描述,例如VXLAN(RFC7348)就包含了一个基于组播的learn-flood控制层,但是在实际使用中,这些协议通常只被当做数据格式的描述。试问多少人知道RFC7348里面有基于组播的flood-learn?

另外,在VXLAN的使用过程中,控制层可能有很多种,例如EVPN,例如SDN controller。这两种控制层比基于组播的控制层要流行的多。而所有这些控制层之间的差别是巨大的。

所以,GENEVE的作者认为,GENEVE应该只关注协议数据格式。他们力求设计一种适用于多种控制层的协议,而非只针对某一种控制层。这样就算控制层变化了,协议本身也不至于被弃用。

underlay负载均衡考虑

几乎所有的underlay网络(例如CLOS架构)都会利用多条等价路径(ECMP)来提高传输的并发性。我们把两个虚机之间的一个传输层连接称为一个数据流。为了达到最好的负载均衡的性能,不同的数据流应当被分布到不同的线路上。而相同的数据流应当被分到同一个线路上,这样才能保证数据的顺序,减少不必要的确认重传。

对于GENEVE来说,因为Ethernet Frame被封装在UDP里面,ECMP设备看到的不是虚机的IP/MAC,而是Tunnel Endpoint的IP/MAC。每个Tunnel Endpoint可能连接多个不同的虚机,而对于两个相同Tunnel Endpoint之间的网络流量,在underlay网络上唯一能看到的不一样的地方就是外层UDP的source port。因此,GENEVE规定,使用外层UDP的source port用来标识实际的数据流。首先,对于同一个数据流来说,外层UDP的source port应该是一样的,其次这个UDP source port,应该根据实际的数据流计算得出,例如根据数据流的五元组。这样,ECMP设备不需要读取内层报文的信息,只需要根据外层UDP的source port,就能完成ECMP的路径选择算法。而这个时候的UDP source port,也不再标识一个UDP连接,而是用来标识overlay的数据流。为了减少重复,GENEVE协议认为应该使用source port的整个16bit(而不是常用的50000-65535)。

兼容性考虑

如果你熟悉VXLAN或者NVGRE的协议格式,你可能已经发现了,如果不考虑Variable Length Options,GENEVE与VXLAN还有NVGRE是不冲突的。特别是VXLAN,也是将Ethernet Frame封装在UDP里面,这样,一些现有的针对VXLAN的优化,例如硬件offload,RSS,可以直接应用在GENEVE上。

OVN

OpenVSwitch的衍生项目OVN(Open Virtual Network)应该是GENEVE的最大拥趸。本文最开始提到的文章[1],也是出自OVN的开发人员。根据OVN的文档[3],OVN只支持GENEVE和STT作为网络虚拟化协议。这是因为OVN除了24bit的VNI之外,还要在overlay数据中传输15bit的源网络端口,和16bit的目的网络端口,以支持更高效的ACL和组播。GENEVE因为是可扩展的,自然是支持传递额外的元数据。STT因为本身的元数据是64bit的,也放得下OVN想要传递的内容。至于其他的协议,例如VXLAN,NVGRE,是没有可能满足OVN的需求。

我们再回过头来看看[1],为什么测试结果显示GENEVE性能要略优于VXLAN。由于VXLAN的普及,目前支持GENEVE的硬件不多,所以测试都是在支持VXLAN RSS的网卡上进行。并且在测试中,GENEVE还额外传递了OVN所需的15bit的源网络端口,和16bit的目的网络端口,也就是说,GENEVE传递的数据更多。

尽管有这些因素的存在,GENEVE的结果要好于VXLAN。首先,这个结果表明了,GENEVE能很好的兼容VXLAN,因为就算是VXLAN的主场,GENEVE最后还是赢了。但是兼容性并不能解释最后的现象,文章本身也没有分析原因,只是提到了UDP checksum。OVN默认打开了GENEVE上的UDP checksum。因为Linux系统内核的一些优化,使得GENEVE数据包被网卡收到之后,网卡会计算并验证外层UDP的checksum。如果验证通过了,网卡会汇报给系统内核。这样系统内核在解析GENEVE时,将不再计算内层报文的任何checksum。相应的网络数据处理会更快一些。而VXLAN协议规定外层UDP的checksum应该为0,这样外层UDP的checksum就没有办法被验证,而内层报文的checksum需要再计算一遍,相应的网络数据处理就要慢一点。

上一篇:JumpServer2.13.2安装部署及踩坑记


下一篇:虚拟网络之虚拟网卡