def _packet_in_handler(self, ev):
        msg = ev.msg
        pkt = packet.Packet(msg.data)

        pkt_ethernet = pkt.get_protocols(ethernet.ethernet)[0]
        datapath = msg.datapath
        port = msg.match['in_port']

        # Checking if it's the probe packet for RTT estimation
        if pkt_ethernet.ethertype == self.PROBE_ETHERTYPE:
            self.probe_packet_handler(pkt)
            return

        # Ignoring LLDP Packets
        try:
            LLDPPacket.lldp_parse(msg.data)
            self.logger.debug('Received LLDP Packet')
            return
        except:
            pass

        self.logger.debug('EventOFPPacketIn %s' % pkt)

        # Handling ARP
        pkt_arp = pkt.get_protocol(arp.arp)
        if pkt_arp:
            self._handle_arp(msg, datapath, port, pkt, pkt_arp)
            return

        pkt_ipv4 = pkt.get_protocol(ipv4.ipv4)
        pkt_icmp = pkt.get_protocol(icmp.icmp)

        # Handling ICMPv4
        if pkt_icmp:
            self._handle_icmpv4(
                msg, datapath, port, pkt_ethernet, pkt_ipv4, pkt_icmp)
            return

        # Handing IPv4
        if pkt_ipv4:
            self._handle_ipv4(datapath, port, pkt_ethernet, pkt_ipv4)
            return

        pkt_ipv6 = pkt.get_protocol(ipv6.ipv6)
        pkt_icmp = pkt.get_protocol(icmpv6.icmpv6)

        # Handling ICMPv6
        if pkt_icmp:
            self._handle_icmpv6(
                datapath, port, pkt_ethernet, pkt_ipv6, pkt_icmp)
            return

        # Handing IPv6
        if pkt_ipv4:
            self._handle_ipv6(datapath, port, pkt_ethernet, pkt_ipv4)
            return

        # Unhandled
        self.logger.debug('Unknown packet %s' % str(pkt))
Esempio n. 2
0
    def _packet_in_handler(self, ev):
        msg = ev.msg
        pkt = packet.Packet(msg.data)

        pkt_ethernet = pkt.get_protocols(ethernet.ethernet)[0]
        datapath = msg.datapath
        port = msg.match['in_port']

        # Checking if it's the probe packet for RTT estimation
        if pkt_ethernet.ethertype == self.PROBE_ETHERTYPE:
            self.probe_packet_handler(pkt)
            return

        # Ignoring LLDP Packets
        try:
            LLDPPacket.lldp_parse(msg.data)
            self.logger.debug('Received LLDP Packet')
            return
        except:
            pass

        self.logger.debug('EventOFPPacketIn %s' % pkt)

        # Handling ARP
        pkt_arp = pkt.get_protocol(arp.arp)
        if pkt_arp:
            self._handle_arp(msg, datapath, port, pkt, pkt_arp)
            return

        pkt_ipv4 = pkt.get_protocol(ipv4.ipv4)
        pkt_icmp = pkt.get_protocol(icmp.icmp)

        # Handling ICMPv4
        if pkt_icmp:
            self._handle_icmpv4(msg, datapath, port, pkt_ethernet, pkt_ipv4,
                                pkt_icmp)
            return

        # Handing IPv4
        if pkt_ipv4:
            self._handle_ipv4(datapath, port, pkt_ethernet, pkt_ipv4)
            return

        pkt_ipv6 = pkt.get_protocol(ipv6.ipv6)
        pkt_icmp = pkt.get_protocol(icmpv6.icmpv6)

        # Handling ICMPv6
        if pkt_icmp:
            self._handle_icmpv6(datapath, port, pkt_ethernet, pkt_ipv6,
                                pkt_icmp)
            return

        # Handing IPv6
        if pkt_ipv4:
            self._handle_ipv6(datapath, port, pkt_ethernet, pkt_ipv4)
            return

        # Unhandled
        self.logger.debug('Unknown packet %s' % str(pkt))
Esempio n. 3
0
    def _packet_in_handler(self, ev):
        # If you hit this you might want to increase
        # the "miss_send_length" of your switch
        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

        try:
            # ignore lldp packet
            LLDPPacket.lldp_parse(msg.data)
            return
        except LLDPPacket.LLDPUnknownFormat:
            pass
        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]

        dst = eth.dst
        src = eth.src

        dpid = datapath.id
        self.mac_to_port.setdefault(dpid, {})

        self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port)

        # learn a mac address to avoid FLOOD next time.
        self.mac_to_port[dpid][src] = in_port

        if dst in self.mac_to_port[dpid]:
            out_port = self.mac_to_port[dpid][dst]
        else:
            out_port = ofproto.OFPP_FLOOD

        actions = [parser.OFPActionOutput(out_port)]

        # install a flow to avoid packet_in next time
        if out_port != ofproto.OFPP_FLOOD:
            match = parser.OFPMatch(in_port=in_port, eth_dst=dst)
            # verify if we have a valid buffer_id, if yes avoid to send both
            # flow_mod & packet_out
            if msg.buffer_id != ofproto.OFP_NO_BUFFER:
                self.add_flow(datapath, 1, match, actions, msg.buffer_id)
                return
            else:
                self.add_flow(datapath, 1, match, actions)
        data = None
        if msg.buffer_id == ofproto.OFP_NO_BUFFER:
            data = msg.data

        out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id,
                                  in_port=in_port, actions=actions, data=data)
        datapath.send_msg(out)
Esempio n. 4
0
File: c.py Progetto: yyzhou94/Ryu
    def packet_in_handler(self, ev):
        msg = ev.msg
        datapath = msg.datapath

        try:
            #LLDP handler
            src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data)
            dst_dpid, dst_port_no = datapath.id, msg.match['in_port']
            self.add_topo(src_dpid, dst_dpid, src_port_no, dst_port_no)
            link = api.get_link(self)
            print self.topo
            for i in link:
                src = i.src
                dst = i.dst
                self.topo[(src.dpid, dst.dpid)] = (src.port_no, dst.port_no)

        except LLDPPacket.LLDPUnknownFormat:
            ofproto = datapath.ofproto
            parser = datapath.ofproto_parser
            pkt = packet.Packet(msg.data)
            eth = pkt.get_protocols(ethernet.ethernet)[0]
            mac = eth.src
            dpid, port = datapath.id, msg.match['in_port']
            actions = [parser.OFPActionOutput(ofproto.OFPP_FLOOD)]
            data = None
            if msg.buffer_id == ofproto.OFP_NO_BUFFER:
                data = msg.data
            out = parser.OFPPacketOut(datapath=datapath,
                                      buffer_id=msg.buffer_id,
                                      in_port=port,
                                      actions=actions,
                                      data=data)
            datapath.send_msg(out)
Esempio n. 5
0
    def packet_in_handler(self, ev):

        """

            Parsing LLDP packet and get the delay of link.

        """

        msg = ev.msg

        try:

            src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data)

            dpid = msg.datapath.id

            if self.sw_module is None:

                self.sw_module = lookup_service_brick('switches')



            for port in self.sw_module.ports.keys():

                if src_dpid == port.dpid and src_port_no == port.port_no:

                    delay = self.sw_module.ports[port].delay

                    self._save_lldp_delay(src=src_dpid, dst=dpid,

                                          lldpdelay=delay)

        except LLDPPacket.LLDPUnknownFormat as e:

            return
Esempio n. 6
0
    def packet_in_handler(self, ev):
        """
                      Controller
                    |        /|\    
                   \|/         |
                Switch----->Switch
        """
        msg = ev.msg
        try:
            src_dpid, src_outport = LLDPPacket.lldp_parse(msg.data)
            dst_dpid = msg.datapath.id
            dst_inport = msg.match['in_port']
            if self.switches is None:
                self.switches = lookup_service_brick("switches")

            for port in self.switches.ports.keys():
                if src_dpid == port.dpid and src_outport == port.port_no:
                    port_data = self.switches.ports[port]
                    timestamp = port_data.timestamp
                    if timestamp:
                        delay = time.time() - timestamp
                        self._save_delay_data(src=src_dpid,
                                              dst=dst_dpid,
                                              src_port=src_outport,
                                              lldpdealy=delay)
        except:
            return
