OVS 带内控制

1、前言

笔者在使用 Open vSwitch(下文简称 OVS)进行开发时,发现某些通过控制器设置的 OpenFlow 流表居然无法匹配到数据包。经过排查,查明原因是 OVS 带内控制的“隐藏”流表优先匹配到了数据包。

2、动机

OpenFlow 协议是基于 TCP 实现的,所以一个 OpenFlow 交换机必须建立并维护和控制器之间的 TCP 连接。如果将交换机所在网络简称为交换网络,这个 TCP 连接所在网络简称为控制网络,那么 OVS 网络可以划分为两种:一种是交换网络与控制网络相互隔离,另一种是交换网络与控制网络重叠。我们称前者为“带外控制”,后者为“带内控制”。

带外控制有以下优点:

  • 简单:简化了交换机的实现。
  • 可靠:交换网络的流量不会影响到控制网络。
  • 安全:处于控制网络以外的机器无法嗅探到控制流量。

而另一方面,带内控制有以下优点:

  • 无需专用端口:没有必要专门使用一个交换机端口进行控制。
  • 无需专用网络:没有必要专门建立和维护一个独立的控制网络。

OVS 同时支持了带外控制和带内控制。可以通过 man ovs-vswitchd.conf.db 来查看 OVS 带内控制的相关说明。

3、原则

带内控制的基本原则是 OpenFlow 交换机必须能够在不访问 OpenFlow 控制器的情况下识别和转发控制流量。这一原则的理由很简单,如果交换机本身无法处理带内控制流量,那么将陷入矛盾:交换机必须要和控制器通信,但却无法通信,因为只有控制器才能设置交换机的相关流表。

以下是这一原则的重点:

  • 无论交换机是否连上控制器,都需要实现带内控制。如果仅仅在交换机没有连接上控制器时才实现带内控制、连上控制器后则由控制器全权控制,这在实践中是不可行的。考虑以下情况:假设控制器没有事先得知交换机的 MAC 地址,在与交换机连接之后,需要发送 ARP 来请求交换机的 MAC 地址。如果此时没有带内控制,那么很有可能交换机将无法完成 ARP 应答。
  • 带内控制的流表可以覆盖由控制器设置的具有相同匹配条件的流表
  • 交换机必须能够识别所有的控制流量。考虑以下情况:假设有两个只能识别发往自身或由自身发出的控制流量的交换机 A 和 B,分别连接到以太网集线器(不是交换机)的端口,然后 OpenFlow 控制器连接到集线器的第三个端口。在这一网络拓扑结构中,交换机 B 会接收到交换机 A 发出的控制流量,然后将其封装为 OFPT_PACKET_IN 消息发送给控制器,而交换机 A 又会接收到交换机 B 的控制流量,将其重新封装到 OFPT_PACKET_IN 消息中,周而复始,最终导致控制流量风暴。
  • 控制器应该使用 echo 请求来检测连接的断开。固然 TCP 可以检测到连接的中断,但这可能需要相当长的时间,这在高性能网络中是不可接受的。所以 OpenFlow 的 OFPT_ECHO_REQUEST 消息则是检测连接的最好方法。

4、实现

OVS 将带内控制实现为“隐藏”流表,即无法通过 OpenFlow 设置和获取的流表,并且这些流表具有比通配符流表更高的优先级。这么做的目的是为了避免 OpenFlow 控制器对与交换机连接的干扰。可以通过 ovs-appctl bridge/dump-flows 来查看所有流表。

OVS 会设置以下带内控制的隐藏流表,这些流表会匹配符合以下条件的流量,并采取 OFPP_NORMAL 动作,即数据包交由 OVS 自身的转发规则完成转发,不再匹配任何 OpenFlow 流表

  1. 由 LOCAL 端口发出的 DHCP 请求。
  2. 发往 LOCAL 端口的 ARP 应答。
  3. 由 LOCAL 端口发出的 ARP 请求。

为了获取控制器的 MAC 地址,OVS 还会设置以下隐藏流表:

  1. 源以太网地址为“下一跳” MAC 的 ARP 请求(如果控制器和交换机在同一个子网内,下一跳就是控制器的 IP 地址,否则就是网关 IP 地址)。
  2. 目标以太网地址为“下一跳” MAC 的 ARP 代答(下一跳的含义同上)。
  3. 源以太网地址为控制 IP 的 ARP 请求。
  4. 目标协议地址为控制器 IP 的 ARP 代答。

此外,为了保证与控制器之间的 TCP 连接正常工作,OVS 还会设置以下隐藏流表:

  1. 源地址和源端口分别是控制器 IP 和端口的 TCP 流量。
  2. 目标地址和目标端口分别是控制器 IP 和端口的 TCP 流量。

举例说明,假设控制器的 IP 和端口分别是 192.168.65.100 和 6633,MAC 地址是 0a:00:27:00:00:18,OVS 的 MAC 地址是 00:00:00:00:00:01,OVS 会设置以下带内控制流表:

priority=180008,tcp,nw_src=192.168.65.100,tp_src=6633,actions=NORMAL
priority=180007,tcp,nw_dst=192.168.65.100,tp_dst=6633,actions=NORMAL
priority=180006,arp,arp_spa=192.168.65.100,arp_op=1,actions=NORMAL
priority=180005,arp,arp_tpa=192.168.65.100,arp_op=2,actions=NORMAL
priority=180002,arp,dl_src=00:00:00:00:00:01,arp_op=1,actions=NORMAL
priority=180004,arp,dl_src=0a:00:27:00:00:18,arp_op=1,actions=NORMAL
priority=180001,arp,dl_dst=00:00:00:00:00:01,arp_op=2,actions=NORMAL
priority=180003,arp,dl_dst=0a:00:27:00:00:18,arp_op=2,actions=NORMAL
priority=180000,udp,in_port=LOCAL,dl_src=00:00:00:00:00:01,tp_src=68,tp_dst=67,actions=NORMAL

由此可见,带内控制的隐藏流表的优先级居然远远超出 OVS OpenFlow 流表优先级的取值区间(0~65535),因此在具有相同匹配条件的情况下,带内控制的隐藏流表会被优先匹配。

5、关闭带内控制

OVS 的带内控制功能是默认开启的。如需关闭,可以执行以下指令:

ovs-vsctl set bridge br0 other-config:disable-in-band=true

6、总结

本文说明了 OVS 带内控制的动机、原理和实现,带内控制的目的是保证 OVS 与控制器之间的控制流量能够正常工作。然而,由于带内控制的相关流表具有更高的优先级,有可能导致 OpenFlow 流表无法匹配,所以可以根据实际需求将带内控制功能关闭。

参考资料

  1. https://docs.openvswitch.org/en/latest/topics/design/?highlight=in-band#in-band-control

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注