实验7:基于REST API的SDN北向应用实践
(一)基础
1.OpenDaylight
(1)删除交换机上的流表
#!/usr/bin/python
import requests
from requests.auth import HTTPBasicAuth
def http_del(url, jstr):
url = url
headers = {'Content-Type': 'application/json'}
resp = requests.delete(url, headers=headers, auth=HTTPBasicAuth('admin', 'admin'))
return resp
if __name__ == "__main__":
url = 'http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/'
with open('my.json') as f:
jstr = f.read()
resp = http_del(url, jstr)
print(resp.content)
(2)硬超时流表
#!/usr/bin/python
import requests
from requests.auth import HTTPBasicAuth
def http_put(url, jstr):
url = url
headers = {'Content-Type': 'application/json'}
resp = requests.put(url, jstr, headers=headers, auth=HTTPBasicAuth('admin', 'admin'))
return resp
if __name__ == "__main__":
url = 'http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/flow-node-inventory:table/0/flow/1'
with open('my.json') as f:
jstr = f.read()
resp = http_put(url, jstr)
print(resp.content)
(3)获取s1上活动的流表数
#!/usr/bin/python
import requests
from requests.auth import HTTPBasicAuth
def http_get(url, jstr):
url = url
headers = {'Content-Type': 'application/json'}
resp = requests.get(url, jstr, headers=headers, auth=HTTPBasicAuth('admin', 'admin'))
return resp
if __name__ == "__main__":
url = 'http://127.0.0.1:8181/restconf/operational/opendaylight-inventory:nodes/node/openflow:1/flow-node-inventory:table/0/opendaylight-flow-table-statistics:flow-table-statistics'
with open('my.json') as f:
jstr = f.read()
resp = http_get(url, jstr)
print(resp.content)
附上json代码:
{
"flow": [
{
"id": "1",
"match": {
"in-port": "1",
"ethernet-match": {
"ethernet-type": {
"type": "0x0800"
}
},
"ipv4-destination": "10.0.0.3/32"
},
"instructions": {
"instruction": [
{
"order": "0",
"apply-actions": {
"action": [
{
"order": "0",
"drop-action": {}
}
]
}
}
]
},
"flow-name": "flow1",
"priority": "65535",
"hard-timeout": "20",
"cookie": "2",
"table_id": "0"
}
]
}
2.Ryu
(1)硬超时
python代码:
import requests
from requests.auth import HTTPBasicAuth
def http_post(url,jstr):
url = url
headers = {'Content-Type': 'application/json'}
resp = requests.post(url,jstr,headers=headers, auth=HTTPBasicAuth('admin', 'admin'))
return resp
if __name__ == "__main__":
url = 'http://127.0.0.1:8080/stats/flowentry/add'
with open('ryu.json') as f:
jstr = f.read()
resp = http_post(url, jstr)
print(resp.content)
json代码:
{
"dpid": 1,
"cookie": 1,
"cookie_mask": 1,
"table_id": 0,
"idle_timeout": 0,
"hard_timeout": 20,
"priority": 65535,
"flags": 1,
"match":{
"in_port":1,
"ip_dst": "10.0.0.3/32"
},
"actions":[]
}
(2)Shell脚本划分vlan
curl -X POST -d '{
"dpid": 1,
"match":{
"in_port": 1
},
"actions":[
{
"type": "PUSH_VLAN", # Push a new VLAN tag if a input frame is non-VLAN-tagged
"ethertype": 33024 # Ethertype 0x8100(=33024): IEEE 802.1Q VLAN-tagged frame
},
{
"type": "SET_FIELD",
"field": "vlan_vid", # Set VLAN ID
"value": 4096 # Describe sum of vlan_id(e.g. 6) | OFPVID_PRESENT(0x1000=4096)
},
{
"type": "OUTPUT",
"port": 3
}
],
"priority":65535
}' http://localhost:8080/stats/flowentry/add
curl -X POST -d '{
"dpid": 1,
"match":{
"in_port": 2
},
"actions":[
{
"type": "PUSH_VLAN", # Push a new VLAN tag if a input frame is non-VLAN-tagged
"ethertype": 33024 # Ethertype 0x8100(=33024): IEEE 802.1Q VLAN-tagged frame
},
{
"type": "SET_FIELD",
"field": "vlan_vid", # Set VLAN ID
"value": 4097 # Describe sum of vlan_id(e.g. 6) | OFPVID_PRESENT(0x1000=4096)
},
{
"type": "OUTPUT",
"port": 3
}
],
"priority":65535
}' http://localhost:8080/stats/flowentry/add
curl -X POST -d '{
"dpid": 1,
"match":{
"vlan_vid": 0
},
"actions":[
{
"type": "POP_VLAN", # Push a new VLAN tag if a input frame is non-VLAN-tagged
"ethertype": 33024 # Ethertype 0x8100(=33024): IEEE 802.1Q VLAN-tagged frame
},
{
"type": "OUTPUT",
"port": 1
}
],
"priority":65535
}' http://localhost:8080/stats/flowentry/add
curl -X POST -d '{
"dpid": 1,
"match":{
"vlan_vid": 1
},
"actions":[
{
"type": "POP_VLAN", # Push a new VLAN tag if a input frame is non-VLAN-tagged
"ethertype": 33024 # Ethertype 0x8100(=33024): IEEE 802.1Q VLAN-tagged frame
},
{
"type": "OUTPUT",
"port": 2
}
],
"priority":65535
}' http://localhost:8080/stats/flowentry/add
curl -X POST -d '{
"dpid": 2,
"match":{
"in_port": 1
},
"actions":[
{
"type": "PUSH_VLAN", # Push a new VLAN tag if a input frame is non-VLAN-tagged
"ethertype": 33024 # Ethertype 0x8100(=33024): IEEE 802.1Q VLAN-tagged frame
},
{
"type": "SET_FIELD",
"field": "vlan_vid", # Set VLAN ID
"value": 4096 # Describe sum of vlan_id(e.g. 6) | OFPVID_PRESENT(0x1000=4096)
},
{
"type": "OUTPUT",
"port":3
}
],
"priority":65535
}' http://localhost:8080/stats/flowentry/add
curl -X POST -d '{
"dpid": 2,
"match":{
"in_port": 2
},
"actions":[
{
"type": "PUSH_VLAN", # Push a new VLAN tag if a input frame is non-VLAN-tagged
"ethertype": 33024 # Ethertype 0x8100(=33024): IEEE 802.1Q VLAN-tagged frame
},
{
"type": "SET_FIELD",
"field": "vlan_vid", # Set VLAN ID
"value": 4097 # Describe sum of vlan_id(e.g. 6) | OFPVID_PRESENT(0x1000=4096)
},
{
"type": "OUTPUT",
"port": 3
}
],
"priority":65535
}' http://localhost:8080/stats/flowentry/add
curl -X POST -d '{
"dpid": 2,
"match":{
"vlan_vid": 0
},
"actions":[
{
"type": "POP_VLAN", # Push a new VLAN tag if a input frame is non-VLAN-tagged
"ethertype": 33024 # Ethertype 0x8100(=33024): IEEE 802.1Q VLAN-tagged frame
},
{
"type": "OUTPUT",
"port": 1
}
],
"priority":65535
}' http://localhost:8080/stats/flowentry/add
curl -X POST -d '{
"dpid": 2,
"match":{
"vlan_vid": 1
},
"actions":[
{
"type": "POP_VLAN", # Push a new VLAN tag if a input frame is non-VLAN-tagged
"ethertype": 33024 # Ethertype 0x8100(=33024): IEEE 802.1Q VLAN-tagged frame
},
{
"type": "OUTPUT",
"port": 2
}
],
"priority":65535
}' http://localhost:8080/stats/flowentry/add
(二)进阶
python代码如下:
import requests
from requests.auth import HTTPBasicAuth
def http_post(url, jstr):
url = url
headers = {'Content-Type': 'application/json'}
resp = requests.post(url, jstr, headers=headers, auth=HTTPBasicAuth('admin', 'admin'))
return resp
if __name__ == "__main__":
url = 'http://127.0.0.1:8080/stats/flowentry/add'
for i in range(8):
filename = 'vlan' + str(i + 1) + '.json'
with open(filename) as f:
jstr = f.read()
resp = http_post(url, jstr)
print(resp.content)
json代码同Ryu(3)中的shell中,此处举例:
{
"dpid": 1,
"match":{
"in_port": 1
},
"actions":[
{
"type": "PUSH_VLAN",
"ethertype": 33024
},
{
"type": "SET_FIELD",
"field": "vlan_vid",
"value": 4096
},
{
"type": "OUTPUT",
"port": 3
}
],
"priority":65535
}
(三)总结
本次实验综合了实验四与实验二,回顾了一些操作,也让我进一步了解代码的含义。
基本要求主要是将代码对应相应控制器的url、增删操作的函数,以及相应的流规则。需要注意:
1.odl的删除操作没有'jstr'参数,且一开始运行测试的时候是没有流表的会报错,添加流表再删除可进行验证。
2.odl的流规则对应在实验四中,ryu的流规则在实验指导的连接中,需要补充上"ip_dst"指定目的地址,action为空表示丢弃数据包。
3.划分vlan要将优先级调高
进阶主要解决的问题是多个json的读取,流规则内容从shell脚本中抠出来就好。
除开vlan划分能找到比较详细的资料外,不理解代码的话在网上查资料还是比较难完成本次的作业。感谢张炜龙同学的指点给了我思路。