SDN期末做業驗收

一.實驗代碼node

import httplib2
import time
import json
class OdlUtil:
    url = ''
    def __init__(self, host, port):
        self.url = 'http://' + host + ':' + str(port)
    def install_flow(self, container_name='default',username="admin", password="admin"):
        http = httplib2.Http()
        http.add_credentials(username, password)
        headers = {'Accept': 'application/json'}
        flow_name = 'flow_' + str(int(time.time()*1000))
        #s2流表
        #h2工做時s2端口1流量空閒時下發的流表
        h2_to_s2_1 ='{"flow": [{"id": "0","match": {"ethernet-match":'\
                    '{"ethernet-type": {"type": "2048"}},'\
                    '"ipv4-source":"10.0.0.2/32","ipv4-destination": "10.0.0.1/32"},'\
                    '"instructions": {"instruction": [{"order": "0",'\
                    '"apply-actions": {"action": [{"output-action": {'\
                    '"output-node-connector": "1"},"order": "0"}]}}]},'\
                    '"priority": "101","cookie": "1","table_id": "0"}]}'
        #h3工做時s2端口1流量空閒時下發的流表
        h3_to_s2_1 ='{"flow": [{"id": "1","match": {"ethernet-match":'\
                    '{"ethernet-type": {"type": "2048"}},'\
                    '"ipv4-source":"10.0.0.3/32","ipv4-destination": "10.0.0.1/32"},'\
                    '"instructions": {"instruction": [{"order": "0",'\
                    '"apply-actions": {"action": [{"output-action": {'\
                    '"output-node-connector": "1"},"order": "0"}]}}]},'\
                    '"priority": "101","cookie": "1","table_id": "0"}]}'
        mh3_to_s2_1 ='{"flow": [{"id": "1","match": {"ethernet-match":'\
                    '{"ethernet-type": {"type": "2048"}},'\
                    '"ipv4-source":"10.0.0.3/32","ipv4-destination": "10.0.0.1/32"},'\
                    '"instructions": {"instruction": [{"order": "0",'\
                    '"apply-actions": {"action": [{"output-action": {'\
                    '"output-node-connector": "1"},"order": "0"}]}}]},'\
                    '"priority": "100","cookie": "1","table_id": "0"}]}'
        #h3工做時s2端口1流量滿載時下發的流表   
        h3_to_s2_2 ='{"flow": [{"id": "2","match": {"ethernet-match":'\
                    '{"ethernet-type": {"type": "2048"}},'\
                    '"ipv4-source":"10.0.0.3/32","ipv4-destination": "10.0.0.1/32"},'\
                    '"instructions": {"instruction": [{"order": "0",'\
                    '"apply-actions": {"action": [{"output-action": {'\
                    '"output-node-connector": "2"},"order": "0"}]}}]},'\
                    '"priority": "101","cookie": "1","table_id": "0"}]}'
        mh3_to_s2_2 ='{"flow": [{"id": "2","match": {"ethernet-match":'\
                    '{"ethernet-type": {"type": "2048"}},'\
                    '"ipv4-source":"10.0.0.3/32","ipv4-destination": "10.0.0.1/32"},'\
                    '"instructions": {"instruction": [{"order": "0",'\
                    '"apply-actions": {"action": [{"output-action": {'\
                    '"output-node-connector": "2"},"order": "0"}]}}]},'\
                    '"priority": "100","cookie": "1","table_id": "0"}]}'
        #s3流表
        s3_1='{"flow": [{"id": "0","match": {"ethernet-match":'\
            '{"ethernet-type": {"type": "2048"}},'\
            '"ipv4-source":"10.0.0.3/32","ipv4-destination": "10.0.0.1/32"},'\
            '"instructions": {"instruction": [{"order": "0",'\
            '"apply-actions": {"action": [{"output-action": {'\
            '"output-node-connector": "1"},"order": "0"}]}}]},'\
            '"priority": "101","cookie": "1","table_id": "0"}]}'
        s3_2='{"flow": [{"id": "1","match": {"ethernet-match":'\
            '{"ethernet-type": {"type": "2048"}},'\
            '"ipv4-source":"10.0.0.1/32","ipv4-destination": "10.0.0.3/32"},'\
            '"instructions": {"instruction": [{"order": "0",'\
            '"apply-actions": {"action": [{"output-action": {'\
            '"output-node-connector": "2"},"order": "0"}]}}]},'\
            '"priority": "101","cookie": "2","table_id": "0"}]}'
        #s1流表
        s1_2To1='{"flow": [{"id": "0","match": {"ethernet-match":'\
                '{"ethernet-type": {"type": "2048"}},'\
                '"ipv4-source":"10.0.0.2/32","ipv4-destination": "10.0.0.1/32"},'\
                '"instructions": {"instruction": [{"order": "0",'\
                '"apply-actions": {"action": [{"output-action": {'\
                '"output-node-connector": "1"},"order": "0"}]}}]},'\
                '"priority": "101","cookie": "1","table_id": "0"}]}'
        s1_3To1='{"flow": [{"id": "1","match": {"ethernet-match":'\
                '{"ethernet-type": {"type": "2048"}},'\
                '"ipv4-source":"10.0.0.3/32","ipv4-destination": "10.0.0.1/32"},'\
                '"instructions": {"instruction": [{"order": "0",'\
                '"apply-actions": {"action": [{"output-action": {'\
                '"output-node-connector": "1"},"order": "0"}]}}]},'\
                '"priority": "101","cookie": "1","table_id": "0"}]}'
        #h1工做時s1端口2流量空閒時下發的流表
        h1_to_s1_2 ='{"flow": [{"id": "2","match": {"ethernet-match":'\
                    '{"ethernet-type": {"type": "2048"}},'\
                    '"ipv4-source":"10.0.0.1/32","ipv4-destination": "10.0.0.3/32"},'\
                    '"instructions": {"instruction": [{"order": "0",'\
                    '"apply-actions": {"action": [{"output-action": {'\
                    '"output-node-connector": "2"},"order": "0"}]}}]},'\
                    '"priority": "101","cookie": "2","table_id": "0"}]}'
        mh1_to_s1_2 ='{"flow": [{"id": "3","match": {"ethernet-match":'\
                    '{"ethernet-type": {"type": "2048"}},'\
                    '"ipv4-source":"10.0.0.1/32","ipv4-destination": "10.0.0.3/32"},'\
                    '"instructions": {"instruction": [{"order": "0",'\
                    '"apply-actions": {"action": [{"output-action": {'\
                    '"output-node-connector": "2"},"order": "0"}]}}]},'\
                    '"priority": "100","cookie": "3","table_id": "0"}]}'
        #h1工做時s1端口2流量滿載時下發的流表   
        h1_to_s1_3 ='{"flow": [{"id": "2","match": {"ethernet-match":'\
                    '{"ethernet-type": {"type": "2048"}},'\
                    '"ipv4-source":"10.0.0.1/32","ipv4-destination": "10.0.0.3/32"},'\
                    '"instructions": {"instruction": [{"order": "0",'\
                    '"apply-actions": {"action": [{"output-action": {'\
                    '"output-node-connector": "3"},"order": "0"}]}}]},'\
                    '"priority": "101","cookie": "2","table_id": "0"}]}'
        mh1_to_s1_3 ='{"flow": [{"id": "3","match": {"ethernet-match":'\
                    '{"ethernet-type": {"type": "2048"}},'\
                    '"ipv4-source":"10.0.0.1/32","ipv4-destination": "10.0.0.3/32"},'\
                    '"instructions": {"instruction": [{"order": "0",'\
                    '"apply-actions": {"action": [{"output-action": {'\
                    '"output-node-connector": "3"},"order": "0"}]}}]},'\
                    '"priority": "100","cookie": "3","table_id": "0"}]}'
        headers = {'Content-type': 'application/json'}
        num=0
        #下發流表,地址由ODL上得到
        #下發s1與s3的流表
        response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/flow-node-inventory:table/0/flow/0', body=s1_2To1, method='PUT',headers=headers)   
        response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/flow-node-inventory:table/0/flow/1', body=s1_3To1, method='PUT',headers=headers)
        response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:3/flow-node-inventory:table/0/flow/0', body=s3_1, method='PUT',headers=headers)
        response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:3/flow-node-inventory:table/0/flow/0', body=s3_2, method='PUT',headers=headers)

        #s2調用h2到1的流表            
        response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:2/flow-node-inventory:table/0/flow/0', body=h2_to_s2_1, method='PUT',headers=headers)
        while num < 4 :
            s1_uri = 'http://127.0.0.1:8181/restconf/operational/opendaylight-inventory:nodes/node/openflow:1/node-connector/openflow:1:2'
            s2_uri = 'http://127.0.0.1:8181/restconf/operational/opendaylight-inventory:nodes/node/openflow:2/node-connector/openflow:2:1'
            #獲取s1端口2的流量
            response, content = http.request(uri=s1_uri, method='GET')
            content = json.loads(content)
            statistics = content['node-connector'][0]['opendaylight-port-statistics:flow-capable-node-connector-statistics']
            s1_bytes1 = statistics['bytes']['transmitted']
            #0.5秒後再次獲取
            time.sleep(0.5)
            response, content = http.request(uri=s1_uri, method='GET')
            content = json.loads(content)
            statistics = content['node-connector'][0]['opendaylight-port-statistics:flow-capable-node-connector-statistics']
            s1_bytes2 = statistics['bytes']['transmitted']

            s1_speed=float(s1_bytes2-s1_bytes1)/0.5
            
            if s1_speed !=0 :#獲取有效的速度
                print ('s1端口2速度:')
                print s1_speed
                #在檢測到s1端口2流量空閒時發的流表
                if s1_speed < 1000 :
                    print(' s1端口2空閒,h1數據包改成往s1端口2經過')
                    response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/flow-node-inventory:table/0/flow/2', body=h1_to_s1_2, method='PUT',headers=headers)
                    response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/flow-node-inventory:table/0/flow/3', body=mh1_to_s1_2, method='PUT',headers=headers)
                #在檢測到s1端口2流量滿載時發的流表
                else :
                    print(' s1端口2滿載,h1數據包改成往s1端口3經過')
                    response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/flow-node-inventory:table/0/flow/2', body=h1_to_s1_3, method='PUT',headers=headers)
                    response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/flow-node-inventory:table/0/flow/3', body=mh1_to_s1_3, method='PUT',headers=headers)

            #獲取s2端口1的流量
            response, content = http.request(uri=s2_uri, method='GET')
            content = json.loads(content)
            statistics = content['node-connector'][0]['opendaylight-port-statistics:flow-capable-node-connector-statistics']
            s2_bytes1 = statistics['bytes']['transmitted']
            #0.5秒後再次獲取
            time.sleep(0.5)
            response, content = http.request(uri=s2_uri, method='GET')
            content = json.loads(content)
            statistics = content['node-connector'][0]['opendaylight-port-statistics:flow-capable-node-connector-statistics']
            s2_bytes2 = statistics['bytes']['transmitted']
            
            s2_speed=float(s2_bytes2-s2_bytes1)/0.5
        
            if s2_speed !=0 :#獲取有效的速度
                print ('s2端口1速度:')
                print s2_speed
                #在檢測到s2端口1流量空閒時發的流表
                if s2_speed < 1000 :
                    print(' s2端口1空閒,h3數據包改成往s2端口1經過')
                    response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:2/flow-node-inventory:table/0/flow/1', body=h3_to_s2_1, method='PUT',headers=headers)
                    response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:2/flow-node-inventory:table/0/flow/2', body=mh3_to_s2_2, method='PUT',headers=headers)
                #在檢測到s2端口1流量滿載時發的流表
                else :
                    print(' s2端口1滿載,h3數據包改成往s2端口2經過')
                    response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:2/flow-node-inventory:table/0/flow/1', body=mh3_to_s2_1, method='PUT',headers=headers)
                    response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:2/flow-node-inventory:table/0/flow/2', body=h3_to_s2_2, method='PUT',headers=headers)
