Open vSwitch流表管理

OpenFlow是用于管理交换机流表的协议,ovs-ofctl是Open vSwitch提供的命令行工具。在没有配置OpenFlow控制器的模式下,用户可以使用ovs-ofctl命令通过OpenFlow协议连接Open vSwitch来创建、修改或删除Open vSwitch中的流表项,并对Open vSwitch的运行状况进行动态监控。ovs-ofctl关于流表管理的常用命令如下表所示。

命令 含义
show SWITCH 输入OpenFlow信息
dump-port SWITCH PORT 输出端口统计信息
dump-port-desc SWITCH 输出端口描述信息
dump-flows SWITCH 输出交换机中所有的流表项
dump-flows SWITCH FLOW 输出交换机中匹配的流表项
add-flow SWITCH FLOW 向交换机添加流表项
add-flows SWITCH FILE 在文件中向交换机添加流表项
mod-flows SWITCH FLOW 修改交换机的流表项
del-flows SWITCH FLOW 删除交换机的流表项

对于add-flowadd-flowsmod-flows这3个命令,还需要指定要执行的动作actions=[target],[target]…,一个流规则中可能有多个动作,按照指定的先后顺序执行。
常见的流表操作如下表所示。

操作 说明
output:port 输出数据包到指定的端口,port是指端口的OpenFlow端口编号
mod_vlan_vid 修改数据包中的VLANtag
strip_vlan 移除数据包中的VLANtag
mod_dl_src/ mod_dl_dest 修改源或者目标的MAC地址信息
mod_nw_src/ mod_nw_dst 修改源或者目标的IPv4地址信息
resubmit:port 替换流表的in_port字段,并重新进行匹配
load:value->dst[start..end] 写数据到指定的字段

在OpenFlow白皮书中,Flow被定义为某个特定的网络流量。例如,一个TCP连接就是一个Flow,或者从某个IP地址发出来的数据包,都可以被认为是一个Flow。支持OpenFlow协议的交换机应该包括一个或多个流表,流表中的条目包含:数据包头的信息、匹配成功后要执行的指令和统计信息。当数据包进入OVS后,会将数据包和流表中的流表项进行匹配,如果发现了匹配的流表项,则执行该流表项中的指令集。相反,如果数据包在流表中没有发现任何匹配,OVS会通过控制通道把数据包发到OpenFlow控制器中。在OVS中,流表项作为ovs-ofctl的参数,采用如下的格式:字段=值,如果有多个字段,可以用逗号或空格分开,一些常用的字段列举如下表所示。

字段名称 说明
in_port=port 传递数据包端口的OpenFlow端口编号
dl_vlan=vlan 数据包的VLANtag值,范围是0~4095,0xffff代表不包含VLAN Tag的数据包
dl_src=<MAC> dl_dst=<MAC> 匹配源或者目标地址的MAC地址:01:00:00:00:00:00:01:00:00:00:00:00代表广播地址;00:00:00:00:00:00/01:00:00:00:00:00代表单播地址
dl_type=ethertype 匹配以太网协议类型,其中:dl_type=0x0800代表IPv4;dl_type=0x086dd代表IPv6;dl_type=0x0806代表ARP
nw_src=ip[/netmask] nw_dst=ip[/netmask] 当dl_type=0x0800时,匹配源或者目标的IPv4地址,可以使用IP地址或者域名
nw_proto=proto 和dl_type字段协同使用。 当dl_type=0x0800时,匹配IP编号;当dl_type=0x086dd代表IPv6编号
table=number 指定要使用流表的编号,范围0~254,在不指定的情况下,默认值为0.通过使用流表编号,可以创建或者修改多个Table中的Flow
reg=value[/mask] 交换机中寄存器的值,当一个数据包进入交换机时,所有的寄存器都被清零,用户可以通过Action的指令修改寄存器中的值

实验操作
查看原有网桥:ovs-vsctl show
删除网桥:ovs-vsctl del-br br-sw

添加网桥:ovs-vsctl add-br br0
查看虚拟交换机基本信息ovs-ofctl show br0可以查看到交换机dpid、流表数量、性能参数、动作参数、MAC地址等信息。
查看虚拟交换机上各端口的状态:ovs-ofctl dump-flows br0输出的结果中包含了各端口上收到的数据包数,字节数,丢包数,错误数据包数等。
添加一条流表项,设置流表项生命周期为1000s,优先级为17,入端口为3,动作是output:2:ovs-ofctl add-flow br0 idle_timeout=1000,priority=17,in_port=3,actions=output:2
删除入端口为3的的流表项:ovs-ofctl del-flows br0 in_port=3

