ovs flow 原理及实验
OpenFlow概述
在支持OpenFlow的交换机中包含了若干个Flow table,Flow table可以用来控制数据包的处理,交换机会执行与flow相匹配的表项中所罗列的动作。
OpenFlow controller通过使用OpenFlow协议来管理交换机,并且controller也能通过使用OpenFlow协议来获取交换机上的端口、流量的统计信息或其他情报,并可以根据这些信息来调整各端口的流量。
交换机中维护的每个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中每个条目中包含的字段如上图所示,其中每个字段的含义可以参考下面的表格。
每个Flow table中的条目(表项)都是由Match Fields和Priority两个字段来共同唯一标识的。
Group table
同样的,上图列出了Group table中每个条目包含的字段,其含义参考下表:
这里简单了解一下两张table的结构,至于table中每个字段的具体含义和用途我们先不着急去了解,在后面结合具体的流程来更方便的去理解。
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
ovs flow 原理及实验的更多相关文章
- OVS + dpdk 安装与实验环境配置
***DPDK datapath的OVS的安装与实验环境配置 首先肯定是DPDK的安装 0:安装必要的工具 make gcc ...
- CRISPR/Cas9基因敲除原理及实验建议
CRISPR/Cas9基因敲除原理及实验建议 CRISPR Cas9已经成为了最受欢迎的基因编辑技术之一,在2016年的国自然基金中也有很多项目是关于 CRISPR Cas9的.目前在市场上已经有 ...
- socket的原理和实验
1.socket原理 根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认. (1)服务器监听:是服务器端套接字并不定位具体的客户端套接 ...
- MySQL主从、主主、半同步节点架构的的原理及实验总结
一.原理及概念: MySQL 主从复制概念 MySQL 主从复制是指数据可以从一个MySQL数据库服务器主节点复制到一个或多个从节点.MySQL 默认采用异步复制方式,这样从节点不用一直访问主服务器来 ...
- 网络初级篇之网络设备的FTP(原理与实验)
一.什么是FTP FTP就是文件传输协议.用于互联网双向传输.二.FTP的作用 控制文件下载空间在服务器复制文件从本地计算机或本地上传文件复制到服务器上的空间,主要的作用就是文件的传输,保 ...
- 网络初级篇之DHCP原理与配置(原理与实验)
一.什么是DHCP DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)通常被应用在大型的局域网络环境中,主要作用是集中的管理.分配IP地址,使网络环境 ...
- Oracle自动统计信息的收集原理及实验
[日期:2014-11-21]来源:Linux社区 作者:stevendbaguo[字体:大 中 小] 从Oracle Database 10g开始,Oracle在建库后就默认创建了一个名为GATH ...
- CTR预估中的贝叶斯平滑方法(一)原理及实验介绍
1. 背景介绍 广告形式: 互联网广告可以分为以下三种: 1)展示广告(display ad) 2)搜索广告(sponsored search ad) 3)上下文广告(contextual ad) ...
- OSPF协议——原理及实验
首先命令部分: ospf 1 进入ospf协议 area 0 划定自治区域 因为实验只用了1个区域所以参数就为0 也就是骨干区域 network +网段+反写掩码(0.0.0.255)指定运行OSPF ...
随机推荐
- servlet 高级知识之Listener
Listener,顾名思义,监听器.它可以监听客户端的请求.服务端的操作等. 通过监听器,可以自动激发一些操作,比如监听在线的用户的数量.当增加一个HttpSession时,就激发sessionCre ...
- firefox 之 event兼容写法
event 在 IE 和 FF(Firefox) 中是不兼容的,IE 中可以直接使用 event 对象,而 FF 中则不可以,解决方法之一如下: var event = window.event || ...
- mybatis学习 十二 多表查询
Mybatis 实现多表查询方式: (1)业务装配.对两个表编写单表查询语句,在业务(Service)把查询的两个结果进行关联. (2)使用Auto Mapping特性,在实现两表联合查询时通过别名完 ...
- Jetty 9的使用
参考来源:https://www.cnblogs.com/empireghost/p/3522834.html
- 2018.11.02 NOIP模拟 飞越行星带(最小生成树/二分+并查集)
传送门 发现题目要求的就是从下到上的瓶颈路. 画个图出来发现跟去年noipnoipnoip提高组的奶酪差不多. 于是可以二分宽度+并查集检验,或者直接求瓶颈. 代码
- 5. Sports 体育运动
5. Sports 体育运动 (1) Sport is not only physically challenging,but it can also be mentally challenging. ...
- 移动赋值运算符(c++11)
1.概念 1)移动赋值运算符是一个重载的赋值运算符,参数为自身类的右值引用,返回值自身类的左值引用,由于不抛出任何异常,用noexcept指定(如果定义在类的外面,那么定义也要用noexcept指定) ...
- str.index()与str.find()比较
def extract_from_tag(tag,line): opener = "<" + tag + ">" closer = "&l ...
- 实现数组(java)
一,数组 java中有对数组的数据结构:数组就是一个存放固定数据的结构. 数组的声明举例:int [] array=new int [3],与之相同的是private in [ ] array; a ...
- 安卓修改开机logo
这里我们是在ubuntu下进行操作我是用root用户登陆的,首先安装netpbm库 执行:apt-get install netpbm 对于Android系统最开始表现logo是在内核当中,所以首先我 ...