Exemplo n.º 1
0
class SimpleSwitch13(app_manager.RyuApp):
    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]

    def __init__(self, *args, **kwargs):
        super(SimpleSwitch13, self).__init__(*args, **kwargs)
        self.graph = DirectedGraph()

    def add_flow(self, datapath, priority, match, actions, buffer_id=None):
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser

        inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                             actions)]
        if buffer_id:
            mod = parser.OFPFlowMod(datapath=datapath, buffer_id=buffer_id,
                                    priority=priority, match=match,
                                    instructions=inst)
        else:
            mod = parser.OFPFlowMod(datapath=datapath, priority=priority,
                                    match=match, instructions=inst)
        datapath.send_msg(mod)

    def update_topology(self):
        self.graph = DirectedGraph()

        switch_list = get_switch(self)
        for switch in switch_list:
            self.graph.add_node(SwitchNode(switch.dp.id, switch))

        links_list = get_link(self)
        for link in links_list:
            self.graph.add_edge(link.src.dpid, link.dst.dpid)
        print(self.graph)

    @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER)
    def _port_status_handler(self, ev):
        self.update_topology()

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def _packet_in_handler(self, ev):
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        in_port = msg.match['in_port']
        pkt = packet.Packet(msg.data)
        eth = pkt.get_protocol(ethernet.ethernet)

        # avoid broadcast from LLDP
        if eth.ethertype == 35020:
            return
Exemplo n.º 2
0
class Graph_test(unittest.TestCase):
    def setUp(self):
        self.graph = DirectedGraph()

    def test_add_node(self):
        self.graph.add_node('A')
        self.assertTrue('A' in self.graph.nodes)
        with self.assertRaises(Already_there):
            self.graph.add_node('A')

    def test_add_edge(self):
        self.graph.add_edge('A', 'B')
        self.assertEqual(self.graph.nodes['A'], set('B'))
        self.assertEqual(self.graph.nodes['B'], set())
        with self.assertRaises(Cant_follow_yourself):
            self.graph.add_edge('D', 'D')

    def test_get_neighbours(self):
        self.graph.add_edge('A', 'B')
        self.graph.add_edge('A', 'C')
        self.graph.add_edge('B', 'C')
        self.assertEqual(self.graph.nodes['A'], set(['B', 'C']))
        self.assertEqual(self.graph.nodes['B'], set(['C']))
        self.assertEqual(self.graph.nodes['C'], set())

    def test_bfs(self):
        self.graph.add_edge('A', 'B')
        self.graph.add_edge('A', 'C')
        self.graph.add_edge('B', 'C')
        self.graph.add_edge('C', 'D')
        self.graph.add_node('E')

        self.assertEqual(self.graph.bfs('A'), set(['A', 'B', 'C', 'D']))
        self.assertEqual(self.graph.bfs('E'), set(['E']))
        self.assertEqual(self.graph.bfs('B'), set(['B', 'C', 'D']))
        self.assertEqual(self.graph.bfs('C'), set(['D', 'C']))
        self.assertEqual(self.graph.bfs('D'), set(['D']))

    def test_path_between(self):
        self.graph.add_edge('A', 'B')
        self.graph.add_edge('A', 'C')
        self.graph.add_edge('B', 'C')
        self.graph.add_edge('C', 'D')
        self.graph.add_node('E')
        self.assertFalse(self.graph.path_between('B', 'A'))
        self.assertTrue(self.graph.path_between('A', 'D'))
        self.assertTrue(self.graph.path_between('A', 'C'))