使用Postman下发流表

一、流表结构

所谓流表,其实可被视作是SDN对网络设备的数据转发功能的一种抽象。在传统网络设备中,交换机和路由器的数据转发需要依赖设备中保存的二层MAC地址转发表或者三层的IP地址路由表,SDN交换机中使用的流表也是如此,不过在它的表项中整合了网络中各个层次的网络配置信息,从而在进行数据转发时可以使用更丰富的规则。其流表中的每个表项结果如下所示:
| Match Fields | Priority | Counter | Instructions | Timeouts | Cookie |
OpenFlow1.3流表的每个表项由6部分组成:
1、匹配域:匹配域即OpenFlow1.0流表中的包头域,用于对交换机接收到的数据包的包头内容进行匹配。在OpenFlow1.0中,流表的包头域中包括了12个元组(Tuple),相关内容如下所示:

入端口 目的MAC地址 以太网类型
Ingress Port Ehter Des Ether Type

如上所示,匹配域中用于和交换机接收到的数据包进行匹配的元组涵盖了ISO网络模型中的第二至第四层的网络配置信息。每一个元组中的数值可以是一个确定的值或者是“ANY”以支持对任意值的匹配。另外,如果交换机能够在IP地址相关元组上支持子网掩码的话,将有助于实现更精确的匹配。
2、优先级:流表项的匹配次序。
3、计数器:计数器可以针对交换机中每条流表、每个数据流、每个设备端口、每个转发队列进行维护,用于统计数据流表的相关信息。
4、Instructions指令集:每个流表项都包含一组指令,当一个数据包匹配表项时指令会被执行。这些指令可以更改数据包,动作集或者流表处理。
5、超时:最大时间计数或流有效时间
6、cookie:由控制器选择的不透明数据值。控制器用来过滤流统计数据、流改变和流删除。但处理数据包时不能使用。

二、 匹配域解析流程

当SDN交换机接收到一个数据包时,将按照优先级从table0依次匹配其本地保存的流表中的表项,并以发生具有最高优先级的匹配表项作为匹配结果,并根据相应的动作对数据包进行操作。同时,一旦匹配成功,对应的计数器将更新;而如果没能找到匹配的表项,则将数据包转发给控制器。
OpenFlow交换机对数据包头的解析和匹配过程的细节操作如图所示:

  1. 初始化包头域,按照包头域的组成—设置每个字段,其中入端口是接收数据包的物理端口。
  2. 如果数据包类型是VLAN(0x8100),那么就使用VLAN ID和PCP字段进行表查找,解封以太网类型为先的以太网类型解析做准备。
  3. (可选)如果是ARP数据包(0x0806),那么匹配字段就可能包含IP源和目的地址。
  4. 如果是IP数据包(0x0800),那么匹配字段就会包含IP首部。如果IP数据包的分段偏移量不为0或者设置了多个分段bit位,那么将所有传输端口设为0。如果IP数据包在IP协议族中的编号为6或者17(分别是TCP/UDP类型),那么匹配字段包含传输端口。如果编号为1(ICMP数据包)则包含Type和Code字段。

三、 OpenFlow1.3流表匹配流程

OpenFlow1.3匹配流程图与之前版本相比多了一个table-miss流表项,事实上此前版本就已经存在table-miss概念,只是没有在流程图中呈现出来而已。Of1.3版本的匹配流程大致如下图所示:

