一、group表介绍

OpenFlow v1.1中增加了组表(Group Table)的概念,并一直被后续的版本所沿用。

OpenFlow支持四种组表类型:

  • Indirect:执行该group中一个已定义的bucket, 该组仅支持一个bucket。 允许多个流表项或组表项指向一个公共的组(例如IP转发的下一跳)。 这是最简单的group类型,交换机通常比较支持这种类型的group。
  • All:执行该group中所有的bucket。这种类型的group用来进行multicast和broadcast。为每个bucket克隆一份数据包,然后分别执行每个bucket中的actions。
  • Select:执行该group中的一个bucket。基于一种选择算法(用户定义的哈希算法或者轮询算法)选择group中的一个bucket对数据包执行actions。这种选择算法应该尽量支持负载均衡并且为每个bucket提供一个权重用于分配。当一个bucket指定的端口down掉,交换机应该将选择限制在剩下的正常的bucket中而不是丢掉,这是为了减少链路中断。
  • Fast failover:执行第一个活动的bucket。 每个action bucket都与控制其活动性的特定端口和/或组相关联。 按照group定义的顺序评估bucket,并选择与活动端口/组关联的第一个bucket。 这个group类型使交换机可以更改转发行为而无需往返于控制器。 如果没有bucket,则丢弃数据包。

group表的常用命令如下:

  • 查看当前设备对group的支持
ovs-ofctl -O OpenFlow13 dump-group-features br0
  • 查看group表
ovs-ofctl -O OpenFlow13 dump-groups br0
  • 创建group表
# 类型为all
ovs-ofctl -O OpenFlow13 add-group br0 group_id=1,type=all,bucket=output:1,bucket=output:2,bucket=output:3
# 类型为select
ovs-ofctl -O OpenFlow13 add-group br0 group_id=2,type=select,bucket=output:1,bucket=output:2,bucket=output:3
# 类型为select,指定hash方法(5元组,OpenFlow1.5+)
ovs-ofctl -O OpenFlow15 add-group br0 group_id=3,type=select,selection_method=hash,fields=ip_src,bucket=output:2,bucket=output:3
  • 删除group表
ovs-ofctl -O OpenFlow13 del-groups br0 group_id=2
  • 创建流表
ovs-ofctl -O OpenFlow13 add-flow br0 in_port=1,actions=group:2

二、group表实验过程

1、实验概述

