多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
需要:
- 基於參數的拓撲腳本:拓撲的生成
- 自定義控制器類腳本:功能的定義
- 用戶(控制器羣)類:整個框架的實例化
- 流表操作腳本:在實例上進行一系列操作
- 兩個終端:一個用於創建mininet,一個用於啓動服務器
- 環境:mininet,RYU,flask
- POSTMAN
前三個腳本(基於參數的拓撲腳本,自定義控制器類腳本,用戶(控制器羣)類)依然使用前一篇博客所使用的腳本(注:在本次實驗中的調用順序和上次有所不同)
拓撲形式:
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
前期工作:
1.安裝POSTMAN(略)
安裝完的效果圖(太大了,截了一部分)
2.安裝flask模塊
在ryu/ryu/app上
#創建新的virtualenv
virtualenv flask
#打開文件夾
cd flask
#激活
source bin/activate
#下載模塊
pip install flask
3.創建好前三個腳本(略)
4.創建流表操作腳本
#!/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/<int:cnum>/',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
}
]
}
5.讓某個控制器中添加流表
在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!,然後再查詢一次流表,發現什麼都沒有:
- h2 ping h3是ping不通的,因爲h1和h2連接的OVS交換機(s1)沒有連向控制器的流表,在h2 想要 ping h3的時候,h2無法向控制器c1發出請求,從而得不到回覆,
- h2 ping h7 也是不通的,因爲要經過s1
- h0 ping h1 是可行的
- 所以h0 ping h7 也是不通,也要經過s1
- h7 ping h8可以ping通,因爲h7h8-s3-c3,s3的流表是沒有被操作過的
如果想要再能ping通,就需要添加一個連向控制器的流表才能ping
9.關閉控制器
在postman上輸入對應的URL:http://localhost:5000/master/kill,使用GET方法
返回一個kill!,然後就不能正常使用流表操作的url了,返回值不是200
總結:
- 後端工作基本完成,準備和前端結合
- 靈活性,功能性,有較大進步
- 後期將添加各種網絡性能測試的功能