首先SDN交换机解析进入设备的报文,然后从table0开始匹配,按照优先级高低依次匹配该流表中的表项,一个报文在一个流表中只会匹配上一条流表项。通常根据报文的类型,报文头的字段例如源MAC地址、目的MAC地址、源IP地址、目的IP地址等进行匹配,大部分匹配还支持掩码进行更精确、灵活的匹配。也可以通过报文的入端口或者元数据信息来进行报文的匹配,一个流表项中可以同时存在多个匹配项,一个报文需要同时普票流表项中所有匹配项才能匹配该流表项。报文匹配按照现有的报文字段进行,比如前一个流表通过apply
actions改变了该报文的某个字段,则下一个表现按照修改后的字段进行匹配。如果匹配成功。则按照指令集里的动作更新动作集,活更新报文/匹配集字段,或更新元数据和计数器。根据指令是否继续前往下一个流表,不继续则终止匹配流程执行动作集,如果指令要去继续前往下一流表则继续匹配,下一个流表的ID需要比当前流表ID大。当报文匹配失败,如果存在无匹配流表项(table-miss)就按照该表项执行指令,一般是将报文转发给控制器、丢弃或者转发给其他流表。如果没有table-miss表项则默认丢弃该报文。
实验操作
一、实验环境检查
步骤1 登录OpenDaylight控制器,使用命令netstat -anlgrep 6633查看端口是否处于监听状态
步骤2 在保证控制器6633端口处于监听状态后,使用root用户登录交换机,查看交换机与控制器连接情况。执行ovs-vsctl show。当出现交换机与控制器连接不成功时,执行ovs-vsctl del-controller br-sw $ovs-vsctl set-controller br-sw tcp:20.0.1.3:6633手动重连,稍等一会后,重新查看连接状态,controller下方显示“is_connected:true” 则表明连接成功。
步骤3 登录主机,查看主机IP地址
步骤4 在两个主机上安装iPerf打流工具。登录主机后,使用如下命令安装iPerf打流工具。sudo apt-get install iperf
步骤5 安装完成可以使用如下命令检查是否安装成功。iperf -s
二、L2层流表下发与验证
L2层即对应OSI模型的二层,也就是说通过匹配源MAC(Ether source)、目的MAC地址(Ether dst)、以太网类型(Ether Type)VLAN id、VLAN优先级等字段来实现流的转发。本实验将基于源和目的MAC进行数据流的转发。
步骤1 登录控制器,在下方的“Application Finder”中搜索“postman”,并打开自带的Postman工具。
步骤2 打开Basic Auth页签,Username字段填写admin,Password字段填写admin完成认证。
步骤3 提交方式为GET,URL地址栏中输入http://127.0.0.1:8080/restconf/operational/network-topology:network-topology ,设置完成单击Send按钮,获取交换机id信息。
步骤4 下发第一条流表。
选择提交方式“PUT”。
URL地址栏输入如下形式的地址:http://{controller-ip}:8080/restconf/config/opendaylight-inventory:nodes/node/{node-id}/table/{table-id}/flow/{flow-id}
其中,{controller-ip}为控制器的ip地址,node-id为上面获取到的交换机id信息,table-id这里为0,flow-id根据下发不同流表变化,可自定义。本实验URL地址栏输入如下地址:
http://127.0.0.1:8080/restconf/config/opendaylight-inventory:nodes/node/openflow:196695411516739/table/0/flow/107
填写Headers信息

Key Value
Content-Type application/xml
Accept application/xml
Authorization Basic YWRtaW46YWRtaW4=

PS:Authorization的值可以发一个空PUT后获取到

步骤5 单击页面右上角的“实验拓扑”按钮,查看主机与交换机的连接情况,记录主机1和主机2的MAC地址
步骤6 “body”中选择“raw”,格式为XML(application/xml),并填写如下消息体:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<flow xmlns="urn:opendaylight:flow:inventory">
<priority>200</priority>
<flow-name>Foo1</flow-name>
<idle-timeout>0</idle-timeout>
<hard-timeout>0</hard-timeout>
<match>
<ethernet-match>
<ethernet-source>
<address>fa:16:3e:b4:50:07</address>
</ethernet-source>
<ethernet-destination>
<address>fa:16:3e:5c:04:6e</address>
</ethernet-destination>
</ethernet-match>
</match>
<id>107</id>
<table_id>0</table_id>
<instructions>
<instruction>
<order>0</order>
<apply-actions>
<action>
<order>0</order>
<output-action>
<output-node-connector>2</output-node-connector>
</output-action>
</action>
</apply-actions>
</instruction>
</instructions>
</flow>

将源、目的MAC地址替换为步骤5中记录的地址;参数说明:

  • Priority:匹配流表的优先级。
  • flow-name:流表的名称。
  • idle-timeout:设定超时时间(seconds),参数为0表示永不超时。
  • hard-timeout:最大超时时间(seconds),参数为0表示永不超时。
  • match:匹配Fields。
  • instructions:修改action配置或pipeline处理。
  • ethernet-source:源MAC地址。
  • ethernet-destination:目的MAC地址。
    步骤7 单击Send按钮
    步骤8~步骤9 重复上诉操作,替换源和目的MAC地址;修改流表id和端口号下发第二条流表
    步骤10 使用root用户登录交换机,查看流表,执行命令ovs-ofctl dump-flows br-sw
    步骤11 登录主机1,ping主机2,如下图所示
    步骤12 再次查看交换机上的流表,可以看到匹配的流表为优先级200的流表,其n_bytes值随着ping而增加
    步骤13 停止主机上的ping操作。
    步骤14 删除刚刚创建的流表,URL输入:http://127.0.0.1:8080/restconf/config/opendaylight-inventory:nodes/node/openflow:196695411516739/table/0/flow/107 ,使用DELETE方法删除流表107
    步骤15 单击Send按钮。
    步骤16 重复上诉操作删除第二条流表
    ###三、L3层流表下发与验证
    L3层对应OSI模型的三层,三层流表主要匹配的是IP包的协议类型和IP地址。

