多RYU控制器连接拓扑以及相关流表操作:
https://blog.csdn.net/a1164520408/article/details/95509549
流表操作相关规范(这里指的是ryu自己封装好的restAPI,不是本人的):
https://ryu.readthedocs.io/en/latest/app/ofctl_rest.html#delete-all-flow-entries
需要:
前三个脚本(基于参数的拓扑脚本,自定义控制器类脚本,用户(控制器群)类)依然使用前一篇博客所使用的脚本(注:在本次实验中的调用顺序和上次有所不同)
拓扑形式:
MASTER
___|___
_____ / | \ _____
____ / / | \ \ ______
/ / / | \ \ \
c0 c1 c2 c3 c4 c5 c6
| | | | | | |
s0 s1 s2 s3 s4 s5 s6
/\ /\ /\ /\ /\ /\ /\
h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13
安装完的效果图(太大了,截了一部分)
在ryu/ryu/app上
#创建新的virtualenv
virtualenv flask
#打开文件夹
cd flask
#激活
source bin/activate
#下载模块
pip install flask
#!/usr/bin/python
#from mininet.net import Mininet
#from mininet.node import Controller, RemoteController, OVSSwitch
#from mininet.cli import CLI
#from mininet.log import setLogLevel, info
#from mininet.link import Link, Intf, TCLink
#from mininet.topo import Topo
from tf import MyController
from flask import Flask
from flask import request
from flask import url_for
from flask import jsonify
from ryu.app.wsgi import ControllerBase
from ryu.app.wsgi import Response
from ryu.app.wsgi import WSGIApplication
from rf import master
import logging
import time
import json
import os
app=Flask(__name__)
flow4='{"dpid":1 ,"cookie": 1,"cookie_mask": 1,"table_id": 0,"idle_timeout": 30,"hard_timeout": 3000,"priority": 11111,"flags": 1,"match":{},"actions":[ { "type": "OUTPUT","port":"controller"}]}'
me=None
@app.route('/master//',methods=['GET'])
def create_master(cnum):
global me
me=master(cnum)
me.clear()
me.createcontroller()
return str(cnum)
@app.route('/master/controller/switch/getflowtable',methods=['POST'])
def get_p_flowtable():
global me
item=request.get_json()
cnum=item["controller"]
snum=item["switch"]
return me.clist[cnum].get_flow_states(str(snum))
@app.route('/master/gets2c',methods=['GET'])
def get_s2c():
global me
a={}
i=0
for controller in me.clist:
sws=str(controller.get_switches())
a[str(i)]=sws
i+=1
return
@app.route('/master/controller/addflow',methods=['POST'])
def add_cs_flow():
global me
item=request.get_json()
flow=json.dumps(item["flow"])
cnum=item["controller"]
return me.clist[cnum].add_flow(flow)
@app.route('/master/controller/deleteflow',methods=['POST'])
def del_cs_flow():
global me
item=request.get_json()
flow=json.dumps(item["flow"])
cnum=item["controller"]
return me.clist[cnum].del_flow_m(flow)
@app.route('/master/controller/switch/clearflow',methods=['POST'])
def clr_flow():
global me
item=request.get_json()
cnum=item["controller"]
snum=item["switch"]
return me.clist[cnum].del_all_flow(str(snum))
@app.route('/master/kill',methods=['GET'])
def kill_master():
global me
me.clear()
return 'kill!'
if __name__ == '__main__':
app.run(host='0.0.0.0',port=5000,debug=True)
1.开启流表操作脚本,如果出现端口占用问题运行下面脚本:
#!/usr/bin/python
from rf import master
from tf import MyController
import logging
import time
import os
a=7
me=master(a)
me.clear()
(注:运行流表操作脚本要在python3,所以要python3 XXX.py)
2用POSTMAN开启这7个控制器:
在postman上输入对应的URL:http://localhost:5000/master/7/,使用GET方法
返回了一个7表示创建了7个
返回值为200,出现(PID)... http://0.0.0.0:wsport表示这个端口对应的控制器开启
3.开启拓扑脚本
可见,拓扑连接上了控制器,并开始有数据包的出现
4.获取某个控制器下的某个交换机的流表
在postman上输入对应的URL:http://localhost:5000/master/controller/switch/getflowtable,使用POST模式,在body一栏选择raw,文件格式json,上传如下json文件(想要查询1号控制器的1号交换机的流表):
{
"controller":1,
"switch":1
}
点击send,如果没有错了话(返回值200)就会返回如下json文件:
{
"1": [
{
"actions": [
"OUTPUT:CONTROLLER"
],
"byte_count": 20430,
"cookie": 0,
"duration_nsec": 606000000,
"duration_sec": 71,
"flags": 0,
"hard_timeout": 0,
"idle_timeout": 0,
"length": 80,
"match": {},
"packet_count": 184,
"priority": 0,
"table_id": 0
}
]
}
在postman上输入对应的URL:http://localhost:5000/master/controller/addflow,使用POST模式,在body一栏选择raw,文件格式json,上传如下json文件(想要向1号控制器添加流表):
{
"controller":1,
"flow":
{
"dpid":1 ,
"cookie": 1,
"cookie_mask": 1,
"table_id": 0,
"idle_timeout": 30,
"hard_timeout": 3000,
"priority": 11111,
"flags": 1,
"match":{},
"actions":[ { "type": "OUTPUT","port":"controller"}]}
}
点击send,会返回一个adding flow,此时再获取一次流表,会返回:
{
"1": [
{
"actions": [
"OUTPUT:CONTROLLER"
],
"byte_count": 22356,
"cookie": 0,
"duration_nsec": 899000000,
"duration_sec": 829,
"flags": 0,
"hard_timeout": 0,
"idle_timeout": 0,
"length": 80,
"match": {},
"packet_count": 202,
"priority": 0,
"table_id": 0
},
{
"actions": [
"OUTPUT:CONTROLLER"
],
"byte_count": 0,
"cookie": 1,
"duration_nsec": 659000000,
"duration_sec": 5,
"flags": 1,
"hard_timeout": 3000,
"idle_timeout": 30,
"length": 80,
"match": {},
"packet_count": 0,
"priority": 11111,
"table_id": 0
}
]
}
6.让某个特定控制器删除流表
在postman上输入对应的URL:http://localhost:5000/master/controller/deleteflow,使用POST模式,在body一栏选择raw,文件格式json,上传和添加流表时一样json文件(想要删掉刚才添加的那个流表(优先级11111的那个))
点击send,返回一个deleting flow,然后再查询一次流表,会发现刚才添加的被删了:
{
"1": [
{
"actions": [
"OUTPUT:CONTROLLER"
],
"byte_count": 22356,
"cookie": 0,
"duration_nsec": 436000000,
"duration_sec": 1019,
"flags": 0,
"hard_timeout": 0,
"idle_timeout": 0,
"length": 80,
"match": {},
"packet_count": 202,
"priority": 0,
"table_id": 0
}
]
}
7. 在mininet做ping操作时影响流表
获取流表的时候会发现,有了很多很多的流表项足足有几千行(因为太多了,就只截图),对照流表规范可知这个流表格式是open flow1.0的:
8. 清空特定控制器下的特定交换机的所有流表
在postman上输入对应的URL:http://localhost:5000/master/controller/switch/clearflow,使用POST模式,在body一栏选择raw,文件格式json,上传和如下json文件(想要清空1号控制器下1号交换机的流表)
{
"controller":1,
"switch":1
}
点击send,返回一个clear!,然后再查询一次流表,发现什么都没有:
如果想要再能ping通,就需要添加一个连向控制器的流表才能ping
9.关闭控制器
在postman上输入对应的URL:http://localhost:5000/master/kill,使用GET方法
返回一个kill!,然后就不能正常使用流表操作的url了,返回值不是200
总结: