ovn vlan东西向流量问题

前言

ovn场景下vlan模式的流量问题,相关资料甚少,当前社区针对vlan网络的问题没有很明确的解决方案。本系列文章旨在阐述ovn vlan网络的关键点和问题,以供参考。

相关技术

首先介绍一下vlan网络模式下,几个相关技术点,了解了这些才能更容易理解问题的产生。
vlan-dvr

dvr

dvr即分布式路由(distributed virtual routing)的缩写,区别于传统集中式的路由模式,它是在每个计算节点上都会驻留一个虚拟router,并实现路由功能。也就是说访问不同网段的虚机流量,在源节点就完成了路由,直接转发给目的虚机。

localnet port

之前文章也提到了localnet port。这种port是连接br-xx和br-int的patch端口,ovn-controller会在br-int与br-xx建立patch,该patch就用于与物理网络通信。

external port

externl port可以用于代理外部网络资源(无法接入br-int)的dhcp或者三层流量,比如裸金属网卡,sriov虚机网卡的流量。该类型的port只会驻留在网关节点上,也就是标记了external-idsovn-cms-options=enable-chassis-as-gw的节点。简单描述就是,裸金属的dhcp报文或者三层,只会被external port所在的网关节点处理。
external port

arp proxy

二层arp-proxy:ovn针对非unkonw的port(配置了address),会进行arp代理。简单理解就是,针对同一网段下的虚机/裸金属发送arp请求后,是由ovn-controller来代答的。

table=16(ls_in_arp_rsp), priority=50, 
match=(arp.tpa == 192.168.111.125 && arp.op == 1),
action=(eth.dst = eth.src; eth.src = fa:16:3e:20:ad:03; arp.op = 2;
/* ARP reply */ arp.tha = arp.sha; arp.sha = fa:16:3e:20:ad:03;
arp.tpa = arp.spa; arp.spa = 192.168.111.125;
outport = inport; flags.loopback = 1; output;)

三层arp-proxy:对于跨网段的访问,dvr模式下也实现了,将报文的目的mac地址修改为目的ip对应的mac。

table=14(lr_in_arp_resolve), priority=100  , 
match=(outport == "lrp-07f9dcf3-4d7e-4047-8065-f2633c539d9f" &&
reg0 == 192.168.111.125),
action=(eth.dst = fa:16:3e:20:ad:03; next;)

mac_binding

路由阶段,对于三层的ip<–>mac解析,比如说跨网段访问未知ip地址,ovn-controller会通过发送arp请求学习ip对应的mac地址,然后写入sb的mac_binding表中。

()[root@ovn-tool-0 /]# ovn-sbctl list mac_binding
_uuid : 7eca2810-cc4a-4a85-a41d-d9a40ca5ab55
datapath : 319f72b6-8128-482f-b8ca-10425c54d5f7
ip : "172.16.10.153"
logical_port : lrp-860f48c9-d948-4d86-8a49-c9b00b1fe242
mac : "fa:16:3e:ab:ab:85"

注意这个表项是没有老化机制的,所以在ip/mac关系有变化的同时进行新的arp学习,或者删除对应表项,要不然就会导致查询到老的ip/mac关系。

大致流程如下:

1.发送给目地ip未知的报文,则通过get_arp查询mac_binding表获取到对应的mac,然后将目的mac地址修改:

table=14(lr_in_arp_resolve ), priority=0, match=(ip4), 
action=(get_arp(outport, reg0); next;)

如果没有查到,则将目的mac置为全0

2.如果目的mac为全0,即上送ovn-controller,将arp请求从lrp发送出去:

table=18(lr_in_arp_request ), priority=100, 
match=(eth.dst == 00:00:00:00:00:00 && ip4),
action=(arp { eth.dst = ff:ff:ff:ff:ff:ff; arp.spa = reg1; arp.tpa = reg0; arp.op = 1; output; };)

3.从lrp收到arp回复报文,ovn-controller会先通过lookup_arp查看在mac_binding表项有没有记录:

table=1 (lr_in_lookup_neighbor), priority=100, 
match=(arp.op == 2),
action=(reg9[2] = lookup_arp(inport, arp.spa, arp.sha); reg9[3] = 1; next;)

4.如果没有记录,则通过put_arp将学习到的ip-mac映射关系写入mac_binding表中:

table=2 (lr_in_learn_neighbor), priority=90, match=(arp), 
action=(put_arp(inport, arp.spa, arp.sha); next;)

二层流量问题分析