Esempio n. 7
0
    def _packet_in_handler(self, ev):
        msg = ev.msg
        try:
            # ignore lldp packet
            LLDPPacket.lldp_parse(msg.data)
            return
        except LLDPPacket.LLDPUnknownFormat:
            pass
        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]

        dst = eth.dst
        src = eth.src

        dpid = datapath.id
        self.mac_to_port.setdefault(dpid, {})

        self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port)

        # learn a mac address to avoid FLOOD next time.
        self.mac_to_port[dpid][src] = in_port

        if dst in self.mac_to_port[dpid]:
            out_port = self.mac_to_port[dpid][dst]
        else:
            out_port = ofproto.OFPP_FLOOD

        actions = [parser.OFPActionOutput(out_port)]

        # install a flow to avoid packet_in next time
        if out_port != ofproto.OFPP_FLOOD:
            match = parser.OFPMatch(in_port=in_port, eth_dst=dst)
            self.add_flow(datapath, 1, match, actions)

        data = None
        if msg.buffer_id == ofproto.OFP_NO_BUFFER:
            data = msg.data

        out = parser.OFPPacketOut(
            datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port, actions=actions, data=data
        )
        datapath.send_msg(out)
Esempio n. 8
0
def main():

    iface = get_if()
    print("iface: ", iface)

    pkt = LLDPPacket.lldp_packet(1, 0, get_if_hwaddr(iface), 10)
    p = Ether(_pkt=pkt)
    sendp(pkt, iface=iface, verbose=False)
Esempio n. 9
0
 def lldp_parse_new(data):
     pkt = packet.Packet(data)
     i = iter(pkt)
     eth_pkt = six.next(i)
     assert type(eth_pkt) == ethernet.ethernet
     lldp_pkt = six.next(i)
     if type(lldp_pkt) != lldp.lldp:
         raise LLDPPacket.LLDPUnknownFormat()
     return lldp_pkt
Esempio n. 10
0
    def _packet_in_handler(self, ev):
        """Handle packet_in events."""
        if not self.link_discovery:
            return
        msg = ev.msg
        in_port = msg.match['in_port']
        packet = Packet(msg.data)
        efm = packet.get_protocol(ethernet.ethernet)
        if efm.ethertype == ether.ETH_TYPE_ARP:
            self.send_event_to_observers(event.EventArpReceived(ev))

        try:
            src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data)
        except LLDPPacket.LLDPUnknownFormat as e:
            # This handler can receive all the packtes which can be
            # not-LLDP packet. Ignore it silently
            return
        else:
            dst_dpid = msg.datapath.id
            dst_port_no = in_port

            src = self._get_port(src_dpid, src_port_no)
            if not src or src.dpid == dst_dpid:
                return

            dst = self._get_port(dst_dpid, dst_port_no)
            if not dst:
                return

            old_peer = self.links.get_peer(src)
            #LOG.debug("Packet-In")
            #LOG.debug("  src=%s", src)
            #LOG.debug("  dst=%s", dst)
            #LOG.debug("  old_peer=%s", old_peer)
            if old_peer and old_peer != dst:
                old_link = Link(src, old_peer)
                self.send_event_to_observers(event.EventLinkDelete(old_link))

            link = Link(src, dst)
            if not link in self.links:
                self.send_event_to_observers(event.EventLinkAdd(link))

            if not self.links.update_link(src, dst):
                # reverse link is not detected yet.
                # So schedule the check early because it's very likely it's up
                try:
                    self.ports.lldp_received(dst)
                except KeyError as e:
                    # There are races between EventOFPPacketIn and
                    # EventDPPortAdd. So packet-in event can happend before
                    # port add event. In that case key error can happend.
                    # LOG.debug('lldp_received: KeyError %s', e)
                    pass
                else:
                    self.ports.move_front(dst)
                    self.lldp_event.set()
Esempio n. 11
0
    def _packet_in_handler(self, ev):
        """Handle packet_in events."""
        if not self.link_discovery:
            return
        msg = ev.msg
        in_port = msg.match['in_port']
        packet = Packet(msg.data)
        efm = packet.next()
        if efm.ethertype == ether.ETH_TYPE_ARP:
            self.send_event_to_observers(event.EventArpReceived(ev))

        try:
            src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data)
        except LLDPPacket.LLDPUnknownFormat as e:
            # This handler can receive all the packtes which can be
            # not-LLDP packet. Ignore it silently
            return
        else:
            dst_dpid = msg.datapath.id
            dst_port_no = in_port

            src = self._get_port(src_dpid, src_port_no)
            if not src or src.dpid == dst_dpid:
                return

            dst = self._get_port(dst_dpid, dst_port_no)
            if not dst:
                return

            old_peer = self.links.get_peer(src)
            #LOG.debug("Packet-In")
            #LOG.debug("  src=%s", src)
            #LOG.debug("  dst=%s", dst)
            #LOG.debug("  old_peer=%s", old_peer)
            if old_peer and old_peer != dst:
                old_link = Link(src, old_peer)
                self.send_event_to_observers(event.EventLinkDelete(old_link))

            link = Link(src, dst)
            if not link in self.links:
                self.send_event_to_observers(event.EventLinkAdd(link))

            if not self.links.update_link(src, dst):
                # reverse link is not detected yet.
                # So schedule the check early because it's very likely it's up
                try:
                    self.ports.lldp_received(dst)
                except KeyError as e:
                    # There are races between EventOFPPacketIn and
                    # EventDPPortAdd. So packet-in event can happend before
                    # port add event. In that case key error can happend.
                    # LOG.debug('lldp_received: KeyError %s', e)
                    pass
                else:
                    self.ports.move_front(dst)
                    self.lldp_event.set()
 def _execute_lldp(self, s, callback):
     time.sleep(s)
     for switch in self.networkMap.getAllSwitches():
         parser = switch.dp.ofproto_parser
         ofproto = switch.dp.ofproto
         for port in self.networkMap.getAllSwitchPorts(switch):
             pkt = LLDPPacket.lldp_packet(switch.dp.id, 1, port.hw_addr, 1)
             actions = [parser.OFPActionOutput(port=port.port_no)]
             callback(switch.dp, actions, pkt, ofproto.OFPP_CONTROLLER)
     self.networkMap.report()
     self._execute_lldp(s, callback)
Esempio n. 13
0
    def _packet_in_handler(self, ev):
        try:
            msg = ev.msg
            LLDPPacket.lldp_parse(msg.data)
            return
        except LLDPPacket.LLDPUnknownFormat:
            # it's host
            dpid = msg.datapath.id
            port = -1

            if msg.datapath.ofproto.OFP_VERSION == ofproto_v1_0.OFP_VERSION:
                port = msg.in_port
            elif msg.datapath.ofproto.OFP_VERSION >= ofproto_v1_2.OFP_VERSION:
                port = msg.match['in_port']

            if port >= 1024:
                # hack: ignore some strange port
                return

            # ignore global host
            for link in self.cross_domain_links:

                if link['src']['dpid'] == dpid and \
                   link['src']['port'] == port:
                    return

            # TODO, check again if host already in global port

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

            if mac not in self.hosts and port != -1 and \
                not self._host_exist_in_port(dpid, port) and \
                    not self._is_switch_port_to_port(dpid, port):
                LOG.debug('Add host %s to %d:%d', mac, dpid, port)
                self.hosts[mac] = (dpid, port)
                self.response_host(mac)
                ev = EventHostDiscovery(dpid, port, mac)
                self.send_event_to_observers(ev)
Esempio n. 14
0
    def _packet_in_handler(self, ev):
        try:
            msg = ev.msg
            LLDPPacket.lldp_parse(msg.data)
            return
        except LLDPPacket.LLDPUnknownFormat:
            # it's host
            dpid = msg.datapath.id
            port = -1

            if msg.datapath.ofproto.OFP_VERSION == ofproto_v1_0.OFP_VERSION:
                port = msg.in_port
            elif msg.datapath.ofproto.OFP_VERSION >= ofproto_v1_2.OFP_VERSION:
                port = msg.match['in_port']

            if port >= 1024:
                # hack: ignore some strange port
                return

            # ignore global host
            for link in self.cross_domain_links:

                if link['src']['dpid'] == dpid and \
                    link['src']['port'] == port:
                    return

            # TODO, check again if host already in global port

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

            if mac not in self.hosts and port != -1 and \
                not self._host_exist_in_port(dpid, port) and \
                not self._is_switch_port_to_port(dpid, port):
                LOG.debug('Add host %s to %d:%d', mac, dpid, port)
                self.hosts[mac] = (dpid, port)
                self.response_host(mac)
                ev = EventHostDiscovery(dpid, port, mac)
                self.send_event_to_observers(ev)