场景一 匹配源IP

步骤1 下发第一条流表。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<flow xmlns="urn:opendaylight:flow:inventory">
<priority>200</priority>
<flow-name>Foo1</flow-name>
<idle-timeout>0</idle-timeout>
<hard-timeout>0</hard-timeout>
<match>
<ethernet-match>
<ethernet-type>
<type>2048</type>
</ethernet-type>
</ethernet-match>
<ipv4-source>30.0.2.5/32</ipv4-source>
</match>
<id>111</id>
<table_id>0</table_id>
<instructions>
<instruction>
<order>0</order>
<apply-actions>
<action>
<order>0</order>
<output-action>
<output-node-connector>2</output-node-connector>
</output-action>
</action>
</apply-actions>
</instruction>
</instructions>
</flow>

步骤3 同样的方式下发第二条流表,将主机2IP段的报文转发到1端口
步骤4 下发第三条流表

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<flow xmlns="urn:opendaylight:flow:inventory">
<priority>200</priority>
<flow-name>Foo1</flow-name>
<idle-timeout>0</idle-timeout>
<hard-timeout>0</hard-timeout>
<match>
<ethernet-match>
<ethernet-type>
<type>2054</type>
</ethernet-type>
</ethernet-match>
</match>
<id>113</id>
<table_id>0</table_id>
<instructions>
<instruction>
<order>0</order>
<apply-actions>
<action>
<order>0</order>
<output-action>
<output-node-connector>NORMAL</output-node-connector>
<max-length>0</max-length>
</output-action>
</action>
</apply-actions>
</instruction>
</instructions>
</flow>

最后重复上述操作进行验证并删除流表。
场景二 匹配nw_proto字段

步骤1 下发第一条流表。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<flow xmlns="urn:opendaylight:flow:inventory">
<priority>200</priority>
<flow-name>Foo1</flow-name>
<idle-timeout>0</idle-timeout>
<hard-timeout>0</hard-timeout>
<match>
<ethernet-match>
<ethernet-type>
<type>2048</type>
</ethernet-type>
</ethernet-match>
<ipv4-destination>30.0.2.13/32</ipv4-destination>
<ip-match>
<ip-protocol>1</ip-protocol>
</ip-match>
</match>
<id>114</id>
<table_id>0</table_id>
<instructions>
<instruction>
<order>0</order>
<apply-actions>
<action>
<order>0</order>
<output-action>
<output-node-connector>2</output-node-connector>
</output-action>
</action>
</apply-actions>
</instruction>
</instructions>
</flow>

步骤2 下发第二条流表,修改上述信息,目的IP地址修改为主机1,转发1端口
步骤3 下发第三条流表。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<flow xmlns="urn:opendaylight:flow:inventory">
<priority>200</priority>
<flow-name>Foo1</flow-name>
<idle-timeout>0</idle-timeout>
<hard-timeout>0</hard-timeout>
<match>
<ethernet-match>
<ethernet-type>
<type>2054</type>
</ethernet-type>
</ethernet-match>
</match>
<id>116</id>
<table_id>0</table_id>
<instructions>
<instruction>
<order>0</order>
<apply-actions>
<action>
<order>0</order>
<output-action>
<output-node-connector>NORMAL</output-node-connector>
<max-length>0</max-length>
</output-action>
</action>
</apply-actions>
</instruction>
</instructions>
</flow>

步骤4 使用ping进行测试并删除流表

四、L4层流表下发与验证

L4对应的OSI模型中的四层,即流表对应的TCP/UDP源端口(TCP/UDP src port)、TCP/UDP目的端口号(TCP/UDP dst port)字段。本实验匹配TCP目的端口。
步骤1 下发第一条流表。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<flow xmlns="urn:opendaylight:flow:inventory">
<priority>200</priority>
<flow-name>Foo1</flow-name>
<idle-timeout>0</idle-timeout>
<hard-timeout>0</hard-timeout>
<match>
<tcp-destination-port>5001</tcp-destination-port>
<ethernet-match>
<ethernet-type>
<type>2048</type>
</ethernet-type>
</ethernet-match>
<ipv4-destination>30.0.2.13/32</ipv4-destination>
<ip-match>
<ip-protocol>6</ip-protocol>
</ip-match>
</match>
<id>117</id>
<table_id>0</table_id>
<instructions>
<instruction>
<order>0</order>
<apply-actions>
<action>
<order>0</order>
<output-action>
<output-node-connector>2</output-node-connector>
</output-action>
</action>
</apply-actions>
</instruction>
</instructions>
</flow>

