本文通过示例在 OpenvSwitch 中验证 OpenFlow 流表单、多 Table 和 Group Table 功能。
环境拓扑
环境初始化
ip netns add ns-1
ip netns add ns-2
ip link add tap1-1 type veth peer name tap1-2
ip link add tap2-1 type veth peer name tap2-2
ip link add tap3-1 type veth peer name tap3-2
ip link add tap4-1 type veth peer name tap4-2
ip link set tap1-1 netns ns-1
ip link set tap2-1 netns ns-1
ip link set tap3-1 netns ns-2
ip link set tap4-1 netns ns-2
$ ovs-vsctl add-br br-0
$ ovs-vsctl show
4ca1f1f2-ddc5-4964-946b-0b12af51136b
Bridge br-0
Port br-0
Interface br-0
type: internal
ovs_version: "2.13.5"
$ ovs-vsctl add-port br-0 tap1-2
$ ovs-vsctl add-port br-0 tap2-2
$ ovs-vsctl add-port br-0 tap3-2
$ ovs-vsctl add-port br-0 tap4-2
$ ovs-vsctl show
4ca1f1f2-ddc5-4964-946b-0b12af51136b
Bridge br-0
Port br-0
Interface br-0
type: internal
Port tap4-2
Interface tap4-2
Port tap3-2
Interface tap3-2
Port tap1-2
Interface tap1-2
Port tap2-2
Interface tap2-2
ovs_version: "2.13.5"
单个 Table 优先级验证
环境配置
- 启动 tap1-1 和 tap3-1 及它们的对端
ip netns exec ns-1 ip link set tap1-1 up
ip netns exec ns-2 ip link set tap3-1 up
ip link set tap1-2 up
ip link set tap3-2 up
ip netns exec ns-1 ip addr add 10.2.0.100 dev tap1-1
ip netns exec ns-2 ip addr add 10.2.0.200 dev tap3-1
ip netns exec ns-1 route add -net 10.2.0.0 netmask 255.255.255.0 dev tap1-1
ip netns exec ns-2 route add -net 10.2.0.0 netmask 255.255.255.0 dev tap3-1
$ ip netns exec ns-1 ping -c1 10.2.0.200
PING 10.2.0.200 (10.2.0.200) 56(84) bytes of data.
64 bytes from 10.2.0.200: icmp_seq=1 ttl=64 time=0.659 ms
--- 10.2.0.200 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.659/0.659/0.659/0.000 ms
$ ovs-vsctl list interface tap1-2 | grep -w ofport
ofport : 1
$ ovs-vsctl list interface tap3-2 | grep -w ofport
ofport : 3
验证过程
$ ovs-ofctl dump-flows br-0
cookie=0x0, duration=661.057s, table=0, n_packets=28, n_bytes=2096, priority=0 actions=NORMAL
有一条 actions
为 NORMAL
的流表项,这是默认存在的,用以实现交换机的基本功能
删除该 flow
后,发现两个 tap 设备之间是无法 ping 通的,操作如下:
$ ovs-ofctl del-flows br-0
$ ovs-ofctl dump-flows br-0
$
$ ip netns exec ns-1 ping -c1 10.2.0.200
PING 10.2.0.200 (10.2.0.200) 56(84) bytes of data.
--- 10.2.0.200 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms
$
总结,如果要实现 tap1-1
和 tap3-1
的互通,其实就是要交换机将 port1
上的数据发往 port3
,port3
上的数据发往 port1
(其中 port1
和 port3
分别是 tap1-1
和 tap3-1
对应的 ovs
端口),通过流表实现方式如下:
$ ovs-ofctl add-flow br-0 "priority=1,in_port=1,actions=output:3"
$ ovs-ofctl add-flow br-0 "priority=2,in_port=3,actions=output:1"
$ ovs-ofctl dump-flows br-0
cookie=0x0, duration=34.976s, table=0, n_packets=0, n_bytes=0, priority=1,in_port="tap1-2" actions=output:"tap3-2"
cookie=0x0, duration=29.916s, table=0, n_packets=1, n_bytes=70, priority=2,in_port="tap3-2" actions=output:"tap1-2"
在次互 ping
是通的,如下:
$ ip netns exec ns-1 ping -c1 10.2.0.200
PING 10.2.0.200 (10.2.0.200) 56(84) bytes of data.
64 bytes from 10.2.0.200: icmp_seq=1 ttl=64 time=0.530 ms
--- 10.2.0.200 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.530/0.530/0.530/0.000 ms
优先级验证
上述两个 flow entry
的优先级分别设置为 1 和 2,根据OpenFlow 协议,flow 的优先级越高,会优先匹配,再增加下面的 flow 来验证:
$ ovs-ofctl add-flow br-0 "priority=3,in_port=1,actions=drop"
$ ovs-ofctl dump-flows br-0
cookie=0x0, duration=298.502s, table=0, n_packets=3, n_bytes=182, priority=1,in_port="tap1-2" actions=output:"tap3-2"
cookie=0x0, duration=293.442s, table=0, n_packets=4, n_bytes=252, priority=2,in_port="tap3-2" actions=output:"tap1-2"
cookie=0x0, duration=6.363s, table=0, n_packets=0, n_bytes=0, priority=3,in_port="tap1-2" actions=drop
该 flow 将所有从 port1 上的进来的数据全部 drop 掉,如果成功匹配,则 tap1-1 和 tap3-1 将不再互通,验证如下:
$ ip netns exec ns-1 ping -c1 10.2.0.200
PING 10.2.0.200 (10.2.0.200) 56(84) bytes of data.
--- 10.2.0.200 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms
$
结论:flow entry 优先级越高,优先匹配
多个 Table 验证
继续验证,首先清除 br-0 上的所有的 flow,重新开始配置:
$ ovs-ofctl del-flows br-0
单个 table 优先级验证
的实验中,flow entry
默认在 table0
中,现在将它们配置到 table1
中:
$ ovs-ofctl add-flow br-0 "table=1,priority=1,in_port=1,actions=output:3"
$ ovs-ofctl add-flow br-0 "table=1,priority=2,in_port=3,actions=output:1"
$ ovs-ofctl dump-flows br-0
cookie=0x0, duration=10.290s, table=1, n_packets=0, n_bytes=0, priority=1,in_port="tap1-2" actions=output:"tap3-2"
cookie=0x0, duration=5.530s, table=1, n_packets=0, n_bytes=0, priority=2,in_port="tap3-2" actions=output:"tap1-2"
同样的 ping
是不通的,因为数据包从 table0
开始处理,当前 table0
中没有匹配的 flow entry
,数据包被自动 drop 掉,如下:
$ ip netns exec ns-1 ping -c1 10.2.0.200
PING 10.2.0.200 (10.2.0.200) 56(84) bytes of data.
--- 10.2.0.200 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms
$
下面给 table0
加上一条 flow entry
:将数据包发送到 table1
,如下:
$ ovs-ofctl add-flow br-0 "table=0,actions=goto_table=1"
$ ovs-ofctl dump-flows br-0
cookie=0x0, duration=8.056s, table=0, n_packets=0, n_bytes=0, actions=resubmit(,1)
cookie=0x0, duration=204.275s, table=1, n_packets=0, n_bytes=0, priority=1,in_port="tap1-2" actions=output:"tap3-2"
cookie=0x0, duration=199.515s, table=1, n_packets=0, n_bytes=0, priority=2,in_port="tap3-2" actions=output:"tap1-2"
ping
验证正常:
$ ip netns exec ns-1 ping -c1 10.2.0.200
PING 10.2.0.200 (10.2.0.200) 56(84) bytes of data.
64 bytes from 10.2.0.200: icmp_seq=1 ttl=64 time=1.76 ms
--- 10.2.0.200 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.763/1.763/1.763/0.000 ms
该实验简单演示了 OpenFlow 多个 table 之间是如何工作的
Group Table 验证
继续验证,首先清除所有的 flow entry:
$ ovs-ofctl del-flows br-0
$ ovs-ofctl dump-flows br-0
$
配置流表:让数据包从 table0
发送到 group table
处理,再发送到 table1
处理
- 首先创建一个 group table,并将数据包发往 table1 处理
$ ovs-ofctl add-group br-0 "group_id=1,type=select,bucket=resubmit(,1)"
$ ovs-ofctl dump-groups br-0
NXST_GROUP_DESC reply (xid=0x2):
group_id=1,type=select,bucket=bucket_id:0,actions=resubmit(,1)
- 下面给
table0
加上一条 flow entry
:将数据包发送到 group table1
,如下:
$ ovs-ofctl add-flow br-0 "table=0,in_port=1,actions=group:1"
$ ovs-ofctl add-flow br-0 "table=0,in_port=3,actions=group:1"
$ ovs-ofctl dump-flows br-0
cookie=0x0, duration=11.512s, table=0, n_packets=1, n_bytes=70, in_port="tap1-2" actions=group:1
cookie=0x0, duration=5.797s, table=0, n_packets=0, n_bytes=0, in_port="tap3-2" actions=group:1
- 下面给
table1
加上两条 flow entry
:将数据包发送到 table1
,如下:
$ ovs-ofctl add-flow br-0 "table=1,priority=1,in_port=1,actions=output:3"
$ ovs-ofctl add-flow br-0 "table=1,priority=2,in_port=3,actions=output:1"
$ ovs-ofctl dump-flows br-0
cookie=0x0, duration=102.499s, table=0, n_packets=1, n_bytes=70, in_port="tap1-2" actions=group:1
cookie=0x0, duration=96.784s, table=0, n_packets=0, n_bytes=0, in_port="tap3-2" actions=group:1
cookie=0x0, duration=16.889s, table=1, n_packets=0, n_bytes=0, priority=1,in_port="tap1-2" actions=output:"tap3-2"
cookie=0x0, duration=11.371s, table=1, n_packets=0, n_bytes=0, priority=2,in_port="tap3-2" actions=output:"tap1-2"
$ ip netns exec ns-1 ping -c1 10.2.0.200
PING 10.2.0.200 (10.2.0.200) 56(84) bytes of data.
64 bytes from 10.2.0.200: icmp_seq=1 ttl=64 time=0.642 ms
--- 10.2.0.200 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.642/0.642/0.642/0.000 ms