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

基本要求

  • 构建拓扑sudo mn --topo=single,3 --mac --controller=remote,ip=127.0.0.1,port=6633 --switch ovsk,protocols=OpenFlow13

ODL操作

  • 删除流表Python代码:
      #!/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)
  • 下发流表Python代码:
      #!/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("./flowtable.json") as f:
              jstr = f.read()
          headers = {'Content-Type': 'application/json'}
          res = requests.put(url, jstr, headers=headers, auth=HTTPBasicAuth('admin', 'admin'))
          print (res.content)

  • flowtable.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"
          }
        ]
      }

  • 获取流表信息Python代码:
      #!/usr/bin/python
      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)


Ryu操作

  • 下发流表Python代码
      #!/usr/bin/python
      import requests

      if __name__ == "__main__":
          url = 'http://127.0.0.1:8080/stats/flowentry/add'
          with open("./flowtable.json") as f:
              jstr = f.read()
          headers = {'Content-Type': 'application/json'}
          res = requests.put(url, jstr, headers=headers)
          print (res.content)


  • flowtable.json文件:
      {
          "dpid": 1,
          "cookie": 1,
          "cookie_mask": 1,
          "table_id": 0,
          "hard_timeout": 20,
          "priority": 65535,
          "flags": 1,
          "match":{
              "in_port":1
          },
          "actions":[

          ]
       }

执行结果

Vlan划分

  • 搭建拓扑,使用openflow13协议,Python代码:
      #!/usr/bin/env python
      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())}

  • 创建拓扑命令:
      sudo sudo mn  --custom mytopo.py --topo mytopo --mac --controller=remote,ip=127.0.0.1,port=6633 --switch ovsk,protocols=OpenFlow13

  • 脚本:
      # 将主机1,2发送来的包打上vlan标记
      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

      # 将主机3,4发送来的包取出vlan标记
       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

      # 将主机3,4发送来的包打上vlan标记
       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

进阶要求

  • 将上述以python代码实现,首先删除s1和s2上的流表:
      curl -X DELETE http://localhost:8080/stats/flowentry/clear/1
      curl -X DELETE http://localhost:8080/stats/flowentry/clear/2

  • 编程代码:
      #!/usr/bin/python
      import json

      import requests

      if __name__ == "__main__":
          url = 'http://127.0.0.1:8080/stats/flowentry/add'
          headers = {'Content-Type': 'application/json'}
          flow1 = {
              "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
                  }
              ]
          }
          flow2 = {
              "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
                  }
              ]
          }
          flow3 = {
              "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
                  }
              ]
          }
          flow4 = {
              "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
                  }
              ]
          }
          flow5 = {
              "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
                  }
              ]
          }
          flow6 = {
              "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
                  }
              ]
          }
          flow7 = {
              "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
                  }
              ]
          }
          flow8 = {
              "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
                  }
              ]
          }
          res1 = requests.post(url, json.dumps(flow1), headers=headers)
          res2 = requests.post(url, json.dumps(flow2), headers=headers)
          res3 = requests.post(url, json.dumps(flow3), headers=headers)
          res4 = requests.post(url, json.dumps(flow4), headers=headers)
          res5 = requests.post(url, json.dumps(flow5), headers=headers)
          res6 = requests.post(url, json.dumps(flow6), headers=headers)
          res7 = requests.post(url, json.dumps(flow7), headers=headers)
          res8 = requests.post(url, json.dumps(flow8), headers=headers)

总结

这次作业难度中等,主要在熟悉ODL和Ryu的RestfulAPI使用。本次实验所耗费时间相对较久。但同时对ODL 和 Ryu的使用和有了深刻了解。 遇到了一些问题,这边做一下记录:

  • requests的请求类型需要时刻注意,由于请求类型不对,而Ryu一直报错404,所以一时没有定位到错误
  • 流表残留
    解决方法:记得在实验开始之前删除流表避免残余流表的影响,需要下载curl
  • 在实验前要先清空已有流表,防止先前实验残余流表造成影响
posted @ 2021-10-26 08:29  mastertime  阅读(27)  评论(0编辑  收藏  举报