Esempio n. 15
0
    def _packet_in_handler(self, ev):
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser

        # get Datapath ID to identify OpenFlow switches.
        dpid = datapath.id
        self.mac_to_port.setdefault(dpid, {})

        # analyse the received packets using the packet library.
        pkt = packet.Packet(msg.data)
        eth_pkt = pkt.get_protocol(ethernet.ethernet)
        dst = eth_pkt.dst
        src = eth_pkt.src

        # get the received port number from packet_in message.
        in_port = msg.match['in_port']

        if eth_pkt.ethertype == ether_types.ETH_TYPE_LLDP:
            print LLDPPacket.lldp_parse(msg.data)
            self.logger.info("packet in %s %s %s %s %x", dpid, src, dst,
                             in_port, eth_pkt.ethertype)
Esempio n. 16
0
 def send_lldp_packet(self, datapath_id, port_no, dl_addr):
     datapath = self.dps.get(datapath_id, None)
     if datapath is None:
         #datapath was already deleted
         return
     ofproto = datapath.ofproto
     parser = datapath.ofproto_parser
     lldp_data = LLDPPacket.lldp_packet(datapath.id, port_no, dl_addr,
                                        self.DEFAULT_TTL)
     output_port = parser.OFPActionOutput(port_no, ofproto.OFPCML_NO_BUFFER)
     packet_out = parser.OFPPacketOut(datapath, ofproto.OFPP_ANY,
                                      ofproto.OFPP_CONTROLLER,
                                      [output_port], lldp_data)
     datapath.send_msg(packet_out)
Esempio n. 17
0
    def packet_in_hander(self, ev):
        msg = ev.msg
        dpid = msg.datapath.id
        try:
            src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data)

            if self.switches is None:
                self.switches = lookup_service_brick('switches')

            for port in self.switches.ports.keys():
                if src_dpid == port.dpid and src_port_no == port.port_no:
                    self.lldp_delay[(src_dpid,
                                     dpid)] = self.switches.ports[port].delay
        except:
            return
Esempio n. 18
0
    def handle_lldp_packet(self, ev):
        msg = ev.msg
        try:
            src_dpid, src_port_no, timestamp = LLDPPacket.lldp_parse(msg.data)
            dpid = msg.datapath.id
            if self.sw_module is None:
                self.sw_module = lookup_service_brick('switches')

            for port in self.sw_module.ports.keys():
                if src_dpid == port.dpid and src_port_no == port.port_no:
                    delay = self.sw_module.ports[port].delay
                    self.graph[src_dpid][dpid]['lldpdelay'] = delay

        except LLDPPacket.LLDPUnknownFormat as e:
            return
Esempio n. 19
0
 def send_lldp_packet(self, datapath_id, port_no, dl_addr):
     datapath = self.dps.get(datapath_id, None)
     if datapath is None:
         #datapath was already deleted
         return
     ofproto = datapath.ofproto
     parser = datapath.ofproto_parser
     lldp_data = LLDPPacket.lldp_packet(datapath.id,
                     port_no,
                     dl_addr,
                     self.DEFAULT_TTL)
     output_port = parser.OFPActionOutput(port_no,
                                         ofproto.OFPCML_NO_BUFFER)
     packet_out = parser.OFPPacketOut(datapath, ofproto.OFPP_ANY,
                                       ofproto.OFPP_CONTROLLER,
                                       [output_port], lldp_data)
     datapath.send_msg(packet_out)
Esempio n. 20
0
    def packet_in_handler(self, ev):
        """
            Parsing LLDP packet and get the delay of link.
        """
        msg = ev.msg
        try:
            src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data)
            dpid = msg.datapath.id
            if self.sw_module is None:
                self.sw_module = lookup_service_brick('switches')

            for port in self.sw_module.ports.keys():
                if src_dpid == port.dpid and src_port_no == port.port_no:
                    delay = self.sw_module.ports[port].delay
                    self._save_lldp_delay(src=src_dpid, dst=dpid,
                                          lldpdelay=delay)
        except LLDPPacket.LLDPUnknownFormat as e:
            return
Esempio n. 21
0
    def packet_in_handler(self, ev):
        self._logger.debug('Packet in')
        msg = ev.msg
        ofp = msg.datapath.ofproto
        pkt = packet.Packet(msg.data)
        headers = dict((p.protocol_name, p)
                       for p in pkt.protocols if type(p) != str)
        src_mac = headers[ETHERNET].src
        try:
            src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data)
        except LLDPPacket.LLDPUnknownFormat as e:
            self._logger.debug('LLDPUnknownFormat %s', e)
            return
        dst_port_no = self.ofctl.get_packet_in_inport(msg)
        dst = self._get_port(dst_port_no)
        self._logger.debug('LLDP from %d.%d -> %d',
                           src_dpid,
                           src_port_no,
                           dst_port_no)
        if not dst:
            self._logger.warning('Dst not found.')
            return
        self.ports.lldp_received(dst)
        src = Port(PortData(src_dpid, port_no=src_port_no, hw_addr=src_mac))
        old_peer = self.links.get_peer(dst)
        need_update = False
        if old_peer and old_peer != src:
            self._logger.info('Peer changed.')
            self._report_link_deleted(Link(old_peer, dst))
            need_update = True
        link = Link(src, dst)
        if link not in self.links:
            need_update = True
            self._report_link_added(Link(src, dst))
            self.lldp_event.set()

        # Always return false, since we don't have the reverse link information
        if need_update:
            self.links.update_link(src, dst)
            self._logger.info('Update link %d.%d -> %d.%d',
                              src.dpid,
                              src.port_no,
                              dst.dpid,
                              dst.port_no)
Esempio n. 22
0
    def packet_in_handler(self, ev):
        msg = ev.msg
        try:
            src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data)
            dpid = msg.datapath.id
            in_port = msg.match['in_port']
            if self.sw_module is None:
                self.sw_module = lookup_service_brick('switches')

            for port in self.sw_module.ports.keys():
                if src_dpid == port.dpid and src_port_no == port.port_no:
                    port_data = self.sw_module.ports[port]
                    timestamp = port_data.timestamp
                    if timestamp:
                        delay = time.time() - timestamp
                        self._save_lldp_delay(src=src_dpid, dst=dpid,
                                              lldpdelay=delay)
        except LLDPPacket.LLDPUnknownFormat as e:
            return
Esempio n. 23
0
    def packet_in_handler(self, ev):
        msg = ev.msg
        try:
            src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data)
            dpid = msg.datapath.id
            in_port = msg.match['in_port']
            if self.sw_module is None:
                self.sw_module = lookup_service_brick('switches')

            for port in self.sw_module.ports.keys():
                if src_dpid == port.dpid and src_port_no == port.port_no:
                    port_data = self.sw_module.ports[port]
                    timestamp = port_data.timestamp
                    if timestamp:
                        delay = time.time() - timestamp
                        self._save_lldp_delay(src=src_dpid,
                                              dst=dpid,
                                              lldpdelay=delay)
        except LLDPPacket.LLDPUnknownFormat as e:
            return
