ovs flow 原理及实验

OpenFlow概述

在支持OpenFlow的交换机中包含了若干个Flow table,Flow table能够用来控制数据包的处理,交换机会执行与flow相匹配的表项中所罗列的动做。html

OpenFlow controller经过使用OpenFlow协议来管理交换机,而且controller也能经过使用OpenFlow协议来获取交换机上的端口、流量的统计信息或其余情报,并能够根据这些信息来调整各端口的流量。cookie

交换机中维护的每一个flow table都包含有不少个条目,这些条目会根据自身的一个优先级从高到底进行排序,优先级最高的条目位于flow table的顶部。网络

当一个数据包进入到交换机时,先和优先级最高的条目进行匹配,若是匹配成功,那么就中止继续匹配动做,去执行该条目中的一组action。若是匹配失败,则按照优先级高低,继续匹配下一条。若是flow table中全部的条目都不匹配,这个数据包就会被丢弃或发送到控制器(问题:如何决定是丢弃仍是发送到控制器)。工具

OpenFlow协议的版本已经从1.0更新到了1.5,其中为了保证OpenFlow能有一个稳定的发展平台,把1.0和1.3版本做为其中长期支持的稳定版本。1.0版本功能比较简单,本次主要学习其中的1.3版本。学习

 

Flow Tables介绍

在OpenFlow中用来控制flow的table主要涉及到flow table和group table,先简单了解一下这两张table的构成。测试

Flow table

Flow table中每一个条目中包含的字段如上图所示,其中每一个字段的含义能够参考下面的表格。spa

每一个Flow table中的条目(表项)都是由Match Fields和Priority两个字段来共同惟一标识的。3d

 

Group table

一样的,上图列出了Group table中每一个条目包含的字段,其含义参考下表:orm

这里简单了解一下两张table的结构,至于table中每一个字段的具体含义和用途咱们先不着急去了解,在后面结合具体的流程来更方便的去理解。htm

 

Pipeline Processing

在了解了上述两张table后,咱们不由会想:在交换机运行过程当中是如何配合这两张表来实现流量转发的呢?

这就不得不提到openflow中的一个重要概念:pipeline processing。什么是pipeline?若是把每一个table当成一道加工工艺的话,pipeline就能够当作是一条加工流水线。在这条流水线上,多个flow table按照其数字编号从小到大排列着(table0, table1, table2 …… table N),进入交换机的数据包都是从pipeline的第一个flow table也就是table0开始处理,按照上文描述的那样,对table0中的条目一条一条开始匹配,若是匹配成功则执行相应的动做(这些动做可能致使从flow table跳到group table中),若果没有全部条目都没有成功匹配,则根据table自身的不一样配置执行相应的处理(Table Miss Flow Entry):

  • drop
  • 转发给下一个table
  • 发送给controller
Table Miss Flow Entry是flow table中专门处理没有成功匹配的数据包的一个条目,它的Match Fields可以匹配任何数据包,而且Priority为0,也就是会被最后执行。
Table Miss Flow Entry不是必须存在的,当不存在的时候,对没成功匹配的数据包会执行table中的默认动做。

 

整个流程形象点的话咱们能够经过下面这张图来理解:

 

这张图是我从网络上复制过来的,相关文章能够在最后的参考连接中查看。

在这张图中咱们能够很形象的看到flow table和group table在数据转发过程当中的地位。

 

在Open vSwitch上的应用

OVS对Open Flow的支持状况

在使用open vswitch来实际应用open flow以前,咱们有必要先了解一下ovs目前对openflow协议各版本的支持状况。为此,我在官网找到了以下这张表(2018年4月):

  • —: Not supported.
  • yes: Supported and enabled by default
  • (*): Supported, but missing features, and must be enabled by user.
  • (%): Experimental, unsafe implementation.

本文中使用的Open vSwitch版本为2.5.0,默认支持Open Flow 1.3。

 

操做Open Flow的工具

在实际的环境中,基本上都是由controller来操做修改交换机的open flow。本实验将经过使用ovs-ofctl工具手动来配置修改OVS交换机的open flow。

ovs-ofctl的使用方法能够参考官方文档:Open vSwitch Manual : ovs-ofctl

基本实验环境

 

环境拓扑

 

基本实验环境

环境拓扑

 

环境构筑

# 建立namespace
ip netns add ns1
ip netns add ns2
ip netns add ns3
ip netns add ns4