Exemplo n.º 3
0
class SimpleSwitchRest13(simple_switch_13.SimpleSwitch13):
    _CONTEXTS = {
        'wsgi': WSGIApplication,
    }

    def __init__(self, *args, **kwargs):
        super(SimpleSwitchRest13, self).__init__(*args, **kwargs)
        self.switches = {}
        wsgi = kwargs['wsgi']

        wsgi.register(SimpleSwitchController,
                      {simple_switch_instance_name: self})

        self.graph = DirectedGraph()
        self.forwarding_tables = []
        self.mac_to_port = {}

    def update_topology(self):
        self.graph = DirectedGraph()

        switch_list = get_switch(self)
        for switch in switch_list:
            self.graph.add_node(SwitchNode(switch.dp.id, switch))

        links_list = get_link(self)
        for link in links_list:
            self.graph.add_edge(link.src.dpid, link.dst.dpid)
        print(self.graph)
        print(len(links_list))
        print("test")

    def add_flow(self, datapath, priority, match, actions, buffer_id=None):
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser

        inst = [
            parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)
        ]
        if buffer_id:
            mod = parser.OFPFlowMod(datapath=datapath,
                                    buffer_id=buffer_id,
                                    priority=priority,
                                    match=match,
                                    instructions=inst)
        else:
            mod = parser.OFPFlowMod(datapath=datapath,
                                    priority=priority,
                                    match=match,
                                    instructions=inst)
        datapath.send_msg(mod)

    def _handle_arp(self, datapath, port, pkt_ethernet, pkt_arp,
                    target_hw_addr, target_ip_addr):
        # see http://osrg.github.io/ryu-book/en/html/packet_lib.html
        if pkt_arp.opcode != arp.ARP_REQUEST:
            return
        pkt = packet.Packet()
        pkt.add_protocol(
            ethernet.ethernet(ethertype=pkt_ethernet.ethertype,
                              dst=pkt_ethernet.src,
                              src=target_hw_addr))
        pkt.add_protocol(
            arp.arp(opcode=arp.ARP_REPLY,
                    src_mac=target_hw_addr,
                    src_ip=target_ip_addr,
                    dst_mac=pkt_arp.src_mac,
                    dst_ip=pkt_arp.src_ip))
        self._send_packet(datapath, port, pkt)

    def _send_packet(self, datapath, port, pkt):
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        pkt.serialize()
        self.logger.info("To dpid {0} packet-out {1}".format(datapath.id, pkt))
        data = pkt.data
        actions = [parser.OFPActionOutput(port=port)]
        out = parser.OFPPacketOut(datapath=datapath,
                                  buffer_id=ofproto.OFP_NO_BUFFER,
                                  in_port=ofproto.OFPP_CONTROLLER,
                                  actions=actions,
                                  data=data)
        datapath.send_msg(out)

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def _packet_in_handler(self, ev):
        if ev.msg.msg_len < ev.msg.total_len:
            self.logger.debug("packet truncated: only %s of %s bytes",
                              ev.msg.msg_len, ev.msg.total_len)
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        in_port = msg.match['in_port']

        pkt = packet.Packet(msg.data)
        eth = pkt.get_protocols(ethernet.ethernet)[0]

        if eth.ethertype == ether_types.ETH_TYPE_LLDP:
            # ignore lldp packet
            return

        dst = eth.dst
        src = eth.src
        dpid = datapath.id

        pkt_arp = pkt.get_protocol(arp.arp)
        if pkt_arp:
            print(pkt_arp)
            d_ip = pkt_arp.dst_ip
            s_ip = pkt_arp.src_ip

            arp_table = None
            for entry in self.forwarding_tables:
                switch_id = entry['switch_id']
                src_ip = entry['src_ip']
                dst_ip = entry['dst_ip']
                eth_src = entry["eth_src"]
                eth_dst = entry["eth_dst"]
                in_port = entry['in_port']
                out_port = entry['out_port']

                if dpid == switch_id and dst_ip == d_ip:
                    arp_table = entry
                    break

            if arp_table:
                self._handle_arp(datapath=datapath,
                                 port=in_port,
                                 pkt_ethernet=pkt.get_protocols(
                                     ethernet.ethernet)[0],
                                 pkt_arp=pkt_arp,
                                 target_hw_addr=arp_table["eth_dst"],
                                 target_ip_addr=d_ip)

        for entry in self.forwarding_tables:
            switch_id = entry['switch_id']
            src_ip = entry['src_ip']
            dst_ip = entry['dst_ip']
            eth_src = entry["eth_src"]
            eth_dst = entry["eth_dst"]
            in_port = entry['in_port']
            out_port = entry['out_port']

            if dpid == switch_id and eth_src == src and eth_dst == dst:
                match = parser.OFPMatch(in_port=in_port,
                                        eth_dst=eth_dst,
                                        eth_src=eth_src)
                actions = [parser.OFPActionOutput(out_port)]
                self.add_flow(datapath, 1, match, actions)
                print(match)

    @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
    def switch_features_handler(self, ev):
        super(SimpleSwitchRest13, self).switch_features_handler(ev)
        datapath = ev.msg.datapath
        self.switches[datapath.id] = datapath
        self.mac_to_port.setdefault(datapath.id, {})

    def set_mac_to_port(self, dpid, entry):
        mac_table = self.mac_to_port.setdefault(dpid, {})
        datapath = self.switches.get(dpid)

        entry_port = entry['port']
        entry_mac = entry['mac']

        if datapath is not None:
            parser = datapath.ofproto_parser
            if entry_port not in mac_table.values():

                for mac, port in mac_table.items():
                    # from known device to new device
                    actions = [parser.OFPActionOutput(entry_port)]
                    match = parser.OFPMatch(in_port=port, eth_dst=entry_mac)
                    self.add_flow(datapath, 1, match, actions)

                    # from new device to known device
                    actions = [parser.OFPActionOutput(port)]
                    match = parser.OFPMatch(in_port=entry_port, eth_dst=mac)
                    self.add_flow(datapath, 1, match, actions)

                mac_table.update({entry_mac: entry_port})
        return mac_table

    def find_src_dpid(self, src_addr):
        switch_list = get_all_switch(self)
        for switch in switch_list:
            port_list = switch.ports
            for port in port_list:
                if src_addr == port.hw_addr:
                    print(port.hw_addr, port.dpid)
                    return (port.hw_addr, port.dpid)

                #    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)

    @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER)
    def _port_status_handler(self, ev):
        msg = ev.msg
        reason = msg.reason
        port_no = msg.desc.port_no

        ofproto = msg.datapath.ofproto

        print("links:")
        links = get_link(self)
        print(links)

        print("switches:")
        switches = get_switch(self)
        print(switches)
        print(" [", end='')
        for switch in switches:
            print(switch.dp.id, end='')
            print(",", end='')
        print("]")

    def remove_table_flows(self, datapath, table_id, match, instructions):
        ofproto = datapath.ofproto
        flow_mod = datapath.ofproto_parser.OFPFlowMod(
            datapath, 0, 0, table_id, ofproto.OFPFC_DELETE, 0, 0, 1,
            ofproto.OFPCML_NO_BUFFER, ofproto.OFPP_ANY, ofproto.OFPG_ANY, 0,
            match, instructions)
        return flow_mod
