天天看點

SDN期末驗收

一.實驗代碼

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()



           

二.實驗場景

SDN期末驗收

伺服器h2 h3上各自有不同的服務,h1是用戶端。實作一個負載均衡的北向程式,當h2和h3向h1傳輸資料時,北向應用根據鍊路的使用狀況動态的調整路由規則。

主要思路:過一定的時間後,下發新的流表,使得流量流向另一個交換機,進而實作負載均衡。類似于輪詢法。

三.視訊示範

1.打開ODL

SDN期末驗收

2.檢視拓撲

SDN期末驗收

3.檢視擁塞狀況

SDN期末驗收

4.調用負載均衡

SDN期末驗收

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

SDN期末驗收

三.小組分工

  • 涼涼隊
    • 負責查找相關資料,參與場景的設計,并與隊友完成代碼的編寫與修改。

四、課程總結

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

1.從對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伺服器、企業關鍵應用伺服器等網絡應用。

2、實踐操作方面:

  • 安裝mininet,用字元指令、可視化界面、Python腳本等生成拓撲,并測試連通性。
  • 安裝floodlight,生成拓撲并連接配接控制器floodlight,利用控制器floodlight檢視圖形拓撲,利用字元界面下發流表,來驗證openflow的hardtime機制。
  • 利用OVS指令下發流表和檢視流表,實作VLAN功能。
  • Wireshark抓包驗證。
  • 利用ODL下發流表,借助Postman通過ODL的北向接口下發流表,再利用ODL北向接口檢視已下發的流表。
  • 利用ODL下發組表、流表,實作負載均衡,利用Wireshark驗證負載均衡的實作。

3、個人感受:

  • 總的來說,接觸了新知識,學習了新東西,感受很多,收獲很多。這門課的收獲還是很大的。以前從沒接觸過網絡程式設計,這次算是有了一個小小的入門。知道了SDN是什麼,知道了SDN可以給我們帶來很多的好處,可以有效地降低負載,同時對負載均衡也有了初步的了解。
  • 對流表的使用ODL的控制以及抓包有了初步的掌握。當然了,經過這門課程的實踐操作,我對指令行的操作比以往熟練了很多,以前隻在作業系統這門課程有一點接觸并不熟練。
  • 接觸了Python,又了解了一門新語言,我發現Python還是挺強大的。