Esempio n. 24
0
    def packet_in_handler(self, ev):
        msg = ev.msg
        dp = msg.datapath
        ofp = dp.ofproto
        parser = dp.ofproto_parser
        dpid = dp.id
        in_port = msg.match['in_port']
        pkt = packet.Packet(msg.data)

        eth_pkt = pkt.get_protocols(ethernet.ethernet)[0]
        dst_mac = eth_pkt.dst
        src_mac = eth_pkt.src

        if eth_pkt.ethertype == ether_types.ETH_TYPE_LLDP:
            try:
                src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data)
                if self.switches is None:
                    self.switches = lookup_service_brick('switches')
                for port in self.switches.ports.keys():
                    if src_dpid == port.dpid and src_port_no == port.port_no:
                        self.lldp_delay[(
                            src_dpid, dpid)] = self.switches.ports[port].delay
            except:
                return
            return
        if eth_pkt.ethertype == ether_types.ETH_TYPE_IPV6:
            return

        if src_mac not in self.graph:
            self.graph.add_node(src_mac)
            self.graph.add_edge(src_mac, dpid, weight=0)
            self.graph.add_edge(dpid, src_mac, weight=0, port=in_port)

        header_list = dict(
            (p.protocol_name, p) for p in pkt.protocols if type(p) != str)

        if dst_mac == ETHERNET_MULTICAST and ARP in header_list:
            arp_dst_ip = header_list[ARP].dst_ip
            if (dpid, src_mac, arp_dst_ip) in self.sw:
                if self.sw[(dpid, src_mac, arp_dst_ip)] != in_port:
                    out = parser.OFPPacketOut(datapath=dp,
                                              buffer_id=ofp.OFP_NO_BUFFER,
                                              in_port=in_port,
                                              actions=[],
                                              data=None)
                    dp.send_msg(out)
                    return
            else:
                self.sw[(dpid, src_mac, arp_dst_ip)] = in_port

        # mac learning
        self.mac_to_port.setdefault(dpid, {})
        self.paths.setdefault(src_mac, {})

        out_port = ofp.OFPP_FLOOD

        if dst_mac in self.mac_to_port[dpid]:
            out_port = self.mac_to_port[dpid][dst_mac]
        else:
            if dst_mac in self.graph:
                if dst_mac not in self.paths[src_mac]:
                    try:
                        path = nx.shortest_path(self.graph,
                                                src_mac,
                                                dst_mac,
                                                weight="weight")
                        self.paths[src_mac][dst_mac] = path
                    except:
                        return
                path = self.paths[src_mac][dst_mac]
                next_hop = path[path.index(dpid) + 1]
                out_port = self.graph[dpid][next_hop]['port']
                self.mac_to_port[dpid][dst_mac] = out_port
                print path

        actions = [parser.OFPActionOutput(out_port)]

        if out_port != ofp.OFPP_FLOOD:
            match = parser.OFPMatch(in_port=in_port, eth_dst=dst_mac)
            self.add_flow(dp, 1, match, actions)

        data = None
        if msg.buffer_id == ofp.OFP_NO_BUFFER:
            data = msg.data
        out = parser.OFPPacketOut(datapath=dp,
                                  buffer_id=msg.buffer_id,
                                  in_port=in_port,
                                  actions=actions,
                                  data=data)
        dp.send_msg(out)
Esempio n. 25
0
    def packet_in_handler(self, ev):
        msg = ev.msg
        datapath = msg.datapath

        try:
            # src: from other switch
            src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data)
            # dst: this switch
            dst_dpid, dst_port_no = datapath.id, msg.match['in_port']

            if src_dpid > 1024 or dst_dpid > 1024:
                # hack: ignote illegal switch
                return
            
            switch = api.get_switch(self, src_dpid)

            # not this topology switch
            if len(switch) != 0:
                return

            # send cross domain link add
            self.local_lib.send_cross_domain_link(dst_dpid, dst_port_no, src_dpid, src_port_no)

            # add global port
            self.global_port.setdefault(dst_dpid, [])
            self.global_port[dst_dpid].append(dst_port_no)

            return
        except LLDPPacket.LLDPUnknownFormat:
            # This handler can receive all the packtes which can be
            # not-LLDP packet. Ignore it silently
            pass

        # non-LLDP
        # local routing
        dpid = datapath.id
        pkt = packet.Packet(msg.data)
        eth = pkt.get_protocols(ethernet.ethernet)[0]
        src = eth.src
        dst = eth.dst

        if dst not in self.local_lib.hosts:
            # can't find host in local topology
            # ask global and let this msg queued
            if dst in mDNS or dst in multicast_list:
                return

            if dst == 'ff:ff:ff:ff:ff:ff':
                self._flood_packet(msg)
                return
            self.route_list.append((dst, msg))
            self.local_lib.get_route(dst)
            return

        LOG.debug('Packet in, from %s, to %s', src, dst)
        # found in local, do local routing
        # two case:
        # 1. In same switch
        # 2. Not in same switch
        host = self.local_lib.hosts[dst]

        # host[0] -> dpid
        # host[1] -> port
        if host[0] == dpid:
            # same switch
            out_port = host[1]
            self._packet_out(msg, out_port)

        else:
            # not same switch
            # calculate path
            self._packet_out_to(msg, host[0], host[1])
