实验7:基于REST API的SDN北向应用实践

一、实验目的
1.能够编写程序调用OpenDaylight REST API实现特定网络功能;
2.能够编写程序调用Ryu REST API实现特定网络功能。

二、实验环境
1.下载虚拟机软件Oracle VisualBox或VMware;
2.在虚拟机中安装Ubuntu 20.04 Desktop amd64,并完整安装Mininet、OpenDaylight(Carbon版本)、Postman和Ryu;

三、实验要求
(一)基本要求
OpenDaylight
(1) 利用Mininet平台搭建下图所示网络拓扑,并连接OpenDaylight;

 

 


编写Python程序,调用OpenDaylight的北向接口下发指令删除s1上的流表数据

  1. #!/usr/bin/python
  2. import requests
  3. from requests.auth import HTTPBasicAuth
  4. def http_delete(url):
  5. url= url
  6. headers = {'Content-Type':'application/json'}
  7. resp = requests.delete(url, headers=headers, auth=HTTPBasicAuth('admin', 'admin'))
  8. return resp
  9. if __name__ == "__main__":
  10. url = 'http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/'
  11. resp = http_delete(url)
  12. print(resp.content)

编写Python程序,调用OpenDaylight的北向接口下发硬超时流表,实现拓扑内主机h1和h3网络中断20s。

  1. #!/usr/bin/python
  2. import requests
  3. from requests.auth import HTTPBasicAuth
  4. def http_put(url,jstr):
  5. url= url
  6. headers = {'Content-Type':'application/json'}
  7. resp = requests.put(url,jstr,headers=headers,auth=HTTPBasicAuth('admin', 'admin'))
  8. return resp
  9. if __name__ == "__main__":
  10. url='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/flow-node-inventory:table/0/flow/1'
  11. with open('no1.json') as f:
  12. jstr = f.read()
  13. resp = http_put(url,jstr)
  14. print (resp.content)

flowtable.json

  1. {
  2. "flow": [
  3. {
  4. "id": "1",
  5. "match": {
  6. "in-port": "1",
  7. "ethernet-match": {
  8. "ethernet-type": {
  9. "type": "0x0800"
  10. }
  11. },
  12. "ipv4-destination": "10.0.0.3/32"
  13. },
  14. "instructions": {
  15. "instruction": [
  16. {
  17. "order": "0",
  18. "apply-actions": {
  19. "action": [
  20. {
  21. "order": "0",
  22. "drop-action": {}
  23. }
  24. ]
  25. }
  26. }
  27. ]
  28. },
  29. "flow-name": "flow1",
  30. "priority": "65535",
  31. "hard-timeout": "20",
  32. "cookie": "2",
  33. "table_id": "0"
  34. }
  35. ]
  36. }

     

     

编写Python程序,调用OpenDaylight的北向接口获取s1上活动的流表数。

  1. #!/usr/bin/python
  2. import requests
  3. from requests.auth import HTTPBasicAuth
  4. def http_get(url):
  5. url= url
  6. headers = {'Content-Type':'application/json'}
  7. resp = requests.get(url,headers=headers,auth=HTTPBasicAuth('admin','admin'))
  8. return resp
  9. if __name__ == "__main__":
  10. 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'
  11. resp = http_get(url)
  12. print(resp.content)

 

 

Ryu
命令行运行ryu
ryu-manager ryu.app.simple_switch_13 ryu.app.ofctl_rest
(1) 编写Python程序,调用Ryu的北向接口,实现上述OpenDaylight实验拓扑上相同的硬超时流表下发。

  1. #!/usr/bin/python
  2. import requests
  3. if __name__ == "__main__":
  4. url = 'http://127.0.0.1:8080/stats/flowentry/add'
  5. with open("./no2.json") as f:
  6. jstr = f.read()
  7. headers = {'Content-Type': 'application/json'}
  8. res = requests.post(url, jstr, headers=headers)
  9. print (res.content)

flowtable.json

  1. {
  2. "dpid": 1,
  3. "cookie": 1,
  4. "cookie_mask": 1,
  5. "table_id": 0,
  6. "hard_timeout": 20,
  7. "priority": 65535,
  8. "flags": 1,
  9. "match":{
  10. "in_port":1
  11. },
  12. "actions":[
  13. ]
  14. }

 

 