odl = OdlUtil('127.0.0.1', '8181')
odl.install_flow()

二.實驗場景

服務器h2 h3上各自有不一樣的服務,h1是客戶端。實現一個負載均衡的北向程序,當h2和h3向h1傳輸數據時,北向應用根據鏈路的使用情況動態的調整路由規則。
主要思路:過必定的時間後,下發新的流表,使得流量流向另外一個交換機,從而實現負載均衡。相似於輪詢法。python


三.視頻演示
1.打開ODL
編程

2.查看拓撲
json

3.查看擁塞情況
ubuntu

4.調用負載均衡
服務器

5.負載均衡調用後的結果
cookie


三.小組分工網絡

  • 負責根據隊友所找的相關資料以及所選的拓撲來進行場景的設計與流表的編寫,同是與隊友共同進行代碼編寫以及後續的修改。

4、課程總結

首先對這學期的學習進行一個回顧總結

一、實踐操做:

  • 對ubuntu操做系統有了進一步的瞭解。
  • 安裝mininet,用字符命令、可視化界面、Python腳本等生成拓撲,並測試連通性。
  • 安裝floodlight,生成拓撲並鏈接控制器floodlight,利用控制器floodlight查看圖形拓撲,利用字符界面下發流表,來驗證openflow的hardtime機制。
  • 利用OVS命令下發流表和查看流表,實現VLAN功能。
  • Wireshark抓包驗證。
  • 利用ODL下發流表,藉助Postman經過ODL的北向接口下發流表,再利用ODL北向接口查看已下發的流表。
  • 利用ODL下發組表、流表,實現負載均衡,利用Wireshark驗證負載均衡的實現。