Esempio n. 26
0
class L2Switch(RyuApp):
    _EVENTS = [
        event.EventSwitchEnter, event.EventSwitchLeave, event.EventPortAdd,
        event.EventPortDelete, event.EventPortModify, event.EventLinkAdd,
        event.EventLinkDelete, event.EventArpReceived
    ]

    OFP_VERSIONS = [OFP_VERSION]

    DEFAULT_TTL = 120  # unused. ignored.
    LLDP_PACKET_LEN = len(LLDPPacket.lldp_packet(0, 0, DONTCARE_STR, 0))

    LLDP_SEND_GUARD = .05
    LLDP_SEND_PERIOD_PER_PORT = .9
    TIMEOUT_CHECK_PERIOD = 15.
    LINK_TIMEOUT = TIMEOUT_CHECK_PERIOD * 2
    LINK_LLDP_DROP = 5

    def __init__(self, *args, **kwargs):
        super(L2Switch, self).__init__(*args, **kwargs)
        self.name = 'switches'
        self.dps = {}  # datapath_id => Datapath class
        self.port_state = {}  # datapath_id => ports
        self.ports = PortDataState()  # Port class -> PortData class
        self.links = LinkState()  # Link class -> timestamp
        self.is_active = True
        self.lldp_event = hub.Event()
        self.link_event = hub.Event()
        self.threads.append(hub.spawn(self.lldp_loop))
        self.threads.append(hub.spawn(self.link_loop))
        self.link_discovery = True

    def close(self):
        self.is_active = False
        if self.link_discovery:
            self.lldp_event.set()
            self.link_event.set()
            hub.joinall(self.threads)

    def lldp_loop(self):
        while self.is_active:
            self.lldp_event.clear()
            now = time.time()
            timeout = None
            ports_now = []
            ports = []
            for (key, data) in self.ports.items():
                if data.timestamp is None:
                    ports_now.append(key)
                    continue

                expire = data.timestamp + self.LLDP_SEND_PERIOD_PER_PORT
                if expire <= now:
                    ports.append(key)
                    continue

                timeout = expire - now
                break
            for port in ports_now:
                self.send_lldp_packet(port.dpid, port.port_no, port.hw_addr)
            for port in ports:
                self.send_lldp_packet(port.dpid, port.port_no, port.hw_addr)
                hub.sleep(self.LLDP_SEND_GUARD)  # don't burst

            if timeout is not None and ports:
                timeout = 0  # We have already slept
            self.lldp_event.wait(timeout=timeout)

    def link_loop(self):
        while self.is_active:
            self.link_event.clear()

            now = time.time()
            deleted = []
            for (link, timestamp) in self.links.items():
                if timestamp + self.LINK_TIMEOUT < now:
                    src = link.src
                    if src in self.ports:
                        port_data = self.ports.get_port(src)
                        if port_data.lldp_dropped() > self.LINK_LLDP_DROP:
                            deleted.append(link)

            for link in deleted:
                self.links.link_down(link)
                self.send_event_to_observers(event.EventLinkDelete(link))

                dst = link.dst
                rev_link = Link(dst, link.src)
                if rev_link not in deleted:
                    # It is very likely that the reverse link is also
                    # disconnected. Check it early.
                    expire = now - self.LINK_TIMEOUT
                    self.links.rev_link_set_timestamp(rev_link, expire)
                    if dst in self.ports:
                        self.ports.move_front(dst)
                        self.lldp_event.set()

            self.link_event.wait(timeout=self.TIMEOUT_CHECK_PERIOD)

    def _get_switch(self, dpid):
        if dpid in self.dps:
            switch = Switch(self.dps[dpid])
            for ofpport in self.port_state[dpid].itervalues():
                switch.add_port(ofpport)
            return switch

    def _get_port(self, dpid, port_no):
        switch = self._get_switch(dpid)
        if switch:
            for p in switch.ports:
                if p.port_no == port_no:
                    return p

    def _port_added(self, port):
        lldp_data = LLDPPacket.lldp_packet(port.dpid, port.port_no,
                                           port.hw_addr, self.DEFAULT_TTL)
        self.ports.add_port(port, lldp_data)
        LOG.debug('_port_added dpid=%s, port_no=%s, live=%s', port.dpid,
                  port.port_no, port.is_live())

    def _register(self, dp):
        assert dp.id is not None
        assert dp.id not in self.dps

        self.dps[dp.id] = dp
        self.port_state[dp.id] = PortState()
        for port in dp.ports.values():
            self.port_state[dp.id].add(port.port_no, port)

    def _link_down(self, port):
        try:
            dst, rev_link_dst = self.links.port_deleted(port)
        except KeyError:
            # LOG.debug('key error. src=%s, dst=%s',
            #           port, self.links.get_peer(port))
            return
        link = Link(port, dst)
        self.send_event_to_observers(event.EventLinkDelete(link))
        if rev_link_dst:
            rev_link = Link(dst, rev_link_dst)
            self.send_event_to_observers(event.EventLinkDelete(rev_link))
        self.ports.move_front(dst)

    @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER)
    def port_status_handler(self, ev):
        msg = ev.msg
        reason = msg.reason
        dp = msg.datapath
        ofpport = msg.desc

        if reason == dp.ofproto.OFPPR_ADD:
            LOG.debug(
                'A port was added.' + '(datapath id = %s, port number = %s)',
                dp.id, ofpport.port_no)
            self.port_state[dp.id].add(ofpport.port_no, ofpport)
            self.send_event_to_observers(
                event.EventPortAdd(Port(dp.id, dp.ofproto, ofpport)))

            if not self.link_discovery:
                return

            port = self._get_port(dp.id, ofpport.port_no)
            if port and not port.is_reserved():
                self._port_added(port)
                self.lldp_event.set()

        elif reason == dp.ofproto.OFPPR_DELETE:
            LOG.debug(
                'A port was deleted.' + '(datapath id = %s, port number = %s)',
                dp.id, ofpport.port_no)
            self.port_state[dp.id].remove(ofpport.port_no)
            self.send_event_to_observers(
                event.EventPortDelete(Port(dp.id, dp.ofproto, ofpport)))

            if not self.link_discovery:
                return

            port = self._get_port(dp.id, ofpport.port_no)
            if port and not port.is_reserved():
                self.ports.del_port(port)
                self._link_down(port)
                self.lldp_event.set()

        else:
            assert reason == dp.ofproto.OFPPR_MODIFY
            LOG.debug(
                'A port was modified.' +
                '(datapath id = %s, port number = %s)', dp.id, ofpport.port_no)
            self.port_state[dp.id].modify(ofpport.port_no, ofpport)
            self.send_event_to_observers(
                event.EventPortModify(Port(dp.id, dp.ofproto, ofpport)))

            if not self.link_discovery:
                return

            port = self._get_port(dp.id, ofpport.port_no)
            if port and not port.is_reserved():
                if self.ports.set_down(port):
                    self._link_down(port)
                    self.lldp_event.set()

    @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
    def switch_features_handler(self, ev):
        """Handle switch features reply to install table miss flow entries."""
        datapath = ev.msg.datapath
        self.install_table_miss(datapath, 0)

    def create_match(self, parser, fields):
        """Create OFP match struct from the list of fields."""
        match = parser.OFPMatch()
        for a in fields:
            match.append_field(*a)
        return match

    def send_barrier_request(self, datapath):
        ofp_parser = datapath.ofproto_parser
        req = ofp_parser.OFPBarrierRequest(datapath)
        datapath.send_msg(req)

    def send_lldp_packet(self, datapath_id, port_no, dl_addr):
        datapath = self.dps.get(datapath_id, None)
        if datapath is None:
            #datapath was already deleted
            return
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        lldp_data = LLDPPacket.lldp_packet(datapath.id, port_no, dl_addr,
                                           self.DEFAULT_TTL)
        output_port = parser.OFPActionOutput(port_no, ofproto.OFPCML_NO_BUFFER)
        packet_out = parser.OFPPacketOut(datapath, ofproto.OFPP_ANY,
                                         ofproto.OFPP_CONTROLLER,
                                         [output_port], lldp_data)
        datapath.send_msg(packet_out)

    @set_ev_cls(ofp_event.EventOFPBarrierReply, MAIN_DISPATCHER)
    def barrier_reply_handler(self, ev):
        msg = ev.msg
        datapath = msg.datapath
        self._register(datapath)
        switch = self._get_switch(datapath.id)
        self.send_event_to_observers(event.EventSwitchEnter(switch))
        for port in switch.ports:
            if not port.is_reserved():
                self._port_added(port)
        self.lldp_event.set()

    def create_flow_mod(self, datapath, priority, table_id, match,
                        instructions):
        """Create OFP flow mod message."""
        ofproto = datapath.ofproto
        flow_mod = datapath.ofproto_parser.OFPFlowMod(
            datapath, 0, 0, table_id, ofproto.OFPFC_ADD, 0, 0, priority,
            ofproto.OFPCML_NO_BUFFER, ofproto.OFPP_ANY, OFPG_ANY, 0, match,
            instructions)
        return flow_mod

    def install_table_miss(self, datapath, table_id):
        """Create and install table miss flow entries."""
        parser = datapath.ofproto_parser
        ofproto = datapath.ofproto
        match = parser.OFPMatch()
        match.set_dl_type(ETH_TYPE_LLDP)
        output = parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
                                        self.LLDP_PACKET_LEN)
        write = parser.OFPInstructionActions(ofproto.OFPIT_WRITE_ACTIONS,
                                             [output])
        instructions = [write]
        flow_mod = self.create_flow_mod(datapath, 0, table_id, match,
                                        instructions)
        datapath.send_msg(flow_mod)
        self.send_barrier_request(datapath)

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def _packet_in_handler(self, ev):
        """Handle packet_in events."""
        if not self.link_discovery:
            return
        msg = ev.msg
        in_port = msg.match['in_port']
        packet = Packet(msg.data)
        efm = packet.get_protocol(ethernet.ethernet)
        if efm.ethertype == ether.ETH_TYPE_ARP:
            self.send_event_to_observers(event.EventArpReceived(ev))

        try:
            src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data)
        except LLDPPacket.LLDPUnknownFormat as e:
            # This handler can receive all the packtes which can be
            # not-LLDP packet. Ignore it silently
            return
        else:
            dst_dpid = msg.datapath.id
            dst_port_no = in_port

            src = self._get_port(src_dpid, src_port_no)
            if not src or src.dpid == dst_dpid:
                return

            dst = self._get_port(dst_dpid, dst_port_no)
            if not dst:
                return

            old_peer = self.links.get_peer(src)
            #LOG.debug("Packet-In")
            #LOG.debug("  src=%s", src)
            #LOG.debug("  dst=%s", dst)
            #LOG.debug("  old_peer=%s", old_peer)
            if old_peer and old_peer != dst:
                old_link = Link(src, old_peer)
                self.send_event_to_observers(event.EventLinkDelete(old_link))

            link = Link(src, dst)
            if not link in self.links:
                self.send_event_to_observers(event.EventLinkAdd(link))

            if not self.links.update_link(src, dst):
                # reverse link is not detected yet.
                # So schedule the check early because it's very likely it's up
                try:
                    self.ports.lldp_received(dst)
                except KeyError as e:
                    # There are races between EventOFPPacketIn and
                    # EventDPPortAdd. So packet-in event can happend before
                    # port add event. In that case key error can happend.
                    # LOG.debug('lldp_received: KeyError %s', e)
                    pass
                else:
                    self.ports.move_front(dst)
                    self.lldp_event.set()
Esempio n. 27
0
 def _port_added(self, port):
     lldp_data = LLDPPacket.lldp_packet(
         port.dpid, port.port_no, port.hw_addr, self.DEFAULT_TTL)
     self.ports.add_port(port, lldp_data)
     LOG.debug('_port_added dpid=%s, port_no=%s, live=%s',
              port.dpid, port.port_no, port.is_live())
