SDN网络负载均衡
sdn.py
代码分析
# -*- coding: utf-8 -*-
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"}]}'
#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"}]}'
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)
#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 :
#获取s2端口1的流量
uri = 'http://127.0.0.1:8181/restconf/operational/opendaylight-inventory:nodes/node/openflow:2/node-connector/openflow:2:1'
response, content = http.request(uri=uri, method='GET')
content = json.loads(content)
statistics = content['node-connector'][0]['opendaylight-port-statistics:flow-capable-node-connector-statistics']
bytes1 = statistics['bytes']['transmitted']
#1秒后再次获取
time.sleep(1)
response, content = http.request(uri=uri, method='GET')
content = json.loads(content)
statistics = content['node-connector'][0]['opendaylight-port-statistics:flow-capable-node-connector-statistics']
bytes2 = statistics['bytes']['transmitted']
#在检测到s2的1口流量空闲时发的流表
speed=float(bytes2-bytes1)/1
if speed !=0 :#获取有效的速度
if speed < 1000 :
print('s2端口1空闲,h3数据包改为往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数据包改为往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()
这段代码是一个使用Python编写的用于与OpenDaylight控制器进行交互的工具类。
首先,定义了一个名为OdlUtil
的类,构造函数中传入了OpenDaylight控制器的IP地址和端口号。然后,类中的install_flow
方法用于安装流表到OpenDaylight控制器。
在install_flow
方法中,首先使用httplib2
库创建一个HTTP对象,并使用提供的用户名和密码进行身份验证。然后,设置HTTP请求的头部信息。
接下来,定义了一系列的流表规则,这些规则以JSON格式表示,用于下发到OpenDaylight控制器。每个流表规则包括匹配条件、指令和优先级等信息。
通过使用http.request
方法,将流表规则作为请求体发送到OpenDaylight控制器的REST API接口,以下发流表。
在下发流表后,代码中使用循环获取s2交换机端口1的流量统计信息。通过发送HTTP GET请求到OpenDaylight控制器的REST API接口,获取端口的传输字节数。
根据获取的字节数计算速度,如果速度小于1000(假设单位为bytes/s),则将流量转发到s2交换机的端口1。如果速度大于等于1000,则将流量转发到s2交换机的端口2。
最后,创建了一个OdlUtil
对象,并调用install_flow
方法来安装流表。
请注意,这段代码假设了OpenDaylight控制器的REST API接口可通过http://127.0.0.1:8181
进行访问,并使用了默认的用户名和密码进行身份验证。你需要根据实际情况进行适当的修改和配置。
这段代码的意图
这段代码的主要目的是通过与OpenDaylight控制器交互来安装流表。它使用Python编写了一个名为OdlUtil
的工具类,其中的install_flow
方法用于向OpenDaylight控制器下发流表规则。
具体而言,代码通过HTTP请求与OpenDaylight控制器的REST API接口进行通信。它首先创建了一个HTTP对象,并使用提供的用户名和密码进行身份验证。然后,通过发送HTTP请求将流表规则作为请求体发送到OpenDaylight控制器。
代码中定义了一系列的流表规则,这些规则以JSON格式表示,包括匹配条件、指令和优先级等信息。根据实际需求,可以修改这些规则以满足特定的网络配置和流量控制需求。
在下发流表规则后,代码使用循环不断获取s2交换机端口1的流量统计信息。它通过发送HTTP GET请求到OpenDaylight控制器的REST API接口,获取端口的传输字节数,并根据字节数计算速度。
根据速度的阈值,代码动态地更新流表规则,将流量从s2交换机的端口1转发到端口2或者将流量从端口2转发到端口1,以实现流量负载均衡或流量控制的目的。
总之,这段代码旨在通过与OpenDaylight控制器交互,实现对网络流量的灵活控制和管理。它可以根据实时的流量情况动态地更新流表规则,以适应网络中的变化和需求。