为了更加直观的观察实验过程,本次实验使用mininet进行网络拓扑的构建,mininet的使用见之前的bolg(https://blog.csdn.net/weixin_40042248/article/details/109274982)。在mininet中,构建两台主机h1、h2作为测试的主机,利用五个交换机构建出两条链路便于测试group的不同类型的数据转发情况,其中s1和s5里使用group表,其余的交换机作为普通的二层交换机使用,具体的拓扑如下图所示。

拓扑构建完成之后,运行拓扑,在终端中查看网卡端口的对应关系,方便添加流表,使用命令links,对应关系如下图所示。

接下来,为h1和h2分配ip

h1 ip addr add 10.0.0.1/24 dev h1-eth0
h2 ip addr add 10.0.0.2/24 dev h2-eth0

为s2、s3、s4添加流表,将这三个交换机作为普通交换机使用,流表添加的命令如下。

ovs-ofctl add-flow s2 priority=0,actions=normal
ovs-ofctl add-flow s3 priority=0,actions=normal
ovs-ofctl add-flow s4 priority=0,actions=normal

(1)添加group表,类型为all

首先为s1进行group表设置,查看s1中的网卡对应的number,命令ovs-ofctl show s1,结果如下图所示。

向s1中添加group表,类型为all,bucket动作为向所有端口转发。

ovs-ofctl -O OpenFlow13 add-group s1 group_id=1,type=all,bucket=output:1,bucket=output:2,bucket=output:3

再向s1中添加流表,从端口1进入的数据转发执行s1内的group表,从2、3端口进入的数据将其从端口1转发出去。这样设置之后,从h1发送的数据就会向所有的路径转发出去,从其他地方进入的数据就会发送给h1。

ovs-ofctl add-flow s1 priority=1,in_port=1,actions=group:1 -O openflow13

ovs-ofctl add-flow s1 priority=1,in_port=2,actions=output:1 -O openflow13

ovs-ofctl add-flow s1 priority=1,in_port=3,actions=output:1 -O openflow13

接下来,为s5进行group表设置,查看s5中的网卡对应的number,命令ovs-ofctl show s5,结果如下图所示。

向s5中添加group表,类型为all,bucket动作为向所有端口转发。

ovs-ofctl add-group s5 group_id=5,type=all,bucket=output:1,bucket=output:2,bucket=output:3 -O openflow13

再向s5中添加流表,从端口1进入的数据转发执行s5内的group表,从1、3端口进入的数据将其从端口2转发出去。这样设置之后,从h2发送的数据就会向所有的路径转发出去,从其他地方进入的数据就会发送给h2。

ovs-ofctl add-flow s5 priority=1,in_port=2,actions=group:5 -O openflow13

ovs-ofctl add-flow s5 priority=1,in_port=1,actions=output:2 -O openflow13

ovs-ofctl add-flow s5 priority=1,in_port=3,actions=output:2 -O openflow13

以上步骤设置成功后,h1--h2之间便有两条链路可以正常通信, 接下来,在mininet命令行下输入h1 ping h2的命令,观察结果如下图所示。

注意:DUP是DUPLICATE的一个缩写,也就是ping包的时候收到多个重复值回应,通常发生在linux环境下比较多,windows环境对ping的reply只接到第一个,后续的重复回应会被废弃。

所以,可以看出两条链路在类型为all的group表下,都可以正常的进行数据转发。

接下来,将一条链路down掉,如下图所示,h1 ping h2观察结果如下图所示。

(2)添加group表,类型为select(实现ECMP)

首先,清除上一步的s1中的group表,添加group表,类型为select,方法用hash,目的是将h1发出的数据按照hash算法选择转发的路径(hash根据五元组)。在s1中添加group表后,如下图所示。

ovs-ofctl add-group s1 group_id=1,selection_method=hash,type=select,selection_method=hash,bucket=output:2,bucket=output:3

在s1中添加流表,actions执行group表。

ovs-ofctl add-flow s1 priority=1,in_port=1,actions=group:1 -O openflow13

接下来,在mininet命令行下输入h1 ping h2,结果如下图所示。由于s5的group仍然为上一步的group表,所以返回的icmp应答报文仍然重复。

为了更好的查看数据转发的过程,当h1 ping h2 后,使用tcpdump监测s2-eth1和s3-eth1数据,如下图所示。可以看出,设置select类型的group表后,icmp请求报文只选择了上面一条路径,由于每次icmp请求的五元组都是一样的,所以每次转发选择的路径都相同。

(3)添加group表,类型为Fast failover

通过fast failover这个名字就能发现该类型是一个快速恢复的类型。具体来说就是当转发的端口down掉之后组表能够感知到并且切换到另一个up的端口。在这种类型的组表的行动桶中,具有设置监视对象端口 的watch_port这一个设置项目,可以实现对物理端口的监控,从而实现当转发的端口down掉之后组表能够感知到并且切换到另一个up的端口。

在这里,重新构建了一个网络拓扑如下所示。其中,h1,h2,h3的ip分别设置为10.0.1.1/24,10.0.1.2/24,10.0.1.3/24。

端口对应的关系如下所示。

实验中,设置两个组表的bucket,分别监听s1-eth2和s1-eth3,output分别对应的h2和h3。组表的命令如下。

ovs-ofctl -O openflow13 add-group s1 group_id=1,type=ff,bucket=watch_port:2,actions=output:2,bucket=watch_port:3,actions=output:3

接下来,对s1添加流表,命令如下。

ovs-ofctl add-flow s1 priority=1,in_port=1,actions=group:1 -O openflow13
ovs-ofctl add-flow s1 priority=1,in_port=2,actions=output:1 -O openflow13
ovs-ofctl add-flow s1 priority=1,in_port=3,actions=output:1 -O openflow13

流表添加完成后,就可以开始实验结果验证了。

首先,在h1中 ping h2,结果如下所示。可以正常的ping通。

然后,在h1中 ping h3,结果如下所示。无法ping 通。

此时,若断开s1-h2之间的链路,就可以实现h1 ping h3了。接下来,将s1-h2之间的链路断开,再在h1中 ping h3,结果如下所示。可以发现已经能够相互ping通了。

 

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