(2) 利用Mininet平台搭建下图所示网络拓扑,要求支持OpenFlow 1.3协议,主机名、交换机名以及端口对应正确。拓扑生成后需连接Ryu,且Ryu应能够提供REST API服务。

 

 

  1. #!/usr/bin/env python
  2. from mininet.topo import Topo
  3. class MyTopo(Topo):
  4. def __init__(self):
  5. # initilaize topology
  6. Topo.__init__(self)
  7. self.addSwitch("s1")
  8. self.addSwitch("s2")
  9. self.addHost("h1")
  10. self.addHost("h2")
  11. self.addHost("h3")
  12. self.addHost("h4")
  13. self.addLink("s1", "h1")
  14. self.addLink("s1", "h2")
  15. self.addLink("s2", "h3")
  16. self.addLink("s2", "h4")
  17. self.addLink("s1", "s2")
  18. topos = {'mytopo': (lambda: MyTopo())}

命令行运行
sudo sudo mn —custom ryu2.py —topo mytopo —mac —controller=remote,ip=127.0.0.1,port=6633 —switch ovsk,protocols=OpenFlow13

(3) 整理一个Shell脚本,参考Ryu REST API的文档,利用curl命令,实现和实验2相同的VLAN。

VLAN_IDHosts
0 h1 h3
1 h2 h4


curl -X DELETE http://localhost:8080/stats/flowentry/clear/1
curl -X DELETE http://localhost:8080/stats/flowentry/clear/2