Esempio n. 28
0
 def _port_added(self, port):
     lldp_data = LLDPPacket.lldp_packet(port.dpid, port.port_no,
                                        port.hw_addr, self.DEFAULT_TTL)
     self.ports.add_port(port, lldp_data)
     LOG.debug('_port_added dpid=%s, port_no=%s, live=%s', port.dpid,
               port.port_no, port.is_live())
Esempio n. 29
0
class Topology(LocalService):
    _EVENTS = {EventPortAdd,
               EventPortDelete,
               EventPortModify,
               EventLinkAdd,
               EventLinkDelete}
    """
    Ryu topology module ported to Local Controller
    """
    DEFAULT_TTL = 64
    LLDP_PACKET_LEN = len(LLDPPacket.lldp_packet(0, 0, DONTCARE_STR, 0))
    LLDP_SEND_GUARD = .05
    LLDP_SEND_PERIOD_PER_PORT = .9
    TIMEOUT_CHECK_PERIOD = 5.
    LINK_TIMEOUT = TIMEOUT_CHECK_PERIOD * 2
    LINK_LLDP_DROP = 5
    LLDP_PRIORITY = 0xFFFF

    def __init__(self, *args, **kwargs):
        super(Topology, self).__init__(*args, **kwargs)
        self.is_active = True
        self.explicit_drop = True
        self.ports = PortDataState()
        self.links = _LinkState()
        self.lldp_event = hub.Event()
        self.link_event = hub.Event()
        self.threads.append(hub.spawn(self.lldp_loop))
        self.threads.append(hub.spawn(self.link_loop))

    def _port_added(self, port):
        lldp_data = LLDPPacket.lldp_packet(
            port.dpid, port.port_no, port.hw_addr, self.DEFAULT_TTL)
        self.ports.add_port(port, lldp_data)

    def _switch_enter(self, dp):
        super(Topology, self)._switch_enter(dp)
        self._init_flows()
        ports = [Port(PortData(dp.id, port, dp.ofproto)) for port in
                 dp.ports.values()]
        for port in ports:
            if not port.is_reserved():
                self._port_added(port)
        self.ryuo.switch_enter(dp.id,
                               [port.port_data for port in self.ports.keys()])
        self.lldp_event.set()

    def _init_flows(self):
        self._logger.info('Init flow table.')
        self.ofctl.set_packet_in_flow(cookie=0, priority=self.LLDP_PRIORITY,
                                      eth_type=ETH_TYPE_LLDP,
                                      eth_dst=lldp.LLDP_MAC_NEAREST_BRIDGE)

    def _switch_leave(self):
        super(Topology, self)._switch_leave()
        self.links.clear()
        self.ports.clear()

    def _get_port(self, port_no):
        for port in self.ports.keys():
            if port.port_no == port_no:
                return port

    def _report_port_added(self, port):
        self.send_event_to_observers(EventPortAdd(port))
        self.ryuo.port_added(port.port_data)

    def _report_port_deleted(self, port):
        self.send_event_to_observers(EventPortDelete(port))
        self.ryuo.port_deleted(port.port_data)

    def _report_port_modified(self, port):
        self.send_event_to_observers(EventPortModify(port))
        self.ryuo.port_modified(port.port_data)

    @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER)
    def _port_status_change(self, ev):
        if self.dp is None:
            return
        msg = ev.msg
        reason = msg.reason
        dp = msg.datapath
        ofpport = msg.desc
        ofp = dp.ofproto

        if reason == ofp.OFPPR_ADD:
            self._logger.info('Port %d added.', ofpport.port_no)
            port = Port(PortData(self.dp.id, ofpport, ofp))
            if not port.is_reserved():
                self._port_added(port)
                self._report_port_added(port)
                self.lldp_event.set()
        elif reason == ofp.OFPPR_DELETE:
            self._logger.info('Port %d deleted.', ofpport.port_no)
            port = self._get_port(ofpport.port_no)
            if port and not port.is_reserved():
                del self.ports[Port(PortData(self.dp.id, ofpport))]
                self._report_port_deleted(port)
                self._link_down(port)
                self.lldp_event.set()
        else:
            self._logger.info('Port %d modified.', ofpport.port_no)
            port = self._get_port(ofpport.port_no)
            port.lldp_reply = False
            if port and not port.is_reserved():
                port.modify(ofpport)
                self._report_port_modified(port)
                if self.ports.set_down(port):
                    self._link_down(port)
                self.lldp_event.set()

    def send_lldp_packet(self, port):
        try:
            port_data = self.ports.lldp_sent(port)
        except KeyError as e:
            # ports can be modified during our sleep in self.lldp_loop()
            self._logger.warning('Missing port %d, %s.', port.port_no, e)
            return
        if port_data.is_down:
            return

        dp = self.dp
        if dp is None:
            # datapath was already deleted
            self._logger.warning('Switch left.')
            return

        self.ofctl.send_packet_out(in_port=dp.ofproto.OFPP_CONTROLLER,
                                   output=port.port_no,
                                   data=port_data.lldp_data)

    def lldp_loop(self):
        while self.is_active:
            self._logger.debug('LLDP loop')
            self.lldp_event.clear()

            now = time.time()
            timeout = None
            ports_now = []
            ports = []
            for (key, data) in self.ports.items():
                if data.timestamp is None:
                    ports_now.append(key)
                    continue

                expire = data.timestamp + self.LLDP_SEND_PERIOD_PER_PORT
                if expire <= now:
                    ports.append(key)
                    continue

                if timeout is None or timeout > expire - now:
                    timeout = expire - now
                    # break

            for port in ports_now:
                self.send_lldp_packet(port)
                self._logger.debug('Sending LLDP to %d.%d',
                                   port.dpid,
                                   port.port_no)
            for port in ports:
                self.send_lldp_packet(port)
                self._logger.debug('Sending LLDP to %d.%d',
                                   port.dpid,
                                   port.port_no)
                hub.sleep(self.LLDP_SEND_GUARD)  # don't burst

            if timeout is not None and ports:
                timeout = 0  # We have already slept
            # LOG.debug('lldp sleep %s', timeout)
            self.lldp_event.wait(timeout=timeout)

    def _report_link_deleted(self, link):
        self.send_event_to_observers(EventLinkDelete(link))
        self.ryuo.link_deleted(link.src.port_data, link.dst.port_data)

    def _report_link_added(self, link):
        self.send_event_to_observers(EventLinkAdd(link))
        self.ryuo.link_added(link.src.port_data, link.dst.port_data)

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def packet_in_handler(self, ev):
        self._logger.debug('Packet in')
        msg = ev.msg
        ofp = msg.datapath.ofproto
        pkt = packet.Packet(msg.data)
        headers = dict((p.protocol_name, p)
                       for p in pkt.protocols if type(p) != str)
        src_mac = headers[ETHERNET].src
        try:
            src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data)
        except LLDPPacket.LLDPUnknownFormat as e:
            self._logger.debug('LLDPUnknownFormat %s', e)
            return
        dst_port_no = self.ofctl.get_packet_in_inport(msg)
        dst = self._get_port(dst_port_no)
        self._logger.debug('LLDP from %d.%d -> %d',
                           src_dpid,
                           src_port_no,
                           dst_port_no)
        if not dst:
            self._logger.warning('Dst not found.')
            return
        self.ports.lldp_received(dst)
        src = Port(PortData(src_dpid, port_no=src_port_no, hw_addr=src_mac))
        old_peer = self.links.get_peer(dst)
        need_update = False
        if old_peer and old_peer != src:
            self._logger.info('Peer changed.')
            self._report_link_deleted(Link(old_peer, dst))
            need_update = True
        link = Link(src, dst)
        if link not in self.links:
            need_update = True
            self._report_link_added(Link(src, dst))
            self.lldp_event.set()

        # Always return false, since we don't have the reverse link information
        if need_update:
            self.links.update_link(src, dst)
            self._logger.info('Update link %d.%d -> %d.%d',
                              src.dpid,
                              src.port_no,
                              dst.dpid,
                              dst.port_no)

    def link_loop(self):
        while self.is_active:
            self.link_event.clear()

            now = time.time()
            deleted = []
            for (link, timestamp) in self.links.items():
                # LOG.debug('%s timestamp %d (now %d)', link, timestamp, now)
                if timestamp + self.LINK_TIMEOUT < now:
                    src = link.src
                    if src in self.ports:
                        port_data = self.ports.get_port(src)
                        # LOG.debug('port_data %s', port_data)
                        if port_data.lldp_dropped() > self.LINK_LLDP_DROP:
                            deleted.append(link)

            for link in deleted:
                self.links.link_down(link)
                # LOG.debug('delete %s', link)
                self._report_link_deleted(link)

            self.link_event.wait(timeout=self.TIMEOUT_CHECK_PERIOD)

    def _link_down(self, port):
        try:
            src, rev_link_dst = self.links.dst_port_deleted(port)
            self._logger.info('Link down: %d.%d -> %d.%d',
                              src.dpid,
                              src.port_no,
                              port.dpid,
                              port.port_no)
        except KeyError:
            self._logger.info('Cannot find peer of %d.%d',
                              port.dpid,
                              port.port_no)
            return
        self._report_link_deleted(Link(src, port))

    def close(self):
        self.is_active = False
        self.lldp_event.set()
        self.link_event.set()
        super(Topology, self).close()