Exemplo n.º 4
0
class SimpleSwitchRest13(simple_switch_13.SimpleSwitch13):
    _CONTEXTS = {
        'wsgi': WSGIApplication,
    }

    def __init__(self, *args, **kwargs):
        super(SimpleSwitchRest13, self).__init__(*args, **kwargs)
        self.switches = {}
        wsgi = kwargs['wsgi']

        wsgi.register(SimpleSwitchController,
                      {simple_switch_instance_name: self})

        self.graph = DirectedGraph()
        self.forwarding_tables = []
        self.mac_to_port = {}

        self.ip_to_mac = {
            "169.254.20.158": "b8:27:eb:17:0d:96",
            "169.254.173.130": "b8:27:eb:7f:7c:ea",
            "169.254.240.121": "b8:27:eb:81:61:47"
        }
        self.link_to_port = {
            (1, "169.254.20.158"): 2,
            (9, "169.254.173.130"): 16,
            (8, "169.254.240.121"): 2
        }

    def update_topology(self):
        self.graph = DirectedGraph()

        switch_list = get_switch(self)
        for switch in switch_list:
            self.graph.add_node(SwitchNode(switch.dp.id, switch))

        links_list = get_link(self)
        for link in links_list:
            self.graph.add_edge(link.src.dpid, link.dst.dpid)
        print(self.graph)
        print(len(links_list))
        print("test")

    def add_flow(self, datapath, priority, match, actions, buffer_id=None):
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser

        inst = [
            parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)
        ]
        if buffer_id:
            mod = parser.OFPFlowMod(datapath=datapath,
                                    buffer_id=buffer_id,
                                    priority=priority,
                                    match=match,
                                    instructions=inst)
        else:
            mod = parser.OFPFlowMod(datapath=datapath,
                                    priority=priority,
                                    match=match,
                                    instructions=inst)
        datapath.send_msg(mod)

    def _handle_arp(self, datapath, port, pkt_ethernet, pkt_arp,
                    target_hw_addr, target_ip_addr):
        # see http://osrg.github.io/ryu-book/en/html/packet_lib.html
        if pkt_arp.opcode != arp.ARP_REQUEST:
            return
        pkt = packet.Packet()
        pkt.add_protocol(
            ethernet.ethernet(ethertype=pkt_ethernet.ethertype,
                              dst=pkt_ethernet.src,
                              src=target_hw_addr))
        pkt.add_protocol(
            arp.arp(opcode=arp.ARP_REPLY,
                    src_mac=target_hw_addr,
                    src_ip=target_ip_addr,
                    dst_mac=pkt_arp.src_mac,
                    dst_ip=pkt_arp.src_ip))
        self._send_packet(datapath, port, pkt)

    def _send_packet(self, datapath, port, pkt):
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        pkt.serialize()
        self.logger.info("To dpid {0} packet-out {1}".format(datapath.id, pkt))
        data = pkt.data
        actions = [parser.OFPActionOutput(port=port)]
        out = parser.OFPPacketOut(datapath=datapath,
                                  buffer_id=ofproto.OFP_NO_BUFFER,
                                  in_port=ofproto.OFPP_CONTROLLER,
                                  actions=actions,
                                  data=data)
        datapath.send_msg(out)

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def _packet_in_handler(self, ev):
        msg = ev.msg
        # print("#############################################")
        datapath = msg.datapath
        dpid = datapath.id
        parser = datapath.ofproto_parser
        ofproto = datapath.ofproto
        port = msg.match['in_port']
        pkt = packet.Packet(data=msg.data)
        # self.logger.info("packet-in: %s" % (pkt,))

        eth = pkt.get_protocols(ethernet.ethernet)[0]

        pkt_eth = pkt.get_protocol(ethernet.ethernet)
        if pkt_eth:
            dst_mac = pkt_eth.dst
            eth_type = pkt_eth.ethertype

        if eth.ethertype == ether_types.ETH_TYPE_LLDP:
            # ignore lldp packet
            return

        pkt_arp = pkt.get_protocol(arp.arp)
        if pkt_arp:
            print("datapath id: " + str(dpid))
            print("port: " + str(port))
            print("pkt_eth.dst: " + str(pkt_eth.dst))
            print("pkt_eth.src: " + str(pkt_eth.src))
            print("pkt_arp: " + str(pkt_arp))
            print("pkt_arp:src_ip: " + str(pkt_arp.src_ip))
            print("pkt_arp:dst_ip: " + str(pkt_arp.dst_ip))
            print("pkt_arp:src_mac: " + str(pkt_arp.src_mac))
            print("pkt_arp:dst_mac: " + str(pkt_arp.dst_mac))

            # Destination and source ip address
            d_ip = pkt_arp.dst_ip
            s_ip = pkt_arp.src_ip

            # Destination and source mac address (HW address)
            d_mac = pkt_arp.dst_mac
            s_mac = pkt_arp.src_mac

            in_port = msg.match['in_port']
            dst_addr = self.ip_to_mac[d_ip]

            self._handle_arp(datapath=datapath,
                             port=in_port,
                             pkt_ethernet=pkt.get_protocols(
                                 ethernet.ethernet)[0],
                             pkt_arp=pkt_arp,
                             target_hw_addr=dst_addr,
                             target_ip_addr=d_ip)
        else:
            print("OTHER")
            print(pkt)
            for entry in self.forwarding_tables:
                switch_id = entry['switch_id']
                src_ip = entry['src_ip']
                dst_ip = entry['dst_ip']
                out_port = entry['out_port']

                if dpid == switch_id:
                    match = parser.OFPMatch(ipv4_src=src_ip,
                                            ipv4_dst=dst_ip,
                                            eth_type=ether.ETH_TYPE_IP)
                    actions = [parser.OFPActionOutput(out_port)]
                    self.add_flow(datapath, 1, match, actions)
                    print("MATCH:")
                    print(match)

    @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
    def switch_features_handler(self, ev):
        super(SimpleSwitchRest13, self).switch_features_handler(ev)
        datapath = ev.msg.datapath
        self.switches[datapath.id] = datapath
        self.mac_to_port.setdefault(datapath.id, {})

    def set_mac_to_port(self, dpid, entry):
        mac_table = self.mac_to_port.setdefault(dpid, {})
        datapath = self.switches.get(dpid)

        entry_port = entry['port']
        entry_mac = entry['mac']

        if datapath is not None:
            parser = datapath.ofproto_parser
            if entry_port not in mac_table.values():

                for mac, port in mac_table.items():
                    # from known device to new device
                    actions = [parser.OFPActionOutput(entry_port)]
                    match = parser.OFPMatch(in_port=port, eth_dst=entry_mac)
                    self.add_flow(datapath, 1, match, actions)

                    # from new device to known device
                    actions = [parser.OFPActionOutput(port)]
                    match = parser.OFPMatch(in_port=entry_port, eth_dst=mac)
                    self.add_flow(datapath, 1, match, actions)

                mac_table.update({entry_mac: entry_port})
        return mac_table

    def find_src_dpid(self, src_addr):
        switch_list = get_all_switch(self)
        for switch in switch_list:
            port_list = switch.ports
            for port in port_list:
                if src_addr == port.hw_addr:
                    print(port.hw_addr, port.dpid)
                    return (port.hw_addr, port.dpid)

                #    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)

    @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER)
    def _port_status_handler(self, ev):
        msg = ev.msg
        reason = msg.reason
        port_no = msg.desc.port_no

        ofproto = msg.datapath.ofproto

        print("links:")
        links = get_link(self)
        print(links)

        print("switches:")
        switches = get_switch(self)
        print(switches)
        print(" [", end='')
        for switch in switches:
            print(switch.dp.id, end='')
            print(",", end='')
        print("]")

    def remove_table_flows(self, datapath, table_id, match, instructions):
        ofproto = datapath.ofproto
        flow_mod = datapath.ofproto_parser.OFPFlowMod(
            datapath, 0, 0, table_id, ofproto.OFPFC_DELETE, 0, 0, 1,
            ofproto.OFPCML_NO_BUFFER, ofproto.OFPP_ANY, ofproto.OFPG_ANY, 0,
            match, instructions)
        return flow_mod