# 建立tap设备
ip link add tap0 type veth peer name tap0_br
ip link add tap1 type veth peer name tap1_br
ip link add tap2 type veth peer name tap2_br
ip link add tap3 type veth peer name tap3_br
ip link add tap4 type veth peer name tap4_br
ip link add tap5 type veth peer name tap5_br
ip link add tap6 type veth peer name tap6_br
ip link add tap7 type veth peer name tap7_br

# 设置tap设备的namespace
ip link set tap0 netns ns1
ip link set tap1 netns ns1
ip link set tap2 netns ns2
ip link set tap3 netns ns2
ip link set tap4 netns ns3
ip link set tap5 netns ns3
ip link set tap6 netns ns4
ip link set tap7 netns ns4

# 建立OVS网桥
ovs-vsctl add-br vswitch0

# 将tap设备另外一端绑到网桥
ovs-vsctl add-port vswitch0 tap0_br
ovs-vsctl add-port vswitch0 tap1_br
ovs-vsctl add-port vswitch0 tap2_br
ovs-vsctl add-port vswitch0 tap3_br
ovs-vsctl add-port vswitch0 tap4_br
ovs-vsctl add-port vswitch0 tap5_br
ovs-vsctl add-port vswitch0 tap6_br
ovs-vsctl add-port vswitch0 tap7_br

  

实验一(单个table及验证其flow的优先级)

 

实验准备

环境配置

 

# 启动tap0和tap3及它们的对端
ip netns exec ns1 ip link set tap0 up
ip netns exec ns2 ip link set tap3 up
ip link set tap0_br up
ip link set tap3_br up

# 设置tap0和tap3的ip地址
ip netns exec ns1 ip addr add 192.168.1.100 dev tap0
ip netns exec ns2 ip addr add 192.168.1.200 dev tap3

# 配置路由
ip netns exec ns1 route add -net 192.168.1.0 netmask 255.255.255.0 dev tap0
ip netns exec ns2 route add -net 192.168.1.0 netmask 255.255.255.0 dev tap3

# 测试网络连通性
ip netns exec ns1 ping 192.168.1.200
>> 64 bytes from 192.168.1.200: icmp_seq=1 ttl=64 time=0.030 ms
>> 64 bytes from 192.168.1.200: icmp_seq=2 ttl=64 time=0.055 ms
 

查看tap设备对应的ovs port

# ovs-vsctl list interface tap0_br | grep "ofport "
ofport              : 1
# ovs-vsctl list interface tap3_br | grep "ofport "
ofport              : 4

实验过程

首先查看一下vswitch0上的flow table:

# ovs-ofctl dump-flows vswitch0
cookie=0x0, duration=267197.837s, table=0, n_packets=459, n_bytes=42190, idle_age=387, hard_age=65534, priority=0 actions=NORMAL

发现有一条actions为NORMAL的流表项,这是默认存在的,用以实现交换机的基本动做。

当咱们把这条flow删除后发现两个tap设备之间已没法ping通:

# ovs-ofctl del-flows vswitch0
# ovs-ofctl dump-flows vswitch0
NXST_FLOW reply (xid=0x4):
# ip netns exec ns1 ping 192.168.1.200
PING 192.168.1.200 (192.168.1.200) 56(84) bytes of data.
^C
--- 192.168.1.200 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2052ms

 简单的讲,若是要实现tap0和tap3之间流量互通,其实就是要交换机将port1上的数据发往port4,port4上的数据发往port1(port1和port4分别是tap0和tap3对应的ovs端口,查看方法见上),因此咱们能够添加下面两条flow: 

# ovs-ofctl add-flow vswitch0 "priority=1,in_port=1,actions=output:4"
# ovs-ofctl add-flow vswitch0 "priority=2,in_port=4,actions=output:1"

当添加完这两条flow后发现tap0和tap3之间又能相互ping通了

# ip netns exec ns1 ping 192.168.1.200
PING 192.168.1.200 (192.168.1.200) 56(84) bytes of data.
64 bytes from 192.168.1.200: icmp_seq=1 ttl=64 time=0.396 ms
64 bytes from 192.168.1.200: icmp_seq=2 ttl=64 time=0.050 ms
^C
--- 192.168.1.200 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1030ms
rtt min/avg/max/mdev = 0.050/0.223/0.396/0.173 ms

 能够看到咱们给这两个flow设置了优先级分别是1和2,根据上文所讲,flow优先级越高,会优先匹配,因此咱们再增长下面的flow来测试: 