Esempio n. 30
0
 def _port_added(self, port):
     lldp_data = LLDPPacket.lldp_packet(
         port.dpid, port.port_no, port.hw_addr, self.DEFAULT_TTL)
     self.ports.add_port(port, lldp_data)
Esempio n. 31
0
    def packet_in_handler(self, ev):
        msg = ev.msg
        datapath = msg.datapath

        try:
            # src: from other switch
            src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data)
            # dst: this switch
            dst_dpid, dst_port_no = datapath.id, msg.match['in_port']

            if src_dpid > 1024 or dst_dpid > 1024:
                # hack: ignote illegal switch
                return

            switch = api.get_switch(self, src_dpid)

            # not this topology switch
            if len(switch) != 0:
                return

            # send cross domain link add
            self.local_lib.send_cross_domain_link(dst_dpid, dst_port_no,
                                                  src_dpid, src_port_no)

            # add global port
            self.global_port.setdefault(dst_dpid, [])
            self.global_port[dst_dpid].append(dst_port_no)

            return
        except LLDPPacket.LLDPUnknownFormat:
            # This handler can receive all the packtes which can be
            # not-LLDP packet. Ignore it silently
            pass

        # non-LLDP
        # local routing
        dpid = datapath.id
        pkt = packet.Packet(msg.data)
        eth = pkt.get_protocols(ethernet.ethernet)[0]
        src = eth.src
        dst = eth.dst

        if dst not in self.local_lib.hosts:
            # can't find host in local topology
            # ask global and let this msg queued
            if dst in mDNS or dst in multicast_list:
                return

            if dst == 'ff:ff:ff:ff:ff:ff':
                self._flood_packet(msg)
                return
            self.route_list.append((dst, msg))
            self.local_lib.get_route(dst)
            return

        LOG.debug('Packet in, from %s, to %s', src, dst)
        # found in local, do local routing
        # two case:
        # 1. In same switch
        # 2. Not in same switch
        host = self.local_lib.hosts[dst]

        # host[0] -> dpid
        # host[1] -> port
        if host[0] == dpid:
            # same switch
            out_port = host[1]
            self._packet_out(msg, out_port)

        else:
            # not same switch
            # calculate path
            self._packet_out_to(msg, host[0], host[1])
Esempio n. 32
0
    def packet_in_handler(self, ev):
        msg = ev.msg
        dp = msg.datapath
        ofp = dp.ofproto
        ofp_parser = dp.ofproto_parser

        port = msg.match['in_port']

        ## parses the packet
        pkt = packet.Packet(data=msg.data)
        # ethernet
        pkt_ethernet = pkt.get_protocol(ethernet.ethernet)

        if not pkt_ethernet:
            return

        # 當為LLDP packet時,把lldpdelay資料取出來
        if pkt_ethernet.ethertype == 35020:
            try:
                src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data)
                dst_dpid = msg.datapath.id
                if self.switch_mod is None:
                    self.switch_mod = lookup_service_brick('switches')

                for port in self.switch_mod.ports.keys():
                    if src_dpid == port.dpid and src_port_no == port.port_no:
                        lldpdelay = self.switch_mod.ports[port].delay
                        self.net[src_dpid][dst_dpid]["lldpdelay"] = lldpdelay
            except LLDPPacket.LLDPUnknownFormat as e:
                return

        if msg.buffer_id == ofp.OFP_NO_BUFFER:
            data = msg.data

        # arp封包处理
        if pkt_ethernet.dst == 'ff:ff:ff:ff:ff:ff':
            if self.mac_learning(dp, pkt_ethernet.src,
                                 port) is False:  #判断是否会造成广播风暴,False代表為是會造成
                out_port = ofp.OFPPC_NO_RECV  #将封包丢掉
            else:
                out_port = ofp.OFPP_FLOOD  #做flooding
                if not self.net.has_node(
                        pkt_ethernet.src):  #若arp封包源沒有包含在圖裡面,則將它加入進圖中
                    self.net.add_node(pkt_ethernet.src)
                    self.net.add_edge(pkt_ethernet.src,
                                      dp.id,
                                      bw=0,
                                      delay=0,
                                      lldpdelay=0)  #添加雙向的邊
                    self.net.add_edge(dp.id,
                                      pkt_ethernet.src,
                                      port=port,
                                      bw=0,
                                      delay=0,
                                      lldpdelay=0)
                    self.idport_to_id.update({(dp.id, port): pkt_ethernet.src})
                    print(self.idport_to_id)
                    print(self.net.nodes())
                    print(self.net.edges())

            actions = [ofp_parser.OFPActionOutput(out_port)]
            #inst = [actions]
            out = ofp_parser.OFPPacketOut(datapath=dp,
                                          buffer_id=msg.buffer_id,
                                          in_port=port,
                                          actions=actions,
                                          data=data)
            dp.send_msg(out)
            return

        if pkt_ethernet.ethertype != 34525 and pkt_ethernet.ethertype != 35020:
            if not self.net.has_node(pkt_ethernet.src):  #如果不在图里则新增
                print("add %s in self.net" % pkt_ethernet.src)
                #print(pkt_ethernet.ethertype)
                self.net.add_node(pkt_ethernet.src)
                self.net.add_edge(pkt_ethernet.src,
                                  dp.id,
                                  bw=0,
                                  delay=0,
                                  lldpdelay=0)
                #self.net.add_edge(dp.id, pkt_ethernet.src, {'port':port})
                self.net.add_edge(dp.id,
                                  pkt_ethernet.src,
                                  port=port,
                                  bw=0,
                                  delay=0,
                                  lldpdelay=0)
                self.idport_to_id.update({(dp.id, port): pkt_ethernet.src})
                print(self.idport_to_id)
                print(self.net.nodes())
                print(self.net.edges.data())

        if self.net.has_node(pkt_ethernet.dst):
            print("%s in self.net" % pkt_ethernet.dst)
            path = nx.dijkstra_path(self.net,
                                    pkt_ethernet.src,
                                    pkt_ethernet.dst,
                                    weight='bw')  #以当前bw作最短路徑轉發
            next_match = ofp_parser.OFPMatch(eth_dst=pkt_ethernet.dst,
                                             eth_src=pkt_ethernet.src)
            back_match = ofp_parser.OFPMatch(eth_dst=pkt_ethernet.src,
                                             eth_src=pkt_ethernet.dst)
            print(path)
            #依照計算后算出的路徑下發流表
            for on_path_switch in range(1, len(path) - 1):
                now_switch = path[on_path_switch]  #这里需要知道現在,之前以及之後的switch
                next_switch = path[on_path_switch + 1]
                back_switch = path[on_path_switch - 1]
                next_port = self.net[now_switch][next_switch]['port']
                back_port = self.net[now_switch][back_switch]['port']
                action = ofp_parser.OFPInstructionActions(
                    ofp.OFPIT_APPLY_ACTIONS,
                    [ofp_parser.OFPActionOutput(next_port)])
                inst = [action]
                self.add_flow(dp=self.switch_map[now_switch],
                              match=next_match,
                              inst=inst,
                              table=0,
                              idle_timeout=5)

                action = ofp_parser.OFPInstructionActions(
                    ofp.OFPIT_APPLY_ACTIONS,
                    [ofp_parser.OFPActionOutput(back_port)])
                inst = [action]
                self.add_flow(dp=self.switch_map[now_switch],
                              match=back_match,
                              inst=inst,
                              table=0,
                              idle_timeout=5)
                print("now switch:%s" % now_switch)

            now_switch = path[1]
            next_switch = path[2]
            out_port = self.net[now_switch][next_switch]['port']
            actions = [ofp_parser.OFPActionOutput(out_port)]
            out = ofp_parser.OFPPacketOut(datapath=dp,
                                          buffer_id=msg.buffer_id,
                                          in_port=port,
                                          actions=actions,
                                          data=data)
            dp.send_msg(out)
        else:
            return