步骤2 下发第二条流表,修改上述信息,目的IP地址修改为主机1,转发1端口
步骤3 下发第三条流表。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<flow xmlns="urn:opendaylight:flow:inventory">
<priority>200</priority>
<flow-name>Foo1</flow-name>
<idle-timeout>0</idle-timeout>
<hard-timeout>0</hard-timeout>
<match>
<ethernet-match>
<ethernet-type>
<type>2054</type>
</ethernet-type>
</ethernet-match>
</match>
<id>119</id>
<table_id>0</table_id>
<instructions>
<instruction>
<order>0</order>
<apply-actions>
<action>
<order>0</order>
<output-action>
<output-node-connector>FLOOD</output-node-connector>
<max-length>0</max-length>
</output-action>
</action>
</apply-actions>
</instruction>
</instructions>
</flow>

Open vSwitch网桥管理

在网络中,交换机和桥概念类似,Open vSwitch是一个虚拟交换软件,也就是说,Open vSwitch实现了网桥的功能。学习Open vSwitch的第一步要弄清楚网桥的概念。网桥是连接两个局域网的设备,工作在数据链路层,根据MAC地址来转发帧。在Open vSwitch中创建一个网桥后,此时网络功能不受影响,但是会产生一个虚拟网卡,之所以会产生一个虚拟网卡,是为了实现接下来的网桥(交换机)功能。有了这个网桥以后,还需要为这个网桥增加端口(port),一个端口就是一个物理网卡,当网卡加入到这个网桥之后,其工作方式就和普通交换机的一个端口的工作方式类似了。以下是一个网桥的具体信息:

在网络中,交换机和桥概念类似,Open vSwitch是一个虚拟交换软件,也就是说,Open vSwitch实现了网桥的功能。学习Open vSwitch的第一步要弄清楚网桥的概念。网桥是连接两个局域网的设备,工作在数据链路层,根据MAC地址来转发帧。在Open vSwitch中创建一个网桥后,此时网络功能不受影响,但是会产生一个虚拟网卡,之所以会产生一个虚拟网卡,是为了实现接下来的网桥(交换机)功能。有了这个网桥以后,还需要为这个网桥增加端口(port),一个端口就是一个物理网卡,当网卡加入到这个网桥之后,其工作方式就和普通交换机的一个端口的工作方式类似了。以下是一个网桥的具体信息:

上述信息显示了一个名为br0的桥(交换机),这个交换机有两个接口,一个是eth0,一个是br0。
上面说到,创建桥的时候会创建一个和桥名字一样的接口,并自动作为该桥的一个端口,那么这个虚拟接口的作用,一方面是可以作为交换机的管理端口,另一方面也是基于这个虚拟接口实现了桥的功能。Open vSwitch的内核模块实现了多个“数据路径”,每个都可以有多个vports。每个数据路径也通过关联流表(flow table)来设置操作,而这些流表中的流都是用户空间在报文头和元数据的基础上映射的关键信息,一般的操作都是将数据包转发到另一个vport。当一个数据包到达一个vport,内核模块所做的处理是提取其流的关键信息并在流表中查找这些关键信息,当有一个匹配的流时它执行对应的操作,如果没有匹配,它会将数据包送到用户空间的处理队列中,作为处理的一部分,用户空间可能会设置一个流用于以后碰到相同类型的数据包可以在内核中执行操作。
ovs-vsctl关于网桥管理的常用命令如下:

命令 含义
init 初始化数据库(前提数据分组为空)
show 打印数据库信息摘要
add-br BRIDGE 添加新的网桥
del-br BRIDGE 删除网桥
list-br 打印网桥摘要信息
list-ports BRIDGE 打印网桥中所有port摘要信息
add-port BRIDGE PORT 向网桥中添加端口
del-port [BRIDGE] PORT 删除网桥上的端口
get-controller BRIDGE 获取网桥的控制器信息
del-controller BRIDGE 删除网桥的控制器信息
set-controller BRIDGE TARGET 向网桥添加控制器

实验操作

一、实验环境检查

步骤1 登录交换机,执行ovs-vsctl show命令,查看镜像中原有的网桥
步骤2 执行以下命令删除当前网桥,并进行确认

ovs-vsctl del-br br-sw
ovs-vsctl show

二、添加网桥和端口

