Untitled

mail@pastecode.io avatar
unknown
python
a year ago
5.6 kB
0
Indexable
Never
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))