Esempio n. 33
0
		def packet_in_handler(self, ev):
				
				AF3 = [104,112,120]
				EF = [184]
				
				msg= ev.msg
				dp = msg.datapath
				ofp = dp.ofproto
				ofp_parser = dp.ofproto_parser

				port = msg.match['in_port']
				
				## parses the packet
				pkt = packet.Packet(data=msg.data)
				# ethernet
				pkt_ethernet = pkt.get_protocol(ethernet.ethernet)
				

				if not pkt_ethernet:
						return

				# 當為LLDP packet時,把lldpdelay資料取出來
				if pkt_ethernet.ethertype == 35020:
					try:	
						src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data)
						dst_dpid = msg.datapath.id
						if self.switch_mod is None:
							self.switch_mod = lookup_service_brick('switches')

						for port in self.switch_mod.ports.keys(): 
							if src_dpid == port.dpid and src_port_no == port.port_no:
								lldpdelay = self.switch_mod.ports[port].delay
								self.net[src_dpid][dst_dpid]["lldpdelay"] = lldpdelay
					except LLDPPacket.LLDPUnknownFormat as e:
						return
				
				if msg.buffer_id == ofp.OFP_NO_BUFFER:
						data = msg.data

				if pkt_ethernet.ethertype != 34525 and pkt_ethernet.ethertype != 35020:
						if not self.net.has_node(pkt_ethernet.src): #如果不在图里则新增
								#print("add %s in self.net" % pkt_ethernet.src)
								#print(pkt_ethernet.ethertype)
								self.net.add_node(pkt_ethernet.src)
								self.net.add_edge(pkt_ethernet.src, dp.id, bw=0, delay=0, lldpdelay=0, load=0)
								self.net.add_edge(dp.id, pkt_ethernet.src, port=port, bw=0, delay=0, lldpdelay=0, load=0)
								self.idport_to_id.update({(dp.id,port):pkt_ethernet.src})
								#print(self.idport_to_id)
								#print(self.net.nodes())
								#print(self.net.edges.data())

				# arp封包处理
				arp_info = pkt.get_protocol(arp.arp)
				if arp_info != None: #代表是arp封包
					if pkt_ethernet.dst == 'ff:ff:ff:ff:ff:ff':
						if self.mac_learning(dp,pkt_ethernet.src,port) is False: #判断是否会造成广播风暴,False代表為是會造成
								out_port = ofp.OFPPC_NO_RECV #将封包丢掉
						else:
								out_port = ofp.OFPP_FLOOD #做flooding
								#更新mac_to_port 表,之后要用来作arp封包的处理
								self.mac_to_port.setdefault(dp.id, {})
								self.mac_to_port[dp.id][pkt_ethernet.src] = port
								if not self.net.has_node(pkt_ethernet.src): #若arp封包源沒有包含在圖裡面,則將它加入進圖中
										self.net.add_node(pkt_ethernet.src)
										self.net.add_edge(pkt_ethernet.src,dp.id,bw=0,delay=0, lldpdelay=0, load=0) #添加雙向的邊
										self.net.add_edge(dp.id,pkt_ethernet.src,port=port,bw=0, delay=0, lldpdelay=0, load=0)
										self.idport_to_id.update({(dp.id,port):pkt_ethernet.src})
										#print(self.idport_to_id)
										#print(self.net.nodes())
										#print(self.net.edges())

						actions = [ofp_parser.OFPActionOutput(out_port)]
						out = ofp_parser.OFPPacketOut(datapath=dp,buffer_id=msg.buffer_id,in_port=port,actions=actions,data=data)
						dp.send_msg(out)
						return
					else:
						if pkt_ethernet.dst in self.mac_to_port[dp.id]:
							out_port = self.mac_to_port[dp.id][pkt_ethernet.dst]
							actions = [ofp_parser.OFPActionOutput(out_port)]
							out = ofp_parser.OFPPacketOut(datapath=dp, buffer_id=msg.buffer_id, in_port=port, actions=actions, data=data)
							dp.send_msg(out)
						return


				
				if self.net.has_node(pkt_ethernet.dst):
						#print("%s in self.net" % pkt_ethernet.dst)
						ip_info = pkt.get_protocol(ipv4.ipv4)
						print(ip_info)
						if ip_info != None:
								path = [p for p in nx.all_shortest_paths(self.net, pkt_ethernet.src, pkt_ethernet.dst)]
								print("All shortest path")
								print(path)
								
								count = 0
								meter_id = None
								print("finding avaliable shortest path...")
								for i in range(len(path)):
										for j in range(len(path[i])-1):
												if (path[i][j], path[i][j+1]) not in self.busy_link:
														count = count + 1
										if count > 2:
												path = path[i]
												print("find shortest path!!")
												break
										count = 0

										if i == len(path) - 1:
												print("cant find avaliable shortest path, finding other path...")
												if ip_info.tos in AF3: 
														path = nx.dijkstra_path(self.net, pkt_ethernet.src, pkt_ethernet.dst, weight='bw') #以当前bw作最短路徑轉發
														meter_id = 3
														print("find min bandwidth path")
												elif ip_info.tos in EF:
														path = nx.dijkstra_path(self.net, pkt_ethernet.src, pkt_ethernet.dst, weight='delay')
														meter_id = 3
														print("find min delay path")
												else:
														path = path[i]
														#ip_info.tos = 0 #强制其tos段等于0
														meter_id = 3
														print("dont change path, tos=0")
								print(path)		
						next_match = ofp_parser.OFPMatch(eth_dst=pkt_ethernet.dst,eth_src=pkt_ethernet.src,eth_type=0x0800,ipv4_src=ip_info.src, ipv4_dst=ip_info.dst, ip_dscp=int(ip_info.tos/4))
						back_match = ofp_parser.OFPMatch(eth_dst=pkt_ethernet.src,eth_src=pkt_ethernet.dst,eth_type=0x0800,ipv4_src=ip_info.src, ipv4_dst=ip_info.dst, ip_dscp=int(ip_info.tos/4))
						#print(path)
						#依照計算后算出的路徑下發流表
						for on_path_switch in range(1, len(path)-1):
								now_switch = path[on_path_switch] #这里需要知道現在,之前以及之後的switch
								next_switch = path[on_path_switch+1]
								back_switch = path[on_path_switch-1]
								next_port = self.net[now_switch][next_switch]['port']
								back_port = self.net[now_switch][back_switch]['port']
								action = ofp_parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, [ofp_parser.OFPActionOutput(next_port)])
								hard_timeout = 0
								if meter_id == None:
										inst = [action]
								else:
										inst = [action, ofp_parser.OFPInstructionMeter(meter_id, ofp.OFPIT_METER)]
										hard_timeout = 10
								
								self.add_flow(dp=self.switch_map[now_switch], match=next_match, inst=inst, table=0, idle_timeout=50, hard_timeout=hard_timeout)
								
								action = ofp_parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, [ofp_parser.OFPActionOutput(back_port)])

								self.add_flow(dp=self.switch_map[now_switch], match=back_match, inst=inst, table=0, idle_timeout=50, hard_timeout=hard_timeout)
								#print("now switch:%s" % now_switch)
						
						now_switch = path[1]
						next_switch = path[2]
						out_port = self.net[now_switch][next_switch]['port']
						actions = [ofp_parser.OFPActionOutput(out_port)]
						out = ofp_parser.OFPPacketOut(datapath=dp,buffer_id=msg.buffer_id,in_port=port,actions=actions,data=data)
						dp.send_msg(out)
				else:
						return