步骤1 执行以下命令添加名为br0的网桥ovs-vsctl add-br br0
步骤2 执行以下命令,列出Open vSwitch中所有网桥ovs-vsctl list-br
步骤3 执行以下命令,将物理网卡挂接到网桥br0上ovs-vsctl add-port br0 eth0说明:port和bridge是多对一的关系,也就是说一个网桥上可以挂接多个物理网卡。
步骤4 执行以下命令,列出挂接到网桥br0上的所有网卡ovs-vsctl list-ports br0
步骤5 执行以下命令,列出挂接到eth0网卡上的所有网桥ovs-vsctl port-to-br eth0
步骤6 执行以下命令,查看Open vSwitch的网络状态ovs-vsctl show

删除网桥和端口

步骤1 执行以下命令,删除挂接到网桥br0上的网卡eth0ovs-vsctl del-port br0 eth0
步骤2 执行以下命令,查看open vswitch的网络状态ovs-vsctl show
可以发现,删除eth0后网桥br0依旧存在
步骤3 执行如下命令,删除网桥br0,并进行确认ovs-vsctl del-br br0说明:如果不删除eth0直接删除br0,br0及挂接到br0上的端口会被一并删除。

OpenFlow建立连接交互流程学习

一、OpenFlow协议简介

2006年,斯坦福大学Clean Slate计划资助的Ethane项目开始部署,致力于企业网架构的创新,OpenFlow协议的雏形就诞生于这个项目。2008年,Nick McKeown教授的一篇重要论文“OpenFlow:Enabling Innovation in Campus Networks”使得OpenFlow正式进入人们的视野,继而成为了标准化组织ONF(Open Network Foundation,开放网络基金会)主推的南向接口协议。经过多年的发展,OpenFlow现已成为SDN的主流南向接口协议之一。目前,OpenFlow协议还在不断地演进中,本实验采用OpenFlow v1.3协议,并对控制器与OpenFlow交换机之间的交互过程进行深入分析。
OpenFlow主要有3种类型的消息,分别是Controller-to-Switch、Asynchronous和Symmetric,其中每个类型又包含多个子类型。Controller-to-Switch消息由控制器发起,用于管理、查看交换机的状态。Asynchronous消息由交换机发起,向控制器汇报交换机的事件和改变。Symmetric消息由控制器或交换机任一方发起,无需请求直接发起消息。详细信息如下表所示:

消息类型 消息例子 描述
Controller-to-Switch Packet_out Barrier Switch Configuration Switch Features Multipart 控制器使用这些消息可以添加、修改或删除流表项 查询交换机的功能和统计 配置交换机 配置交换机端口属性 将数据包发送出指定交换机端口
Asynchronous(异步) Error Packet_in Port Status Table Status Controller Role Status 由交换机发起,发送消息给控制器 这些消息可以是没有匹配交换机中任意流表项的数据包或数据包头 因此需要发送给控制器进行处理 在流状态、端口状态改变,或者产生错误消息时,进行通知
Symmetric(对称) Hello Echo Experimenter Hello消息在控制器与交换机建立连接过程中使用 Echo消息用来确定Controller-to-Switch连接的延时,验证连接是否处于活跃状态 Experimenter消息用于未来消息的扩展

二、OpenFlow连接建立交互流程


