实验教程
任务内容
1、 熟悉Flow-Mod消息触发场景。
2、 掌握Flow-Mod消息格式和常用字段含义。
任务环境
设备名称 | 软件环境(镜像) | 硬件环境 |
---|---|---|
控制器 | RYU4.7.0桌面版 | CPU:2核 内存:4G 磁盘:20G |
主机 | Mininet2.2.0桌面版 | CPU:1核 内存:2G 磁盘:20G |
注:
root用户的用户名/密码为root
/root@openlab
;
openlab用户的用户名/密码为openlab
/user@openlab
。
任务内容
1、 熟悉Flow-Mod消息触发场景。
2、 掌握Flow-Mod消息格式和常用字段含义。
实验原理
OpenFlow 协议支持3种消息类型:Controller-to-Switch
(控制器—交换机)、Asynchronous
(异步)和Symmetric
(对称),每一类消息又有多个子消息类型。
1、 Controller-Switch
(控制器—交换机)消息,这类消息由控制器发起。包括Features、Configuration、Modify-State、Read-State、Send-Packet、Barrier等几类消息,用于对OF交换机的管理。
2、 Asynchronous
(异步)消息,这类消息用来将网络事件或交换机状态的变化更新到控制器。主要包括4种子类型:Packet-in、Flow-Removed、Port-status和Error消息。
3、 Symmetric
(同步)消息与前两类消息有所不同,Symmetric类的消息可由控制器或者OF交换机中的任意一侧发起,这类消息包括以下3种类型:Hello、Echo和Vendor。
Modify-State消息是OpenFlow消息中最为重要的消息类型,控制器通过Port-mod消息用来管理端口状态,通过Flow-mod消息增删交换机的流表项,考虑到流表在OpenFlow的重要意义,在此针对Flow-mod消息进行详尽分析。
图1是Flow-mod消息的具体格式,其主要字段含义介绍如下:
- 前4个字段,表示OpenFlow消息的通用报头。
wildcard
字段,表示匹配时12元组的掩码位,被掩盖掉的元组不参加匹配。- 从
in_port
到tp_dst
字段,表示流表项12元组的信息。 cookie
字段,在处理数据分组时不会用到,控制器通过该字段来过滤流的统计信息。command
字段,表示对流表的操作,包括增加(Add)、删除(Delete)、修改(Modify)等。idle_time
字段,表示当这条流表项在这段时间内没有匹配到数据分组,则该流表项失效。hard_time
字段,表示自流表项下发后只要过了这段时间即刻失效。priority
字段,表示该流表项被处理的优先级,原则上优先级越高,所属的Table号就越小。buffer_id
字段,表示对应Packet-in消息的buffer_id。out_port
字段,仅在command为Delete或者Delete Strict时有效,表明当某表项不仅匹配了Flow-mod中给出的12元组,且转发动作中指定端口等于该out_port的动作时才予以删除,即对删除操作的一种额外限制。flags
字段,该字段为标志位,OpenFlow v1.0中包括3项:OFPFF_SEND_FLOW_REM(流表失效时是否向控制器发送Flow-removed消息),OFPFF_CHECK_OVERLAP(交换机是否检测流表冲突),OFPFF_EMERG(该流表项将被存于Emergency Flow Cache中,仅在交换机处于紧急模式时生效)。actions
字段,该字段是个数组,表示要对满足过滤条件的流做的动作列表,actions[0]即代表其中第一个动作。
图 1 Flow-mod消息格式
实验步骤
一、创建实验
步骤1 登录OpenLab实验平台,选择“实验课程 > SDN > OpenFlow Flow-Mod消息学习”。
说明:当前有正在进行的实验课程时,请单击“结束”,结束课程。
步骤2 创建实验,目前支持两种创建实验的模式,具体如下:
- 实验模式为“上课模式”时:单击实验名称出现一提示框,单击“进入详情”进入实验详情页面,后台自动创建实验,单击“进入实验“即可。
- 实验模式为“浏览模式”时,单击实验名称进入实验详情页面,单击“开始实验”,创建实验。
步骤3 课程实验创建完成后,进入对应的操作界面。
步骤4 选择控制器1,打开命令行终端,登录RYU控制器。执行ifconfig命令,查看控制器IP,如下图所示。
步骤5 执行cd openlab/ryu/ryu/app命令,进入RYU主程序所在的文件位置。
执行如下命令,启动RYU控制器。
$sudo ryu-manager --verbose simple_switch_13.py ofctl_rest.py rest_topology.py
步骤6 选择主机1,打开命令行终端,登录Mininet所在主机,执行ifconfig命令,查看Mininet所在主机的IP,如下图所示。
二、Flow-Mod消息解析
场景一 控制器自动下发流表
步骤1 登录RYU控制器,启动抓包工具Wireshark,捕获控制器与交换机建立连接后,控制器自动发送给交换机的flow_mod消息。执行以下命令:
$ 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 登录RYU控制器,停止Wireshark,观察数据包列表。
可以看到控制器会发出flow_mod
消息,该消息的Commend
为ADD,表示添加流表项。整个消息可以分为三部分:openflow主体部分、match部分、instruction部分,其中instruction部分可以省略。match部分是匹配条件,instruction部分是指令,当一个数据包满足匹配条件就会执行instruction中的指令。控制器发送的add消息中action为output,而output的端口是controller,也就是说让交换机将符合匹配要求的数据包都转发给控制器,如下图所示。
场景二 手动下发流表
步骤1 选择控制器1,打开命令行终端,登录RYU控制器,执行sudo wireshark命令,启动Wireshark。
步骤2 在控制器中再打开一个Terminal,输入以下命令获取交换机DPID,如下图所示。
$ curl http://localhost:8080/stats/switches
可以看到获取到的交换机DPID为1。
步骤3 添加流表项,执行以下命令,具体命令如下所示。
$ curl -X POST -d '{"dpid": 1, "cookie": 1, "cookie_mask": 1,"table_id": 1,"idle_timeout": 300,"hard_timeout": 300,"priority": 35,"flags": 1,"match":{"in_port":1},"actions":[{"type":"OUTPUT","port": 2}]}' http://localhost:8080/stats/flowentry/add
dpid的值就是上面获取到交换机的DPID
,priority
是流表项的优先级,默认值是32767
,最大值也是32767。本例中,可以理解为“将交换机port1端口接收到的数据包都从port2转发出去”。
步骤4 查看flow_mod消息,从priority可以看出这个第二条流表项,Commond为ADD。匹配条件是in_port为1,对应的动作是output到端口2,如下图所示。
步骤5 执行以下命令,修改流表项1的优先级和action。
$ curl -X POST -d '{"dpid": 1, "cookie": 1, "cookie_mask": 1, "table_id": 1, "idle_timeout": 300, "hard_timeout": 300, "priority": 30, "flags": 1, "match":{"in_port":1},"actions":[]}' http://localhost:8080/stats/flowentry/modify_strict
步骤6 查看对应的flow_mod消息,Commond是MODIFY_STRICT,MODIFY_STRICT类型息用来修改某一条指定的流表项。从消息可以看出被修改的流表项的priority是30,匹配条件是in_port为1,如下图所示。
步骤7 执行以下命令,删除流表项1。
$ curl -X POST -d '{"dpid": 1, "cookie": 1, "cookie_mask": 1, "table_id": 1, "idle_timeout": 300, "hard_timeout": 300, "priority": 30, "flags": 1, "match":{"in_port":1},"actions":[]}' http://localhost:8080/stats/flowentry/delete_strict