1.作业要求:
-
实验拓扑
1.实验拓扑见2019 SDN上机第2次作业;
2.要求:使用Python脚本完成拓扑搭建,并连接ryu控制器;
-
使用Ryu的REST API下发流表实现和第2次实验同样的VLAN
1.参考资料:REST API:可以在线学习中国大学MOOC 《软件定义网络》第六讲 北向接口
Ryu控制器的API文档:ryu.app.ofctl_rest
Ryu的拓扑展示
助教博客:基于RYU restful api实现的VLAN网络虚拟化2.要求:完成自动化脚本编写,一键下发流表;
-
对比两种方法,写出你的实验体会
-
作业博客链接:https://edu.cnblogs.com/campus/fzu/fzusdn2019/homework/10134
2.具体操作步骤与截图说明:
实验环境:VMware Workstation Pro14.1、ubuntu-16.04
(1)实验拓扑:
-
给定的实验拓扑图如下所示:
-
编写Python脚本x.py,完成拓扑搭建,实验代码如下所示:
from mininet.topo import Topo
class Topo2( Topo ):
def __init__( self ):
# Initialize topology
Topo.__init__( self )
# add switches
s1 = self.addSwitch('s1')
s2 = self.addSwitch('s2')
# add hosts
h1 = self.addHost('h1')
h2 = self.addHost('h2')
h3 = self.addHost('h3')
h4 = self.addHost('h4')
h5 = self.addHost('h5')
h6 = self.addHost('h6')
# add links
self.addLink(h1,s1,1,1)
self.addLink(h2,s1,1,2)
self.addLink(h3,s1,1,3)
self.addLink(s1,s2,4,4)
self.addLink(h4,s2,1,1)
self.addLink(h5,s2,1,2)
self.addLink(h6,s2,1,3)
topos = { 'mytopo': ( lambda: Topo2() ) }
- 输入如下命令运行Python脚本x.py,其结果如下所示:
sudo mn --custom ./x.py --topo mytopo --controller=remote,ip=127.0.0.1,port=6653 --switch ovsk,protocols=OpenFlow13
-
使用net查看端口连接情况并测试主机之间的连通性:
-
进入ryu/ryu/app文件,打开终端运行如下命令,连接ryu控制器:
ryu-manager ofctl_rest.py
(2)使用Ryu的REST API下发流表实现和第2次实验同样的VLAN:
- 根据端口连接情况,编写脚本x.sh,脚本内容如下所示:
#交换机s1的脚本:
#交换机s1接收从1号端口发送来的数据包,从4号端口将其转发给s2
curl -X POST -d '{
"dpid": 1, #dpid代表交换机的编号,“1”代表交换机s1
"priority":1,
"match":{
"in_port":1
},
"actions":[
{
"type": "PUSH_VLAN", # 给进入交换机的包打上vlan_tag
"ethertype": 33024 # 帧类型0x8100(=33024): 表示IEEE 802.1Q的VLAN数据帧
},
{
"type": "SET_FIELD",
"field": "vlan_vid", # 设置VLAN ID
"value": 4096 # 设置vlan_id的值
},
{
"type": "OUTPUT",
"port": 4
}
]
}' http://127.0.0.1:8080/stats/flowentry/add
#交换机s1接收从2号端口发送来的数据包,从4号端口将其转发给s2
curl -X POST -d '{
"dpid": 1,
"priority":1,
"match":{
"in_port":2
},
"actions":[
{
"type": "PUSH_VLAN", # 给进入交换机的包打上vlan_tag
"ethertype": 33024 # 帧类型0x8100(=33024): 表示IEEE 802.1Q的VLAN数据帧
},
{
"type": "SET_FIELD",
"field": "vlan_vid", # 设置VLAN ID
"value": 4097 # 设置vlan_id的值
},
{
"type": "OUTPUT",
"port": 4
}
]
}' http://127.0.0.1:8080/stats/flowentry/add
#交换机s1接收从3号端口发送来的数据包,从4号端口将其转发给s2
curl -X POST -d '{
"dpid": 1,
"priority":1,
"match":{
"in_port":3
},
"actions":[
{
"type": "PUSH_VLAN", # 给进入交换机的包打上vlan_tag
"ethertype": 33024 # 帧类型0x8100(=33024): 表示IEEE 802.1Q的VLAN数据帧
},
{
"type": "SET_FIELD",
"field": "vlan_vid", # 设置VLAN ID
"value": 4098 # 设置vlan_id的值
},
{
"type": "OUTPUT",
"port": 4
}
]
}' http://127.0.0.1:8080/stats/flowentry/add
#交换机s1将收到的数据包根据其对应的vlan_tag从端口1转发
curl -X POST -d '{
"dpid": 1,
"priority":1,
"match":{
"dl_vlan": "0"
},
"actions":[
{
"type": "POP_VLAN", # 给进入交换机的包去除 vlan_tag
},
{
"type": "OUTPUT",
"port": 1
}
]
}' http://localhost:8080/stats/flowentry/add
#交换机s1将收到的数据包根据其对应的vlan_tag从端口2转发
curl -X POST -d '{
"dpid": 1,
"priority":1,
"match":{
"dl_vlan": "1"
},
"actions":[
{
"type": "POP_VLAN", # 给进入交换机的包去除 vlan_tag
},
{
"type": "OUTPUT",
"port": 2
}
]
}' http://localhost:8080/stats/flowentry/add
#交换机s1将收到的数据包根据其对应的vlan_tag从端口3转发
curl -X POST -d '{
"dpid": 1,
"priority":1,
"match":{
"dl_vlan": "2"
},
"actions":[
{
"type": "POP_VLAN", # 给进入交换机的包去除 vlan_tag
},
{
"type": "OUTPUT",
"port": 3
}
]
}' http://localhost:8080/stats/flowentry/add
#交换机s2的脚本:
#交换机s2接收从1号端口发送来的数据包,从4号端口将其转发给s1
curl -X POST -d '{
"dpid": 2, #dpid代表交换机的编号,“2”代表交换机s2
"priority":1,
"match":{
"in_port":1
},
"actions":[
{
"type": "PUSH_VLAN", # 给进入交换机的包打上vlan_tag
"ethertype": 33024 # 帧类型0x8100(=33024): 表示IEEE 802.1Q的VLAN数据帧
},
{
"type": "SET_FIELD",
"field": "vlan_vid", # 设置VLAN ID
"value": 4096 # 设置vlan_id的值
},
{
"type": "OUTPUT",
"port": 4
}
]
}' http://127.0.0.1:8080/stats/flowentry/add
#交换机s2接收从2号端口发送来的数据包,从4号端口将其转发给s1
curl -X POST -d '{
"dpid": 2,
"priority":1,
"match":{
"in_port":2
},
"actions":[
{
"type": "PUSH_VLAN", # 给进入交换机的包打上vlan_tag
"ethertype": 33024 # 帧类型0x8100(=33024): 表示IEEE 802.1Q的VLAN数据帧
},
{
"type": "SET_FIELD",
"field": "vlan_vid", # 设置VLAN ID
"value": 4097 # 设置vlan_id的值
},
{
"type": "OUTPUT",
"port": 4
}
]
}' http://127.0.0.1:8080/stats/flowentry/add
#交换机s2接收从3号端口发送来的数据包,从4号端口将其转发给s1
curl -X POST -d '{
"dpid": 2,
"priority":1,
"match":{
"in_port":3
},
"actions":[
{
"type": "PUSH_VLAN", # 给进入交换机的包打上vlan_tag
"ethertype": 33024 # 帧类型0x8100(=33024): 表示IEEE 802.1Q的VLAN数据帧
},
{
"type": "SET_FIELD",
"field": "vlan_vid", # 设置VLAN ID
"value": 4098 # 设置vlan_id的值
},
{
"type": "OUTPUT",
"port": 4
}
]
}' http://127.0.0.1:8080/stats/flowentry/add
#交换机s2将收到的数据包根据其对应的vlan_tag从端口1转发
curl -X POST -d '{
"dpid": 2,
"priority":1,
"match":{
"dl_vlan": "0"
},
"actions":[
{
"type": "POP_VLAN", # 给进入交换机的包去除 vlan_tag
},
{
"type": "OUTPUT",
"port": 1
}
]
}' http://localhost:8080/stats/flowentry/add
##交换机s2将收到的数据包根据其对应的vlan_tag从端口2转发
curl -X POST -d '{
"dpid": 2,
"priority":1,
"match":{
"dl_vlan": "1"
},
"actions":[
{
"type": "POP_VLAN", # 给进入交换机的包去除 vlan_tag
},
{
"type": "OUTPUT",
"port": 2
}
]
}' http://localhost:8080/stats/flowentry/add
#交换机s2将收到的数据包根据其对应的vlan_tag从端口3转发
curl -X POST -d '{
"dpid": 2,
"priority":1,
"match":{
"dl_vlan": "2"
},
"actions":[
{
"type": "POP_VLAN", # 给进入交换机的包去除 vlan_tag
},
{
"type": "OUTPUT",
"port": 3
}
]
}' http://localhost:8080/stats/flowentry/add
- 编写好脚本之后,打开终端用下列命令运行脚本文件x.sh:
sudo bash x.sh
-
在RYU控制器端可以查看到下发的流表已经被接收:
-
在下发完所有流表后,查看s1、s2的流表如下所示:
-
再次测试主机之间的连通性:
从主机之间连通性的测试结果中可以看出,我们得到了和第2次实验同样的VLAN。
在完成实验后,可以参考Ryu控制器的API文档:ryu.app.ofctl_rest,获取搭建的拓扑中所有的交换机信息、desc统计信息、流量统计信息:
(3)对比两种方法,写出你的实验体会:
对比使用Ryu的REST API下发流表和直接在Open vSwitch下发流表这两种方法,我认为使用Ryu的REST API下发流表会更简单一些,也更容易理解和实现。Ryu的REST API使用的是json格式,流表的结构更为清晰直白,也比较容易修改,同时通过执行脚本下发流表也比在Open vSwitch下发流表的过程更加简便,而使用ovs命令直接在Open vSwitch上下发流表实现VLAN是需要每台交换机分别配置的,会比较麻烦一些。通过这次实验,我更进一步懂得了ryu控制器的使用方法,同时也掌握了通过Ryu的REST API下发流表的基本原理以及方法。