在OpenFlow1.3协议的情况下,控制器与OpenFlow交换机的消息完整交互流程如下:
1、 控制器与OpenFlow交换机通过TCP“三次握手”,建立有效的连接。其中,控制器一端的端口号为6633。
2、 控制器与OpenFlow交换机之间相互发送Hello消息,用于协商双方的OpenFlow版本号。在双方支持的最高版本号不一致的情况下,协商的结果将以较低的OpenFlow版本为准。如果双方协商不一致,还会产生Error消息。
3、 控制器向OpenFlow交换机发送Features Request消息,请求OpenFlow交换机上传自己的详细参数。OpenFlow交换机收到请求后,向控制器发送Features Reply消息,详细汇报自身参数,包括支持的buffer数目、流表数以及Actions等。
4、 控制器通过Set Config消息下发配置参数,然后通过Get config Request消息请求OpenFlow交换机上传修改后的配置信息。OpenFlow交换机通过Get config Reply消息向控制器发送当前的配置信息。
5、 控制器与OpenFlow交换机之间发送Packet_out、Packet_in消息,通过Packet_out中内置的LLDP包,进行网络拓扑的探测。
6、 控制器与OpenFlow交换机之间通过发送Multipart Request、Mutipart Reply消息,控制器能获取OpenFlow交换机的状态信息,包括流的信息、端口信息等。
7、 控制器与OpenFlow交换机之间通过发送Echo Request、Echo Reply消息,保证二者之间存在有效连接,避免失联。
说明:以上为控制器与OpenFlow交换机之间的标准交互流程,在具体实验过程中某些阶段可能会缺失。
实验操作
一、实验环境检查
步骤1 登录控制器,查看控制器所在主机的IP地址
步骤2 登录主机1,查看Mininet所在主机的IP地址
二、捕获数据包
步骤1 登录Floodlight控制器,启动抓包工具Wireshark,捕获控制器与交换机建立连接过程中的数据包,通过分析这些数据包了解控制器与交换机基于OpenFlow协议进行交互的流程。执行以下命令:sudo wireshark
步骤2 双击eth0网卡,查看eth0网卡上数据包收发情况
步骤3 登录Mininet虚拟机,启动Mininet。通过“–controller”参数设置Mininet连接远程控制器,并指定控制器的IP和端口号sudo mn --controller=remote,ip=30.0.1.3,port=6633 --switch=ovsk,protocols=OpenFlow13
步骤4 登录Floodlight控制器,停止Wireshark,观察数据包列表,可以看出控制器与交换机的基本交互流程。
三、OpenFlow1.3交互流程分析
步骤1 交换机连接控制器的6633端口,经过3次握手后双方建立TCP连接。查看捕获到的数据包,分析交换机与控制器建立TCP连接的流程。分析TCP连接建立过程,需要先了解TCP的状态位,主要包括SYN、FIN、ACK、PSH、RST和URG。SYN表示建立连接,FIN表示关闭连接,ACK表示响应,PSH表示有DATA数据传输,RST表示连接重置。可以看出交换机与控制器经历一次连接重置后,成功完成三次握手,建立TCP连接
步骤2 当控制器与交换机建立TCP连接后,由其中某一方发起Hello消息,双方协调协OpenFlow议版本号。控制器和交换机都会向对方发送一条Hello消息,消息中附上自己支持的OpenFlow的最高版本。接收到对方Hello消息后,判断自己能否支持对方发送的版本,能支持则版本协商成功,不能支持则回复一条OFPT_ERROR消息。查看Hello消息详情,本实验中由于交换机和控制器都能支持OpenFlow1.3版本,所以版本协商为1.3。
步骤3 OpenFlow版本协商完成后,控制器发送一条features_request消息获取交换机的特性信息,包括交换机的ID(DPID)、缓冲区数量、端口及端口属性等等。相应的,交换机回复features_reply消息,如下图所示。
ofpt_feature_reply数据包详情如下,交换机的DPID是数据通道独一无二的标识符,低48位是一个MAC地址,高16位是自定义的。本实验中交换机缓冲区数量(n_buffers)为256,交换机支持的流表数量(n_tables)为254,交换机所支持的功能。
步骤4 OpenFlow1.0协议中feature_reply消息还包含交换机端口信息,OpenFlow 1.3协议将‘stats’框架更名为‘multipart’框架,并且将端口描述移植到multipart消息中。其中OPPT_PORT_DESC类型的multipart消息就是用于获取交换机端口信息的。
查看OPPT_PORT_DESC类型multipart_reply消息,消息中列出了交换机的端口以及每个端口的详细信息,包括端口名称和mac地址等
步骤5 OFPMP_DESC类型的multipart_reply消息包含了交换机的其他信息,包括交换机厂商名称、交换机名称以及交换机版本等。本实验中使用的是Mininet仿真软件中自带的开源交换机Open vSwitch(2.0.2),而Open vSwitch是由Nicira Networks主导开发的
步骤6 在连接过程中,控制器不断的发送echo_request消息给交换机,确认交换机与控制器之间的连接状态。相应的,交换机会回复echo_reply消息

基于RESTCONF的流表管理

所谓流表,其实可被视作是SDN对网络设备的数据转发功能的一种抽象。在传统网络设备中,交换机和路由器的数据转发需要依赖设备中保存的二层MAC地址转发表或者三层的IP地址路由表,SDN交换机中使用的流表也是如此,不过在它的表项中整合了网络中各个层次的网络配置信息,从而在进行数据转发时可以使用更丰富的规则。
在使用RESTCONF下发流表时,需要学习的是请求消息的BODY的结构。实例如下:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<flow xmlns="urn:opendaylight:flow:inventory">
   <flow-name>add-flow</flow-name>
    <table_id>0</table_id>
   <id>100</id>
    <strict>false</strict>
  <priority>1</priority>
    <instructions>
        <instruction>
            <order>0</order>
            <apply-actions>
                <action>
                    <order>0</order>
                    <output-action>
