一、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请求的五元组都是一样的,所以每次转发选择的路径都相同。