ovs-ofctl add-flow vswitch0 "priority=3,in_port=1,actions=drop"

这条flow是将全部从port1上的数据所有drop掉,若是成功匹配,则tap0和tap3将再也不互通。

# ip netns exec ns1 ping 192.168.1.200
PING 192.168.1.200 (192.168.1.200) 56(84) bytes of data.
^C
--- 192.168.1.200 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2057ms 

发现果真ping不通了,这就验证了上文的描述:优先级越高,优先匹配。

 

实验二(多个table)

 

在实验一的基础上继续往下作。

首先清除全部的flow,从新开始配置

# ovs-ofctl del-flows vswitch0

还记得转发的两条flow吗?在实验一中咱们配置到了table0,如今将他们配置到table1

# ovs-ofctl add-flow vswitch0 "table=1,priority=1,in_port=1,actions=output:4"
# ovs-ofctl add-flow vswitch0 "table=1,priority=2,in_port=4,actions=output:1"
# ovs-ofctl dump-flows vswitch0
NXST_FLOW reply (xid=0x4):
 cookie=0x0, duration=3.485s, table=1, n_packets=0, n_bytes=0, idle_age=3, priority=1,in_port=1 actions=output:4
 cookie=0x0, duration=3.033s, table=1, n_packets=0, n_bytes=0, idle_age=3, priority=2,in_port=4 actions=output:1

 尝试ping对端设备,发现没法ping通,由于数据包从table0开始处理,当前table0中没有匹配的flow,因此数据包被drop掉了。

# ip netns exec ns1 ping 192.168.1.200
PING 192.168.1.200 (192.168.1.200) 56(84) bytes of data.
^C
--- 192.168.1.200 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2026ms

  

如今给table0加上一条将数据包发送到table1处理的flow

# ovs-ofctl add-flow vswitch0 "table=0,actions=goto_table=1" 

再次尝试ping对端的设备,能够正常ping通

# ip netns exec ns1 ping 192.168.1.200
PING 192.168.1.200 (192.168.1.200) 56(84) bytes of data.
64 bytes from 192.168.1.200: icmp_seq=1 ttl=64 time=0.309 ms
64 bytes from 192.168.1.200: icmp_seq=2 ttl=64 time=0.050 ms
^C
--- 192.168.1.200 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1054ms
rtt min/avg/max/mdev = 0.050/0.179/0.309/0.130 ms

  

 

实验三(group table)

继续使用这个环境,第一步仍是清除全部的flow

# ovs-ofctl del-flows vswitch0

查看交换机上存在的group表,发现当前没有任何group table。

# ovs-ofctl -O OpenFlow13 dump-groups vswitch0
OFPST_GROUP_DESC reply (OF1.3) (xid=0x2):

咱们计划让数据包从table0发送到group table处理,再发送到table1处理。

# ovs-ofctl -O OpenFlow13 add-group vswitch0 "group_id=1,type=select,bucket=resubmit(,1)"
# ovs-ofctl -O OpenFlow13 dump-groups vswitch0
OFPST_GROUP_DESC reply (OF1.3) (xid=0x2):
 group_id=1,type=select,bucket=actions=resubmit(,1)

在table0中增长两条flow,目的是将数据包发送到group table1

# ovs-ofctl -O OpenFlow13 add-flow vswitch0 "table=0,in_port=1,actions=group:1"
# ovs-ofctl -O OpenFlow13 add-flow vswitch0 "table=0,in_port=4,actions=group:1"

向table1中增长两条flow,真正的数据转发在table1中进行。

# ovs-ofctl add-flow vswitch0 "table=1,priority=1,in_port=1,actions=output:4"
# ovs-ofctl add-flow vswitch0 "table=1,priority=2,in_port=4,actions=output:1"

尝试ping对端,能够成功ping通,说明数据包被正确处理。

 

# ip netns exec ns1 ping 192.168.1.200
PING 192.168.1.200 (192.168.1.200) 56(84) bytes of data.
64 bytes from 192.168.1.200: icmp_seq=1 ttl=64 time=0.329 ms
64 bytes from 192.168.1.200: icmp_seq=2 ttl=64 time=0.048 ms
^C
--- 192.168.1.200 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1048ms
rtt min/avg/max/mdev = 0.048/0.188/0.329/0.141 ms
相关文章
相关标签/搜索