<output-node-connector>FLOOD</output-node-connector>
                    </output-action>
                </action>
            </apply-actions>
        </instruction>
    </instructions>
    <match>
    </match>
</flow>

BODY中定义了流表名称(flowname)、flow所在的table(table_id)、flow的id(id)、是否严格匹配(strict)、优先级和匹配字段(match fields)、优先级(priority)、指令(instructions)、超时(timeouts)、cookie等值。

实验操作
一、实验环境检查
步骤1 登录交换机查看网络连通性。由于OpenDaylight组件过于庞大,所以启动比较慢,容易导致控制器与交换机连接不成功的现象,间接导致主机无法获取IP。所以使用OpenDaylight控制器时,需要先检查网络连通性,查看交换机与控制器连接情况。执行以下命令:ovs-vsctl showis_connected: true可知当前控制器与交换机已经连接成功
步骤2 登录控制器,查看控制器IP
步骤3 登录交换机,执行ovs-vsctl set-manager tcp:20.0.1.3:6640命令连接控制器
(原本控制器与交换机之间的连接是通过OpenFlow协议的,在此基于OVSDB协议创建一个新的连接,其中20.0.1.3是控制器IP地址,6640是OVSDB协议对应的侦听端口。)
二、删除ODL自动下发的流表
在实验过程中需要验证两个不能通信的主机,通过REST北向接口下发流表,使得两个主机能够通信,所以需要删除原先的默认通信流表。

步骤1 登录交换机,执行ovs-ofctl del-flows -O OpenFlow13 br-sw删除流表。
步骤2 执行ovs-ofctl dump-flows -O OpenFlow13 br-sw查看是否删除成功
步骤3 登录其中的一个主机,查看主机间网络网络连通情况,此时主机间无法进行通信
三、下发通信流表
步骤1 登录控制器,打开浏览器,输入URL: http://[controller_ip]:8181/index.html ,输入有户名:admin,密码:admin
单击登录。登录后,单击Nodes菜单,获取交换机node id
步骤2 单击Applications MenuDevelopmentPostman打开postman应用
步骤3 输入URL http://[controller-ip]:8181/restconf/config/opendaylight-inventory:nodes/node/[node-id]/table/0/flow/100
[controller-ip]为当前控制器的数据层的ip,[node-id]即步骤1中获得的node id请求类型选择PUT。问一个页面需要输入用户名和密码,同样,用Postman发送请求也需要一定的权限。单击Authorization,type选择basic auth。输入用户名和密码,用户名和密码都是admin。选择BODY的类型raw ->XML(application/xml)
步骤4 输入Body内容如下:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<flow xmlns="urn:opendaylight:flow:inventory">
    <flow-name>add-flow</flow-name>
    <table_id>0</table_id>
    <id>100</id>
    <installHw>false</installHw>
    <strict>false</strict>
  <priority>1</priority>
    <instructions>
        <instruction>
            <order>0</order>
            <apply-actions>
                <action>
                    <order>0</order>
                    <output-action>
<output-node-connector>FLOOD</output-node-connector>
                    </output-action>
                </action>
            </apply-actions>
        </instruction>
    </instructions>
    <match>
    </match>
</flow>

步骤5 点击Send按钮
步骤6 输入URL http://[controller-ip]:8181/restconf/config/opendaylight-inventory:nodes/node/[node-id]/table/0/
[controller-ip]为当前控制器的数据层的ip,[node-id]即【四、下发通信流表】步骤1获得的node id请求类型选择GET。问一个页面需要输入用户名和密码,同样,用Postman发送请求也需要一定的权限。单击Authorization,type选择basic auth。输入用户名和密码,用户名和密码都是admin
步骤7 点击Send按钮
步骤8 登录其中的一个主机,查看主机间网络网络情况,此时主机间能够进行通行
四、使用Postman删除流表
步骤1 输入URL http://[controller-ip]:8181/restconf/config/opendaylight-inventory:nodes/node/[node-id]/table/0/flow/[flow-id]
[controller-ip]为当前控制器的数据层的ip,[node-id]即【四、下发通信流表】步骤1获得的node id,[flow-id]为之前下发流表的id,可以到【四、下发通信流表】的BODY中查看。请求类型选择DELETE.访问一个页面需要输入用户名和密码,同样,用Postman发送请求也需要一定的权限。单击Authorization,type选择basic auth。输入用户名和密码,用户名和密码都是admin。点击Send
步骤2登录交换机,切换至root用户。执行命令ovs-ofctl dump-flows -O OpenFlow13 br-sw,可验证流表已删除

作者 Assaultcore

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注