2.對SDN的認識:

(1)瞭解了SDN:

  • 軟件定義網絡(Software Defined Network, SDN ),是Emulex網絡一種新型網絡創新架構,是網絡虛擬化的一種實現方式,其核心技術OpenFlow經過將網絡設備控制面與數據面分離開來,從而實現了網絡流量的靈活控制,使網絡做爲管道變得更加智能。

(2)SDN基本思想:

  • 利用分層的思想,SDN將數據與控制相分離。在控制層,包括具備邏輯中心化和可編程的控制器,可掌握全局網絡信息,方便運營商和科研人員管理配置網絡和部署新協議等。在數據層,包括啞的交換機,交換機僅提供簡單的數據轉發功能,能夠快速處理匹配的數據包,適應流量日益增加的需求.兩層之間採用開放的統一接口進行交互。控制器經過標準接口向交換機下發統一標準規則,交換機僅需按照這些規則執行相應的動做便可。

(3)SDN優點:

  • SDN 技術可以有效下降設備負載,協助網絡運營商更好地控制基礎設施,下降總體運營成本。
  • SDN解放了手工操做,減小了配置錯誤,易於統一快速部署。

(4)瞭解了mininet

  • Mininet是由一些虛擬的終端節點(end-hosts)、交換機、路由器鏈接而成的一個網絡仿真器,它採用輕量級的虛擬化技術使得系統能夠和真實網絡相媲美。
  • Mininet能夠很方便地建立一個支持SDN的網絡:host就像真實的電腦同樣工做,可使用ssh登陸,啓動應用程序,程序能夠向以太網端口發送數據包,數據包會被交換機、路由器接收並處理。有了這個網絡,就能夠靈活地爲網絡添加新的功能並進行相關測試,而後輕鬆部署到真實的硬件環境中。

