Experiment 7: SDN northbound application practice based on REST API
1. The purpose of the experiment
- Ability to write programs to call OpenDaylight REST API to implement specific network functions;
- Ability to write programs to call Ryu REST API to implement specific network functions.
2. Experimental environment
- Download the virtual machine software Oracle VisualBox or VMware;
- Install Ubuntu 20.04 Desktop amd64 in a virtual machine, and fully install Mininet, OpenDaylight (Carbon version), Postman and Ryu;
3. Experimental requirements
(1) Basic requirements
Write a Python program to call the northbound interface of OpenDaylight to achieve the following functions
(1) Use the Mininet platform to build the network topology shown in the figure below, and connect to OpenDaylight;
(2) Issue an instruction to delete the flow table data on s1.
delete.py
#!/usr/bin/python import requests from requests.auth import HTTPBasicAuth if __name__ == "__main__": url = 'http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/' headers = {'Content-Type': 'application/json'} res = requests.delete(url, headers=headers, auth=HTTPBasicAuth('admin', 'admin')) print (res.content)
(3) Distribute the hard timeout flow table to realize the network interruption of hosts h1 and h3 in the topology for 20s.
timeOut.py
#!/usr/bin/python import requests from requests.auth import HTTPBasicAuth 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("./timeOut.json") as file: str = file.read() headers = {'Content-Type': 'application/json'} res = requests.put(url, str, headers=headers, auth=HTTPBasicAuth('admin', 'admin')) print (res.content)
timeOut.json
# timeout.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": "flow", "priority": "65535", "hard-timeout": "20", "cookie": "2", "table_id": "0" } ] }
(4) Get the number of active flow tables on s1.
getflow.py
# getflow.py import requests from requests.auth import HTTPBasicAuth 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' headers = {'Content-Type': 'application/json'} res = requests.get(url,headers=headers, auth=HTTPBasicAuth('admin', 'admin')) print (res.content)
Write a Python program to call Ryu's northbound interface to achieve the following functions
(1) Implement the same hard timeout flow table delivery on the OpenDaylight experimental topology above.
ryu_timeout.py
# ryu_timeout.py import requests if __name__ == "__main__": url = 'http://127.0.0.1:8080/stats/flowentry/add' with open("./ryu_timeout.json") as file: str = file.read() headers = {'Content-Type': 'application/json'} res = requests.post(url, str, headers=headers) print (res.content)
ryu_timeout.json
# ryu_timeout.json { "dpid": 1, "cookie": 1, "cookie_mask": 1, "table_id": 0, "hard_timeout": 20, "priority": 65535, "flags": 1, "match":{ "in_port":1 }, "actions":[ ] }
(2) Refer to the documentation of Ryu REST API, based on the network topology of the VLAN experiment, program the same VLAN configuration.
Tip: Ryu needs to be connected after topology generation, and Ryu should be able to provide REST API services
VLAN_ID Hosts | |
---|---|
0 | h1 h3 |
1 | h2 h4 |
Create a topology map
sudo mn --custom mytopo.py --topo mytopo --mac --controller=remote,ip=127.0.0.1,port=6633 --switch ovsk,protocols=OpenFlow13
topo.py
from mininet.topo import Topo class MyTopo(Topo): def __init__(self): # initilaize topology Topo.__init__(self) self.addSwitch("s1") self.addSwitch("s2") self.addHost("h1") self.addHost("h2") self.addHost("h3") self.addHost("h4") self.addLink("s1", "h1") self.addLink("s1", "h2") self.addLink("s2", "h3") self.addLink("s2", "h4") self.addLink("s1", "s2") topos = {'mytopo': (lambda: MyTopo())}
shell.sh
curl -X POST -d '{ "dpid": 1, "priority": 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 } ] }' http://localhost:8080/stats/flowentry/add curl -X POST -d '{ "dpid": 1, "priority": 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 } ] }' http://localhost:8080/stats/flowentry/add curl -X POST -d '{ "dpid": 1, "priority": 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 } ] }' http://localhost:8080/stats/flowentry/add curl -X POST -d '{ "dpid": 1, "priority": 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 } ] }' http://localhost:8080/stats/flowentry/add curl -X POST -d '{ "dpid": 2, "priority": 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 } ] }' http://localhost:8080/stats/flowentry/add curl -X POST -d '{ "dpid": 2, "priority": 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 } ] }' http://localhost:8080/stats/flowentry/add curl -X POST -d '{ "dpid": 2, "priority": 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 } ] }' http://localhost:8080/stats/flowentry/add curl -X POST -d '{ "dpid": 2, "priority": 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 } ] }' http://localhost:8080/stats/flowentry/add
(3) Experimental summary
In this experiment, I learned how to write a program to call the OpenDaylight REST API to implement specific network functions, and how to write a program to call the Ryu REST API to implement specific network functions
. In the experiment, I used the python program to issue instructions to delete the cursor data on s1, and to issue the hard timeout flow table, so that the network of hosts h1 and h3 in the topology was interrupted for 20s, and the number of active flow tables on s1 was obtained. In general, this experiment was very difficult. I did it for a few hours before completing it. During the period, I encountered many problems that I did not know, and I solved it through Baidu and asking my classmates. I didn't do advanced steps, but the experiment went smoothly. In this experiment, I experienced how to use python programs to control network functions. This experiment has benefited a lot, and I hope to gain more knowledge in the next study.