shell.sh

  1. # 将主机1,2发送来的包打上vlan标记
  2. curl -X POST -d '{
  3. "dpid": 1,
  4. "priority": 1,
  5. "match":{
  6. "in_port": 1
  7. },
  8. "actions":[
  9. {
  10. "type": "PUSH_VLAN", # Push a new VLAN tag if a input frame is non-VLAN-tagged
  11. "ethertype": 33024 # Ethertype 0x8100(=33024): IEEE 802.1Q VLAN-tagged frame
  12. },
  13. {
  14. "type": "SET_FIELD",
  15. "field": "vlan_vid", # Set VLAN ID
  16. "value": 4096 # Describe sum of vlan_id(e.g. 6) | OFPVID_PRESENT(0x1000=4096)
  17. },
  18. {
  19. "type": "OUTPUT",
  20. "port": 3
  21. }
  22. ]
  23. }' http://localhost:8080/stats/flowentry/add
  24. curl -X POST -d '{
  25. "dpid": 1,
  26. "priority": 1,
  27. "match":{
  28. "in_port": 2
  29. },
  30. "actions":[
  31. {
  32. "type": "PUSH_VLAN", # Push a new VLAN tag if a input frame is non-VLAN-tagged
  33. "ethertype": 33024 # Ethertype 0x8100(=33024): IEEE 802.1Q VLAN-tagged frame
  34. },
  35. {
  36. "type": "SET_FIELD",
  37. "field": "vlan_vid", # Set VLAN ID
  38. "value": 4097 # Describe sum of vlan_id(e.g. 6) | OFPVID_PRESENT(0x1000=4096)
  39. },
  40. {
  41. "type": "OUTPUT",
  42. "port": 3
  43. }
  44. ]
  45. }' http://localhost:8080/stats/flowentry/add
  46. # 将主机3,4发送来的包取出vlan标记
  47. curl -X POST -d '{
  48. "dpid": 1,
  49. "priority": 1,
  50. "match":{
  51. "vlan_vid": 0
  52. },
  53. "actions":[
  54. {
  55. "type": "POP_VLAN", # Push a new VLAN tag if a input frame is non-VLAN-tagged
  56. "ethertype": 33024 # Ethertype 0x8100(=33024): IEEE 802.1Q VLAN-tagged frame
  57. },
  58. {
  59. "type": "OUTPUT",
  60. "port": 1
  61. }
  62. ]
  63. }' http://localhost:8080/stats/flowentry/add
  64. curl -X POST -d '{
  65. "dpid": 1,
  66. "priority": 1,
  67. "match":{
  68. "vlan_vid": 1
  69. },
  70. "actions":[
  71. {
  72. "type": "POP_VLAN", # Push a new VLAN tag if a input frame is non-VLAN-tagged
  73. "ethertype": 33024 # Ethertype 0x8100(=33024): IEEE 802.1Q VLAN-tagged frame
  74. },
  75. {
  76. "type": "OUTPUT",
  77. "port": 2
  78. }
  79. ]
  80. }' http://localhost:8080/stats/flowentry/add
  81. # 将主机3,4发送来的包打上vlan标记
  82. curl -X POST -d '{
  83. "dpid": 2,
  84. "priority": 1,
  85. "match":{
  86. "in_port": 1
  87. },
  88. "actions":[
  89. {
  90. "type": "PUSH_VLAN", # Push a new VLAN tag if a input frame is non-VLAN-tagged
  91. "ethertype": 33024 # Ethertype 0x8100(=33024): IEEE 802.1Q VLAN-tagged frame
  92. },
  93. {
  94. "type": "SET_FIELD",
  95. "field": "vlan_vid", # Set VLAN ID
  96. "value": 4096 # Describe sum of vlan_id(e.g. 6) | OFPVID_PRESENT(0x1000=4096)
  97. },
  98. {
  99. "type": "OUTPUT",
  100. "port": 3
  101. }
  102. ]
  103. }' http://localhost:8080/stats/flowentry/add
  104. curl -X POST -d '{
  105. "dpid": 2,
  106. "priority": 1,
  107. "match":{
  108. "in_port": 2
  109. },
  110. "actions":[
  111. {
  112. "type": "PUSH_VLAN", # Push a new VLAN tag if a input frame is non-VLAN-tagged
  113. "ethertype": 33024 # Ethertype 0x8100(=33024): IEEE 802.1Q VLAN-tagged frame
  114. },
  115. {
  116. "type": "SET_FIELD",
  117. "field": "vlan_vid", # Set VLAN ID
  118. "value": 4097 # Describe sum of vlan_id(e.g. 6) | OFPVID_PRESENT(0x1000=4096)
  119. },
  120. {
  121. "type": "OUTPUT",
  122. "port": 3
  123. }
  124. ]
  125. }' http://localhost:8080/stats/flowentry/add
  126. curl -X POST -d '{
  127. "dpid": 2,
  128. "priority": 1,
  129. "match":{
  130. "vlan_vid": 0
  131. },
  132. "actions":[
  133. {
  134. "type": "POP_VLAN", # Push a new VLAN tag if a input frame is non-VLAN-tagged
  135. "ethertype": 33024 # Ethertype 0x8100(=33024): IEEE 802.1Q VLAN-tagged frame
  136. },
  137. {
  138. "type": "OUTPUT",
  139. "port": 1
  140. }
  141. ]
  142. }' http://localhost:8080/stats/flowentry/add
  143. curl -X POST -d '{
  144. "dpid": 2,
  145. "priority": 1,
  146. "match":{
  147. "vlan_vid": 1
  148. },
  149. "actions":[
  150. {
  151. "type": "POP_VLAN", # Push a new VLAN tag if a input frame is non-VLAN-tagged
  152. "ethertype": 33024 # Ethertype 0x8100(=33024): IEEE 802.1Q VLAN-tagged frame
  153. },
  154. {
  155. "type": "OUTPUT",
  156. "port": 2
  157. }
  158. ]
  159. }' http://localhost:8080/stats/flowentry/add      

三)实验总结

  • 实验难度:本次实验难度较大。
  • 遇到的困难及解决办法:
  1. 运行ryu却无法ping通 老是unreachable  然后,我其他同学告诉我只要一直put命令一直输就可以,最后解决了
  2. 不知道怎么打开ryu,
  3. 这次实验收获还是比较大的,学会了ODL和RYU的控制,能够比较熟练的搭建拓扑并且调用所需要的软件工具
posted @ 2021-10-27 12:20  夕顔  阅读(55)  评论(0编辑  收藏  举报