目錄
一些postman介紹、基本使用,以及mininet創建拓撲之類的我就不再重複寫了。
本文使用拓撲:SDN-Mininet安裝使用
實驗環境
- VM14.0
- Ubuntu 18.04
- JDK1.8
- OpenDaylight-Nitro版本
- Mininet
- postman
實驗步驟
打開opendaylight
使用mininet創建拓撲並連接opendaylight
Postman查看流表
訪問網址,http://你的ip:8181/index.html
打開Nodes標籤,查看Node Id
打開YANG UI標籤,opendaylight-inventory rev.2013-08-19->operational->nodes->node{id}->table{id}
點擊小眼睛獲得完整url
複製url,粘貼到postman。選擇GET方式,驗證方式爲Basic Auth,Headers中的Content-Type和Accept填入application/xml(不填的話默認是application/json格式),賬號密碼均爲admin,填入參數,table的id爲0,node的id爲之前Node標籤看到的。
python代碼查看流表
import urllib.request
from base64 import encodebytes
ip = "192.168.31.174"
node_id = "openflow:1"
table_id = "0"
username = "admin"
password = "admin"
url = "http://" + ip + ":8181/restconf/operational/opendaylight-inventory:nodes/node/" + node_id + "/flow-node-inventory:table/" + table_id
print(url)
# 添加請求的url
req = urllib.request.Request(url)
# 添加請求方法
req.get_method = lambda: "GET"
# 添加header
b64str = encodebytes(bytes('%s:%s' % (username, password), 'utf-8'))[:-1]
req.add_header("Authorization", "Basic %s" % b64str.decode('utf-8'))
returnData = urllib.request.urlopen(req)
res_json = returnData.read().decode('utf-8')
print(res_json)
xml形式的流表
<table xmlns="urn:opendaylight:flow:inventory">
<id>0</id>
<flow>
<id>L2switch-2</id>
<flow-statistics xmlns="urn:opendaylight:flow:statistics">
<packet-count>1</packet-count>
<duration>
<nanosecond>645000000</nanosecond>
<second>258</second>
</duration>
<byte-count>70</byte-count>
</flow-statistics>
<priority>2</priority>
<table_id>0</table_id>
<hard-timeout>0</hard-timeout>
<match>
<in-port>openflow:1:3</in-port>
</match>
<cookie>3098476543630901250</cookie>
<instructions>
<instruction>
<order>0</order>
<apply-actions>
<action>
<order>0</order>
<output-action>
<max-length>65535</max-length>
<output-node-connector>2</output-node-connector>
</output-action>
</action>
<action>
<order>2</order>
<output-action>
<max-length>65535</max-length>
<output-node-connector>CONTROLLER</output-node-connector>
</output-action>
</action>
<action>
<order>1</order>
<output-action>
<max-length>65535</max-length>
<output-node-connector>1</output-node-connector>
</output-action>
</action>
</apply-actions>
</instruction>
</instructions>
<idle-timeout>0</idle-timeout>
</flow>
<flow>
<id>L2switch-1</id>
<flow-statistics xmlns="urn:opendaylight:flow:statistics">
<packet-count>53</packet-count>
<duration>
<nanosecond>145000000</nanosecond>
<second>264</second>
</duration>
<byte-count>4505</byte-count>
</flow-statistics>
<priority>100</priority>
<table_id>0</table_id>
<hard-timeout>0</hard-timeout>
<match>
<ethernet-match>
<ethernet-type>
<type>35020</type>
</ethernet-type>
</ethernet-match>
</match>
<cookie>3098476543630901249</cookie>
<instructions>
<instruction>
<order>0</order>
<apply-actions>
<action>
<order>0</order>
<output-action>
<max-length>65535</max-length>
<output-node-connector>CONTROLLER</output-node-connector>
</output-action>
</action>
</apply-actions>
</instruction>
</instructions>
<idle-timeout>0</idle-timeout>
</flow>
<flow>
<id>#UF$TABLE*0-2</id>
<flow-statistics xmlns="urn:opendaylight:flow:statistics">
<packet-count>0</packet-count>
<duration>
<nanosecond>145000000</nanosecond>
<second>264</second>
</duration>
<byte-count>0</byte-count>
</flow-statistics>
<priority>0</priority>
<table_id>0</table_id>
<hard-timeout>0</hard-timeout>
<match></match>
<cookie>3098476543630901249</cookie>
<idle-timeout>0</idle-timeout>
</flow>
<flow>
<id>L2switch-0</id>
<flow-statistics xmlns="urn:opendaylight:flow:statistics">
<packet-count>1</packet-count>
<duration>
<nanosecond>652000000</nanosecond>
<second>258</second>
</duration>
<byte-count>70</byte-count>
</flow-statistics>
<priority>2</priority>
<table_id>0</table_id>
<hard-timeout>0</hard-timeout>
<match>
<in-port>openflow:1:2</in-port>
</match>
<cookie>3098476543630901248</cookie>
<instructions>
<instruction>
<order>0</order>
<apply-actions>
<action>
<order>0</order>
<output-action>
<max-length>65535</max-length>
<output-node-connector>1</output-node-connector>
</output-action>
</action>
<action>
<order>2</order>
<output-action>
<max-length>65535</max-length>
<output-node-connector>CONTROLLER</output-node-connector>
</output-action>
</action>
<action>
<order>1</order>
<output-action>
<max-length>65535</max-length>
<output-node-connector>3</output-node-connector>
</output-action>
</action>
</apply-actions>
</instruction>
</instructions>
<idle-timeout>0</idle-timeout>
</flow>
<flow>
<id>#UF$TABLE*0-3</id>
<flow-statistics xmlns="urn:opendaylight:flow:statistics">
<packet-count>3</packet-count>
<duration>
<nanosecond>647000000</nanosecond>
<second>258</second>
</duration>
<byte-count>247</byte-count>
</flow-statistics>
<priority>2</priority>
<table_id>0</table_id>
<hard-timeout>0</hard-timeout>
<match>
<in-port>openflow:1:1</in-port>
</match>
<cookie>3098476543630901249</cookie>
<instructions>
<instruction>
<order>0</order>
<apply-actions>
<action>
<order>0</order>
<output-action>
<max-length>65535</max-length>
<output-node-connector>2</output-node-connector>
</output-action>
</action>
<action>
<order>1</order>
<output-action>
<max-length>65535</max-length>
<output-node-connector>3</output-node-connector>
</output-action>
</action>
</apply-actions>
</instruction>
</instructions>
<idle-timeout>0</idle-timeout>
</flow>
<flow-table-statistics xmlns="urn:opendaylight:flow:table:statistics">
<packets-matched>57</packets-matched>
<active-flows>5</active-flows>
<packets-looked-up>105</packets-looked-up>
</flow-table-statistics>
</table>
流表分析
從這個xml中,我們可以看到流表的一些信息,包括流表的id,使用的交換機,一個流表項的入端口等,另外<flow></flow>標籤中是流表的一個流表項,共5條。
字段 | 含義 |
---|---|
table_id | int,流表的id |
id | string,流表項的id |
priority | int,流表項的優先級 |
cookie | int,控制器發出的標識符 |
cookie_mask | int,掩碼,用於限制必須匹配的cookie位 |
idle-timeout | int,丟棄前的空閒時間(秒) |
hard-timeout | int,丟棄前的最長時間(秒) |
match | dict,匹配域 |
ethernet-match | dict,以太網匹配 |
ethernet-type | dict,以太網類型 |
type | str,0x0800:使用ip匹配,0x8847:使用mac匹配 |
ipv4-destination | ipv4的目的ip地址 |
instructions | dict,動作集 |
instruction | list,動作,指令 |
order | int,順序 |
Postman查看流表項
json格式的流表項
{
"flow-node-inventory:flow": [
{
"id": "L2switch-2",
"opendaylight-flow-statistics:flow-statistics": {
"packet-count": 2,
"duration": {
"nanosecond": 81000000,
"second": 768
},
"byte-count": 140
},
"priority": 2,
"table_id": 0,
"hard-timeout": 0,
"match": {
"in-port": "openflow:1:3"
},
"cookie": 3098476543630901250,
"instructions": {
"instruction": [
{
"order": 0,
"apply-actions": {
"action": [
{
"order": 0,
"output-action": {
"max-length": 65535,
"output-node-connector": "2"
}
},
{
"order": 2,
"output-action": {
"max-length": 65535,
"output-node-connector": "CONTROLLER"
}
},
{
"order": 1,
"output-action": {
"max-length": 65535,
"output-node-connector": "1"
}
}
]
}
}
]
},
"idle-timeout": 0
}
]
}
Python代碼查看流表項
import urllib.request
from base64 import encodebytes
ip = "192.168.31.174"
node_id = "openflow:1"
table_id = "0"
flow_id = "L2switch-2"
username = "admin"
password = "admin"
url = "http://" + ip + ":8181/restconf/operational/opendaylight-inventory:nodes/node/" + node_id + "/flow-node-inventory:table/" + table_id +"/flow/"+flow_id
print(url)
# 添加請求的url和method
req = urllib.request.Request(url, method="GET")
# 添加header
b64str = encodebytes(bytes('%s:%s' % (username, password), 'utf-8'))[:-1]
req.add_header("Authorization", "Basic %s" % b64str.decode('utf-8'))
returnData = urllib.request.urlopen(req)
res_json = returnData.read().decode('utf-8')
print(res_json)
Postman添加流表項
使用PUT方式,賬號密碼依然還是admin,注意url是使用的config,不是operational,選擇json格式,點擊send。
再次查看流表後發現添加了一條流表項,h1、h2使用的是交換機s1的端口s1-eth1與s1-eth2,所以,h1與h2可以ping通。
Python添加流表項
import urllib.request
from base64 import encodebytes
from django.contrib.sites import requests
ip = "192.168.31.174"
# node_id = "openflow:1"
print("please input name of switch:")
node_id = input()
table_id = "0"
# flow_id = "L2switch-2"
print("please input id of flow:")
flow_id = input()
username = "admin"
password = "admin"
url = "http://" + ip + ":8181/restconf/config/opendaylight-inventory:nodes/node/" + node_id + "/flow-node-inventory:table/" + table_id + "/flow/" + flow_id
print(url)
flow = {
"flow-node-inventory:flow": [
{
"id": "L2switch-2",
"priority": 2,
"table_id": 0,
"hard-timeout": 0,
"match": {
"in-port": "openflow:1:3"
},
"cookie": 3098476543630901250,
"instructions": {
"instruction": [
{
"order": 0,
"apply-actions": {
"action": [
{
"order": 0,
"output-action": {
"max-length": 65535,
"output-node-connector": "2"
}
}
]
}
}
]
},
"idle-timeout": 0
}
]
}
flow["flow-node-inventory:flow"][0]["id"] = flow_id
print("please input priority of this flow:")
flow["flow-node-inventory:flow"][0]["priority"] = int(input())
print("please input hard-timeout of this flow:")
flow["flow-node-inventory:flow"][0]["hard-timeout"] = int(input())
print("please input idle-timeout of this flow:")
flow["flow-node-inventory:flow"][0]["idle-timeout"] = int(input())
print("please input in-port of this flow:")
flow["flow-node-inventory:flow"][0]["match"]["in-port"] = node_id + ":" + input()
print("please input output-port of this flow:")
flow["flow-node-inventory:flow"][0]["instructions"]["instruction"][0]["apply-actions"]["action"][0]["output-action"][
"output-node-connector"] = input()
print("flow_id:" + str(flow["flow-node-inventory:flow"][0]["id"]))
print("priority:" + str(flow["flow-node-inventory:flow"][0]["priority"]))
print("hard-timeout:" + str(flow["flow-node-inventory:flow"][0]["hard-timeout"]))
print("idle-timeout:" + str(flow["flow-node-inventory:flow"][0]["idle-timeout"]))
print("in-port:" + flow["flow-node-inventory:flow"][0]["match"]["in-port"])
print("output-port:" +
flow["flow-node-inventory:flow"][0]["instructions"]["instruction"][0]["apply-actions"]["action"][0][
"output-action"]["output-node-connector"])
print(flow)
# 添加請求的url、data、method
req = urllib.request.Request(url=url, data=bytes(str(flow), 'utf-8'), method="PUT")
# 添加header
b64str = encodebytes(bytes('%s:%s' % (username, password), 'utf-8'))[:-1]
req.add_header("Authorization", "Basic %s" % b64str.decode('utf-8'))
req.add_header("Accept", "application/json")
req.add_header("Content-Type", "application/json")
returnData = urllib.request.urlopen(req)
res_json = returnData.read().decode('utf-8')
print(res_json)
我是通過端口添加的流表項,除此之外,你還可以使用ip或mac添加,使用ethernet-type、ipv4-destination等字段。
Postman、Python修改流表項
這個只需要使你請求的數據中流表項的id在流表中存在,就會覆蓋掉原來的。
更多SDN相關內容,請查看:SDN-自學筆記
有問題請下方評論,轉載請註明出處,並附有原文鏈接,謝謝!如有侵權,請及時聯繫。