这种情况早前我们遇到比较频繁:发现同vlan网段的虚机icmp报文,在所有的计算节点都能抓到该报文,即单播报文被广播。
对于vlan模式的二层广播问题,结合前面基本概念里就提到的,ovn-controller会对已知port进行arp代答。这样导致的后果就是:

  • 虚机/裸机的mac地址,在被访问的期间未被物理交换机fdb所学习到。
  • 源虚机/裸机通过ovn-controller拿到目的mac后,直接封装目的地址,将报文发送出去了。

基于以上两种情况,就可能会出现,交换机在处理报文时会认为mac地址是未知的,进而将报文进行广播。直到下一次交换机学习到mac。

我们的解决方案:ovn侧提供了一个可选参数 arp-proxy用于使能网络的arp代答功能,默认关闭了vlan网络的arp代答,除localnet port,localport外的其它所有port,产生流量期间都需要主动发送arp报文,从而使得交换机能适时地学习到mac。

东西向路由问题分析

vlan的东西向路由,有如下需要注意的地方

mtu

大家都知道geneve的包头更长,跨vlan网段访问geneve网络的时候,vlan网络的mtu值其实是不准确的了,所以这种情况下,需要将物理层面的mtu调整得更大。

裸金属跨网段

上面提到了,裸金属的流量由对应的external port代理,包括它的三层流量,除external port所在节点的其它网关节点默认丢弃该报文。
又如果路由采用了集中式而不是dvr,即所有三层的流量都要集中转发到一个节点上处理。
那么就会出现一个矛盾的地方,如果external port所在节点和路由器网关节点不是同一个的话,裸金属访问三层的流量将会被丢掉。

这是neutron的一个较早的问题,通过reside-on-redirect-chassis强制所有vlan要上路由的流量转发到路由节点,那么router就不是分布式的了。(最新的neutron做了部分调整)

ovn为什么引入该参数?是为了规避vlan mtu的问题,有兴趣可以去了解。
解决方案:修改了ml2/ovn插件代码不走集中式路由,并利用ovn侧的这两个功能:OVN: Enable E-W Traffic, Vlan backed DVR, OVN: Vlan backed DVR N-S, redirect packet via localnet port,解决了裸金属的跨网段流量不通的问题。

ovn-chassis-mac-mappings的使用

正常使用vlan网络接入dvr,会有如下问题:

  • 跨网段访问vlan网段报文,src mac是vlan网段网关mac,如果多个节点都有报文跨网段转发的话,物理交换机就会从不同节点学习到相同mac,这样就会出现流量冲突。

对于以上问题,ovn提出了ovn-chassis-mac-mappings这个配置项,使用该配置项为每一个chassis(节点)配置一组不同的mac地址,ovn-controller会将src mac是子网网关mac的vlan报文,替换src mac为ovn-chassis-mac-mappings配置的对应mac。这样的话,就能保证跨网段的报文从不同节点发出的源mac是不同的,避免了交换机上mac冲突。
配置命令:

ovs-vsctl set Open_vSwitch . external-ids:ovn-chassis-mac-mappings=physnet1:aa:bb:cc:dd:ee:ff,physnet2:bb:aa:cc:dd:ee:ff

广播问题

类似二层vlan的广播问题,在三层路由时也会存在。当访问垮网段访问vlan网络时,由于ovn-controller进行了目的mac代理,所以如果物理交换机fdb没有目的mac的记录,则会判断报文目的mac为未知mac,然后将报文进行广播。

可能有人会提出,采用类似上面提到的关闭arp代理的方案是不是就可以解决问题了,实际是不行的。如果关闭arp代理,按照ovn逻辑路由的流程,它还会走mac_binding的流程。即前面提到的,ovn在三层路由里实现了对未知ip的mac学习功能,也就是说即便arp代理关闭了,它还可以通过arp学习完成。

目前dvr下的广播问题,社区讨论dvr for vlan is not completely supported有一个很粗略的方案,简单描述就是,定期的往物理交换机上送虚机rarp报文,让交换机定期学习到mac。

这个patch:controller: send GARPs for LSPs in vlan-backed network scenario提供参数使ovn-controller替虚机网卡发送rarp,不过看上去不能替裸机/sriov虚机发送。

总结

总的来看,ovn的vlan网络存在诸多问题,其中像mtu和dvr子网网关mac冲突这些都还可以workaround的方式规避掉,但是广播问题却是没有好的方案去解决。所以我们目前是禁止vlan租户网络(不包括外部网络)接入dvr,如果你有更好的方案恳请沟通交流(^_^)。

下一篇文章将会分析ovn vlan网络下的南北向流量问题。

个人分析,欢迎指正,若转载请注明出处!