作者:张华 发表于:2021-08-25
版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明
(http://blog.csdn.net/quqi99 )

目前ovn based dvr环境下的vlan tenant network是有问题的。见https://docs.openstack.org/neutron/latest/admin/ovn/sriov.html 中的:

Routing on VLAN tenant network will not work with SR-IOV. This is because the external ports are not being co-located with the logical router’s gateway ports, for more information take a look at bug #1875852.

何为neutron vlan tenant network

neutron中按概念标准划分有external newtork与tenant/private network,按实现类型标准划分有provider network与tunnel network

  • provider network, 使用了provider-physical-network属性的就是provider network, 是由管理员创建的。
juju config neutron-api vlan-ranges="physnet1:1000:2000"
vni_ranges = 1001:2000(or the range that you configure)
flat_networks = bridge,extern
bridge_mappings = bridge:br-vlan,extern:br-ext
tenant_network_types = vxlan,vlan,flat,local
type_drivers = vxlan,vlan,flat,local

local:openstack network create NAME --provider:network_type local
flat:openstack network create NAME --provider:network_type flat --provider:physical_network PHYS_NET_NAME
vlan:openstack network create NAME --provider:network_type vlan --provider:physical_network PHYS_NET_NAME --provider:segmentation_id VID
gre:openstack network create NAME --provider:network_type gre --provider:segmentation_id TUNNEL_ID
vxlan:openstack network create NAME --provider:network_type vxlan --provider:segmentation_id TUNNEL_ID
  • tunnel network, 没使用provider属性的就是tunnel network, 是由用户自己创建的。
openstack network create --provider-network-type gre --provider:segmentation_id 1012 gre_net
  • external network, 无论是provider network还是tenant network加了–external的就是external network
openstack network create --external --provider-network-type vlan --provider-physical-network bridge vlan_net

可以创建vlan的private network吗?

openstack network create --provider-network-type vlan --provider:segmentation_id 1012 vlan_tenant_net

这里有一个非常好的博客(http://dani.foroselectronica.es/ovn-external-ports-604/)解释了这些分类。例:
在这里插入图片描述
可以这样理解:

  • external network, 无论是provider network还是tunnel network都有–external属性
    1, provider network(flat/vlan, 有–external属性)
    2, tunnel network(gre/vxlan/geneve, 有–external属性)
  • private/tenant network, 无论是provider network还是tunnel network都没有–external属性
    1, provider network(flat, vlan, 有provider:physical_network属性)
    2, tunnel network(gre, vxlan, geneve,没有provider:physical_network属性)

如上图的租户tenant有两个vlan类型的provider network:

  • network1(vlan=190): 192.168.0.0/24
  • network2(vlan=170): 192.168.1.0/24
    还有一个flat类型的provider network作为external network
  • external: 172.24.14.0/24 used for Floating IP traffic

ovn external port原理

继续上面测试环境的图,环境的三个分布式网关和测试虚机信息如下:

One Logical router that connects both private networks and the Floating IP network
router1-net1: "40:44:00:00:00:03" "192.168.0.1/24"
router1-net2: "40:44:33:00:00:05" "192.168.1.1/24"
router1-public: "40:44:00:00:00:04" "172.24.14.1/24"
4 Virtual Machines (simulated with network namespaces), 2 on each network
vm1: addresses: ["40:44:00:00:00:01 192.168.0.11"]
vm2: addresses: ["40:44:00:00:00:02 192.168.0.12"]
vm3: addresses: ["40:44:33:00:00:03 192.168.1.13"]
pext: addresses: ["40:44:44:00:00:10 192.168.1.111"]

1, 先看有FIP的情况 (南北向L3)
注意:在ovn实现上图的拓扑中,192.168.0.1(cr-lrp)与192.168.1.1(cr-lrp)(在gw1上)和external port (pext)可以分布在不同的机器上的, 这些网关之间流量走Geneve overlay tunnel.

注意:此处cr-lrp与pext port不在同一个机器上会造成无法响应vm1对192.168.0.1的arp请求,因为这里有pext所以默认情况下对于有external port的VM(vm1)的arp请求只有gw2没有drop (而现在192.168.0.1在gw1只有gw1能回答arp), 所以如果此时支持dvr (worker1上配置external_ids:ovn-chassis-mac-mappings让cr-lrp调度在worker1上,这样worker1自己负责自己上的vm的arp)。所以这种问题只有vlan作为private network才有问题(这时它才有cr-lrp, 如果直接这个vlan network不需要NAT的话就没这个问题了). 毕竟,南北向流量相较东西向流量最大的区别在于南北向流量有一个gateway chassis (cr-lrp)来提供NAT

More context history,chasis和gateway chassis之间(worker1和gw1)之后默认采用overlay encapsulation来redirect流量,这个实验(https://bugs.launchpad.net/neutron/+bug/1875852/comments/2)在说使用redirect=overlay + external_ids:ovn-chassis-mac-mappings works, 但是redirect=bridge + external_ids:ovn-chassis-mac-mappings不work, 可能是这个patch 有问题 - https://github.com/openstack/networking-ovn/commit/d22cc2a0dc8de7b792dc4be471277167fc2a94d3
为了让chassis(worker1)和gatewa chassis(gw1)之间的流量直接走vlan而不是tunnel, ovn为vlan gateway port添加reside-on-redirect-chassis参数让它中心化(https://github.com/openvswitch/ovs/commit/85706c34d53d4810f54bec1de662392a3c06a996),这样又整出了上面的pext(gw2)与cr-lrp(gw1)不在同一个chassis带来的arp问题(最好在worker1上面那就是ovn dvr)

关于这个reside-on-redirect-chassis,更多的研究如下:

例如: sw0<sw0-lr0> -> <lr0-sw0, 00:00:00:00:af:12 192.168.1.1>lr0, 当存在dvr port (lr0-public)时,
当sw0上设置了reside-on-redirect-chassis时(is_chassis_resident("cr-lr0-public")=true, cr-lr0-public是ovn-northd在SBDB中为lr0-public创建的chassisredirect port binding), 这个时候会有下列流将到gw port时流直接走gw port而不会走dvr port (https://github.com/openvswitch/ovs/commit/85706c34d53d4810f54bec1de662392a3c06a996)

table=16(ls_in_l2_lkup), priority=50,
match=(eth.dst == 00:00:00:00:af:12 && is_chassis_resident("cr-lr0-public")),
action=(outport = "sw0-lr0"; output;)

上面的流会让package不会引入dvr source pipline in the source chassis, 它会将包发从sw0的localnet中发出,
然后gw chassis接收这个package, 然后运行logical router pipeline来appy NAT rules, 然后从从br-ex的localnet发出.

ovn vlan南北向流量问题见: https://liushy.com/2022/06/26/ovn-vlan-issue2/

若没设置reside-on-redirect-chassis时,到gw chassis的流量会从tunnel port走,而不是localnet port哦.这样东西流量就没有使用vlan.

所以,下图显然是non-dvr环境,如果是dvr,那cr-lrp应该在worker1而不是gw1上j
在这里插入图片描述
上面,vm1(192.168.0.11)有FIP:

  • vm1在worker1上
  • gateway port 192.168.0.1在gw1上
  • 处理dhcp和medata的external port (pext) 在gw2上
  • 运行ping命令的机器在host1上, 它配置了一个namespace连向ovs bridge, 有一个vlan 170 (network2)的vlan device

当在host1上ping vm1’s FIP时流程如下:

  • host1属于vlan 170(192.168.1.0.24), 它ping虚机的FIP, FIP这个external port在gw2上,dst mac是network 2 router port)
  • external port导流到中心化网关上(gw1), 这是通过Geneve overlay tunnel走的。
  • 中心化网关(gw1上)发送流量到vm1的FIP上(经flat network 172.24.14.0/24, src IP is 172.24.14.1)
  • 这样request就到了worker1, local ovn-controller un-NATs the packet to the vm1

此时,vm1如何返回reply呢?

  • vm1 (192.168.0.11)发送reply到tap inerface, 然后发到它的中心化网关(gw1上,这中间还得NATed to the FIP 172.14.14.100)。
  • gw1路由流量到network2
  • 然后就是从network2 router所在chassis(gw1)因为在同一个子网network2就直接通过dvr 到host1 chassis了(使用该机制:ovs-vsctl get open . external_ids:ovn-chassis-mac-mappings,每个chassis上有一个不同的IP).

2, 没有FIP时的南北流量 (东西向L3)
在这里插入图片描述
此时虚机vm1没有FIP:

  • 由于运行ping的host1机器的网卡的mac与pext同,所以从host1发出的ping实际上就是从pext发出的。
  • 既然是从pext发出的ping,当然先从gw2开始(eth1.170)
  • 这里没有FIP, 到vm1所有的vlan 170实际上属于东西向流量,通过dvr机器就过去worker1了,不需要经过gw1
  • reply回程也是,直接worker1就回host1了

3, 东西向L2流量
在这里插入图片描述
就是纯粹的dvr机制了。每个chassis上有唯一的mac, 从一个chassis到另一个chassis之后,该chassis上的ovn-controller也知道每个虚机的mac/ip,当然就知道怎么转发了。

OpenStack在处理external port时的南北向流量问题

先回顾这篇中的内容: https://blog.csdn.net/quqi99/article/details/125004749
如上,使用了ovn based sriov port就涉及到external port, 又有FIP就涉及到了中心化的网关port。然后以上为例,这就存在:

  • vm1在worker1上
  • gateway port 192.168.0.1在gw1上
  • 处理dhcp和medata的external port (pext) 在gw2上
  • 运行ping命令的机器在host1上, 它配置了一个namespace连向ovs bridge, 有一个vlan 170 (network2)的vlan device

上面的流程都没问题,为什么openstack有问题呢?因为openstack还不支持external_ids:ovn-chassis-mac-mappings模式的dvr机制。这样当虚机(在worker1上)需要它的网关192.168.0.1的mac地址时,worker1上的ovn-controller根本就不知道。

  • worker1自己由于如上原因不支持external_ids:ovn-chassis-mac-mappings缺乏dvr特性支持所以自己不会回答192.168.0.1的mac
  • 那应只能是192.168.0.1所在的gw1回答这个mac (对于vlan router port使用了reside-on-redirect-chassis见:https://github.com/openstack/networking-ovn/commit/d22cc2a0dc8de7b792dc4be471277167fc2a94d3)
  • 但是对于这种有external port的VM发出的arp所以的chassis默认都是drop的,只有host external port的gw2除外,这样理想情况下应该是gw2来回答

这样就有两种解决方案:

  • 让gw1与gw2合并,cr-lrp port与pext port合在一块就没这问题了
  • 支持dvr模式(external_ids:ovn-chassis-mac-mappings),让cr-lrp port在worker1上,这样worker1自己负责自己的arp
    见:https://bugs.launchpad.net/neutron/+bug/1875852
      https://bugzilla.redhat.com/show_bug.cgi?id=1766930

回顾neutron ovs based dvr

openstack ovs based dvr ( https://blog.csdn.net/quqi99/article/details/20711303 ) 由于每个计算节点上都有gateway, 所以每个gateway都要有唯一的mac,这样在进出gateway时需要将router port mac转成这个gateway unique mac.
在这里插入图片描述
在这里插入图片描述

回顾neutron ovn based dvr

dvr改成ovn based之后, 原理一样,也得每个gateway-chassis上都配置不同的mac ( ovn-chassis-mac-mappings = physnet:aa:bb:cc:dd:ee:ff ), 在vlan流量从chaasis到physical network时ovn-controller都要编程flow用chassis mac代替router port mac

For example: chassis_mac = “aa:bb:cc:dd:ee:ff”, router_port_mac = “00:00:01:01:02:04”
cookie=0x0, duration=30.226s, table=65, n_packets=0, n_bytes=0, idle_age=30, priority=150,reg15=0x5,metadata=0x2,
dl_src=00:00:01:01:02:04 actions=mod_dl_src:aa:bb:cc:dd:ee:ff,output:30,mod_vlan_vid:118

在这里插入图片描述

  • ovn-controller直接产生arp reply到router port, 这样TOR就能学习VM的mac了。gateway-chassis能够独立解决router
  • port的ARP之后就可以进行南北流量了(一个chaasis变成gateway-chaasis之后会发GARP来广播router port的mac)
  • NAT, 转发package到gateway-chassis时用router port mac做为dest mac,

20240118 - ovn dvr再次总结

在这里插入图片描述
VM -> OVN DR(compute) -> OVN GR(GW, lrp) -> br-ex
OVN默认就是支持DVR的,但它这个OVN DVR与ovs DVR不同,它只是针对东西向流量的。南北向流量即使有VM FIP也是默认走东西向流量的。
东西向流量主要是针对private tenant network的:

  • tunnel (geneve) tenant network的东西向流量,肯定是有geneve tunnel, 天生支持dvr, 在计算节点上会自动走dvr port来运行dvr pipline, 若是到其他节点(无论是计算节点还是网关节点)都是默认走geneve tunnel的。
  • vlan tenant network的东西向流量(ovn-chassis-mac-mappings),默认还走geneve tunnel当然不会有问题。但都设置vlan了那想东西向流量走vlan咋地? 那得设置reside-on-redirect-chassis=true强制将流导到gw port而不会走dvr port(也就绕开了dvr pipline) . 但是由于这个tenant network就会有nat就需要lrp (若是vlan external network就没有nat不需要lrp呢), lrp port(GW1)和external port(GW2)可能就会在不同的GW节点上从而造成arp问题(因为external port即使代理sriov VM或VM with external NIC的L3流量自然是得drop掉除GW2以外的所有流量的,这样GW1无法为external port响应arp reply). 解决这个问题的办法就是为所有节点(计算节点和网关节点)都添加ovn-chassis-mac-mappings让每个计算节点负责自己节点上虚机的ARP解析(而不是依赖GW1). 当然,若没有用vlan的需求也就不一定需要用ovn-chassis-mac-mappings

南北向流量呢?当然南北向流量也是针对private tenant network的:

  • tunnel (geneve) tenant network的南北向流量(redirect-type=overlay),默认经geneve tunnel到GW chassis后出
  • vlan tenant network的南北向流量设置(redirect-type=overlay)从GW节点出,采用默认的redirect-type=overlay时经 geneve tunnel到GW chassis后出也不会没问题。
  • vlan tenant network的南北向流量设置(redirect-type=bridge)从GW节点出,当是当想用vlan中转流量呢?那就得设置redirect-type=bridge从GW节点出也不会有问题
  • vlan tenant network的南北向流量在有VM FIP设置(redirect-type=bridge)从计算节点出,用redirect-type=bridge就是走vlan那也得首先用ovn-chassis-mac-mappings将lrp创建在自己节点上负责自己VM的arp来避免上面的arp问题,如果想走vlan想也想从compute进出得:ovn-chassis-mac-mappings+reside-on-redirect-chassis=false 南北向流量FIP流量若想从compute进出(compute节点需做nat修改:src mac=FIP MAC, dst mac=external GW MAC, snat=FIP),得: ovn-chassis-mac-mappings + reside-on-redirect-chassis=false(redirect-type=overlay), 若是reside-type=bridge就会有一个bug, 它的下一步(dst mac)转的是lrp MAC而不是external GW MAC
例:FIP mac:fa:16:3e:e3:a1:f5, lrp(172.90.0.102)mac:fa:16:3e:d6:42:62, external GW(172.90.0.1)mac:f8:bc:12:4e:44:dd
用tcpdump可以看到下列错的到lrp MAC:
fa:16:3e:e3:a1:f5 > fa:16:3e:d6:42:62, ethertype 802.1Q (0x8100), length 102: vlan 2901, p 0, ethertype IPv4, 172.90.0.100 > 110.242.68.3: ICMP echo request, id 29185, seq 160, length 64
  • 参考: Understanding OVN DVR and its options - https://www.dnzydn.com/2023/12/20/understanding-ovn-dvr-and-its-options/ 和 ovn vlan南北向流量问题 - https://liushy.com/2022/06/26/ovn-vlan-issue2/

所以只想用默认的geneve tunnel而不考虑vlan来中转东西向的dvr流量的话:

  • 东西向流量,用默认的配置(redirect-type=overlay, reside-on-redirect-chassis=false,ovn-chassis-mac-mappings=empty) dvr会将一个计算节点的流量导到另一个计算节点。
  • 南北向流量,用默认的配置(redirect-type=overlay, reside-on-redirect-chassis=false,ovn-chassis-mac-mappings=empty) ,dvr会将一个计算节点的流量导到GW节点,然后在GW节点上做nat后出。
  • 南北向流量,用默认的配置(redirect-type=overlay, reside-on-redirect-chassis=false,ovn-chassis-mac-mappings=empty) ,想VM FIP的流量从计算节点进出怎么办? 那是需要在计算节点上也配置使用br-ex的

东西向流量默认走geneve tunnel, 若是vlan tenant network还走tunnel就不合需求了,此时可以设置reside-on-redirect-chassis=true(ovn-nbctl set logical_router_port foo options:reside-on-redirect-chassis=true, 将流导到gw port而不会走dvr port)让东西向流量走vlan (intead of tunnel), 这样从一个vlan tenant network的VM1的流量就被导到了GW1 (若没有vlan tenant network, 或者即使有它,没有让东西向流量走vlan的需求,东西向流量会默认走geneve tunnel).

此时默认情况下compute上又没有external_ids:ovn-chassis-mac-mappings所以lrp在GW上 (只是vlan tenant network才会在GW1上有lrp, 若是vlan external network不会有因为它不需要lrp来做nat), 此时若有一个sriov VM1或有external NIC的VM1就会有external port来代理这个VM1的 dhcp和L3流量 , 假设external port在GW2上,那它既然代理了L3流量那除了GW2上以外的所有节点都会drop掉这个external port的流量,包括GW1, 那此时GW1将不会为external port回答VM1的ARP,那VM1与VM with external port就无法通信了。

东西向vlan dvr, ovn-chassis-mac-mappings, 只是解决vlan dvr东西向流量的workaround, 有没有它都叫ovn默认已经支持dvr, 有了它不再使用is_chassis_resident参数来判断外部网关是否在本主机上来限制东西向路由,vlan的东西向流量在计算节点间就处理掉了
南北向vlan dvr, ovn-chassis-mac-mappings + redirect-type (overlay|bridged), 默认是overlay, 若指定bridged时并配合chassis mac, 在流量出计算节点的时候修改GW mac为chassis mac(注:src mac被替换为chassis mac后,physical switch就可能学不到GW mac了也就会出问题了,所以compute节点需要chassis-mac, 但lrp GW节点的chassis-mac配置没有实际用处需要去掉),并打上外部网络的vlan,通过localnet port将流量牵引到网关节点处理。目前社区还是采用overlay作默认转发(redirect=overlay + external_ids:ovn-chassis-mac-mappings, redirect=bridge + external_ids:ovn-chassis-mac-mappings不work).

其他笔记:
port类型有:
dvr, DVR是计算节点上不同子网的流量不经GW节点直接在源节点上完成路由后发给目的虚机
localnet port, ovn-controller会在br-int和br-data之间建立patch, patch用于与物理网络通信
external port, 对于如sriov或exteral NIC无法接入br-int,就弄出来了external port(ovn-cms-options=enable-chassis-as-gw)来代理dhcp或L3流量. sriov VM的dhcp与三层流量应该由external port代理,这样除external port所在节点的其他网关节点默认都应该丢弃该报文。如果路由采用了集中式而不是dvr, 所有的L3流量都要集中转发到一个节点上处理,此时如果external port与route port不在同一个节点的话,这些流量就会被drop掉。通过reside-on-redirect-chassis在即使是dvr时也能强制所有vlan要上路由的流量转发到集中式路由节点

ARP处理流程:
1, 发送给unknown IP的报文,则通过get_arp查询SB mac_binding表获取mac, 若没有查到就上送ovn-controller将arp请求从lrp port发送出去查询, 之后ovn-controller再将arp结果通过pu_arp更新到SB mac_binding表中
2, ovn-controller对虚机/裸机的 known mac代答,会导致mac不会被physical switch的fdb学习到, 这时候physical switch拿到报文时就会广播,直到下一次physical switch学习到mac. 这样会导致第一次同vlan网段的虚机icmp报文(单播)在所有计算节点上都能被抓到(即单播报文被广播). ovn提供了一个可选参数arp-proxy来默认关闭vlan网络的arp代答,除localnet port, localport外的其它所有port, 产生流量期间都需要主动发送arp报文,从而使得交换机能适时地学习到mac。
3, 上面即使用arp-proxy在L2层关闭了arp代答,ovn在L3也能对未知IP的MAC进行学习,学习后ovn-controller代答之后physical switch又没有学习到又得发广播学习。一个方案是ovn-controller定期替虚机网卡发rarp报文让交换机定期学习到mac

ovn vlan东西向流量问题 - https://liushy.com/2022/06/25/ovn-vlan-issue1/
Understanding OVN DVR and its options - https://www.dnzydn.com/2023/12/20/understanding-ovn-dvr-and-its-options/

20250620 - 再次总结

三个重要参数的意思:

  • reside-on-redirect-chassis=true将会将compute node上的流量往gw port上导(略过dvr port)
  • redirect-type=bridge, compute node上的流量往其他compute node或gw node上导时采用vlan, 而不是geneve
  • ovs-chaassi-mac-mappings, 设置之后该compute node上的ovn-chassis会负责本节点VM的arp

流量走向:

  • 相同子网的东西向流量不经过dvr port, 不同子网的流量默认经过dvr port (reside-on-redirect-chassis设置后才skip dvr port走centralized gw port) , 它们默认也是走tunnel(要走vlan需设置redirect-type=bridge)
  • 南北向流量哪怕是flat/vlan默认也是走geneve (设置redirect-type=bridge之后才走vlan物理桥)默认也是走centralized gw的, VM有FIP后要求从compute node直接进出的话还需要设置ovn-chaasis-mac-mapping来让compute node上的ovn-chassis应答gw port与它上所有VM的arp.
  • 默认情况下没有设置ovn-chaasis-mac-mapping, 所以qg-xxx/qr-xxx两种port(在ovn中统称lrp-xxx)都会被调度到gateway_chassis上(可通过non-ha和ha mode两种模式指定哪些节点能作gw node)

20251226 update - 再谈ovn dvr

这篇文章说得不错 ( https://cloudification.io/cloud-blog/ovn-traffic-flow-troubleshooting-in-openstack/ ),
1, non-dvr
在这里插入图片描述
2, dvr

在这里插入图片描述

reference

[1] https://www.openvswitch.org/support/ovscon2018/6/1440-sharma.pdf

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