Untitled
unknown
python
2 years ago
5.6 kB
5
Indexable
from ryu.base import app_manager
from ryu.controller.handler import set_ev_cls
from ryu.ofproto import ofproto_v1_3
from ryu.topology import event
from ryu.topology.api import get_switch, get_link
from ryu.lib import hub
import networkx as nx
class EuclerCycle(app_manager.RyuApp):
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
def __init__(self, *args, **kwargs):
super(EuclerCycle, self).__init__(*args, **kwargs)
self.Topology_db = {}
self.network_changed_thread = hub.spawn_after(1,None)
self.graph = nx.Graph()
@set_ev_cls(event.EventSwitchEnter)
def handler_switch_enter(self, ev):
print("Switch entering---------------")
hub.kill(self.network_changed_thread)
self.network_changed_thread = hub.spawn_after(1,self.network_changed)
@set_ev_cls(event.EventSwitchLeave)
def handler_switch_leave(self, ev):
print("Switch leaving---------------")
hub.kill(self.network_changed_thread)
self.network_changed_thread = hub.spawn_after(1,self.network_changed)
def network_changed(self):
self.topo_raw_switches = get_switch(self, None)
self.topo_raw_links = get_link(self, None)
print("\nCurrent Links:")
for l in self.topo_raw_links:
print (str(l))
print("\nCurrent Switches:")
for s in self.topo_raw_switches:
print (str(s))
print("")
self.BuildTopology()
def BuildTopology(self):
self.graph.clear()
for l in self.topo_raw_links:
_dpid_src = l.src.dpid
_dpid_dst = l.dst.dpid
_port_src = l.src.port_no
_port_dst = l.dst.port_no
self.graph.add_edge(_dpid_src, _dpid_dst, port_src=_port_src, port_dst=_port_dst)
print("\nTopology Graph -------------------------------")
print(self.graph.edges())
self.FindEulerCycle()
self.Topology_db = {}
for switch in self.topo_raw_switches:
self.Topology_db[switch.dp.id] = {'datapath': switch.dp, 'ports': {}}
for port in switch.ports.values():
self.Topology_db[switch.dp.id]['ports'][port.port_no] = port
print("\nTopology Database -------------------------------")
print(self.Topology_db)
def FindEulerCycle(self):
try:
cycle = nx.eulerian_circuit(self.graph)
euler_cycle_nodes = []
print("\nEuler Cycle: ")
for node in cycle:
euler_cycle_nodes.append(node[0])
# Euler_cycle_nodes is a list containing the nodes in the Euler cycle
first_node = euler_cycle_nodes[0]
euler_cycle_nodes.append(first_node)
print(euler_cycle_nodes)
#self.AddReversePaths(euler_cycle_nodes, num_segments=2) # call the method to add branch paths
self.AddReversePaths(euler_cycle_nodes, num_segments=3)
except nx.NetworkXError as e:
print("Could not find Euler cycle: ", e)
def AddReversePaths(self, backbone_path, num_segments):
segment_length = len(backbone_path) // num_segments
branch_nodes = [backbone_path[i * segment_length] for i in range(1, num_segments)]
branch_nodes.append(backbone_path[-1]) # add the last node as a branch node
reverse_paths = []
for i in range(num_segments):
start = backbone_path[i * segment_length]
end = branch_nodes[i]
path = nx.shortest_path(self.graph, start, end)
path.reverse()
reverse_paths.append(path)
# Convert branch paths to topology paths
branch_paths = []
for i, path in enumerate(reverse_paths):
branch_path = []
for node in path:
if node in self.Topology_db:
datapath = self.Topology_db[node]['datapath']
branch_path.append(datapath)
else:
print("Switch {} not found in Topology_db".format(node))
branch_paths.append(branch_path)
# Print the branch paths
print(branch_paths)
# Modify the flow tables of switches based on the branch paths
for i, path in enumerate(branch_paths):
for j in range(len(path) - 1):
src_dpid = path[j].id
dst_dpid = path[j+1].id
if src_dpid in self.Topology_db:
datapath = self.Topology_db[src_dpid]['datapath']
src_port = self.graph[src_dpid][dst_dpid]['port_src']
dst_port = self.graph[src_dpid][dst_dpid]['port_dst']
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
match = parser.OFPMatch(in_port=src_port)
actions = [parser.OFPActionOutput(dst_port)]
inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)]
mod = parser.OFPFlowMod(datapath=datapath, priority=1, match=match, instructions=inst)
datapath.send_msg(mod)
print("Added flow entry to switch {} to forward packets from port {} to port {}".format(src_dpid, src_port, dst_port))
else:
print("Switch {} not found in Topology_db".format(src_dpid))
Editor is loading...