(5)瞭解了OpenFlow流表:

  • OpenFlow的每一個流表項都由3部分組成:
    • 用於數據包匹配的包頭域(Header Fields);
    • 用於統計匹配數據包個數的計數器(Counters);
    • 用於展現匹配的數據包如何處理的動做(Actions)。
  • OpenFlow流表的優勢:
    • 多級流表將數據包的處理邏輯劃分爲多個子邏輯,並由多張流表分別來匹配和處理,從而使得數據包的處理變成了一條流水線。單流表是沒法知足複雜的業務邏輯要求的。多線程

    • 多級流表的設計使得流表項聚合成爲可能,節省了流表空間,可減小流表項個數,也提升了編程處理邏輯的靈活性。架構

(6)SDN控制器:

  • POX:徹底使用Python語言編寫,採用與NOX一直的事件處理機制和編程模式,增長了多線程支持,
  • Floodlight:是基於Java語言的開源SDN控制器,當前支持的南向協議爲OpenFlow1.0協議。
  • OpenContrail: 是由 Juniper 推出的基於 C++的 SDN 控制器,提供了用於網絡虛擬化的基本組件。
  • Ryu:是基於 Python 語言的 開源 SDN 控制器。提供的完備 API 有助於網絡運營者高效便捷地開發 SDN 管理和控制應用。
  • onos:架構專一於電信運營商領域控制器關鍵需求:高可擴展性,高性能,高實時性,高可靠性。

(7)等價多路徑(Equal-CostMultipathRouting):

  • 存在多條不一樣鏈路到達同一目的地址的網絡環境中
  • 當設備支持等價路由時,發往該目的 IP 或者目的網段的三層轉發流量就能夠經過不一樣的路徑分擔,實現網絡的負載均衡,並在其中某些路徑出現故障時,由其它路徑代替完成轉發處理,實現路由冗餘備份功能。

(8)負載均衡(Load Balance):

  • 單個重負載的運算分擔到多臺節點設備上作並行處理,每一個節點設備處理結束後,將結果彙總,返回給用戶,系統處理能力獲得大幅度提升,這就是常說的集羣(clustering)技術。
  • 大量的併發訪問或數據流量分擔到多臺節點設備上分別處理,減小用戶等待響應的時間,這主要針對Web服務器、FTP服務器、企業關鍵應用服務器等網絡應用。

三、我的感覺:

  • SDN這門課程在理論知識方面給我帶來了不小的收穫,讓我瞭解到了一些歷來沒有接觸過的東西和理論,雖然如今網絡無處不在,可是在上這門課以前,我對網絡的認識還十分有限,對網絡的理解還僅僅停留在表面。通過了這門課程的學習,我對網絡有了新的認識,我明白了網速的快慢不只僅取決於網絡設備的性能,還取決於調配網絡資源的方案。SDN是在物理的網絡上面架設了一層虛擬的網絡,經過這個虛擬的網絡對物理網絡上的資源進行合理的分配,能極大的提升物理鏈路的利用率,從而達到提高網絡質量的效果。「軟件定義網絡」,讓我明白了在網絡不只僅取決於「硬件」,還取決於「軟件」。
  • 同時這門課又是一門實踐課,通過了幾回的上機練習,我不只對SDN有了更全面的瞭解,也對ubuntu有了更進一步的理解,同時這門課程也使我接觸到了一門新的語言,python。以前只是有據說過這門語言,而通過這門課程的學習讓我對這門語言有了初步的認識。在學習這門課程的過程當中必定程度上也提高了個人編碼能力。
相關文章
相關標籤/搜索