Exemplo n.º 5
0
class SimpleSwitchRest13(simple_switch_13.SimpleSwitch13):
    _CONTEXTS = {
        'wsgi': WSGIApplication,
    }

    def __init__(self, *args, **kwargs):
        super(SimpleSwitchRest13, self).__init__(*args, **kwargs)
        self.switches = {}
        wsgi = kwargs['wsgi']

        wsgi.register(SimpleSwitchController,
                      {simple_switch_instance_name: self})

        self.graph = DirectedGraph()

    def update_topology(self):
        self.graph = DirectedGraph()

        switch_list = get_switch(self)
        for switch in switch_list:
            self.graph.add_node(SwitchNode(switch.dp.id, switch))

        links_list = get_link(self)
        for link in links_list:
            self.graph.add_edge(link.src.dpid, link.dst.dpid)
        print(self.graph)
        print(len(links_list))
        print("test")

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def _packet_in_handler(self, ev):
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        in_port = msg.match['in_port']
        pkt = packet.Packet(msg.data)
        eth = pkt.get_protocol(ethernet.ethernet)

        # avoid broadcast from LLDP
        if eth.ethertype == 35020:
            return

        print(pkt)

    @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
    def switch_features_handler(self, ev):
        super(SimpleSwitchRest13, self).switch_features_handler(ev)
        datapath = ev.msg.datapath
        self.switches[datapath.id] = datapath
        self.mac_to_port.setdefault(datapath.id, {})

    def set_mac_to_port(self, dpid, entry):
        mac_table = self.mac_to_port.setdefault(dpid, {})
        datapath = self.switches.get(dpid)

        entry_port = entry['port']
        entry_mac = entry['mac']

        if datapath is not None:
            parser = datapath.ofproto_parser
            if entry_port not in mac_table.values():

                for mac, port in mac_table.items():
                    # from known device to new device
                    actions = [parser.OFPActionOutput(entry_port)]
                    match = parser.OFPMatch(in_port=port, eth_dst=entry_mac)
                    self.add_flow(datapath, 1, match, actions)

                    # from new device to known device
                    actions = [parser.OFPActionOutput(port)]
                    match = parser.OFPMatch(in_port=entry_port, eth_dst=mac)
                    self.add_flow(datapath, 1, match, actions)

                mac_table.update({entry_mac: entry_port})
        return mac_table

    def find_src_dpid(self, src_addr):
        switch_list = get_all_switch(self)
        for switch in switch_list:
            port_list = switch.ports
            for port in port_list:
                if src_addr == port.hw_addr:
                    print(port.hw_addr, port.dpid)
                    return (port.hw_addr, port.dpid)

                #    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)

    @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER)
    def _port_status_handler(self, ev):
        msg = ev.msg
        reason = msg.reason
        port_no = msg.desc.port_no

        ofproto = msg.datapath.ofproto

        print("links:")
        links = get_link(self)
        print(links)

        print("switches:")
        switches = get_switch(self)
        print(switches)
        print(" [", end='')
        for switch in switches:
            print(switch.dp.id, end='')
            print(",", end='')
        print("]")

    def remove_table_flows(self, datapath, table_id, match, instructions):
        ofproto = datapath.ofproto
        flow_mod = datapath.ofproto_parser.OFPFlowMod(
            datapath, 0, 0, table_id, ofproto.OFPFC_DELETE, 0, 0, 1,
            ofproto.OFPCML_NO_BUFFER, ofproto.OFPP_ANY, ofproto.OFPG_ANY, 0,
            match, instructions)
        return flow_mod