一.實驗代碼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
三.小組分工網絡
多級流表將數據包的處理邏輯劃分爲多個子邏輯,並由多張流表分別來匹配和處理,從而使得數據包的處理變成了一條流水線。單流表是沒法知足複雜的業務邏輯要求的。多線程
多級流表的設計使得流表項聚合成爲可能,節省了流表空間,可減小流表項個數,也提升了編程處理邏輯的靈活性。架構